aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>2010-02-10 23:03:05 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-10 23:03:05 -0500
commit15682bc488d4af8c9bb998844a94281025e0a333 (patch)
tree2534589c00cbf695e6c2906f5c228a0006174904
parent375c568844e49d292885c7485d4a255f71680e56 (diff)
ethtool: Introduce n-tuple filter programming support
This patchset enables the ethtool layer to program n-tuple filters to an underlying device. The idea is to allow capable hardware to have static rules applied that can assist steering flows into appropriate queues. Hardware that is known to support these types of filters today are ixgbe and niu. Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/ethtool.h50
-rw-r--r--include/linux/netdevice.h3
-rw-r--r--net/core/dev.c5
-rw-r--r--net/core/ethtool.c329
4 files changed, 386 insertions, 1 deletions
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index ef4a2d84d922..a3cac53a0766 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -14,6 +14,7 @@
14#define _LINUX_ETHTOOL_H 14#define _LINUX_ETHTOOL_H
15 15
16#include <linux/types.h> 16#include <linux/types.h>
17#include <linux/rculist.h>
17 18
18/* This should work for both 32 and 64 bit userland. */ 19/* This should work for both 32 and 64 bit userland. */
19struct ethtool_cmd { 20struct ethtool_cmd {
@@ -242,6 +243,7 @@ enum ethtool_stringset {
242 ETH_SS_TEST = 0, 243 ETH_SS_TEST = 0,
243 ETH_SS_STATS, 244 ETH_SS_STATS,
244 ETH_SS_PRIV_FLAGS, 245 ETH_SS_PRIV_FLAGS,
246 ETH_SS_NTUPLE_FILTERS,
245}; 247};
246 248
247/* for passing string sets for data tagging */ 249/* for passing string sets for data tagging */
@@ -290,6 +292,7 @@ struct ethtool_perm_addr {
290 */ 292 */
291enum ethtool_flags { 293enum ethtool_flags {
292 ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */ 294 ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */
295 ETH_FLAG_NTUPLE = (1 << 27), /* N-tuple filters enabled */
293}; 296};
294 297
295/* The following structures are for supporting RX network flow 298/* The following structures are for supporting RX network flow
@@ -363,6 +366,35 @@ struct ethtool_rxnfc {
363 __u32 rule_locs[0]; 366 __u32 rule_locs[0];
364}; 367};
365 368
369struct ethtool_rx_ntuple_flow_spec {
370 __u32 flow_type;
371 union {
372 struct ethtool_tcpip4_spec tcp_ip4_spec;
373 struct ethtool_tcpip4_spec udp_ip4_spec;
374 struct ethtool_tcpip4_spec sctp_ip4_spec;
375 struct ethtool_ah_espip4_spec ah_ip4_spec;
376 struct ethtool_ah_espip4_spec esp_ip4_spec;
377 struct ethtool_rawip4_spec raw_ip4_spec;
378 struct ethtool_ether_spec ether_spec;
379 struct ethtool_usrip4_spec usr_ip4_spec;
380 __u8 hdata[64];
381 } h_u, m_u; /* entry, mask */
382
383 __u16 vlan_tag;
384 __u16 vlan_tag_mask;
385 __u64 data; /* user-defined flow spec data */
386 __u64 data_mask; /* user-defined flow spec mask */
387
388 /* signed to distinguish between queue and actions (DROP) */
389 __s32 action;
390#define ETHTOOL_RXNTUPLE_ACTION_DROP -1
391};
392
393struct ethtool_rx_ntuple {
394 __u32 cmd;
395 struct ethtool_rx_ntuple_flow_spec fs;
396};
397
366#define ETHTOOL_FLASH_MAX_FILENAME 128 398#define ETHTOOL_FLASH_MAX_FILENAME 128
367enum ethtool_flash_op_type { 399enum ethtool_flash_op_type {
368 ETHTOOL_FLASH_ALL_REGIONS = 0, 400 ETHTOOL_FLASH_ALL_REGIONS = 0,
@@ -377,6 +409,18 @@ struct ethtool_flash {
377 409
378#ifdef __KERNEL__ 410#ifdef __KERNEL__
379 411
412struct ethtool_rx_ntuple_flow_spec_container {
413 struct ethtool_rx_ntuple_flow_spec fs;
414 struct list_head list;
415};
416
417struct ethtool_rx_ntuple_list {
418#define ETHTOOL_MAX_NTUPLE_LIST_ENTRY 1024
419#define ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY 14
420 struct list_head list;
421 unsigned int count;
422};
423
380struct net_device; 424struct net_device;
381 425
382/* Some generic methods drivers may use in their ethtool_ops */ 426/* Some generic methods drivers may use in their ethtool_ops */
@@ -394,6 +438,7 @@ u32 ethtool_op_get_ufo(struct net_device *dev);
394int ethtool_op_set_ufo(struct net_device *dev, u32 data); 438int ethtool_op_set_ufo(struct net_device *dev, u32 data);
395u32 ethtool_op_get_flags(struct net_device *dev); 439u32 ethtool_op_get_flags(struct net_device *dev);
396int ethtool_op_set_flags(struct net_device *dev, u32 data); 440int ethtool_op_set_flags(struct net_device *dev, u32 data);
441void ethtool_ntuple_flush(struct net_device *dev);
397 442
398/** 443/**
399 * &ethtool_ops - Alter and report network device settings 444 * &ethtool_ops - Alter and report network device settings
@@ -500,6 +545,8 @@ struct ethtool_ops {
500 int (*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *); 545 int (*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *);
501 int (*flash_device)(struct net_device *, struct ethtool_flash *); 546 int (*flash_device)(struct net_device *, struct ethtool_flash *);
502 int (*reset)(struct net_device *, u32 *); 547 int (*reset)(struct net_device *, u32 *);
548 int (*set_rx_ntuple)(struct net_device *, struct ethtool_rx_ntuple *);
549 int (*get_rx_ntuple)(struct net_device *, u32 stringset, void *);
503}; 550};
504#endif /* __KERNEL__ */ 551#endif /* __KERNEL__ */
505 552
@@ -559,6 +606,9 @@ struct ethtool_ops {
559#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */ 606#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */
560#define ETHTOOL_RESET 0x00000034 /* Reset hardware */ 607#define ETHTOOL_RESET 0x00000034 /* Reset hardware */
561 608
609#define ETHTOOL_SRXNTUPLE 0x00000035 /* Add an n-tuple filter to device */
610#define ETHTOOL_GRXNTUPLE 0x00000036 /* Get n-tuple filters from device */
611
562/* compatibility with older code */ 612/* compatibility with older code */
563#define SPARC_ETH_GSET ETHTOOL_GSET 613#define SPARC_ETH_GSET ETHTOOL_GSET
564#define SPARC_ETH_SSET ETHTOOL_SSET 614#define SPARC_ETH_SSET ETHTOOL_SSET
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index e535700a3b72..cdf53a8d9ff5 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -746,6 +746,7 @@ struct net_device {
746#define NETIF_F_FCOE_CRC (1 << 24) /* FCoE CRC32 */ 746#define NETIF_F_FCOE_CRC (1 << 24) /* FCoE CRC32 */
747#define NETIF_F_SCTP_CSUM (1 << 25) /* SCTP checksum offload */ 747#define NETIF_F_SCTP_CSUM (1 << 25) /* SCTP checksum offload */
748#define NETIF_F_FCOE_MTU (1 << 26) /* Supports max FCoE MTU, 2158 bytes*/ 748#define NETIF_F_FCOE_MTU (1 << 26) /* Supports max FCoE MTU, 2158 bytes*/
749#define NETIF_F_NTUPLE (1 << 27) /* N-tuple filters supported */
749 750
750 /* Segmentation offload features */ 751 /* Segmentation offload features */
751#define NETIF_F_GSO_SHIFT 16 752#define NETIF_F_GSO_SHIFT 16
@@ -954,6 +955,8 @@ struct net_device {
954 /* max exchange id for FCoE LRO by ddp */ 955 /* max exchange id for FCoE LRO by ddp */
955 unsigned int fcoe_ddp_xid; 956 unsigned int fcoe_ddp_xid;
956#endif 957#endif
958 /* n-tuple filter list attached to this device */
959 struct ethtool_rx_ntuple_list ethtool_ntuple_list;
957}; 960};
958#define to_net_dev(d) container_of(d, struct net_device, dev) 961#define to_net_dev(d) container_of(d, struct net_device, dev)
959 962
diff --git a/net/core/dev.c b/net/core/dev.c
index 94c1eeed25e5..ae75f25ac0a5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5419,6 +5419,8 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
5419 5419
5420 netdev_init_queues(dev); 5420 netdev_init_queues(dev);
5421 5421
5422 INIT_LIST_HEAD(&dev->ethtool_ntuple_list.list);
5423 dev->ethtool_ntuple_list.count = 0;
5422 INIT_LIST_HEAD(&dev->napi_list); 5424 INIT_LIST_HEAD(&dev->napi_list);
5423 INIT_LIST_HEAD(&dev->unreg_list); 5425 INIT_LIST_HEAD(&dev->unreg_list);
5424 INIT_LIST_HEAD(&dev->link_watch_list); 5426 INIT_LIST_HEAD(&dev->link_watch_list);
@@ -5455,6 +5457,9 @@ void free_netdev(struct net_device *dev)
5455 /* Flush device addresses */ 5457 /* Flush device addresses */
5456 dev_addr_flush(dev); 5458 dev_addr_flush(dev);
5457 5459
5460 /* Clear ethtool n-tuple list */
5461 ethtool_ntuple_flush(dev);
5462
5458 list_for_each_entry_safe(p, n, &dev->napi_list, dev_list) 5463 list_for_each_entry_safe(p, n, &dev->napi_list, dev_list)
5459 netif_napi_del(p); 5464 netif_napi_del(p);
5460 5465
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index d8aee584e8d1..6ec73d3983a3 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -120,7 +120,7 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data)
120 * NETIF_F_xxx values in include/linux/netdevice.h 120 * NETIF_F_xxx values in include/linux/netdevice.h
121 */ 121 */
122static const u32 flags_dup_features = 122static const u32 flags_dup_features =
123 ETH_FLAG_LRO; 123 (ETH_FLAG_LRO | ETH_FLAG_NTUPLE);
124 124
125u32 ethtool_op_get_flags(struct net_device *dev) 125u32 ethtool_op_get_flags(struct net_device *dev)
126{ 126{
@@ -139,9 +139,26 @@ int ethtool_op_set_flags(struct net_device *dev, u32 data)
139 else 139 else
140 dev->features &= ~NETIF_F_LRO; 140 dev->features &= ~NETIF_F_LRO;
141 141
142 if (data & ETH_FLAG_NTUPLE)
143 dev->features |= NETIF_F_NTUPLE;
144 else
145 dev->features &= ~NETIF_F_NTUPLE;
146
142 return 0; 147 return 0;
143} 148}
144 149
150void ethtool_ntuple_flush(struct net_device *dev)
151{
152 struct ethtool_rx_ntuple_flow_spec_container *fsc, *f;
153
154 list_for_each_entry_safe(fsc, f, &dev->ethtool_ntuple_list.list, list) {
155 list_del(&fsc->list);
156 kfree(fsc);
157 }
158 dev->ethtool_ntuple_list.count = 0;
159}
160EXPORT_SYMBOL(ethtool_ntuple_flush);
161
145/* Handlers for each ethtool command */ 162/* Handlers for each ethtool command */
146 163
147static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) 164static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
@@ -266,6 +283,307 @@ err_out:
266 return ret; 283 return ret;
267} 284}
268 285
286static int __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list,
287 struct ethtool_rx_ntuple_flow_spec *spec)
288{
289 struct ethtool_rx_ntuple_flow_spec_container *fsc;
290
291 /* don't add filters forever */
292 if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY)
293 return 0;
294
295 fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC);
296 if (!fsc)
297 return -ENOMEM;
298
299 /* Copy the whole filter over */
300 fsc->fs.flow_type = spec->flow_type;
301 memcpy(&fsc->fs.h_u, &spec->h_u, sizeof(spec->h_u));
302 memcpy(&fsc->fs.m_u, &spec->m_u, sizeof(spec->m_u));
303
304 fsc->fs.vlan_tag = spec->vlan_tag;
305 fsc->fs.vlan_tag_mask = spec->vlan_tag_mask;
306 fsc->fs.data = spec->data;
307 fsc->fs.data_mask = spec->data_mask;
308 fsc->fs.action = spec->action;
309
310 /* add to the list */
311 list_add_tail_rcu(&fsc->list, &list->list);
312 list->count++;
313
314 return 0;
315}
316
317static int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr)
318{
319 struct ethtool_rx_ntuple cmd;
320 const struct ethtool_ops *ops = dev->ethtool_ops;
321 int ret;
322
323 if (!ops->set_rx_ntuple)
324 return -EOPNOTSUPP;
325
326 if (!(dev->features & NETIF_F_NTUPLE))
327 return -EINVAL;
328
329 if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
330 return -EFAULT;
331
332 ret = ops->set_rx_ntuple(dev, &cmd);
333
334 /*
335 * Cache filter in dev struct for GET operation only if
336 * the underlying driver doesn't have its own GET operation, and
337 * only if the filter was added successfully.
338 */
339 if (!ops->get_rx_ntuple && !ret)
340 if (__rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs))
341 return -ENOMEM;
342
343 return ret;
344}
345
346static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr)
347{
348 struct ethtool_gstrings gstrings;
349 const struct ethtool_ops *ops = dev->ethtool_ops;
350 struct ethtool_rx_ntuple_flow_spec_container *fsc;
351 u8 *data;
352 char *p;
353 int ret, i, num_strings = 0;
354
355 if (!ops->get_sset_count)
356 return -EOPNOTSUPP;
357
358 if (copy_from_user(&gstrings, useraddr, sizeof(gstrings)))
359 return -EFAULT;
360
361 ret = ops->get_sset_count(dev, gstrings.string_set);
362 if (ret < 0)
363 return ret;
364
365 gstrings.len = ret;
366
367 data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
368 if (!data)
369 return -ENOMEM;
370
371 if (ops->get_rx_ntuple) {
372 /* driver-specific filter grab */
373 ret = ops->get_rx_ntuple(dev, gstrings.string_set, data);
374 goto copy;
375 }
376
377 /* default ethtool filter grab */
378 i = 0;
379 p = (char *)data;
380 list_for_each_entry(fsc, &dev->ethtool_ntuple_list.list, list) {
381 sprintf(p, "Filter %d:\n", i);
382 p += ETH_GSTRING_LEN;
383 num_strings++;
384
385 switch (fsc->fs.flow_type) {
386 case TCP_V4_FLOW:
387 sprintf(p, "\tFlow Type: TCP\n");
388 p += ETH_GSTRING_LEN;
389 num_strings++;
390 break;
391 case UDP_V4_FLOW:
392 sprintf(p, "\tFlow Type: UDP\n");
393 p += ETH_GSTRING_LEN;
394 num_strings++;
395 break;
396 case SCTP_V4_FLOW:
397 sprintf(p, "\tFlow Type: SCTP\n");
398 p += ETH_GSTRING_LEN;
399 num_strings++;
400 break;
401 case AH_ESP_V4_FLOW:
402 sprintf(p, "\tFlow Type: AH ESP\n");
403 p += ETH_GSTRING_LEN;
404 num_strings++;
405 break;
406 case ESP_V4_FLOW:
407 sprintf(p, "\tFlow Type: ESP\n");
408 p += ETH_GSTRING_LEN;
409 num_strings++;
410 break;
411 case IP_USER_FLOW:
412 sprintf(p, "\tFlow Type: Raw IP\n");
413 p += ETH_GSTRING_LEN;
414 num_strings++;
415 break;
416 case IPV4_FLOW:
417 sprintf(p, "\tFlow Type: IPv4\n");
418 p += ETH_GSTRING_LEN;
419 num_strings++;
420 break;
421 default:
422 sprintf(p, "\tFlow Type: Unknown\n");
423 p += ETH_GSTRING_LEN;
424 num_strings++;
425 goto unknown_filter;
426 };
427
428 /* now the rest of the filters */
429 switch (fsc->fs.flow_type) {
430 case TCP_V4_FLOW:
431 case UDP_V4_FLOW:
432 case SCTP_V4_FLOW:
433 sprintf(p, "\tSrc IP addr: 0x%x\n",
434 fsc->fs.h_u.tcp_ip4_spec.ip4src);
435 p += ETH_GSTRING_LEN;
436 num_strings++;
437 sprintf(p, "\tSrc IP mask: 0x%x\n",
438 fsc->fs.m_u.tcp_ip4_spec.ip4src);
439 p += ETH_GSTRING_LEN;
440 num_strings++;
441 sprintf(p, "\tDest IP addr: 0x%x\n",
442 fsc->fs.h_u.tcp_ip4_spec.ip4dst);
443 p += ETH_GSTRING_LEN;
444 num_strings++;
445 sprintf(p, "\tDest IP mask: 0x%x\n",
446 fsc->fs.m_u.tcp_ip4_spec.ip4dst);
447 p += ETH_GSTRING_LEN;
448 num_strings++;
449 sprintf(p, "\tSrc Port: %d, mask: 0x%x\n",
450 fsc->fs.h_u.tcp_ip4_spec.psrc,
451 fsc->fs.m_u.tcp_ip4_spec.psrc);
452 p += ETH_GSTRING_LEN;
453 num_strings++;
454 sprintf(p, "\tDest Port: %d, mask: 0x%x\n",
455 fsc->fs.h_u.tcp_ip4_spec.pdst,
456 fsc->fs.m_u.tcp_ip4_spec.pdst);
457 p += ETH_GSTRING_LEN;
458 num_strings++;
459 sprintf(p, "\tTOS: %d, mask: 0x%x\n",
460 fsc->fs.h_u.tcp_ip4_spec.tos,
461 fsc->fs.m_u.tcp_ip4_spec.tos);
462 p += ETH_GSTRING_LEN;
463 num_strings++;
464 break;
465 case AH_ESP_V4_FLOW:
466 case ESP_V4_FLOW:
467 sprintf(p, "\tSrc IP addr: 0x%x\n",
468 fsc->fs.h_u.ah_ip4_spec.ip4src);
469 p += ETH_GSTRING_LEN;
470 num_strings++;
471 sprintf(p, "\tSrc IP mask: 0x%x\n",
472 fsc->fs.m_u.ah_ip4_spec.ip4src);
473 p += ETH_GSTRING_LEN;
474 num_strings++;
475 sprintf(p, "\tDest IP addr: 0x%x\n",
476 fsc->fs.h_u.ah_ip4_spec.ip4dst);
477 p += ETH_GSTRING_LEN;
478 num_strings++;
479 sprintf(p, "\tDest IP mask: 0x%x\n",
480 fsc->fs.m_u.ah_ip4_spec.ip4dst);
481 p += ETH_GSTRING_LEN;
482 num_strings++;
483 sprintf(p, "\tSPI: %d, mask: 0x%x\n",
484 fsc->fs.h_u.ah_ip4_spec.spi,
485 fsc->fs.m_u.ah_ip4_spec.spi);
486 p += ETH_GSTRING_LEN;
487 num_strings++;
488 sprintf(p, "\tTOS: %d, mask: 0x%x\n",
489 fsc->fs.h_u.ah_ip4_spec.tos,
490 fsc->fs.m_u.ah_ip4_spec.tos);
491 p += ETH_GSTRING_LEN;
492 num_strings++;
493 break;
494 case IP_USER_FLOW:
495 sprintf(p, "\tSrc IP addr: 0x%x\n",
496 fsc->fs.h_u.raw_ip4_spec.ip4src);
497 p += ETH_GSTRING_LEN;
498 num_strings++;
499 sprintf(p, "\tSrc IP mask: 0x%x\n",
500 fsc->fs.m_u.raw_ip4_spec.ip4src);
501 p += ETH_GSTRING_LEN;
502 num_strings++;
503 sprintf(p, "\tDest IP addr: 0x%x\n",
504 fsc->fs.h_u.raw_ip4_spec.ip4dst);
505 p += ETH_GSTRING_LEN;
506 num_strings++;
507 sprintf(p, "\tDest IP mask: 0x%x\n",
508 fsc->fs.m_u.raw_ip4_spec.ip4dst);
509 p += ETH_GSTRING_LEN;
510 num_strings++;
511 break;
512 case IPV4_FLOW:
513 sprintf(p, "\tSrc IP addr: 0x%x\n",
514 fsc->fs.h_u.usr_ip4_spec.ip4src);
515 p += ETH_GSTRING_LEN;
516 num_strings++;
517 sprintf(p, "\tSrc IP mask: 0x%x\n",
518 fsc->fs.m_u.usr_ip4_spec.ip4src);
519 p += ETH_GSTRING_LEN;
520 num_strings++;
521 sprintf(p, "\tDest IP addr: 0x%x\n",
522 fsc->fs.h_u.usr_ip4_spec.ip4dst);
523 p += ETH_GSTRING_LEN;
524 num_strings++;
525 sprintf(p, "\tDest IP mask: 0x%x\n",
526 fsc->fs.m_u.usr_ip4_spec.ip4dst);
527 p += ETH_GSTRING_LEN;
528 num_strings++;
529 sprintf(p, "\tL4 bytes: 0x%x, mask: 0x%x\n",
530 fsc->fs.h_u.usr_ip4_spec.l4_4_bytes,
531 fsc->fs.m_u.usr_ip4_spec.l4_4_bytes);
532 p += ETH_GSTRING_LEN;
533 num_strings++;
534 sprintf(p, "\tTOS: %d, mask: 0x%x\n",
535 fsc->fs.h_u.usr_ip4_spec.tos,
536 fsc->fs.m_u.usr_ip4_spec.tos);
537 p += ETH_GSTRING_LEN;
538 num_strings++;
539 sprintf(p, "\tIP Version: %d, mask: 0x%x\n",
540 fsc->fs.h_u.usr_ip4_spec.ip_ver,
541 fsc->fs.m_u.usr_ip4_spec.ip_ver);
542 p += ETH_GSTRING_LEN;
543 num_strings++;
544 sprintf(p, "\tProtocol: %d, mask: 0x%x\n",
545 fsc->fs.h_u.usr_ip4_spec.proto,
546 fsc->fs.m_u.usr_ip4_spec.proto);
547 p += ETH_GSTRING_LEN;
548 num_strings++;
549 break;
550 };
551 sprintf(p, "\tVLAN: %d, mask: 0x%x\n",
552 fsc->fs.vlan_tag, fsc->fs.vlan_tag_mask);
553 p += ETH_GSTRING_LEN;
554 num_strings++;
555 sprintf(p, "\tUser-defined: 0x%Lx\n", fsc->fs.data);
556 p += ETH_GSTRING_LEN;
557 num_strings++;
558 sprintf(p, "\tUser-defined mask: 0x%Lx\n", fsc->fs.data_mask);
559 p += ETH_GSTRING_LEN;
560 num_strings++;
561 if (fsc->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
562 sprintf(p, "\tAction: Drop\n");
563 else
564 sprintf(p, "\tAction: Direct to queue %d\n",
565 fsc->fs.action);
566 p += ETH_GSTRING_LEN;
567 num_strings++;
568unknown_filter:
569 i++;
570 }
571copy:
572 /* indicate to userspace how many strings we actually have */
573 gstrings.len = num_strings;
574 ret = -EFAULT;
575 if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
576 goto out;
577 useraddr += sizeof(gstrings);
578 if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
579 goto out;
580 ret = 0;
581
582out:
583 kfree(data);
584 return ret;
585}
586
269static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) 587static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
270{ 588{
271 struct ethtool_regs regs; 589 struct ethtool_regs regs;
@@ -313,6 +631,9 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
313 if (copy_from_user(&reset, useraddr, sizeof(reset))) 631 if (copy_from_user(&reset, useraddr, sizeof(reset)))
314 return -EFAULT; 632 return -EFAULT;
315 633
634 /* Clear ethtool n-tuple list */
635 ethtool_ntuple_flush(dev);
636
316 ret = dev->ethtool_ops->reset(dev, &reset.data); 637 ret = dev->ethtool_ops->reset(dev, &reset.data);
317 if (ret) 638 if (ret)
318 return ret; 639 return ret;
@@ -1112,6 +1433,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
1112 case ETHTOOL_RESET: 1433 case ETHTOOL_RESET:
1113 rc = ethtool_reset(dev, useraddr); 1434 rc = ethtool_reset(dev, useraddr);
1114 break; 1435 break;
1436 case ETHTOOL_SRXNTUPLE:
1437 rc = ethtool_set_rx_ntuple(dev, useraddr);
1438 break;
1439 case ETHTOOL_GRXNTUPLE:
1440 rc = ethtool_get_rx_ntuple(dev, useraddr);
1441 break;
1115 default: 1442 default:
1116 rc = -EOPNOTSUPP; 1443 rc = -EOPNOTSUPP;
1117 } 1444 }