diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 466da01ba2e3..105682237a9d 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1119,10 +1119,14 @@ static void veth_disable_xdp_range(struct net_device *dev, int start, int end,
 
 static int veth_enable_xdp(struct net_device *dev)
 {
-	bool napi_already_on = veth_gro_requested(dev) && (dev->flags & IFF_UP);
 	struct veth_priv *priv = netdev_priv(dev);
+	bool napi_already_on;
+	struct veth_rq *rq;
 	int err, i;
 
+	rq = &priv->rq[0];
+	napi_already_on = (dev->flags & IFF_UP) && rcu_access_pointer(rq->napi);
+
 	if (!xdp_rxq_info_is_reg(&priv->rq[0].xdp_rxq)) {
 		err = veth_enable_xdp_range(dev, 0, dev->real_num_rx_queues, napi_already_on);
 		if (err)
@@ -1323,18 +1327,28 @@ static int veth_set_channels(struct net_device *dev,
 
 static int veth_open(struct net_device *dev)
 {
-	struct veth_priv *priv = netdev_priv(dev);
+	struct veth_priv *peer_priv, *priv = netdev_priv(dev);
 	struct net_device *peer = rtnl_dereference(priv->peer);
+	struct veth_rq *peer_rq;
 	int err;
 
 	if (!peer)
 		return -ENOTCONN;
 
+	peer_priv = netdev_priv(peer);
+	peer_rq = &peer_priv->rq[0];
+
 	if (priv->_xdp_prog) {
 		err = veth_enable_xdp(dev);
 		if (err)
 			return err;
-	} else if (veth_gro_requested(dev)) {
+		/* refer to the logic in veth_xdp_set() */
+		if (!rtnl_dereference(peer_rq->napi)) {
+			err = veth_napi_enable(peer);
+			if (err)
+				return err;
+		}
+	} else if (veth_gro_requested(dev) || peer_priv->_xdp_prog) {
 		err = veth_napi_enable(dev);
 		if (err)
 			return err;
@@ -1350,17 +1364,29 @@ static int veth_open(struct net_device *dev)
 
 static int veth_close(struct net_device *dev)
 {
-	struct veth_priv *priv = netdev_priv(dev);
+	struct veth_priv *peer_priv, *priv = netdev_priv(dev);
 	struct net_device *peer = rtnl_dereference(priv->peer);
+	struct veth_rq *peer_rq;
 
 	netif_carrier_off(dev);
-	if (peer)
-		netif_carrier_off(peer);
+	if (peer) {
+		peer_priv = netdev_priv(peer);
+		peer_rq = &peer_priv->rq[0];
+	}
 
-	if (priv->_xdp_prog)
+	if (priv->_xdp_prog) {
 		veth_disable_xdp(dev);
-	else if (veth_gro_requested(dev))
+		/* refer to the logic in veth_xdp_set */
+		if (peer && rtnl_dereference(peer_rq->napi)) {
+			if (!veth_gro_requested(peer) && !peer_priv->_xdp_prog)
+				veth_napi_del(peer);
+		}
+	} else if (veth_gro_requested(dev) || (peer && peer_priv->_xdp_prog)) {
 		veth_napi_del(dev);
+	}
+
+	if (peer)
+		netif_carrier_off(peer);
 
 	return 0;
 }
@@ -1470,17 +1496,21 @@ static int veth_set_features(struct net_device *dev,
 {
 	netdev_features_t changed = features ^ dev->features;
 	struct veth_priv *priv = netdev_priv(dev);
+	struct veth_rq *rq = &priv->rq[0];
 	int err;
 
 	if (!(changed & NETIF_F_GRO) || !(dev->flags & IFF_UP) || priv->_xdp_prog)
 		return 0;
 
 	if (features & NETIF_F_GRO) {
-		err = veth_napi_enable(dev);
-		if (err)
-			return err;
+		if (!rtnl_dereference(rq->napi)) {
+			err = veth_napi_enable(dev);
+			if (err)
+				return err;
+		}
 	} else {
-		veth_napi_del(dev);
+		if (rtnl_dereference(rq->napi))
+			veth_napi_del(dev);
 	}
 	return 0;
 }
@@ -1512,14 +1542,19 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
 			struct netlink_ext_ack *extack)
 {
 	struct veth_priv *priv = netdev_priv(dev);
+	struct veth_priv *peer_priv;
 	struct bpf_prog *old_prog;
+	struct veth_rq *peer_rq;
 	struct net_device *peer;
+	bool napi_already_off;
 	unsigned int max_mtu;
+	bool noreq_napi;
 	int err;
 
 	old_prog = priv->_xdp_prog;
 	priv->_xdp_prog = prog;
 	peer = rtnl_dereference(priv->peer);
+	peer_priv = netdev_priv(peer);
 
 	if (prog) {
 		if (!peer) {
@@ -1556,6 +1591,24 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
 			}
 		}
 
+		if (peer && (peer->flags & IFF_UP)) {
+			peer_rq = &peer_priv->rq[0];
+
+			/* If the peer hasn't enabled GRO and loaded xdp,
+			 * then we enable napi automatically if its napi
+			 * is not ready.
+			 */
+			napi_already_off = !rtnl_dereference(peer_rq->napi);
+			if (napi_already_off) {
+				err = veth_napi_enable(peer);
+				if (err) {
+					NL_SET_ERR_MSG_MOD(extack,
+							   "Failed to automatically enable napi of peer");
+					goto err;
+				}
+			}
+		}
+
 		if (!old_prog) {
 			peer->hw_features &= ~NETIF_F_GSO_SOFTWARE;
 			peer->max_mtu = max_mtu;
@@ -1570,6 +1623,17 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
 			if (peer) {
 				peer->hw_features |= NETIF_F_GSO_SOFTWARE;
 				peer->max_mtu = ETH_MAX_MTU;
+				peer_rq = &peer_priv->rq[0];
+
+				/* If the peer doesn't has its xdp and enabled
+				 * GRO, then we disable napi if its napi is ready;
+				 */
+				if (rtnl_dereference(peer_rq->napi)) {
+					noreq_napi = !veth_gro_requested(peer) &&
+						     !peer_priv->_xdp_prog;
+					if (noreq_napi && (peer->flags & IFF_UP))
+						veth_napi_del(peer);
+				}
 			}
 		}
 		bpf_prog_put(old_prog);
