@@ -57,6 +57,7 @@ struct veth_rq_stats {
5757
5858struct veth_rq {
5959 struct napi_struct xdp_napi ;
60+ struct napi_struct __rcu * napi ; /* points to xdp_napi when the latter is initialized */
6061 struct net_device * dev ;
6162 struct bpf_prog __rcu * xdp_prog ;
6263 struct xdp_mem_info xdp_mem ;
@@ -299,7 +300,7 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
299300 struct veth_rq * rq = NULL ;
300301 struct net_device * rcv ;
301302 int length = skb -> len ;
302- bool rcv_xdp = false;
303+ bool use_napi = false;
303304 int rxq ;
304305
305306 rcu_read_lock ();
@@ -313,20 +314,24 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
313314 rxq = skb_get_queue_mapping (skb );
314315 if (rxq < rcv -> real_num_rx_queues ) {
315316 rq = & rcv_priv -> rq [rxq ];
316- rcv_xdp = rcu_access_pointer (rq -> xdp_prog );
317+
318+ /* The napi pointer is available when an XDP program is
319+ * attached or when GRO is enabled
320+ */
321+ use_napi = rcu_access_pointer (rq -> napi );
317322 skb_record_rx_queue (skb , rxq );
318323 }
319324
320325 skb_tx_timestamp (skb );
321- if (likely (veth_forward_skb (rcv , skb , rq , rcv_xdp ) == NET_RX_SUCCESS )) {
322- if (!rcv_xdp )
326+ if (likely (veth_forward_skb (rcv , skb , rq , use_napi ) == NET_RX_SUCCESS )) {
327+ if (!use_napi )
323328 dev_lstats_add (dev , length );
324329 } else {
325330drop :
326331 atomic64_inc (& priv -> dropped );
327332 }
328333
329- if (rcv_xdp )
334+ if (use_napi )
330335 __veth_xdp_flush (rq );
331336
332337 rcu_read_unlock ();
@@ -903,7 +908,7 @@ static int veth_poll(struct napi_struct *napi, int budget)
903908 return done ;
904909}
905910
906- static int veth_napi_add (struct net_device * dev )
911+ static int __veth_napi_enable (struct net_device * dev )
907912{
908913 struct veth_priv * priv = netdev_priv (dev );
909914 int err , i ;
@@ -920,6 +925,7 @@ static int veth_napi_add(struct net_device *dev)
920925 struct veth_rq * rq = & priv -> rq [i ];
921926
922927 napi_enable (& rq -> xdp_napi );
928+ rcu_assign_pointer (priv -> rq [i ].napi , & priv -> rq [i ].xdp_napi );
923929 }
924930
925931 return 0 ;
@@ -938,6 +944,7 @@ static void veth_napi_del(struct net_device *dev)
938944 for (i = 0 ; i < dev -> real_num_rx_queues ; i ++ ) {
939945 struct veth_rq * rq = & priv -> rq [i ];
940946
947+ rcu_assign_pointer (priv -> rq [i ].napi , NULL );
941948 napi_disable (& rq -> xdp_napi );
942949 __netif_napi_del (& rq -> xdp_napi );
943950 }
@@ -951,16 +958,23 @@ static void veth_napi_del(struct net_device *dev)
951958 }
952959}
953960
961+ static bool veth_gro_requested (const struct net_device * dev )
962+ {
963+ return !!(dev -> wanted_features & NETIF_F_GRO );
964+ }
965+
954966static int veth_enable_xdp (struct net_device * dev )
955967{
968+ bool napi_already_on = veth_gro_requested (dev ) && (dev -> flags & IFF_UP );
956969 struct veth_priv * priv = netdev_priv (dev );
957970 int err , i ;
958971
959972 if (!xdp_rxq_info_is_reg (& priv -> rq [0 ].xdp_rxq )) {
960973 for (i = 0 ; i < dev -> real_num_rx_queues ; i ++ ) {
961974 struct veth_rq * rq = & priv -> rq [i ];
962975
963- netif_napi_add (dev , & rq -> xdp_napi , veth_poll , NAPI_POLL_WEIGHT );
976+ if (!napi_already_on )
977+ netif_napi_add (dev , & rq -> xdp_napi , veth_poll , NAPI_POLL_WEIGHT );
964978 err = xdp_rxq_info_reg (& rq -> xdp_rxq , dev , i , rq -> xdp_napi .napi_id );
965979 if (err < 0 )
966980 goto err_rxq_reg ;
@@ -975,13 +989,25 @@ static int veth_enable_xdp(struct net_device *dev)
975989 rq -> xdp_mem = rq -> xdp_rxq .mem ;
976990 }
977991
978- err = veth_napi_add (dev );
979- if (err )
980- goto err_rxq_reg ;
992+ if (!napi_already_on ) {
993+ err = __veth_napi_enable (dev );
994+ if (err )
995+ goto err_rxq_reg ;
996+
997+ if (!veth_gro_requested (dev )) {
998+ /* user-space did not require GRO, but adding XDP
999+ * is supposed to get GRO working
1000+ */
1001+ dev -> features |= NETIF_F_GRO ;
1002+ netdev_features_change (dev );
1003+ }
1004+ }
9811005 }
9821006
983- for (i = 0 ; i < dev -> real_num_rx_queues ; i ++ )
1007+ for (i = 0 ; i < dev -> real_num_rx_queues ; i ++ ) {
9841008 rcu_assign_pointer (priv -> rq [i ].xdp_prog , priv -> _xdp_prog );
1009+ rcu_assign_pointer (priv -> rq [i ].napi , & priv -> rq [i ].xdp_napi );
1010+ }
9851011
9861012 return 0 ;
9871013err_reg_mem :
@@ -991,7 +1017,8 @@ static int veth_enable_xdp(struct net_device *dev)
9911017 struct veth_rq * rq = & priv -> rq [i ];
9921018
9931019 xdp_rxq_info_unreg (& rq -> xdp_rxq );
994- netif_napi_del (& rq -> xdp_napi );
1020+ if (!napi_already_on )
1021+ netif_napi_del (& rq -> xdp_napi );
9951022 }
9961023
9971024 return err ;
@@ -1004,7 +1031,19 @@ static void veth_disable_xdp(struct net_device *dev)
10041031
10051032 for (i = 0 ; i < dev -> real_num_rx_queues ; i ++ )
10061033 rcu_assign_pointer (priv -> rq [i ].xdp_prog , NULL );
1007- veth_napi_del (dev );
1034+
1035+ if (!netif_running (dev ) || !veth_gro_requested (dev )) {
1036+ veth_napi_del (dev );
1037+
1038+ /* if user-space did not require GRO, since adding XDP
1039+ * enabled it, clear it now
1040+ */
1041+ if (!veth_gro_requested (dev ) && netif_running (dev )) {
1042+ dev -> features &= ~NETIF_F_GRO ;
1043+ netdev_features_change (dev );
1044+ }
1045+ }
1046+
10081047 for (i = 0 ; i < dev -> real_num_rx_queues ; i ++ ) {
10091048 struct veth_rq * rq = & priv -> rq [i ];
10101049
@@ -1013,6 +1052,29 @@ static void veth_disable_xdp(struct net_device *dev)
10131052 }
10141053}
10151054
1055+ static int veth_napi_enable (struct net_device * dev )
1056+ {
1057+ struct veth_priv * priv = netdev_priv (dev );
1058+ int err , i ;
1059+
1060+ for (i = 0 ; i < dev -> real_num_rx_queues ; i ++ ) {
1061+ struct veth_rq * rq = & priv -> rq [i ];
1062+
1063+ netif_napi_add (dev , & rq -> xdp_napi , veth_poll , NAPI_POLL_WEIGHT );
1064+ }
1065+
1066+ err = __veth_napi_enable (dev );
1067+ if (err ) {
1068+ for (i = 0 ; i < dev -> real_num_rx_queues ; i ++ ) {
1069+ struct veth_rq * rq = & priv -> rq [i ];
1070+
1071+ netif_napi_del (& rq -> xdp_napi );
1072+ }
1073+ return err ;
1074+ }
1075+ return err ;
1076+ }
1077+
10161078static int veth_open (struct net_device * dev )
10171079{
10181080 struct veth_priv * priv = netdev_priv (dev );
@@ -1026,6 +1088,10 @@ static int veth_open(struct net_device *dev)
10261088 err = veth_enable_xdp (dev );
10271089 if (err )
10281090 return err ;
1091+ } else if (veth_gro_requested (dev )) {
1092+ err = veth_napi_enable (dev );
1093+ if (err )
1094+ return err ;
10291095 }
10301096
10311097 if (peer -> flags & IFF_UP ) {
@@ -1047,6 +1113,8 @@ static int veth_close(struct net_device *dev)
10471113
10481114 if (priv -> _xdp_prog )
10491115 veth_disable_xdp (dev );
1116+ else if (veth_gro_requested (dev ))
1117+ veth_napi_del (dev );
10501118
10511119 return 0 ;
10521120}
@@ -1145,10 +1213,32 @@ static netdev_features_t veth_fix_features(struct net_device *dev,
11451213 if (peer_priv -> _xdp_prog )
11461214 features &= ~NETIF_F_GSO_SOFTWARE ;
11471215 }
1216+ if (priv -> _xdp_prog )
1217+ features |= NETIF_F_GRO ;
11481218
11491219 return features ;
11501220}
11511221
1222+ static int veth_set_features (struct net_device * dev ,
1223+ netdev_features_t features )
1224+ {
1225+ netdev_features_t changed = features ^ dev -> features ;
1226+ struct veth_priv * priv = netdev_priv (dev );
1227+ int err ;
1228+
1229+ if (!(changed & NETIF_F_GRO ) || !(dev -> flags & IFF_UP ) || priv -> _xdp_prog )
1230+ return 0 ;
1231+
1232+ if (features & NETIF_F_GRO ) {
1233+ err = veth_napi_enable (dev );
1234+ if (err )
1235+ return err ;
1236+ } else {
1237+ veth_napi_del (dev );
1238+ }
1239+ return 0 ;
1240+ }
1241+
11521242static void veth_set_rx_headroom (struct net_device * dev , int new_hr )
11531243{
11541244 struct veth_priv * peer_priv , * priv = netdev_priv (dev );
@@ -1267,6 +1357,7 @@ static const struct net_device_ops veth_netdev_ops = {
12671357#endif
12681358 .ndo_get_iflink = veth_get_iflink ,
12691359 .ndo_fix_features = veth_fix_features ,
1360+ .ndo_set_features = veth_set_features ,
12701361 .ndo_features_check = passthru_features_check ,
12711362 .ndo_set_rx_headroom = veth_set_rx_headroom ,
12721363 .ndo_bpf = veth_xdp ,
@@ -1329,6 +1420,13 @@ static int veth_validate(struct nlattr *tb[], struct nlattr *data[],
13291420
13301421static struct rtnl_link_ops veth_link_ops ;
13311422
1423+ static void veth_disable_gro (struct net_device * dev )
1424+ {
1425+ dev -> features &= ~NETIF_F_GRO ;
1426+ dev -> wanted_features &= ~NETIF_F_GRO ;
1427+ netdev_update_features (dev );
1428+ }
1429+
13321430static int veth_newlink (struct net * src_net , struct net_device * dev ,
13331431 struct nlattr * tb [], struct nlattr * data [],
13341432 struct netlink_ext_ack * extack )
@@ -1401,6 +1499,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
14011499 if (err < 0 )
14021500 goto err_register_peer ;
14031501
1502+ /* keep GRO disabled by default to be consistent with the established
1503+ * veth behavior
1504+ */
1505+ veth_disable_gro (peer );
14041506 netif_carrier_off (peer );
14051507
14061508 err = rtnl_configure_link (peer , ifmp );
@@ -1438,6 +1540,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
14381540 priv = netdev_priv (peer );
14391541 rcu_assign_pointer (priv -> peer , dev );
14401542
1543+ veth_disable_gro (dev );
14411544 return 0 ;
14421545
14431546err_register_dev :
0 commit comments