aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/pktgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/pktgen.c')
-rw-r--r--net/core/pktgen.c222
1 files changed, 44 insertions, 178 deletions
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index aeeece72b72f..f76079cd750c 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -156,6 +156,7 @@
156#include <linux/wait.h> 156#include <linux/wait.h>
157#include <linux/etherdevice.h> 157#include <linux/etherdevice.h>
158#include <linux/kthread.h> 158#include <linux/kthread.h>
159#include <linux/prefetch.h>
159#include <net/net_namespace.h> 160#include <net/net_namespace.h>
160#include <net/checksum.h> 161#include <net/checksum.h>
161#include <net/ipv6.h> 162#include <net/ipv6.h>
@@ -449,7 +450,6 @@ static void pktgen_stop(struct pktgen_thread *t);
449static void pktgen_clear_counters(struct pktgen_dev *pkt_dev); 450static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);
450 451
451static unsigned int scan_ip6(const char *s, char ip[16]); 452static unsigned int scan_ip6(const char *s, char ip[16]);
452static unsigned int fmt_ip6(char *s, const char ip[16]);
453 453
454/* Module parameters, defaults. */ 454/* Module parameters, defaults. */
455static int pg_count_d __read_mostly = 1000; 455static int pg_count_d __read_mostly = 1000;
@@ -556,21 +556,13 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
556 pkt_dev->skb_priority); 556 pkt_dev->skb_priority);
557 557
558 if (pkt_dev->flags & F_IPV6) { 558 if (pkt_dev->flags & F_IPV6) {
559 char b1[128], b2[128], b3[128];
560 fmt_ip6(b1, pkt_dev->in6_saddr.s6_addr);
561 fmt_ip6(b2, pkt_dev->min_in6_saddr.s6_addr);
562 fmt_ip6(b3, pkt_dev->max_in6_saddr.s6_addr);
563 seq_printf(seq, 559 seq_printf(seq,
564 " saddr: %s min_saddr: %s max_saddr: %s\n", b1, 560 " saddr: %pI6c min_saddr: %pI6c max_saddr: %pI6c\n"
565 b2, b3); 561 " daddr: %pI6c min_daddr: %pI6c max_daddr: %pI6c\n",
566 562 &pkt_dev->in6_saddr,
567 fmt_ip6(b1, pkt_dev->in6_daddr.s6_addr); 563 &pkt_dev->min_in6_saddr, &pkt_dev->max_in6_saddr,
568 fmt_ip6(b2, pkt_dev->min_in6_daddr.s6_addr); 564 &pkt_dev->in6_daddr,
569 fmt_ip6(b3, pkt_dev->max_in6_daddr.s6_addr); 565 &pkt_dev->min_in6_daddr, &pkt_dev->max_in6_daddr);
570 seq_printf(seq,
571 " daddr: %s min_daddr: %s max_daddr: %s\n", b1,
572 b2, b3);
573
574 } else { 566 } else {
575 seq_printf(seq, 567 seq_printf(seq,
576 " dst_min: %s dst_max: %s\n", 568 " dst_min: %s dst_max: %s\n",
@@ -706,10 +698,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
706 pkt_dev->cur_src_mac_offset); 698 pkt_dev->cur_src_mac_offset);
707 699
708 if (pkt_dev->flags & F_IPV6) { 700 if (pkt_dev->flags & F_IPV6) {
709 char b1[128], b2[128]; 701 seq_printf(seq, " cur_saddr: %pI6c cur_daddr: %pI6c\n",
710 fmt_ip6(b1, pkt_dev->cur_in6_daddr.s6_addr); 702 &pkt_dev->cur_in6_saddr,
711 fmt_ip6(b2, pkt_dev->cur_in6_saddr.s6_addr); 703 &pkt_dev->cur_in6_daddr);
712 seq_printf(seq, " cur_saddr: %s cur_daddr: %s\n", b2, b1);
713 } else 704 } else
714 seq_printf(seq, " cur_saddr: 0x%x cur_daddr: 0x%x\n", 705 seq_printf(seq, " cur_saddr: 0x%x cur_daddr: 0x%x\n",
715 pkt_dev->cur_saddr, pkt_dev->cur_daddr); 706 pkt_dev->cur_saddr, pkt_dev->cur_daddr);
@@ -1309,7 +1300,7 @@ static ssize_t pktgen_if_write(struct file *file,
1309 buf[len] = 0; 1300 buf[len] = 0;
1310 1301
1311 scan_ip6(buf, pkt_dev->in6_daddr.s6_addr); 1302 scan_ip6(buf, pkt_dev->in6_daddr.s6_addr);
1312 fmt_ip6(buf, pkt_dev->in6_daddr.s6_addr); 1303 snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_daddr);
1313 1304
1314 ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->in6_daddr); 1305 ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->in6_daddr);
1315 1306
@@ -1332,7 +1323,7 @@ static ssize_t pktgen_if_write(struct file *file,
1332 buf[len] = 0; 1323 buf[len] = 0;
1333 1324
1334 scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); 1325 scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr);
1335 fmt_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); 1326 snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->min_in6_daddr);
1336 1327
1337 ipv6_addr_copy(&pkt_dev->cur_in6_daddr, 1328 ipv6_addr_copy(&pkt_dev->cur_in6_daddr,
1338 &pkt_dev->min_in6_daddr); 1329 &pkt_dev->min_in6_daddr);
@@ -1355,7 +1346,7 @@ static ssize_t pktgen_if_write(struct file *file,
1355 buf[len] = 0; 1346 buf[len] = 0;
1356 1347
1357 scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); 1348 scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr);
1358 fmt_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); 1349 snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->max_in6_daddr);
1359 1350
1360 if (debug) 1351 if (debug)
1361 printk(KERN_DEBUG "pktgen: dst6_max set to: %s\n", buf); 1352 printk(KERN_DEBUG "pktgen: dst6_max set to: %s\n", buf);
@@ -1376,7 +1367,7 @@ static ssize_t pktgen_if_write(struct file *file,
1376 buf[len] = 0; 1367 buf[len] = 0;
1377 1368
1378 scan_ip6(buf, pkt_dev->in6_saddr.s6_addr); 1369 scan_ip6(buf, pkt_dev->in6_saddr.s6_addr);
1379 fmt_ip6(buf, pkt_dev->in6_saddr.s6_addr); 1370 snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_saddr);
1380 1371
1381 ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &pkt_dev->in6_saddr); 1372 ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &pkt_dev->in6_saddr);
1382 1373
@@ -1430,11 +1421,6 @@ static ssize_t pktgen_if_write(struct file *file,
1430 return count; 1421 return count;
1431 } 1422 }
1432 if (!strcmp(name, "dst_mac")) { 1423 if (!strcmp(name, "dst_mac")) {
1433 char *v = valstr;
1434 unsigned char old_dmac[ETH_ALEN];
1435 unsigned char *m = pkt_dev->dst_mac;
1436 memcpy(old_dmac, pkt_dev->dst_mac, ETH_ALEN);
1437
1438 len = strn_len(&user_buffer[i], sizeof(valstr) - 1); 1424 len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
1439 if (len < 0) 1425 if (len < 0)
1440 return len; 1426 return len;
@@ -1442,35 +1428,16 @@ static ssize_t pktgen_if_write(struct file *file,
1442 memset(valstr, 0, sizeof(valstr)); 1428 memset(valstr, 0, sizeof(valstr));
1443 if (copy_from_user(valstr, &user_buffer[i], len)) 1429 if (copy_from_user(valstr, &user_buffer[i], len))
1444 return -EFAULT; 1430 return -EFAULT;
1445 i += len;
1446
1447 for (*m = 0; *v && m < pkt_dev->dst_mac + 6; v++) {
1448 int value;
1449
1450 value = hex_to_bin(*v);
1451 if (value >= 0)
1452 *m = *m * 16 + value;
1453
1454 if (*v == ':') {
1455 m++;
1456 *m = 0;
1457 }
1458 }
1459 1431
1432 if (!mac_pton(valstr, pkt_dev->dst_mac))
1433 return -EINVAL;
1460 /* Set up Dest MAC */ 1434 /* Set up Dest MAC */
1461 if (compare_ether_addr(old_dmac, pkt_dev->dst_mac)) 1435 memcpy(&pkt_dev->hh[0], pkt_dev->dst_mac, ETH_ALEN);
1462 memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN);
1463 1436
1464 sprintf(pg_result, "OK: dstmac"); 1437 sprintf(pg_result, "OK: dstmac %pM", pkt_dev->dst_mac);
1465 return count; 1438 return count;
1466 } 1439 }
1467 if (!strcmp(name, "src_mac")) { 1440 if (!strcmp(name, "src_mac")) {
1468 char *v = valstr;
1469 unsigned char old_smac[ETH_ALEN];
1470 unsigned char *m = pkt_dev->src_mac;
1471
1472 memcpy(old_smac, pkt_dev->src_mac, ETH_ALEN);
1473
1474 len = strn_len(&user_buffer[i], sizeof(valstr) - 1); 1441 len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
1475 if (len < 0) 1442 if (len < 0)
1476 return len; 1443 return len;
@@ -1478,26 +1445,13 @@ static ssize_t pktgen_if_write(struct file *file,
1478 memset(valstr, 0, sizeof(valstr)); 1445 memset(valstr, 0, sizeof(valstr));
1479 if (copy_from_user(valstr, &user_buffer[i], len)) 1446 if (copy_from_user(valstr, &user_buffer[i], len))
1480 return -EFAULT; 1447 return -EFAULT;
1481 i += len;
1482
1483 for (*m = 0; *v && m < pkt_dev->src_mac + 6; v++) {
1484 int value;
1485
1486 value = hex_to_bin(*v);
1487 if (value >= 0)
1488 *m = *m * 16 + value;
1489
1490 if (*v == ':') {
1491 m++;
1492 *m = 0;
1493 }
1494 }
1495 1448
1449 if (!mac_pton(valstr, pkt_dev->src_mac))
1450 return -EINVAL;
1496 /* Set up Src MAC */ 1451 /* Set up Src MAC */
1497 if (compare_ether_addr(old_smac, pkt_dev->src_mac)) 1452 memcpy(&pkt_dev->hh[6], pkt_dev->src_mac, ETH_ALEN);
1498 memcpy(&(pkt_dev->hh[6]), pkt_dev->src_mac, ETH_ALEN);
1499 1453
1500 sprintf(pg_result, "OK: srcmac"); 1454 sprintf(pg_result, "OK: srcmac %pM", pkt_dev->src_mac);
1501 return count; 1455 return count;
1502 } 1456 }
1503 1457
@@ -2514,7 +2468,6 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
2514{ 2468{
2515 struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; 2469 struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;
2516 int err = 0; 2470 int err = 0;
2517 struct iphdr *iph;
2518 2471
2519 if (!x) 2472 if (!x)
2520 return 0; 2473 return 0;
@@ -2524,7 +2477,6 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
2524 return 0; 2477 return 0;
2525 2478
2526 spin_lock(&x->lock); 2479 spin_lock(&x->lock);
2527 iph = ip_hdr(skb);
2528 2480
2529 err = x->outer_mode->output(x, skb); 2481 err = x->outer_mode->output(x, skb);
2530 if (err) 2482 if (err)
@@ -2624,6 +2576,7 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb,
2624 } else { 2576 } else {
2625 int frags = pkt_dev->nfrags; 2577 int frags = pkt_dev->nfrags;
2626 int i, len; 2578 int i, len;
2579 int frag_len;
2627 2580
2628 2581
2629 if (frags > MAX_SKB_FRAGS) 2582 if (frags > MAX_SKB_FRAGS)
@@ -2635,6 +2588,8 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb,
2635 } 2588 }
2636 2589
2637 i = 0; 2590 i = 0;
2591 frag_len = (datalen/frags) < PAGE_SIZE ?
2592 (datalen/frags) : PAGE_SIZE;
2638 while (datalen > 0) { 2593 while (datalen > 0) {
2639 if (unlikely(!pkt_dev->page)) { 2594 if (unlikely(!pkt_dev->page)) {
2640 int node = numa_node_id(); 2595 int node = numa_node_id();
@@ -2648,38 +2603,18 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb,
2648 skb_shinfo(skb)->frags[i].page = pkt_dev->page; 2603 skb_shinfo(skb)->frags[i].page = pkt_dev->page;
2649 get_page(pkt_dev->page); 2604 get_page(pkt_dev->page);
2650 skb_shinfo(skb)->frags[i].page_offset = 0; 2605 skb_shinfo(skb)->frags[i].page_offset = 0;
2651 skb_shinfo(skb)->frags[i].size = 2606 /*last fragment, fill rest of data*/
2652 (datalen < PAGE_SIZE ? datalen : PAGE_SIZE); 2607 if (i == (frags - 1))
2608 skb_shinfo(skb)->frags[i].size =
2609 (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
2610 else
2611 skb_shinfo(skb)->frags[i].size = frag_len;
2653 datalen -= skb_shinfo(skb)->frags[i].size; 2612 datalen -= skb_shinfo(skb)->frags[i].size;
2654 skb->len += skb_shinfo(skb)->frags[i].size; 2613 skb->len += skb_shinfo(skb)->frags[i].size;
2655 skb->data_len += skb_shinfo(skb)->frags[i].size; 2614 skb->data_len += skb_shinfo(skb)->frags[i].size;
2656 i++; 2615 i++;
2657 skb_shinfo(skb)->nr_frags = i; 2616 skb_shinfo(skb)->nr_frags = i;
2658 } 2617 }
2659
2660 while (i < frags) {
2661 int rem;
2662
2663 if (i == 0)
2664 break;
2665
2666 rem = skb_shinfo(skb)->frags[i - 1].size / 2;
2667 if (rem == 0)
2668 break;
2669
2670 skb_shinfo(skb)->frags[i - 1].size -= rem;
2671
2672 skb_shinfo(skb)->frags[i] =
2673 skb_shinfo(skb)->frags[i - 1];
2674 get_page(skb_shinfo(skb)->frags[i].page);
2675 skb_shinfo(skb)->frags[i].page =
2676 skb_shinfo(skb)->frags[i - 1].page;
2677 skb_shinfo(skb)->frags[i].page_offset +=
2678 skb_shinfo(skb)->frags[i - 1].size;
2679 skb_shinfo(skb)->frags[i].size = rem;
2680 i++;
2681 skb_shinfo(skb)->nr_frags = i;
2682 }
2683 } 2618 }
2684 2619
2685 /* Stamp the time, and sequence number, 2620 /* Stamp the time, and sequence number,
@@ -2917,79 +2852,6 @@ static unsigned int scan_ip6(const char *s, char ip[16])
2917 return len; 2852 return len;
2918} 2853}
2919 2854
2920static char tohex(char hexdigit)
2921{
2922 return hexdigit > 9 ? hexdigit + 'a' - 10 : hexdigit + '0';
2923}
2924
2925static int fmt_xlong(char *s, unsigned int i)
2926{
2927 char *bak = s;
2928 *s = tohex((i >> 12) & 0xf);
2929 if (s != bak || *s != '0')
2930 ++s;
2931 *s = tohex((i >> 8) & 0xf);
2932 if (s != bak || *s != '0')
2933 ++s;
2934 *s = tohex((i >> 4) & 0xf);
2935 if (s != bak || *s != '0')
2936 ++s;
2937 *s = tohex(i & 0xf);
2938 return s - bak + 1;
2939}
2940
2941static unsigned int fmt_ip6(char *s, const char ip[16])
2942{
2943 unsigned int len;
2944 unsigned int i;
2945 unsigned int temp;
2946 unsigned int compressing;
2947 int j;
2948
2949 len = 0;
2950 compressing = 0;
2951 for (j = 0; j < 16; j += 2) {
2952
2953#ifdef V4MAPPEDPREFIX
2954 if (j == 12 && !memcmp(ip, V4mappedprefix, 12)) {
2955 inet_ntoa_r(*(struct in_addr *)(ip + 12), s);
2956 temp = strlen(s);
2957 return len + temp;
2958 }
2959#endif
2960 temp = ((unsigned long)(unsigned char)ip[j] << 8) +
2961 (unsigned long)(unsigned char)ip[j + 1];
2962 if (temp == 0) {
2963 if (!compressing) {
2964 compressing = 1;
2965 if (j == 0) {
2966 *s++ = ':';
2967 ++len;
2968 }
2969 }
2970 } else {
2971 if (compressing) {
2972 compressing = 0;
2973 *s++ = ':';
2974 ++len;
2975 }
2976 i = fmt_xlong(s, temp);
2977 len += i;
2978 s += i;
2979 if (j < 14) {
2980 *s++ = ':';
2981 ++len;
2982 }
2983 }
2984 }
2985 if (compressing) {
2986 *s++ = ':';
2987 ++len;
2988 }
2989 *s = 0;
2990 return len;
2991}
2992
2993static struct sk_buff *fill_packet_ipv6(struct net_device *odev, 2855static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2994 struct pktgen_dev *pkt_dev) 2856 struct pktgen_dev *pkt_dev)
2995{ 2857{
@@ -3682,13 +3544,12 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
3682 return -ENOMEM; 3544 return -ENOMEM;
3683 3545
3684 strcpy(pkt_dev->odevname, ifname); 3546 strcpy(pkt_dev->odevname, ifname);
3685 pkt_dev->flows = vmalloc_node(MAX_CFLOWS * sizeof(struct flow_state), 3547 pkt_dev->flows = vzalloc_node(MAX_CFLOWS * sizeof(struct flow_state),
3686 node); 3548 node);
3687 if (pkt_dev->flows == NULL) { 3549 if (pkt_dev->flows == NULL) {
3688 kfree(pkt_dev); 3550 kfree(pkt_dev);
3689 return -ENOMEM; 3551 return -ENOMEM;
3690 } 3552 }
3691 memset(pkt_dev->flows, 0, MAX_CFLOWS * sizeof(struct flow_state));
3692 3553
3693 pkt_dev->removal_mark = 0; 3554 pkt_dev->removal_mark = 0;
3694 pkt_dev->min_pkt_size = ETH_ZLEN; 3555 pkt_dev->min_pkt_size = ETH_ZLEN;
@@ -3846,6 +3707,7 @@ static int __init pg_init(void)
3846{ 3707{
3847 int cpu; 3708 int cpu;
3848 struct proc_dir_entry *pe; 3709 struct proc_dir_entry *pe;
3710 int ret = 0;
3849 3711
3850 pr_info("%s", version); 3712 pr_info("%s", version);
3851 3713
@@ -3856,11 +3718,10 @@ static int __init pg_init(void)
3856 pe = proc_create(PGCTRL, 0600, pg_proc_dir, &pktgen_fops); 3718 pe = proc_create(PGCTRL, 0600, pg_proc_dir, &pktgen_fops);
3857 if (pe == NULL) { 3719 if (pe == NULL) {
3858 pr_err("ERROR: cannot create %s procfs entry\n", PGCTRL); 3720 pr_err("ERROR: cannot create %s procfs entry\n", PGCTRL);
3859 proc_net_remove(&init_net, PG_PROC_DIR); 3721 ret = -EINVAL;
3860 return -EINVAL; 3722 goto remove_dir;
3861 } 3723 }
3862 3724
3863 /* Register us to receive netdevice events */
3864 register_netdevice_notifier(&pktgen_notifier_block); 3725 register_netdevice_notifier(&pktgen_notifier_block);
3865 3726
3866 for_each_online_cpu(cpu) { 3727 for_each_online_cpu(cpu) {
@@ -3874,13 +3735,18 @@ static int __init pg_init(void)
3874 3735
3875 if (list_empty(&pktgen_threads)) { 3736 if (list_empty(&pktgen_threads)) {
3876 pr_err("ERROR: Initialization failed for all threads\n"); 3737 pr_err("ERROR: Initialization failed for all threads\n");
3877 unregister_netdevice_notifier(&pktgen_notifier_block); 3738 ret = -ENODEV;
3878 remove_proc_entry(PGCTRL, pg_proc_dir); 3739 goto unregister;
3879 proc_net_remove(&init_net, PG_PROC_DIR);
3880 return -ENODEV;
3881 } 3740 }
3882 3741
3883 return 0; 3742 return 0;
3743
3744 unregister:
3745 unregister_netdevice_notifier(&pktgen_notifier_block);
3746 remove_proc_entry(PGCTRL, pg_proc_dir);
3747 remove_dir:
3748 proc_net_remove(&init_net, PG_PROC_DIR);
3749 return ret;
3884} 3750}
3885 3751
3886static void __exit pg_cleanup(void) 3752static void __exit pg_cleanup(void)