aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/pktgen.c
diff options
context:
space:
mode:
authorSteven Whitehouse <steve@chygwyn.com>2006-03-23 04:10:26 -0500
committerDavid S. Miller <davem@davemloft.net>2006-03-23 04:10:26 -0500
commitca6549af77f0f28ac5d23b662fb8f72713eb16d3 (patch)
tree597e48060de9052ef034a0b49bcc5a1dbfd7e644 /net/core/pktgen.c
parent2e6e33bab6e1996a5dec9108fb467b52b841e7a8 (diff)
[PKTGEN]: Add MPLS extension.
Signed-off-by: Steven Whitehouse <steve@chygwyn.com> Signed-off-by: Robert Olsson <robert.olsson@its.uu.se> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/pktgen.c')
-rw-r--r--net/core/pktgen.c158
1 files changed, 147 insertions, 11 deletions
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