@@ -57,6 +57,7 @@ struct veth_rq_stats {
57
57
58
58
struct veth_rq {
59
59
struct napi_struct xdp_napi ;
60
+ struct napi_struct __rcu * napi ; /* points to xdp_napi when the latter is initialized */
60
61
struct net_device * dev ;
61
62
struct bpf_prog __rcu * xdp_prog ;
62
63
struct xdp_mem_info xdp_mem ;
@@ -299,7 +300,7 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
299
300
struct veth_rq * rq = NULL ;
300
301
struct net_device * rcv ;
301
302
int length = skb -> len ;
302
- bool rcv_xdp = false;
303
+ bool use_napi = false;
303
304
int rxq ;
304
305
305
306
rcu_read_lock ();
@@ -313,20 +314,24 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
313
314
rxq = skb_get_queue_mapping (skb );
314
315
if (rxq < rcv -> real_num_rx_queues ) {
315
316
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 );
317
322
skb_record_rx_queue (skb , rxq );
318
323
}
319
324
320
325
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 )
323
328
dev_lstats_add (dev , length );
324
329
} else {
325
330
drop :
326
331
atomic64_inc (& priv -> dropped );
327
332
}
328
333
329
- if (rcv_xdp )
334
+ if (use_napi )
330
335
__veth_xdp_flush (rq );
331
336
332
337
rcu_read_unlock ();
@@ -903,7 +908,7 @@ static int veth_poll(struct napi_struct *napi, int budget)
903
908
return done ;
904
909
}
905
910
906
- static int veth_napi_add (struct net_device * dev )
911
+ static int __veth_napi_enable (struct net_device * dev )
907
912
{
908
913
struct veth_priv * priv = netdev_priv (dev );
909
914
int err , i ;
@@ -920,6 +925,7 @@ static int veth_napi_add(struct net_device *dev)
920
925
struct veth_rq * rq = & priv -> rq [i ];
921
926
922
927
napi_enable (& rq -> xdp_napi );
928
+ rcu_assign_pointer (priv -> rq [i ].napi , & priv -> rq [i ].xdp_napi );
923
929
}
924
930
925
931
return 0 ;
@@ -938,6 +944,7 @@ static void veth_napi_del(struct net_device *dev)
938
944
for (i = 0 ; i < dev -> real_num_rx_queues ; i ++ ) {
939
945
struct veth_rq * rq = & priv -> rq [i ];
940
946
947
+ rcu_assign_pointer (priv -> rq [i ].napi , NULL );
941
948
napi_disable (& rq -> xdp_napi );
942
949
__netif_napi_del (& rq -> xdp_napi );
943
950
}
@@ -951,16 +958,23 @@ static void veth_napi_del(struct net_device *dev)
951
958
}
952
959
}
953
960
961
+ static bool veth_gro_requested (const struct net_device * dev )
962
+ {
963
+ return !!(dev -> wanted_features & NETIF_F_GRO );
964
+ }
965
+
954
966
static int veth_enable_xdp (struct net_device * dev )
955
967
{
968
+ bool napi_already_on = veth_gro_requested (dev ) && (dev -> flags & IFF_UP );
956
969
struct veth_priv * priv = netdev_priv (dev );
957
970
int err , i ;
958
971
959
972
if (!xdp_rxq_info_is_reg (& priv -> rq [0 ].xdp_rxq )) {
960
973
for (i = 0 ; i < dev -> real_num_rx_queues ; i ++ ) {
961
974
struct veth_rq * rq = & priv -> rq [i ];
962
975
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 );
964
978
err = xdp_rxq_info_reg (& rq -> xdp_rxq , dev , i , rq -> xdp_napi .napi_id );
965
979
if (err < 0 )
966
980
goto err_rxq_reg ;
@@ -975,13 +989,25 @@ static int veth_enable_xdp(struct net_device *dev)
975
989
rq -> xdp_mem = rq -> xdp_rxq .mem ;
976
990
}
977
991
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
+ }
981
1005
}
982
1006
983
- for (i = 0 ; i < dev -> real_num_rx_queues ; i ++ )
1007
+ for (i = 0 ; i < dev -> real_num_rx_queues ; i ++ ) {
984
1008
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
+ }
985
1011
986
1012
return 0 ;
987
1013
err_reg_mem :
@@ -991,7 +1017,8 @@ static int veth_enable_xdp(struct net_device *dev)
991
1017
struct veth_rq * rq = & priv -> rq [i ];
992
1018
993
1019
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 );
995
1022
}
996
1023
997
1024
return err ;
@@ -1004,7 +1031,19 @@ static void veth_disable_xdp(struct net_device *dev)
1004
1031
1005
1032
for (i = 0 ; i < dev -> real_num_rx_queues ; i ++ )
1006
1033
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
+
1008
1047
for (i = 0 ; i < dev -> real_num_rx_queues ; i ++ ) {
1009
1048
struct veth_rq * rq = & priv -> rq [i ];
1010
1049
@@ -1013,6 +1052,29 @@ static void veth_disable_xdp(struct net_device *dev)
1013
1052
}
1014
1053
}
1015
1054
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
+
1016
1078
static int veth_open (struct net_device * dev )
1017
1079
{
1018
1080
struct veth_priv * priv = netdev_priv (dev );
@@ -1026,6 +1088,10 @@ static int veth_open(struct net_device *dev)
1026
1088
err = veth_enable_xdp (dev );
1027
1089
if (err )
1028
1090
return err ;
1091
+ } else if (veth_gro_requested (dev )) {
1092
+ err = veth_napi_enable (dev );
1093
+ if (err )
1094
+ return err ;
1029
1095
}
1030
1096
1031
1097
if (peer -> flags & IFF_UP ) {
@@ -1047,6 +1113,8 @@ static int veth_close(struct net_device *dev)
1047
1113
1048
1114
if (priv -> _xdp_prog )
1049
1115
veth_disable_xdp (dev );
1116
+ else if (veth_gro_requested (dev ))
1117
+ veth_napi_del (dev );
1050
1118
1051
1119
return 0 ;
1052
1120
}
@@ -1145,10 +1213,32 @@ static netdev_features_t veth_fix_features(struct net_device *dev,
1145
1213
if (peer_priv -> _xdp_prog )
1146
1214
features &= ~NETIF_F_GSO_SOFTWARE ;
1147
1215
}
1216
+ if (priv -> _xdp_prog )
1217
+ features |= NETIF_F_GRO ;
1148
1218
1149
1219
return features ;
1150
1220
}
1151
1221
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
+
1152
1242
static void veth_set_rx_headroom (struct net_device * dev , int new_hr )
1153
1243
{
1154
1244
struct veth_priv * peer_priv , * priv = netdev_priv (dev );
@@ -1267,6 +1357,7 @@ static const struct net_device_ops veth_netdev_ops = {
1267
1357
#endif
1268
1358
.ndo_get_iflink = veth_get_iflink ,
1269
1359
.ndo_fix_features = veth_fix_features ,
1360
+ .ndo_set_features = veth_set_features ,
1270
1361
.ndo_features_check = passthru_features_check ,
1271
1362
.ndo_set_rx_headroom = veth_set_rx_headroom ,
1272
1363
.ndo_bpf = veth_xdp ,
@@ -1329,6 +1420,13 @@ static int veth_validate(struct nlattr *tb[], struct nlattr *data[],
1329
1420
1330
1421
static struct rtnl_link_ops veth_link_ops ;
1331
1422
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
+
1332
1430
static int veth_newlink (struct net * src_net , struct net_device * dev ,
1333
1431
struct nlattr * tb [], struct nlattr * data [],
1334
1432
struct netlink_ext_ack * extack )
@@ -1401,6 +1499,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
1401
1499
if (err < 0 )
1402
1500
goto err_register_peer ;
1403
1501
1502
+ /* keep GRO disabled by default to be consistent with the established
1503
+ * veth behavior
1504
+ */
1505
+ veth_disable_gro (peer );
1404
1506
netif_carrier_off (peer );
1405
1507
1406
1508
err = rtnl_configure_link (peer , ifmp );
@@ -1438,6 +1540,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
1438
1540
priv = netdev_priv (peer );
1439
1541
rcu_assign_pointer (priv -> peer , dev );
1440
1542
1543
+ veth_disable_gro (dev );
1441
1544
return 0 ;
1442
1545
1443
1546
err_register_dev :
0 commit comments