@@ -1022,6 +1022,15 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
1022
1022
if (copy_from_user (& info , useraddr , info_size ))
1023
1023
return - EFAULT ;
1024
1024
1025
+ /* If FLOW_RSS was requested then user-space must be using the
1026
+ * new definition, as FLOW_RSS is newer.
1027
+ */
1028
+ if (cmd == ETHTOOL_GRXFH && info .flow_type & FLOW_RSS ) {
1029
+ info_size = sizeof (info );
1030
+ if (copy_from_user (& info , useraddr , info_size ))
1031
+ return - EFAULT ;
1032
+ }
1033
+
1025
1034
if (info .cmd == ETHTOOL_GRXCLSRLALL ) {
1026
1035
if (info .rule_cnt > 0 ) {
1027
1036
if (info .rule_cnt <= KMALLOC_MAX_SIZE / sizeof (u32 ))
@@ -1251,9 +1260,11 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
1251
1260
user_key_size = rxfh .key_size ;
1252
1261
1253
1262
/* Check that reserved fields are 0 for now */
1254
- if (rxfh .rss_context || rxfh .rsvd8 [0 ] || rxfh .rsvd8 [1 ] ||
1255
- rxfh .rsvd8 [2 ] || rxfh .rsvd32 )
1263
+ if (rxfh .rsvd8 [0 ] || rxfh .rsvd8 [1 ] || rxfh .rsvd8 [2 ] || rxfh .rsvd32 )
1256
1264
return - EINVAL ;
1265
+ /* Most drivers don't handle rss_context, check it's 0 as well */
1266
+ if (rxfh .rss_context && !ops -> get_rxfh_context )
1267
+ return - EOPNOTSUPP ;
1257
1268
1258
1269
rxfh .indir_size = dev_indir_size ;
1259
1270
rxfh .key_size = dev_key_size ;
@@ -1276,7 +1287,12 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
1276
1287
if (user_key_size )
1277
1288
hkey = rss_config + indir_bytes ;
1278
1289
1279
- ret = dev -> ethtool_ops -> get_rxfh (dev , indir , hkey , & dev_hfunc );
1290
+ if (rxfh .rss_context )
1291
+ ret = dev -> ethtool_ops -> get_rxfh_context (dev , indir , hkey ,
1292
+ & dev_hfunc ,
1293
+ rxfh .rss_context );
1294
+ else
1295
+ ret = dev -> ethtool_ops -> get_rxfh (dev , indir , hkey , & dev_hfunc );
1280
1296
if (ret )
1281
1297
goto out ;
1282
1298
@@ -1306,6 +1322,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
1306
1322
u8 * hkey = NULL ;
1307
1323
u8 * rss_config ;
1308
1324
u32 rss_cfg_offset = offsetof(struct ethtool_rxfh , rss_config [0 ]);
1325
+ bool delete = false;
1309
1326
1310
1327
if (!ops -> get_rxnfc || !ops -> set_rxfh )
1311
1328
return - EOPNOTSUPP ;
@@ -1319,9 +1336,11 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
1319
1336
return - EFAULT ;
1320
1337
1321
1338
/* Check that reserved fields are 0 for now */
1322
- if (rxfh .rss_context || rxfh .rsvd8 [0 ] || rxfh .rsvd8 [1 ] ||
1323
- rxfh .rsvd8 [2 ] || rxfh .rsvd32 )
1339
+ if (rxfh .rsvd8 [0 ] || rxfh .rsvd8 [1 ] || rxfh .rsvd8 [2 ] || rxfh .rsvd32 )
1324
1340
return - EINVAL ;
1341
+ /* Most drivers don't handle rss_context, check it's 0 as well */
1342
+ if (rxfh .rss_context && !ops -> set_rxfh_context )
1343
+ return - EOPNOTSUPP ;
1325
1344
1326
1345
/* If either indir, hash key or function is valid, proceed further.
1327
1346
* Must request at least one change: indir size, hash key or function.
@@ -1346,7 +1365,8 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
1346
1365
if (ret )
1347
1366
goto out ;
1348
1367
1349
- /* rxfh.indir_size == 0 means reset the indir table to default.
1368
+ /* rxfh.indir_size == 0 means reset the indir table to default (master
1369
+ * context) or delete the context (other RSS contexts).
1350
1370
* rxfh.indir_size == ETH_RXFH_INDIR_NO_CHANGE means leave it unchanged.
1351
1371
*/
1352
1372
if (rxfh .indir_size &&
@@ -1359,9 +1379,13 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
1359
1379
if (ret )
1360
1380
goto out ;
1361
1381
} else if (rxfh .indir_size == 0 ) {
1362
- indir = (u32 * )rss_config ;
1363
- for (i = 0 ; i < dev_indir_size ; i ++ )
1364
- indir [i ] = ethtool_rxfh_indir_default (i , rx_rings .data );
1382
+ if (rxfh .rss_context == 0 ) {
1383
+ indir = (u32 * )rss_config ;
1384
+ for (i = 0 ; i < dev_indir_size ; i ++ )
1385
+ indir [i ] = ethtool_rxfh_indir_default (i , rx_rings .data );
1386
+ } else {
1387
+ delete = true;
1388
+ }
1365
1389
}
1366
1390
1367
1391
if (rxfh .key_size ) {
@@ -1374,15 +1398,25 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
1374
1398
}
1375
1399
}
1376
1400
1377
- ret = ops -> set_rxfh (dev , indir , hkey , rxfh .hfunc );
1401
+ if (rxfh .rss_context )
1402
+ ret = ops -> set_rxfh_context (dev , indir , hkey , rxfh .hfunc ,
1403
+ & rxfh .rss_context , delete );
1404
+ else
1405
+ ret = ops -> set_rxfh (dev , indir , hkey , rxfh .hfunc );
1378
1406
if (ret )
1379
1407
goto out ;
1380
1408
1381
- /* indicate whether rxfh was set to default */
1382
- if (rxfh .indir_size == 0 )
1383
- dev -> priv_flags &= ~IFF_RXFH_CONFIGURED ;
1384
- else if (rxfh .indir_size != ETH_RXFH_INDIR_NO_CHANGE )
1385
- dev -> priv_flags |= IFF_RXFH_CONFIGURED ;
1409
+ if (copy_to_user (useraddr + offsetof(struct ethtool_rxfh , rss_context ),
1410
+ & rxfh .rss_context , sizeof (rxfh .rss_context )))
1411
+ ret = - EFAULT ;
1412
+
1413
+ if (!rxfh .rss_context ) {
1414
+ /* indicate whether rxfh was set to default */
1415
+ if (rxfh .indir_size == 0 )
1416
+ dev -> priv_flags &= ~IFF_RXFH_CONFIGURED ;
1417
+ else if (rxfh .indir_size != ETH_RXFH_INDIR_NO_CHANGE )
1418
+ dev -> priv_flags |= IFF_RXFH_CONFIGURED ;
1419
+ }
1386
1420
1387
1421
out :
1388
1422
kfree (rss_config );
0 commit comments