diff options
| author | Robert Olsson <robert@herjulf.net> | 2010-03-18 18:44:30 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-03-21 23:33:36 -0400 |
| commit | e99b99b471c21b071132e51bb7aa6b7a8796dc02 (patch) | |
| tree | 7bcd7b8d5093e3a5d88f3eb0c7fa65cfb016041a | |
| parent | 99fe3c391d50d381687fd84ed0ab22d57079e41f (diff) | |
pktgen node allocation
Here is patch to manipulate packet node allocation and implicitly
how packets are DMA'd etc.
The flag NODE_ALLOC enables the function and numa_node_id();
when enabled it can also be explicitly controlled via a new
node parameter
Tested this with 10 Intel 82599 ports w. TYAN S7025 E5520 CPU's.
Was able to TX/DMA ~80 Gbit/s to Ethernet wires.
Signed-off-by: Robert Olsson <robert.olsson@its.uu.se>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | net/core/pktgen.c | 58 |
1 files changed, 53 insertions, 5 deletions
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 43923811bd6a..2ad68da418df 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
| @@ -169,7 +169,7 @@ | |||
| 169 | #include <asm/dma.h> | 169 | #include <asm/dma.h> |
| 170 | #include <asm/div64.h> /* do_div */ | 170 | #include <asm/div64.h> /* do_div */ |
| 171 | 171 | ||
| 172 | #define VERSION "2.72" | 172 | #define VERSION "2.73" |
| 173 | #define IP_NAME_SZ 32 | 173 | #define IP_NAME_SZ 32 |
| 174 | #define MAX_MPLS_LABELS 16 /* This is the max label stack depth */ | 174 | #define MAX_MPLS_LABELS 16 /* This is the max label stack depth */ |
| 175 | #define MPLS_STACK_BOTTOM htonl(0x00000100) | 175 | #define MPLS_STACK_BOTTOM htonl(0x00000100) |
| @@ -190,6 +190,7 @@ | |||
| 190 | #define F_IPSEC_ON (1<<12) /* ipsec on for flows */ | 190 | #define F_IPSEC_ON (1<<12) /* ipsec on for flows */ |
| 191 | #define F_QUEUE_MAP_RND (1<<13) /* queue map Random */ | 191 | #define F_QUEUE_MAP_RND (1<<13) /* queue map Random */ |
| 192 | #define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */ | 192 | #define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */ |
| 193 | #define F_NODE (1<<15) /* Node memory alloc*/ | ||
| 193 | 194 | ||
| 194 | /* Thread control flag bits */ | 195 | /* Thread control flag bits */ |
| 195 | #define T_STOP (1<<0) /* Stop run */ | 196 | #define T_STOP (1<<0) /* Stop run */ |
| @@ -372,6 +373,7 @@ struct pktgen_dev { | |||
| 372 | 373 | ||
| 373 | u16 queue_map_min; | 374 | u16 queue_map_min; |
| 374 | u16 queue_map_max; | 375 | u16 queue_map_max; |
| 376 | int node; /* Memory node */ | ||
| 375 | 377 | ||
| 376 | #ifdef CONFIG_XFRM | 378 | #ifdef CONFIG_XFRM |
| 377 | __u8 ipsmode; /* IPSEC mode (config) */ | 379 | __u8 ipsmode; /* IPSEC mode (config) */ |
| @@ -607,6 +609,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v) | |||
| 607 | if (pkt_dev->traffic_class) | 609 | if (pkt_dev->traffic_class) |
| 608 | seq_printf(seq, " traffic_class: 0x%02x\n", pkt_dev->traffic_class); | 610 | seq_printf(seq, " traffic_class: 0x%02x\n", pkt_dev->traffic_class); |
| 609 | 611 | ||
| 612 | if (pkt_dev->node >= 0) | ||
| 613 | seq_printf(seq, " node: %d\n", pkt_dev->node); | ||
| 614 | |||
| 610 | seq_printf(seq, " Flags: "); | 615 | seq_printf(seq, " Flags: "); |
| 611 | 616 | ||
| 612 | if (pkt_dev->flags & F_IPV6) | 617 | if (pkt_dev->flags & F_IPV6) |
| @@ -660,6 +665,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v) | |||
| 660 | if (pkt_dev->flags & F_SVID_RND) | 665 | if (pkt_dev->flags & F_SVID_RND) |
| 661 | seq_printf(seq, "SVID_RND "); | 666 | seq_printf(seq, "SVID_RND "); |
| 662 | 667 | ||
| 668 | if (pkt_dev->flags & F_NODE) | ||
| 669 | seq_printf(seq, "NODE_ALLOC "); | ||
| 670 | |||
| 663 | seq_puts(seq, "\n"); | 671 | seq_puts(seq, "\n"); |
| 664 | 672 | ||
| 665 | /* not really stopped, more like last-running-at */ | 673 | /* not really stopped, more like last-running-at */ |
| @@ -1074,6 +1082,21 @@ static ssize_t pktgen_if_write(struct file *file, | |||
| 1074 | pkt_dev->dst_mac_count); | 1082 | pkt_dev->dst_mac_count); |
| 1075 | return count; | 1083 | return count; |
| 1076 | } | 1084 | } |
| 1085 | if (!strcmp(name, "node")) { | ||
| 1086 | len = num_arg(&user_buffer[i], 10, &value); | ||
| 1087 | if (len < 0) | ||
| 1088 | return len; | ||
| 1089 | |||
| 1090 | i += len; | ||
| 1091 | |||
| 1092 | if (node_possible(value)) { | ||
| 1093 | pkt_dev->node = value; | ||
| 1094 | sprintf(pg_result, "OK: node=%d", pkt_dev->node); | ||
| 1095 | } | ||
| 1096 | else | ||
| 1097 | sprintf(pg_result, "ERROR: node not possible"); | ||
| 1098 | return count; | ||
| 1099 | } | ||
| 1077 | if (!strcmp(name, "flag")) { | 1100 | if (!strcmp(name, "flag")) { |
| 1078 | char f[32]; | 1101 | char f[32]; |
| 1079 | memset(f, 0, 32); | 1102 | memset(f, 0, 32); |
| @@ -1166,12 +1189,18 @@ static ssize_t pktgen_if_write(struct file *file, | |||
| 1166 | else if (strcmp(f, "!IPV6") == 0) | 1189 | else if (strcmp(f, "!IPV6") == 0) |
| 1167 | pkt_dev->flags &= ~F_IPV6; | 1190 | pkt_dev->flags &= ~F_IPV6; |
| 1168 | 1191 | ||
| 1192 | else if (strcmp(f, "NODE_ALLOC") == 0) | ||
| 1193 | pkt_dev->flags |= F_NODE; | ||
| 1194 | |||
| 1195 | else if (strcmp(f, "!NODE_ALLOC") == 0) | ||
| 1196 | pkt_dev->flags &= ~F_NODE; | ||
| 1197 | |||
| 1169 | else { | 1198 | else { |
| 1170 | sprintf(pg_result, | 1199 | sprintf(pg_result, |
| 1171 | "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", | 1200 | "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", |
| 1172 | f, | 1201 | f, |
| 1173 | "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " | 1202 | "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " |
| 1174 | "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC\n"); | 1203 | "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC, NODE_ALLOC\n"); |
| 1175 | return count; | 1204 | return count; |
| 1176 | } | 1205 | } |
| 1177 | sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags); | 1206 | sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags); |
| @@ -2572,9 +2601,27 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
| 2572 | mod_cur_headers(pkt_dev); | 2601 | mod_cur_headers(pkt_dev); |
| 2573 | 2602 | ||
| 2574 | datalen = (odev->hard_header_len + 16) & ~0xf; | 2603 | datalen = (odev->hard_header_len + 16) & ~0xf; |
| 2575 | skb = __netdev_alloc_skb(odev, | 2604 | |
| 2576 | pkt_dev->cur_pkt_size + 64 | 2605 | if (pkt_dev->flags & F_NODE) { |
| 2577 | + datalen + pkt_dev->pkt_overhead, GFP_NOWAIT); | 2606 | int node; |
| 2607 | |||
| 2608 | if (pkt_dev->node >= 0) | ||
| 2609 | node = pkt_dev->node; | ||
| 2610 | else | ||
| 2611 | node = numa_node_id(); | ||
| 2612 | |||
| 2613 | skb = __alloc_skb(NET_SKB_PAD + pkt_dev->cur_pkt_size + 64 | ||
| 2614 | + datalen + pkt_dev->pkt_overhead, GFP_NOWAIT, 0, node); | ||
| 2615 | if (likely(skb)) { | ||
| 2616 | skb_reserve(skb, NET_SKB_PAD); | ||
| 2617 | skb->dev = odev; | ||
| 2618 | } | ||
| 2619 | } | ||
| 2620 | else | ||
| 2621 | skb = __netdev_alloc_skb(odev, | ||
| 2622 | pkt_dev->cur_pkt_size + 64 | ||
| 2623 | + datalen + pkt_dev->pkt_overhead, GFP_NOWAIT); | ||
| 2624 | |||
| 2578 | if (!skb) { | 2625 | if (!skb) { |
| 2579 | sprintf(pkt_dev->result, "No memory"); | 2626 | sprintf(pkt_dev->result, "No memory"); |
| 2580 | return NULL; | 2627 | return NULL; |
| @@ -3674,6 +3721,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) | |||
| 3674 | pkt_dev->svlan_p = 0; | 3721 | pkt_dev->svlan_p = 0; |
| 3675 | pkt_dev->svlan_cfi = 0; | 3722 | pkt_dev->svlan_cfi = 0; |
| 3676 | pkt_dev->svlan_id = 0xffff; | 3723 | pkt_dev->svlan_id = 0xffff; |
| 3724 | pkt_dev->node = -1; | ||
| 3677 | 3725 | ||
| 3678 | err = pktgen_setup_dev(pkt_dev, ifname); | 3726 | err = pktgen_setup_dev(pkt_dev, ifname); |
| 3679 | if (err) | 3727 | if (err) |
