Steven Whitehouse writes:
> Here is the updated patch. If you are happy with this, then will you send
> it on to Dave, or should I do that?
Hello!
Yes the minor problem with the "return code" is fixed as:
Result: OK: mpls=0001000a,0002000a,0000000a
So I'll guess Dave will apply it.
Signed-off-by: Robert Olsson <[EMAIL PROTECTED]>
Thanks.
--ro
>
> Signed-off-by: Steven Whitehouse <[EMAIL PROTECTED]>
>
> diff --git a/Documentation/networking/pktgen.txt
> b/Documentation/networking/pktgen.txt
> --- a/Documentation/networking/pktgen.txt
> +++ b/Documentation/networking/pktgen.txt
> @@ -109,6 +109,22 @@ Examples:
> cycle through the port range.
> pgset "udp_dst_max 9" set UDP destination port max.
>
> + pgset "mpls 0001000a,0002000a,0000000a" set MPLS labels (in this example
> + outer label=16,middle label=32,
> + inner label=0 (IPv4 NULL)) Note that
> + there must be no spaces between the
> + arguments. Leading zeros are required.
> + Do not set the bottom of stack bit,
> + thats done automatically. If you do
> + set the bottom of stack bit, that
> + indicates that you want to randomly
> + generate that address and the flag
> + MPLS_RND will be turned on. You
> + can have any mix of random and fixed
> + labels in the label stack.
> +
> + pgset "mpls 0" turn off mpls (or any invalid argument works
> too!)
> +
> pgset stop aborts injection. Also, ^C aborts generator.
>
>
> @@ -167,6 +183,8 @@ pkt_size
> min_pkt_size
> max_pkt_size
>
> +mpls
> +
> udp_src_min
> udp_src_max
>
> @@ -211,4 +229,4 @@ Grant Grundler for testing on IA-64 and
> Stephen Hemminger, Andi Kleen, Dave Miller and many others.
>
>
> -Good luck with the linux net-development.
> \ No newline at end of file
> +Good luck with the linux net-development.
> diff --git a/net/core/pktgen.c b/net/core/pktgen.c
> --- a/net/core/pktgen.c
> +++ b/net/core/pktgen.c
> @@ -106,6 +106,9 @@
> *
> * interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <[EMAIL
> PROTECTED]>
> * 050103
> + *
> + * MPLS support by Steven Whitehouse <[EMAIL PROTECTED]>
> + *
> */
> #include <linux/sys.h>
> #include <linux/types.h>
> @@ -154,7 +157,7 @@
> #include <asm/div64.h> /* do_div */
> #include <asm/timex.h>
>
> -#define VERSION "pktgen v2.66: Packet Generator for packet performance
> testing.\n"
> +#define VERSION "pktgen v2.67: Packet Generator for packet performance
> testing.\n"
>
> /* #define PG_DEBUG(a) a */
> #define PG_DEBUG(a)
> @@ -162,6 +165,8 @@
> /* The buckets are exponential in 'width' */
> #define LAT_BUCKETS_MAX 32
> #define IP_NAME_SZ 32
> +#define MAX_MPLS_LABELS 16 /* This is the max label stack depth */
> +#define MPLS_STACK_BOTTOM __constant_htonl(0x00000100)
>
> /* Device flag bits */
> #define F_IPSRC_RND (1<<0) /* IP-Src Random */
> @@ -172,6 +177,7 @@
> #define F_MACDST_RND (1<<5) /* MAC-Dst Random */
> #define F_TXSIZE_RND (1<<6) /* Transmit size is random */
> #define F_IPV6 (1<<7) /* Interface in IPV6 Mode */
> +#define F_MPLS_RND (1<<8) /* Random MPLS labels */
>
> /* Thread control flag bits */
> #define T_TERMINATE (1<<0)
> @@ -278,6 +284,10 @@ struct pktgen_dev {
> __u16 udp_dst_min; /* inclusive, dest UDP port */
> __u16 udp_dst_max; /* exclusive, dest UDP port */
>
> + /* MPLS */
> + unsigned nr_labels; /* Depth of stack, 0 = no MPLS */
> + __be32 labels[MAX_MPLS_LABELS];
> +
> __u32 src_mac_count; /* How many MACs to iterate through */
> __u32 dst_mac_count; /* How many MACs to iterate through */
>
> @@ -623,9 +633,19 @@ static int pktgen_if_show(struct seq_fil
> pkt_dev->udp_dst_min, pkt_dev->udp_dst_max);
>
> seq_printf(seq,
> - " src_mac_count: %d dst_mac_count: %d \n Flags: ",
> + " src_mac_count: %d dst_mac_count: %d\n",
> pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
>
> + if (pkt_dev->nr_labels) {
> + unsigned i;
> + seq_printf(seq, " mpls: ");
> + for(i = 0; i < pkt_dev->nr_labels; i++)
> + seq_printf(seq, "%08x%s", ntohl(pkt_dev->labels[i]),
> + i == pkt_dev->nr_labels-1 ? "\n" : ", ");
> + }
> +
> + seq_printf(seq, " Flags: ");
> +
> if (pkt_dev->flags & F_IPV6)
> seq_printf(seq, "IPV6 ");
>
> @@ -644,6 +664,9 @@ static int pktgen_if_show(struct seq_fil
> if (pkt_dev->flags & F_UDPDST_RND)
> seq_printf(seq, "UDPDST_RND ");
>
> + if (pkt_dev->flags & F_MPLS_RND)
> + seq_printf(seq, "MPLS_RND ");
> +
> if (pkt_dev->flags & F_MACSRC_RND)
> seq_printf(seq, "MACSRC_RND ");
>
> @@ -691,6 +714,29 @@ static int pktgen_if_show(struct seq_fil
> return 0;
> }
>
> +
> +static int hex32_arg(const char __user *user_buffer, __u32 *num)
> +{
> + int i = 0;
> + *num = 0;
> +
> + for(; i < 8; i++) {
> + char c;
> + *num <<= 4;
> + if (get_user(c, &user_buffer[i]))
> + return -EFAULT;
> + if ((c >= '0') && (c <= '9'))
> + *num |= c - '0';
> + else if ((c >= 'a') && (c <= 'f'))
> + *num |= c - 'a' + 10;
> + else if ((c >= 'A') && (c <= 'F'))
> + *num |= c - 'A' + 10;
> + else
> + break;
> + }
> + return i;
> +}
> +
> static int count_trail_chars(const char __user * user_buffer,
> unsigned int maxlen)
> {
> @@ -759,6 +805,35 @@ done_str:
> return i;
> }
>
> +static ssize_t get_labels(const char __user *buffer, struct pktgen_dev
> *pkt_dev)
> +{
> + unsigned n = 0;
> + char c;
> + ssize_t i = 0;
> + int len;
> +
> + pkt_dev->nr_labels = 0;
> + do {
> + __u32 tmp;
> + len = hex32_arg(&buffer[i], &tmp);
> + if (len <= 0)
> + return len;
> + pkt_dev->labels[n] = htonl(tmp);
> + if (pkt_dev->labels[n] & MPLS_STACK_BOTTOM)
> + pkt_dev->flags |= F_MPLS_RND;
> + i += len;
> + if (get_user(c, &buffer[i]))
> + return -EFAULT;
> + i++;
> + n++;
> + if (n >= MAX_MPLS_LABELS)
> + return -E2BIG;
> + } while(c == ',');
> +
> + pkt_dev->nr_labels = n;
> + return i;
> +}
> +
> static ssize_t pktgen_if_write(struct file *file,
> const char __user * user_buffer, size_t count,
> loff_t * offset)
> @@ -1059,6 +1134,12 @@ static ssize_t pktgen_if_write(struct fi
> else if (strcmp(f, "!MACDST_RND") == 0)
> pkt_dev->flags &= ~F_MACDST_RND;
>
> + else if (strcmp(f, "MPLS_RND") == 0)
> + pkt_dev->flags |= F_MPLS_RND;
> +
> + else if (strcmp(f, "!MPLS_RND") == 0)
> + pkt_dev->flags &= ~F_MPLS_RND;
> +
> else {
> sprintf(pg_result,
> "Flag -:%s:- unknown\nAvailable flags, (prepend
> ! to un-set flag):\n%s",
> @@ -1354,6 +1435,19 @@ static ssize_t pktgen_if_write(struct fi
> return count;
> }
>
> + if (!strcmp(name, "mpls")) {
> + unsigned n, offset;
> + len = get_labels(&user_buffer[i], pkt_dev);
> + if (len < 0) { return len; }
> + i += len;
> + offset = sprintf(pg_result, "OK: mpls=");
> + for(n = 0; n < pkt_dev->nr_labels; n++)
> + offset += sprintf(pg_result + offset,
> + "%08x%s", ntohl(pkt_dev->labels[n]),
> + n == pkt_dev->nr_labels-1 ? "" : ",");
> + return count;
> + }
> +
> sprintf(pkt_dev->result, "No such parameter \"%s\"", name);
> return -EINVAL;
> }
> @@ -1846,6 +1940,15 @@ static void mod_cur_headers(struct pktge
> pkt_dev->hh[1] = tmp;
> }
>
> + if (pkt_dev->flags & F_MPLS_RND) {
> + unsigned i;
> + for(i = 0; i < pkt_dev->nr_labels; i++)
> + if (pkt_dev->labels[i] & MPLS_STACK_BOTTOM)
> + pkt_dev->labels[i] = MPLS_STACK_BOTTOM |
> + (pktgen_random() &
> + htonl(0x000fffff));
> + }
> +
> if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {
> if (pkt_dev->flags & F_UDPSRC_RND)
> pkt_dev->cur_udp_src =
> @@ -1968,6 +2071,16 @@ static void mod_cur_headers(struct pktge
> pkt_dev->flows[flow].count++;
> }
>
> +static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev)
> +{
> + unsigned i;
> + for(i = 0; i < pkt_dev->nr_labels; i++) {
> + *mpls++ = pkt_dev->labels[i] & ~MPLS_STACK_BOTTOM;
> + }
> + mpls--;
> + *mpls |= MPLS_STACK_BOTTOM;
> +}
> +
> static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
> struct pktgen_dev *pkt_dev)
> {
> @@ -1977,6 +2090,11 @@ static struct sk_buff *fill_packet_ipv4(
> int datalen, iplen;
> struct iphdr *iph;
> struct pktgen_hdr *pgh = NULL;
> + __be16 protocol = __constant_htons(ETH_P_IP);
> + __be32 *mpls;
> +
> + if (pkt_dev->nr_labels)
> + protocol = __constant_htons(ETH_P_MPLS_UC);
>
> /* Update any of the values, used when we're incrementing various
> * fields.
> @@ -1984,7 +2102,8 @@ static struct sk_buff *fill_packet_ipv4(
> mod_cur_headers(pkt_dev);
>
> datalen = (odev->hard_header_len + 16) & ~0xf;
> - skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen, GFP_ATOMIC);
> + skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen +
> + pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC);
> if (!skb) {
> sprintf(pkt_dev->result, "No memory");
> return NULL;
> @@ -1994,13 +2113,18 @@ static struct sk_buff *fill_packet_ipv4(
>
> /* Reserve for ethernet and IP header */
> eth = (__u8 *) skb_push(skb, 14);
> + mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
> + if (pkt_dev->nr_labels)
> + mpls_push(mpls, pkt_dev);
> iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
> udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
>
> memcpy(eth, pkt_dev->hh, 12);
> - *(u16 *) & eth[12] = __constant_htons(ETH_P_IP);
> + *(u16 *) & eth[12] = protocol;
>
> - datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8; /* Eth + IPh + UDPh */
> + /* Eth + IPh + UDPh + mpls */
> + datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -
> + pkt_dev->nr_labels*sizeof(u32);
> if (datalen < sizeof(struct pktgen_hdr))
> datalen = sizeof(struct pktgen_hdr);
>
> @@ -2021,8 +2145,8 @@ static struct sk_buff *fill_packet_ipv4(
> iph->tot_len = htons(iplen);
> iph->check = 0;
> iph->check = ip_fast_csum((void *)iph, iph->ihl);
> - skb->protocol = __constant_htons(ETH_P_IP);
> - skb->mac.raw = ((u8 *) iph) - 14;
> + skb->protocol = protocol;
> + skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
> skb->dev = odev;
> skb->pkt_type = PACKET_HOST;
>
> @@ -2274,13 +2398,19 @@ static struct sk_buff *fill_packet_ipv6(
> int datalen;
> struct ipv6hdr *iph;
> struct pktgen_hdr *pgh = NULL;
> + __be16 protocol = __constant_htons(ETH_P_IPV6);
> + __be32 *mpls;
> +
> + if (pkt_dev->nr_labels)
> + protocol = __constant_htons(ETH_P_MPLS_UC);
>
> /* Update any of the values, used when we're incrementing various
> * fields.
> */
> mod_cur_headers(pkt_dev);
>
> - skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC);
> + skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16 +
> + pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC);
> if (!skb) {
> sprintf(pkt_dev->result, "No memory");
> return NULL;
> @@ -2290,13 +2420,19 @@ static struct sk_buff *fill_packet_ipv6(
>
> /* Reserve for ethernet and IP header */
> eth = (__u8 *) skb_push(skb, 14);
> + mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
> + if (pkt_dev->nr_labels)
> + mpls_push(mpls, pkt_dev);
> iph = (struct ipv6hdr *)skb_put(skb, sizeof(struct ipv6hdr));
> udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
>
> memcpy(eth, pkt_dev->hh, 12);
> *(u16 *) & eth[12] = __constant_htons(ETH_P_IPV6);
>
> - datalen = pkt_dev->cur_pkt_size - 14 - sizeof(struct ipv6hdr) -
> sizeof(struct udphdr); /* Eth + IPh + UDPh */
> + /* Eth + IPh + UDPh + mpls */
> + datalen = pkt_dev->cur_pkt_size - 14 -
> + sizeof(struct ipv6hdr) - sizeof(struct udphdr) -
> + pkt_dev->nr_labels*sizeof(u32);
>
> if (datalen < sizeof(struct pktgen_hdr)) {
> datalen = sizeof(struct pktgen_hdr);
> @@ -2320,8 +2456,8 @@ static struct sk_buff *fill_packet_ipv6(
> ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr);
> ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr);
>
> - skb->mac.raw = ((u8 *) iph) - 14;
> - skb->protocol = __constant_htons(ETH_P_IPV6);
> + skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
> + skb->protocol = protocol;
> skb->dev = odev;
> skb->pkt_type = PACKET_HOST;
>
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html