aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/pktgen.txt20
-rw-r--r--net/core/pktgen.c158
2 files changed, 166 insertions, 12 deletions
diff --git a/Documentation/networking/pktgen.txt b/Documentation/networking/pktgen.txt
index cc4b4d04129c..278771c9ad99 100644
--- a/Documentation/networking/pktgen.txt
+++ b/Documentation/networking/pktgen.txt
@@ -109,6 +109,22 @@ Examples:
109 cycle through the port range. 109 cycle through the port range.
110 pgset "udp_dst_max 9" set UDP destination port max. 110 pgset "udp_dst_max 9" set UDP destination port max.
111 111
112 pgset "mpls 0001000a,0002000a,0000000a" set MPLS labels (in this example
113 outer label=16,middle label=32,
114 inner label=0 (IPv4 NULL)) Note that
115 there must be no spaces between the
116 arguments. Leading zeros are required.
117 Do not set the bottom of stack bit,
118 thats done automatically. If you do
119 set the bottom of stack bit, that
120 indicates that you want to randomly
121 generate that address and the flag
122 MPLS_RND will be turned on. You
123 can have any mix of random and fixed
124 labels in the label stack.
125
126 pgset "mpls 0" turn off mpls (or any invalid argument works too!)
127
112 pgset stop aborts injection. Also, ^C aborts generator. 128 pgset stop aborts injection. Also, ^C aborts generator.
113 129
114 130
@@ -167,6 +183,8 @@ pkt_size
167min_pkt_size 183min_pkt_size
168max_pkt_size 184max_pkt_size
169 185
186mpls
187
170udp_src_min 188udp_src_min
171udp_src_max 189udp_src_max
172 190
@@ -211,4 +229,4 @@ Grant Grundler for testing on IA-64 and parisc, Harald Welte, Lennert Buytenhek
211Stephen Hemminger, Andi Kleen, Dave Miller and many others. 229Stephen Hemminger, Andi Kleen, Dave Miller and many others.
212 230
213 231
214Good luck with the linux net-development. \ No newline at end of file 232Good luck with the linux net-development.
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 8eedaedba743..c23e9c06ee23 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -106,6 +106,9 @@
106 * 106 *
107 * interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <nacc@us.ibm.com> 107 * interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <nacc@us.ibm.com>
108 * 050103 108 * 050103
109 *
110 * MPLS support by Steven Whitehouse <steve@chygwyn.com>
111 *
109 */ 112 */
110#include <linux/sys.h> 113#include <linux/sys.h>
111#include <linux/types.h> 114#include <linux/types.h>
@@ -154,7 +157,7 @@
154#include <asm/div64.h> /* do_div */ 157#include <asm/div64.h> /* do_div */
155#include <asm/timex.h> 158#include <asm/timex.h>
156 159
157#define VERSION "pktgen v2.66: Packet Generator for packet performance testing.\n" 160#define VERSION "pktgen v2.67: Packet Generator for packet performance testing.\n"
158 161
159/* #define PG_DEBUG(a) a */ 162/* #define PG_DEBUG(a) a */
160#define PG_DEBUG(a) 163#define PG_DEBUG(a)
@@ -162,6 +165,8 @@
162/* The buckets are exponential in 'width' */ 165/* The buckets are exponential in 'width' */
163#define LAT_BUCKETS_MAX 32 166#define LAT_BUCKETS_MAX 32
164#define IP_NAME_SZ 32 167#define IP_NAME_SZ 32
168#define MAX_MPLS_LABELS 16 /* This is the max label stack depth */
169#define MPLS_STACK_BOTTOM __constant_htonl(0x00000100)
165 170
166/* Device flag bits */ 171/* Device flag bits */
167#define F_IPSRC_RND (1<<0) /* IP-Src Random */ 172#define F_IPSRC_RND (1<<0) /* IP-Src Random */
@@ -172,6 +177,7 @@
172#define F_MACDST_RND (1<<5) /* MAC-Dst Random */ 177#define F_MACDST_RND (1<<5) /* MAC-Dst Random */
173#define F_TXSIZE_RND (1<<6) /* Transmit size is random */ 178#define F_TXSIZE_RND (1<<6) /* Transmit size is random */
174#define F_IPV6 (1<<7) /* Interface in IPV6 Mode */ 179#define F_IPV6 (1<<7) /* Interface in IPV6 Mode */
180#define F_MPLS_RND (1<<8) /* Random MPLS labels */
175 181
176/* Thread control flag bits */ 182/* Thread control flag bits */
177#define T_TERMINATE (1<<0) 183#define T_TERMINATE (1<<0)
@@ -278,6 +284,10 @@ struct pktgen_dev {
278 __u16 udp_dst_min; /* inclusive, dest UDP port */ 284 __u16 udp_dst_min; /* inclusive, dest UDP port */
279 __u16 udp_dst_max; /* exclusive, dest UDP port */ 285 __u16 udp_dst_max; /* exclusive, dest UDP port */
280 286
287 /* MPLS */
288 unsigned nr_labels; /* Depth of stack, 0 = no MPLS */
289 __be32 labels[MAX_MPLS_LABELS];
290
281 __u32 src_mac_count; /* How many MACs to iterate through */ 291 __u32 src_mac_count; /* How many MACs to iterate through */
282 __u32 dst_mac_count; /* How many MACs to iterate through */ 292 __u32 dst_mac_count; /* How many MACs to iterate through */
283 293
@@ -623,9 +633,19 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
623 pkt_dev->udp_dst_min, pkt_dev->udp_dst_max); 633 pkt_dev->udp_dst_min, pkt_dev->udp_dst_max);
624 634
625 seq_printf(seq, 635 seq_printf(seq,
626 " src_mac_count: %d dst_mac_count: %d \n Flags: ", 636 " src_mac_count: %d dst_mac_count: %d\n",
627 pkt_dev->src_mac_count, pkt_dev->dst_mac_count); 637 pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
628 638
639 if (pkt_dev->nr_labels) {
640 unsigned i;
641 seq_printf(seq, " mpls: ");
642 for(i = 0; i < pkt_dev->nr_labels; i++)
643 seq_printf(seq, "%08x%s", ntohl(pkt_dev->labels[i]),
644 i == pkt_dev->nr_labels-1 ? "\n" : ", ");
645 }
646
647 seq_printf(seq, " Flags: ");
648
629 if (pkt_dev->flags & F_IPV6) 649 if (pkt_dev->flags & F_IPV6)
630 seq_printf(seq, "IPV6 "); 650 seq_printf(seq, "IPV6 ");
631 651
@@ -644,6 +664,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
644 if (pkt_dev->flags & F_UDPDST_RND) 664 if (pkt_dev->flags & F_UDPDST_RND)
645 seq_printf(seq, "UDPDST_RND "); 665 seq_printf(seq, "UDPDST_RND ");
646 666
667 if (pkt_dev->flags & F_MPLS_RND)
668 seq_printf(seq, "MPLS_RND ");
669
647 if (pkt_dev->flags & F_MACSRC_RND) 670 if (pkt_dev->flags & F_MACSRC_RND)
648 seq_printf(seq, "MACSRC_RND "); 671 seq_printf(seq, "MACSRC_RND ");
649 672
@@ -691,6 +714,29 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
691 return 0; 714 return 0;
692} 715}
693 716
717
718static int hex32_arg(const char __user *user_buffer, __u32 *num)
719{
720 int i = 0;
721 *num = 0;
722
723 for(; i < 8; i++) {
724 char c;
725 *num <<= 4;
726 if (get_user(c, &user_buffer[i]))
727 return -EFAULT;
728 if ((c >= '0') && (c <= '9'))
729 *num |= c - '0';
730 else if ((c >= 'a') && (c <= 'f'))
731 *num |= c - 'a' + 10;
732 else if ((c >= 'A') && (c <= 'F'))
733 *num |= c - 'A' + 10;
734 else
735 break;
736 }
737 return i;
738}
739
694static int count_trail_chars(const char __user * user_buffer, 740static int count_trail_chars(const char __user * user_buffer,
695 unsigned int maxlen) 741 unsigned int maxlen)
696{ 742{
@@ -759,6 +805,35 @@ done_str:
759 return i; 805 return i;
760} 806}
761 807
808static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev)
809{
810 unsigned n = 0;
811 char c;
812 ssize_t i = 0;
813 int len;
814
815 pkt_dev->nr_labels = 0;
816 do {
817 __u32 tmp;
818 len = hex32_arg(&buffer[i], &tmp);
819 if (len <= 0)
820 return len;
821 pkt_dev->labels[n] = htonl(tmp);
822 if (pkt_dev->labels[n] & MPLS_STACK_BOTTOM)
823 pkt_dev->flags |= F_MPLS_RND;
824 i += len;
825 if (get_user(c, &buffer[i]))
826 return -EFAULT;
827 i++;
828 n++;
829 if (n >= MAX_MPLS_LABELS)
830 return -E2BIG;
831 } while(c == ',');
832
833 pkt_dev->nr_labels = n;
834 return i;
835}
836
762static ssize_t pktgen_if_write(struct file *file, 837static ssize_t pktgen_if_write(struct file *file,
763 const char __user * user_buffer, size_t count, 838 const char __user * user_buffer, size_t count,
764 loff_t * offset) 839 loff_t * offset)
@@ -1059,6 +1134,12 @@ static ssize_t pktgen_if_write(struct file *file,
1059 else if (strcmp(f, "!MACDST_RND") == 0) 1134 else if (strcmp(f, "!MACDST_RND") == 0)
1060 pkt_dev->flags &= ~F_MACDST_RND; 1135 pkt_dev->flags &= ~F_MACDST_RND;
1061 1136
1137 else if (strcmp(f, "MPLS_RND") == 0)
1138 pkt_dev->flags |= F_MPLS_RND;
1139
1140 else if (strcmp(f, "!MPLS_RND") == 0)
1141 pkt_dev->flags &= ~F_MPLS_RND;
1142
1062 else { 1143 else {
1063 sprintf(pg_result, 1144 sprintf(pg_result,
1064 "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", 1145 "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
@@ -1354,6 +1435,19 @@ static ssize_t pktgen_if_write(struct file *file,
1354 return count; 1435 return count;
1355 } 1436 }
1356 1437
1438 if (!strcmp(name, "mpls")) {
1439 unsigned n, offset;
1440 len = get_labels(&user_buffer[i], pkt_dev);
1441 if (len < 0) { return len; }
1442 i += len;
1443 offset = sprintf(pg_result, "OK: mpls=");
1444 for(n = 0; n < pkt_dev->nr_labels; n++)
1445 offset += sprintf(pg_result + offset,
1446 "%08x%s", ntohl(pkt_dev->labels[n]),
1447 n == pkt_dev->nr_labels-1 ? "" : ",");
1448 return count;
1449 }
1450
1357 sprintf(pkt_dev->result, "No such parameter \"%s\"", name); 1451 sprintf(pkt_dev->result, "No such parameter \"%s\"", name);
1358 return -EINVAL; 1452 return -EINVAL;
1359} 1453}
@@ -1846,6 +1940,15 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
1846 pkt_dev->hh[1] = tmp; 1940 pkt_dev->hh[1] = tmp;
1847 } 1941 }
1848 1942
1943 if (pkt_dev->flags & F_MPLS_RND) {
1944 unsigned i;
1945 for(i = 0; i < pkt_dev->nr_labels; i++)
1946 if (pkt_dev->labels[i] & MPLS_STACK_BOTTOM)
1947 pkt_dev->labels[i] = MPLS_STACK_BOTTOM |
1948 (pktgen_random() &
1949 htonl(0x000fffff));
1950 }
1951
1849 if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) { 1952 if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {
1850 if (pkt_dev->flags & F_UDPSRC_RND) 1953 if (pkt_dev->flags & F_UDPSRC_RND)
1851 pkt_dev->cur_udp_src = 1954 pkt_dev->cur_udp_src =
@@ -1968,6 +2071,16 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
1968 pkt_dev->flows[flow].count++; 2071 pkt_dev->flows[flow].count++;
1969} 2072}
1970 2073
2074static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev)
2075{
2076 unsigned i;
2077 for(i = 0; i < pkt_dev->nr_labels; i++) {
2078 *mpls++ = pkt_dev->labels[i] & ~MPLS_STACK_BOTTOM;
2079 }
2080 mpls--;
2081 *mpls |= MPLS_STACK_BOTTOM;
2082}
2083
1971static struct sk_buff *fill_packet_ipv4(struct net_device *odev, 2084static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
1972 struct pktgen_dev *pkt_dev) 2085 struct pktgen_dev *pkt_dev)
1973{ 2086{
@@ -1977,6 +2090,11 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
1977 int datalen, iplen; 2090 int datalen, iplen;
1978 struct iphdr *iph; 2091 struct iphdr *iph;
1979 struct pktgen_hdr *pgh = NULL; 2092 struct pktgen_hdr *pgh = NULL;
2093 __be16 protocol = __constant_htons(ETH_P_IP);
2094 __be32 *mpls;
2095
2096 if (pkt_dev->nr_labels)
2097 protocol = __constant_htons(ETH_P_MPLS_UC);
1980 2098
1981 /* Update any of the values, used when we're incrementing various 2099 /* Update any of the values, used when we're incrementing various
1982 * fields. 2100 * fields.
@@ -1984,7 +2102,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
1984 mod_cur_headers(pkt_dev); 2102 mod_cur_headers(pkt_dev);
1985 2103
1986 datalen = (odev->hard_header_len + 16) & ~0xf; 2104 datalen = (odev->hard_header_len + 16) & ~0xf;
1987 skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen, GFP_ATOMIC); 2105 skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen +
2106 pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC);
1988 if (!skb) { 2107 if (!skb) {
1989 sprintf(pkt_dev->result, "No memory"); 2108 sprintf(pkt_dev->result, "No memory");
1990 return NULL; 2109 return NULL;
@@ -1994,13 +2113,18 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
1994 2113
1995 /* Reserve for ethernet and IP header */ 2114 /* Reserve for ethernet and IP header */
1996 eth = (__u8 *) skb_push(skb, 14); 2115 eth = (__u8 *) skb_push(skb, 14);
2116 mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
2117 if (pkt_dev->nr_labels)
2118 mpls_push(mpls, pkt_dev);
1997 iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr)); 2119 iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
1998 udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr)); 2120 udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
1999 2121
2000 memcpy(eth, pkt_dev->hh, 12); 2122 memcpy(eth, pkt_dev->hh, 12);
2001 *(u16 *) & eth[12] = __constant_htons(ETH_P_IP); 2123 *(u16 *) & eth[12] = protocol;
2002 2124
2003 datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8; /* Eth + IPh + UDPh */ 2125 /* Eth + IPh + UDPh + mpls */
2126 datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -
2127 pkt_dev->nr_labels*sizeof(u32);
2004 if (datalen < sizeof(struct pktgen_hdr)) 2128 if (datalen < sizeof(struct pktgen_hdr))
2005 datalen = sizeof(struct pktgen_hdr); 2129 datalen = sizeof(struct pktgen_hdr);
2006 2130
@@ -2021,8 +2145,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
2021 iph->tot_len = htons(iplen); 2145 iph->tot_len = htons(iplen);
2022 iph->check = 0; 2146 iph->check = 0;
2023 iph->check = ip_fast_csum((void *)iph, iph->ihl); 2147 iph->check = ip_fast_csum((void *)iph, iph->ihl);
2024 skb->protocol = __constant_htons(ETH_P_IP); 2148 skb->protocol = protocol;
2025 skb->mac.raw = ((u8 *) iph) - 14; 2149 skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
2026 skb->dev = odev; 2150 skb->dev = odev;
2027 skb->pkt_type = PACKET_HOST; 2151 skb->pkt_type = PACKET_HOST;
2028 2152
@@ -2274,13 +2398,19 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2274 int datalen; 2398 int datalen;
2275 struct ipv6hdr *iph; 2399 struct ipv6hdr *iph;
2276 struct pktgen_hdr *pgh = NULL; 2400 struct pktgen_hdr *pgh = NULL;
2401 __be16 protocol = __constant_htons(ETH_P_IPV6);
2402 __be32 *mpls;
2403
2404 if (pkt_dev->nr_labels)
2405 protocol = __constant_htons(ETH_P_MPLS_UC);
2277 2406
2278 /* Update any of the values, used when we're incrementing various 2407 /* Update any of the values, used when we're incrementing various
2279 * fields. 2408 * fields.
2280 */ 2409 */
2281 mod_cur_headers(pkt_dev); 2410 mod_cur_headers(pkt_dev);
2282 2411
2283 skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC); 2412 skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16 +
2413 pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC);
2284 if (!skb) { 2414 if (!skb) {
2285 sprintf(pkt_dev->result, "No memory"); 2415 sprintf(pkt_dev->result, "No memory");
2286 return NULL; 2416 return NULL;
@@ -2290,13 +2420,19 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2290 2420
2291 /* Reserve for ethernet and IP header */ 2421 /* Reserve for ethernet and IP header */
2292 eth = (__u8 *) skb_push(skb, 14); 2422 eth = (__u8 *) skb_push(skb, 14);
2423 mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
2424 if (pkt_dev->nr_labels)
2425 mpls_push(mpls, pkt_dev);
2293 iph = (struct ipv6hdr *)skb_put(skb, sizeof(struct ipv6hdr)); 2426 iph = (struct ipv6hdr *)skb_put(skb, sizeof(struct ipv6hdr));
2294 udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr)); 2427 udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
2295 2428
2296 memcpy(eth, pkt_dev->hh, 12); 2429 memcpy(eth, pkt_dev->hh, 12);
2297 *(u16 *) & eth[12] = __constant_htons(ETH_P_IPV6); 2430 *(u16 *) & eth[12] = __constant_htons(ETH_P_IPV6);
2298 2431
2299 datalen = pkt_dev->cur_pkt_size - 14 - sizeof(struct ipv6hdr) - sizeof(struct udphdr); /* Eth + IPh + UDPh */ 2432 /* Eth + IPh + UDPh + mpls */
2433 datalen = pkt_dev->cur_pkt_size - 14 -
2434 sizeof(struct ipv6hdr) - sizeof(struct udphdr) -
2435 pkt_dev->nr_labels*sizeof(u32);
2300 2436
2301 if (datalen < sizeof(struct pktgen_hdr)) { 2437 if (datalen < sizeof(struct pktgen_hdr)) {
2302 datalen = sizeof(struct pktgen_hdr); 2438 datalen = sizeof(struct pktgen_hdr);
@@ -2320,8 +2456,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2320 ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr); 2456 ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr);
2321 ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr); 2457 ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr);
2322 2458
2323 skb->mac.raw = ((u8 *) iph) - 14; 2459 skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
2324 skb->protocol = __constant_htons(ETH_P_IPV6); 2460 skb->protocol = protocol;
2325 skb->dev = odev; 2461 skb->dev = odev;
2326 skb->pkt_type = PACKET_HOST; 2462 skb->pkt_type = PACKET_HOST;
2327 2463