aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/ethtool.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/ethtool.c')
-rw-r--r--net/core/ethtool.c387
1 files changed, 373 insertions, 14 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index d8aee584e8d1..0f2f82185ec4 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{
@@ -134,19 +134,44 @@ u32 ethtool_op_get_flags(struct net_device *dev)
134 134
135int ethtool_op_set_flags(struct net_device *dev, u32 data) 135int ethtool_op_set_flags(struct net_device *dev, u32 data)
136{ 136{
137 const struct ethtool_ops *ops = dev->ethtool_ops;
138 unsigned long features = dev->features;
139
137 if (data & ETH_FLAG_LRO) 140 if (data & ETH_FLAG_LRO)
138 dev->features |= NETIF_F_LRO; 141 features |= NETIF_F_LRO;
139 else 142 else
140 dev->features &= ~NETIF_F_LRO; 143 features &= ~NETIF_F_LRO;
144
145 if (data & ETH_FLAG_NTUPLE) {
146 if (!ops->set_rx_ntuple)
147 return -EOPNOTSUPP;
148 features |= NETIF_F_NTUPLE;
149 } else {
150 /* safe to clear regardless */
151 features &= ~NETIF_F_NTUPLE;
152 }
141 153
154 dev->features = features;
142 return 0; 155 return 0;
143} 156}
144 157
158void ethtool_ntuple_flush(struct net_device *dev)
159{
160 struct ethtool_rx_ntuple_flow_spec_container *fsc, *f;
161
162 list_for_each_entry_safe(fsc, f, &dev->ethtool_ntuple_list.list, list) {
163 list_del(&fsc->list);
164 kfree(fsc);
165 }
166 dev->ethtool_ntuple_list.count = 0;
167}
168EXPORT_SYMBOL(ethtool_ntuple_flush);
169
145/* Handlers for each ethtool command */ 170/* Handlers for each ethtool command */
146 171
147static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) 172static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
148{ 173{
149 struct ethtool_cmd cmd = { ETHTOOL_GSET }; 174 struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET };
150 int err; 175 int err;
151 176
152 if (!dev->ethtool_ops->get_settings) 177 if (!dev->ethtool_ops->get_settings)
@@ -174,7 +199,10 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr)
174 return dev->ethtool_ops->set_settings(dev, &cmd); 199 return dev->ethtool_ops->set_settings(dev, &cmd);
175} 200}
176 201
177static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) 202/*
203 * noinline attribute so that gcc doesnt use too much stack in dev_ethtool()
204 */
205static noinline int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr)
178{ 206{
179 struct ethtool_drvinfo info; 207 struct ethtool_drvinfo info;
180 const struct ethtool_ops *ops = dev->ethtool_ops; 208 const struct ethtool_ops *ops = dev->ethtool_ops;
@@ -209,7 +237,10 @@ static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr)
209 return 0; 237 return 0;
210} 238}
211 239
212static int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) 240/*
241 * noinline attribute so that gcc doesnt use too much stack in dev_ethtool()
242 */
243static noinline int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr)
213{ 244{
214 struct ethtool_rxnfc cmd; 245 struct ethtool_rxnfc cmd;
215 246
@@ -222,7 +253,10 @@ static int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr)
222 return dev->ethtool_ops->set_rxnfc(dev, &cmd); 253 return dev->ethtool_ops->set_rxnfc(dev, &cmd);
223} 254}
224 255
225static int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr) 256/*
257 * noinline attribute so that gcc doesnt use too much stack in dev_ethtool()
258 */
259static noinline int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr)
226{ 260{
227 struct ethtool_rxnfc info; 261 struct ethtool_rxnfc info;
228 const struct ethtool_ops *ops = dev->ethtool_ops; 262 const struct ethtool_ops *ops = dev->ethtool_ops;
@@ -266,6 +300,315 @@ err_out:
266 return ret; 300 return ret;
267} 301}
268 302
303static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list,
304 struct ethtool_rx_ntuple_flow_spec *spec,
305 struct ethtool_rx_ntuple_flow_spec_container *fsc)
306{
307
308 /* don't add filters forever */
309 if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) {
310 /* free the container */
311 kfree(fsc);
312 return;
313 }
314
315 /* Copy the whole filter over */
316 fsc->fs.flow_type = spec->flow_type;
317 memcpy(&fsc->fs.h_u, &spec->h_u, sizeof(spec->h_u));
318 memcpy(&fsc->fs.m_u, &spec->m_u, sizeof(spec->m_u));
319
320 fsc->fs.vlan_tag = spec->vlan_tag;
321 fsc->fs.vlan_tag_mask = spec->vlan_tag_mask;
322 fsc->fs.data = spec->data;
323 fsc->fs.data_mask = spec->data_mask;
324 fsc->fs.action = spec->action;
325
326 /* add to the list */
327 list_add_tail_rcu(&fsc->list, &list->list);
328 list->count++;
329}
330
331/*
332 * noinline attribute so that gcc doesnt use too much stack in dev_ethtool()
333 */
334static noinline int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr)
335{
336 struct ethtool_rx_ntuple cmd;
337 const struct ethtool_ops *ops = dev->ethtool_ops;
338 struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL;
339 int ret;
340
341 if (!(dev->features & NETIF_F_NTUPLE))
342 return -EINVAL;
343
344 if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
345 return -EFAULT;
346
347 /*
348 * Cache filter in dev struct for GET operation only if
349 * the underlying driver doesn't have its own GET operation, and
350 * only if the filter was added successfully. First make sure we
351 * can allocate the filter, then continue if successful.
352 */
353 if (!ops->get_rx_ntuple) {
354 fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC);
355 if (!fsc)
356 return -ENOMEM;
357 }
358
359 ret = ops->set_rx_ntuple(dev, &cmd);
360 if (ret) {
361 kfree(fsc);
362 return ret;
363 }
364
365 if (!ops->get_rx_ntuple)
366 __rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs, fsc);
367
368 return ret;
369}
370
371static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr)
372{
373 struct ethtool_gstrings gstrings;
374 const struct ethtool_ops *ops = dev->ethtool_ops;
375 struct ethtool_rx_ntuple_flow_spec_container *fsc;
376 u8 *data;
377 char *p;
378 int ret, i, num_strings = 0;
379
380 if (!ops->get_sset_count)
381 return -EOPNOTSUPP;
382
383 if (copy_from_user(&gstrings, useraddr, sizeof(gstrings)))
384 return -EFAULT;
385
386 ret = ops->get_sset_count(dev, gstrings.string_set);
387 if (ret < 0)
388 return ret;
389
390 gstrings.len = ret;
391
392 data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
393 if (!data)
394 return -ENOMEM;
395
396 if (ops->get_rx_ntuple) {
397 /* driver-specific filter grab */
398 ret = ops->get_rx_ntuple(dev, gstrings.string_set, data);
399 goto copy;
400 }
401
402 /* default ethtool filter grab */
403 i = 0;
404 p = (char *)data;
405 list_for_each_entry(fsc, &dev->ethtool_ntuple_list.list, list) {
406 sprintf(p, "Filter %d:\n", i);
407 p += ETH_GSTRING_LEN;
408 num_strings++;
409
410 switch (fsc->fs.flow_type) {
411 case TCP_V4_FLOW:
412 sprintf(p, "\tFlow Type: TCP\n");
413 p += ETH_GSTRING_LEN;
414 num_strings++;
415 break;
416 case UDP_V4_FLOW:
417 sprintf(p, "\tFlow Type: UDP\n");
418 p += ETH_GSTRING_LEN;
419 num_strings++;
420 break;
421 case SCTP_V4_FLOW:
422 sprintf(p, "\tFlow Type: SCTP\n");
423 p += ETH_GSTRING_LEN;
424 num_strings++;
425 break;
426 case AH_ESP_V4_FLOW:
427 sprintf(p, "\tFlow Type: AH ESP\n");
428 p += ETH_GSTRING_LEN;
429 num_strings++;
430 break;
431 case ESP_V4_FLOW:
432 sprintf(p, "\tFlow Type: ESP\n");
433 p += ETH_GSTRING_LEN;
434 num_strings++;
435 break;
436 case IP_USER_FLOW:
437 sprintf(p, "\tFlow Type: Raw IP\n");
438 p += ETH_GSTRING_LEN;
439 num_strings++;
440 break;
441 case IPV4_FLOW:
442 sprintf(p, "\tFlow Type: IPv4\n");
443 p += ETH_GSTRING_LEN;
444 num_strings++;
445 break;
446 default:
447 sprintf(p, "\tFlow Type: Unknown\n");
448 p += ETH_GSTRING_LEN;
449 num_strings++;
450 goto unknown_filter;
451 };
452
453 /* now the rest of the filters */
454 switch (fsc->fs.flow_type) {
455 case TCP_V4_FLOW:
456 case UDP_V4_FLOW:
457 case SCTP_V4_FLOW:
458 sprintf(p, "\tSrc IP addr: 0x%x\n",
459 fsc->fs.h_u.tcp_ip4_spec.ip4src);
460 p += ETH_GSTRING_LEN;
461 num_strings++;
462 sprintf(p, "\tSrc IP mask: 0x%x\n",
463 fsc->fs.m_u.tcp_ip4_spec.ip4src);
464 p += ETH_GSTRING_LEN;
465 num_strings++;
466 sprintf(p, "\tDest IP addr: 0x%x\n",
467 fsc->fs.h_u.tcp_ip4_spec.ip4dst);
468 p += ETH_GSTRING_LEN;
469 num_strings++;
470 sprintf(p, "\tDest IP mask: 0x%x\n",
471 fsc->fs.m_u.tcp_ip4_spec.ip4dst);
472 p += ETH_GSTRING_LEN;
473 num_strings++;
474 sprintf(p, "\tSrc Port: %d, mask: 0x%x\n",
475 fsc->fs.h_u.tcp_ip4_spec.psrc,
476 fsc->fs.m_u.tcp_ip4_spec.psrc);
477 p += ETH_GSTRING_LEN;
478 num_strings++;
479 sprintf(p, "\tDest Port: %d, mask: 0x%x\n",
480 fsc->fs.h_u.tcp_ip4_spec.pdst,
481 fsc->fs.m_u.tcp_ip4_spec.pdst);
482 p += ETH_GSTRING_LEN;
483 num_strings++;
484 sprintf(p, "\tTOS: %d, mask: 0x%x\n",
485 fsc->fs.h_u.tcp_ip4_spec.tos,
486 fsc->fs.m_u.tcp_ip4_spec.tos);
487 p += ETH_GSTRING_LEN;
488 num_strings++;
489 break;
490 case AH_ESP_V4_FLOW:
491 case ESP_V4_FLOW:
492 sprintf(p, "\tSrc IP addr: 0x%x\n",
493 fsc->fs.h_u.ah_ip4_spec.ip4src);
494 p += ETH_GSTRING_LEN;
495 num_strings++;
496 sprintf(p, "\tSrc IP mask: 0x%x\n",
497 fsc->fs.m_u.ah_ip4_spec.ip4src);
498 p += ETH_GSTRING_LEN;
499 num_strings++;
500 sprintf(p, "\tDest IP addr: 0x%x\n",
501 fsc->fs.h_u.ah_ip4_spec.ip4dst);
502 p += ETH_GSTRING_LEN;
503 num_strings++;
504 sprintf(p, "\tDest IP mask: 0x%x\n",
505 fsc->fs.m_u.ah_ip4_spec.ip4dst);
506 p += ETH_GSTRING_LEN;
507 num_strings++;
508 sprintf(p, "\tSPI: %d, mask: 0x%x\n",
509 fsc->fs.h_u.ah_ip4_spec.spi,
510 fsc->fs.m_u.ah_ip4_spec.spi);
511 p += ETH_GSTRING_LEN;
512 num_strings++;
513 sprintf(p, "\tTOS: %d, mask: 0x%x\n",
514 fsc->fs.h_u.ah_ip4_spec.tos,
515 fsc->fs.m_u.ah_ip4_spec.tos);
516 p += ETH_GSTRING_LEN;
517 num_strings++;
518 break;
519 case IP_USER_FLOW:
520 sprintf(p, "\tSrc IP addr: 0x%x\n",
521 fsc->fs.h_u.raw_ip4_spec.ip4src);
522 p += ETH_GSTRING_LEN;
523 num_strings++;
524 sprintf(p, "\tSrc IP mask: 0x%x\n",
525 fsc->fs.m_u.raw_ip4_spec.ip4src);
526 p += ETH_GSTRING_LEN;
527 num_strings++;
528 sprintf(p, "\tDest IP addr: 0x%x\n",
529 fsc->fs.h_u.raw_ip4_spec.ip4dst);
530 p += ETH_GSTRING_LEN;
531 num_strings++;
532 sprintf(p, "\tDest IP mask: 0x%x\n",
533 fsc->fs.m_u.raw_ip4_spec.ip4dst);
534 p += ETH_GSTRING_LEN;
535 num_strings++;
536 break;
537 case IPV4_FLOW:
538 sprintf(p, "\tSrc IP addr: 0x%x\n",
539 fsc->fs.h_u.usr_ip4_spec.ip4src);
540 p += ETH_GSTRING_LEN;
541 num_strings++;
542 sprintf(p, "\tSrc IP mask: 0x%x\n",
543 fsc->fs.m_u.usr_ip4_spec.ip4src);
544 p += ETH_GSTRING_LEN;
545 num_strings++;
546 sprintf(p, "\tDest IP addr: 0x%x\n",
547 fsc->fs.h_u.usr_ip4_spec.ip4dst);
548 p += ETH_GSTRING_LEN;
549 num_strings++;
550 sprintf(p, "\tDest IP mask: 0x%x\n",
551 fsc->fs.m_u.usr_ip4_spec.ip4dst);
552 p += ETH_GSTRING_LEN;
553 num_strings++;
554 sprintf(p, "\tL4 bytes: 0x%x, mask: 0x%x\n",
555 fsc->fs.h_u.usr_ip4_spec.l4_4_bytes,
556 fsc->fs.m_u.usr_ip4_spec.l4_4_bytes);
557 p += ETH_GSTRING_LEN;
558 num_strings++;
559 sprintf(p, "\tTOS: %d, mask: 0x%x\n",
560 fsc->fs.h_u.usr_ip4_spec.tos,
561 fsc->fs.m_u.usr_ip4_spec.tos);
562 p += ETH_GSTRING_LEN;
563 num_strings++;
564 sprintf(p, "\tIP Version: %d, mask: 0x%x\n",
565 fsc->fs.h_u.usr_ip4_spec.ip_ver,
566 fsc->fs.m_u.usr_ip4_spec.ip_ver);
567 p += ETH_GSTRING_LEN;
568 num_strings++;
569 sprintf(p, "\tProtocol: %d, mask: 0x%x\n",
570 fsc->fs.h_u.usr_ip4_spec.proto,
571 fsc->fs.m_u.usr_ip4_spec.proto);
572 p += ETH_GSTRING_LEN;
573 num_strings++;
574 break;
575 };
576 sprintf(p, "\tVLAN: %d, mask: 0x%x\n",
577 fsc->fs.vlan_tag, fsc->fs.vlan_tag_mask);
578 p += ETH_GSTRING_LEN;
579 num_strings++;
580 sprintf(p, "\tUser-defined: 0x%Lx\n", fsc->fs.data);
581 p += ETH_GSTRING_LEN;
582 num_strings++;
583 sprintf(p, "\tUser-defined mask: 0x%Lx\n", fsc->fs.data_mask);
584 p += ETH_GSTRING_LEN;
585 num_strings++;
586 if (fsc->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
587 sprintf(p, "\tAction: Drop\n");
588 else
589 sprintf(p, "\tAction: Direct to queue %d\n",
590 fsc->fs.action);
591 p += ETH_GSTRING_LEN;
592 num_strings++;
593unknown_filter:
594 i++;
595 }
596copy:
597 /* indicate to userspace how many strings we actually have */
598 gstrings.len = num_strings;
599 ret = -EFAULT;
600 if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
601 goto out;
602 useraddr += sizeof(gstrings);
603 if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
604 goto out;
605 ret = 0;
606
607out:
608 kfree(data);
609 return ret;
610}
611
269static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) 612static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
270{ 613{
271 struct ethtool_regs regs; 614 struct ethtool_regs regs;
@@ -324,7 +667,7 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
324 667
325static int ethtool_get_wol(struct net_device *dev, char __user *useraddr) 668static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
326{ 669{
327 struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; 670 struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
328 671
329 if (!dev->ethtool_ops->get_wol) 672 if (!dev->ethtool_ops->get_wol)
330 return -EOPNOTSUPP; 673 return -EOPNOTSUPP;
@@ -456,9 +799,12 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)
456 return ret; 799 return ret;
457} 800}
458 801
459static int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) 802/*
803 * noinline attribute so that gcc doesnt use too much stack in dev_ethtool()
804 */
805static noinline int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr)
460{ 806{
461 struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; 807 struct ethtool_coalesce coalesce = { .cmd = ETHTOOL_GCOALESCE };
462 808
463 if (!dev->ethtool_ops->get_coalesce) 809 if (!dev->ethtool_ops->get_coalesce)
464 return -EOPNOTSUPP; 810 return -EOPNOTSUPP;
@@ -470,7 +816,10 @@ static int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr)
470 return 0; 816 return 0;
471} 817}
472 818
473static int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) 819/*
820 * noinline attribute so that gcc doesnt use too much stack in dev_ethtool()
821 */
822static noinline int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr)
474{ 823{
475 struct ethtool_coalesce coalesce; 824 struct ethtool_coalesce coalesce;
476 825
@@ -485,7 +834,7 @@ static int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr)
485 834
486static int ethtool_get_ringparam(struct net_device *dev, void __user *useraddr) 835static int ethtool_get_ringparam(struct net_device *dev, void __user *useraddr)
487{ 836{
488 struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; 837 struct ethtool_ringparam ringparam = { .cmd = ETHTOOL_GRINGPARAM };
489 838
490 if (!dev->ethtool_ops->get_ringparam) 839 if (!dev->ethtool_ops->get_ringparam)
491 return -EOPNOTSUPP; 840 return -EOPNOTSUPP;
@@ -839,7 +1188,7 @@ static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr)
839static int ethtool_get_value(struct net_device *dev, char __user *useraddr, 1188static int ethtool_get_value(struct net_device *dev, char __user *useraddr,
840 u32 cmd, u32 (*actor)(struct net_device *)) 1189 u32 cmd, u32 (*actor)(struct net_device *))
841{ 1190{
842 struct ethtool_value edata = { cmd }; 1191 struct ethtool_value edata = { .cmd = cmd };
843 1192
844 if (!actor) 1193 if (!actor)
845 return -EOPNOTSUPP; 1194 return -EOPNOTSUPP;
@@ -880,7 +1229,10 @@ static int ethtool_set_value(struct net_device *dev, char __user *useraddr,
880 return actor(dev, edata.data); 1229 return actor(dev, edata.data);
881} 1230}
882 1231
883static int ethtool_flash_device(struct net_device *dev, char __user *useraddr) 1232/*
1233 * noinline attribute so that gcc doesnt use too much stack in dev_ethtool()
1234 */
1235static noinline int ethtool_flash_device(struct net_device *dev, char __user *useraddr)
884{ 1236{
885 struct ethtool_flash efl; 1237 struct ethtool_flash efl;
886 1238
@@ -927,6 +1279,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
927 case ETHTOOL_GPERMADDR: 1279 case ETHTOOL_GPERMADDR:
928 case ETHTOOL_GUFO: 1280 case ETHTOOL_GUFO:
929 case ETHTOOL_GGSO: 1281 case ETHTOOL_GGSO:
1282 case ETHTOOL_GGRO:
930 case ETHTOOL_GFLAGS: 1283 case ETHTOOL_GFLAGS:
931 case ETHTOOL_GPFLAGS: 1284 case ETHTOOL_GPFLAGS:
932 case ETHTOOL_GRXFH: 1285 case ETHTOOL_GRXFH:
@@ -1112,6 +1465,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
1112 case ETHTOOL_RESET: 1465 case ETHTOOL_RESET:
1113 rc = ethtool_reset(dev, useraddr); 1466 rc = ethtool_reset(dev, useraddr);
1114 break; 1467 break;
1468 case ETHTOOL_SRXNTUPLE:
1469 rc = ethtool_set_rx_ntuple(dev, useraddr);
1470 break;
1471 case ETHTOOL_GRXNTUPLE:
1472 rc = ethtool_get_rx_ntuple(dev, useraddr);
1473 break;
1115 default: 1474 default:
1116 rc = -EOPNOTSUPP; 1475 rc = -EOPNOTSUPP;
1117 } 1476 }