diff options
Diffstat (limited to 'net/core/pktgen.c')
| -rw-r--r-- | net/core/pktgen.c | 222 |
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); | |||
| 449 | static void pktgen_clear_counters(struct pktgen_dev *pkt_dev); | 450 | static void pktgen_clear_counters(struct pktgen_dev *pkt_dev); |
| 450 | 451 | ||
| 451 | static unsigned int scan_ip6(const char *s, char ip[16]); | 452 | static unsigned int scan_ip6(const char *s, char ip[16]); |
| 452 | static unsigned int fmt_ip6(char *s, const char ip[16]); | ||
| 453 | 453 | ||
| 454 | /* Module parameters, defaults. */ | 454 | /* Module parameters, defaults. */ |
| 455 | static int pg_count_d __read_mostly = 1000; | 455 | static 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 | ||
| 2920 | static char tohex(char hexdigit) | ||
| 2921 | { | ||
| 2922 | return hexdigit > 9 ? hexdigit + 'a' - 10 : hexdigit + '0'; | ||
| 2923 | } | ||
| 2924 | |||
| 2925 | static 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 | |||
| 2941 | static 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 | |||
| 2993 | static struct sk_buff *fill_packet_ipv6(struct net_device *odev, | 2855 | static 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 | ||
| 3886 | static void __exit pg_cleanup(void) | 3752 | static void __exit pg_cleanup(void) |
