[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>
This commit is contained in:
parent
2e6e33bab6
commit
ca6549af77
2 changed files with 166 additions and 12 deletions
|
@ -109,6 +109,22 @@ Examples:
|
||||||
cycle through the port range.
|
cycle through the port range.
|
||||||
pgset "udp_dst_max 9" set UDP destination port max.
|
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.
|
pgset stop aborts injection. Also, ^C aborts generator.
|
||||||
|
|
||||||
|
|
||||||
|
@ -167,6 +183,8 @@ pkt_size
|
||||||
min_pkt_size
|
min_pkt_size
|
||||||
max_pkt_size
|
max_pkt_size
|
||||||
|
|
||||||
|
mpls
|
||||||
|
|
||||||
udp_src_min
|
udp_src_min
|
||||||
udp_src_max
|
udp_src_max
|
||||||
|
|
||||||
|
@ -211,4 +229,4 @@ Grant Grundler for testing on IA-64 and parisc, Harald Welte, Lennert Buytenhek
|
||||||
Stephen Hemminger, Andi Kleen, Dave Miller and many others.
|
Stephen Hemminger, Andi Kleen, Dave Miller and many others.
|
||||||
|
|
||||||
|
|
||||||
Good luck with the linux net-development.
|
Good luck with the linux net-development.
|
||||||
|
|
|
@ -106,6 +106,9 @@
|
||||||
*
|
*
|
||||||
* interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <nacc@us.ibm.com>
|
* interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <nacc@us.ibm.com>
|
||||||
* 050103
|
* 050103
|
||||||
|
*
|
||||||
|
* MPLS support by Steven Whitehouse <steve@chygwyn.com>
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
#include <linux/sys.h>
|
#include <linux/sys.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
@ -154,7 +157,7 @@
|
||||||
#include <asm/div64.h> /* do_div */
|
#include <asm/div64.h> /* do_div */
|
||||||
#include <asm/timex.h>
|
#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) a */
|
||||||
#define PG_DEBUG(a)
|
#define PG_DEBUG(a)
|
||||||
|
@ -162,6 +165,8 @@
|
||||||
/* The buckets are exponential in 'width' */
|
/* The buckets are exponential in 'width' */
|
||||||
#define LAT_BUCKETS_MAX 32
|
#define LAT_BUCKETS_MAX 32
|
||||||
#define IP_NAME_SZ 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 */
|
/* Device flag bits */
|
||||||
#define F_IPSRC_RND (1<<0) /* IP-Src Random */
|
#define F_IPSRC_RND (1<<0) /* IP-Src Random */
|
||||||
|
@ -172,6 +177,7 @@
|
||||||
#define F_MACDST_RND (1<<5) /* MAC-Dst Random */
|
#define F_MACDST_RND (1<<5) /* MAC-Dst Random */
|
||||||
#define F_TXSIZE_RND (1<<6) /* Transmit size is random */
|
#define F_TXSIZE_RND (1<<6) /* Transmit size is random */
|
||||||
#define F_IPV6 (1<<7) /* Interface in IPV6 Mode */
|
#define F_IPV6 (1<<7) /* Interface in IPV6 Mode */
|
||||||
|
#define F_MPLS_RND (1<<8) /* Random MPLS labels */
|
||||||
|
|
||||||
/* Thread control flag bits */
|
/* Thread control flag bits */
|
||||||
#define T_TERMINATE (1<<0)
|
#define T_TERMINATE (1<<0)
|
||||||
|
@ -278,6 +284,10 @@ struct pktgen_dev {
|
||||||
__u16 udp_dst_min; /* inclusive, dest UDP port */
|
__u16 udp_dst_min; /* inclusive, dest UDP port */
|
||||||
__u16 udp_dst_max; /* exclusive, 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 src_mac_count; /* How many MACs to iterate through */
|
||||||
__u32 dst_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_file *seq, void *v)
|
||||||
pkt_dev->udp_dst_min, pkt_dev->udp_dst_max);
|
pkt_dev->udp_dst_min, pkt_dev->udp_dst_max);
|
||||||
|
|
||||||
seq_printf(seq,
|
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);
|
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)
|
if (pkt_dev->flags & F_IPV6)
|
||||||
seq_printf(seq, "IPV6 ");
|
seq_printf(seq, "IPV6 ");
|
||||||
|
|
||||||
|
@ -644,6 +664,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
|
||||||
if (pkt_dev->flags & F_UDPDST_RND)
|
if (pkt_dev->flags & F_UDPDST_RND)
|
||||||
seq_printf(seq, "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)
|
if (pkt_dev->flags & F_MACSRC_RND)
|
||||||
seq_printf(seq, "MACSRC_RND ");
|
seq_printf(seq, "MACSRC_RND ");
|
||||||
|
|
||||||
|
@ -691,6 +714,29 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
|
||||||
return 0;
|
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,
|
static int count_trail_chars(const char __user * user_buffer,
|
||||||
unsigned int maxlen)
|
unsigned int maxlen)
|
||||||
{
|
{
|
||||||
|
@ -759,6 +805,35 @@ static int strn_len(const char __user * user_buffer, unsigned int maxlen)
|
||||||
return i;
|
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,
|
static ssize_t pktgen_if_write(struct file *file,
|
||||||
const char __user * user_buffer, size_t count,
|
const char __user * user_buffer, size_t count,
|
||||||
loff_t * offset)
|
loff_t * offset)
|
||||||
|
@ -1059,6 +1134,12 @@ static ssize_t pktgen_if_write(struct file *file,
|
||||||
else if (strcmp(f, "!MACDST_RND") == 0)
|
else if (strcmp(f, "!MACDST_RND") == 0)
|
||||||
pkt_dev->flags &= ~F_MACDST_RND;
|
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 {
|
else {
|
||||||
sprintf(pg_result,
|
sprintf(pg_result,
|
||||||
"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
|
"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,
|
||||||
return count;
|
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);
|
sprintf(pkt_dev->result, "No such parameter \"%s\"", name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -1846,6 +1940,15 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
|
||||||
pkt_dev->hh[1] = tmp;
|
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->udp_src_min < pkt_dev->udp_src_max) {
|
||||||
if (pkt_dev->flags & F_UDPSRC_RND)
|
if (pkt_dev->flags & F_UDPSRC_RND)
|
||||||
pkt_dev->cur_udp_src =
|
pkt_dev->cur_udp_src =
|
||||||
|
@ -1968,6 +2071,16 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
|
||||||
pkt_dev->flows[flow].count++;
|
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,
|
static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
|
||||||
struct pktgen_dev *pkt_dev)
|
struct pktgen_dev *pkt_dev)
|
||||||
{
|
{
|
||||||
|
@ -1977,6 +2090,11 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
|
||||||
int datalen, iplen;
|
int datalen, iplen;
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct pktgen_hdr *pgh = NULL;
|
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
|
/* Update any of the values, used when we're incrementing various
|
||||||
* fields.
|
* fields.
|
||||||
|
@ -1984,7 +2102,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
|
||||||
mod_cur_headers(pkt_dev);
|
mod_cur_headers(pkt_dev);
|
||||||
|
|
||||||
datalen = (odev->hard_header_len + 16) & ~0xf;
|
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) {
|
if (!skb) {
|
||||||
sprintf(pkt_dev->result, "No memory");
|
sprintf(pkt_dev->result, "No memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1994,13 +2113,18 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
|
||||||
|
|
||||||
/* Reserve for ethernet and IP header */
|
/* Reserve for ethernet and IP header */
|
||||||
eth = (__u8 *) skb_push(skb, 14);
|
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));
|
iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
|
||||||
udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
|
udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
|
||||||
|
|
||||||
memcpy(eth, pkt_dev->hh, 12);
|
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))
|
if (datalen < sizeof(struct pktgen_hdr))
|
||||||
datalen = sizeof(struct pktgen_hdr);
|
datalen = sizeof(struct pktgen_hdr);
|
||||||
|
|
||||||
|
@ -2021,8 +2145,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
|
||||||
iph->tot_len = htons(iplen);
|
iph->tot_len = htons(iplen);
|
||||||
iph->check = 0;
|
iph->check = 0;
|
||||||
iph->check = ip_fast_csum((void *)iph, iph->ihl);
|
iph->check = ip_fast_csum((void *)iph, iph->ihl);
|
||||||
skb->protocol = __constant_htons(ETH_P_IP);
|
skb->protocol = protocol;
|
||||||
skb->mac.raw = ((u8 *) iph) - 14;
|
skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
|
||||||
skb->dev = odev;
|
skb->dev = odev;
|
||||||
skb->pkt_type = PACKET_HOST;
|
skb->pkt_type = PACKET_HOST;
|
||||||
|
|
||||||
|
@ -2274,13 +2398,19 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
|
||||||
int datalen;
|
int datalen;
|
||||||
struct ipv6hdr *iph;
|
struct ipv6hdr *iph;
|
||||||
struct pktgen_hdr *pgh = NULL;
|
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
|
/* Update any of the values, used when we're incrementing various
|
||||||
* fields.
|
* fields.
|
||||||
*/
|
*/
|
||||||
mod_cur_headers(pkt_dev);
|
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) {
|
if (!skb) {
|
||||||
sprintf(pkt_dev->result, "No memory");
|
sprintf(pkt_dev->result, "No memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2290,13 +2420,19 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
|
||||||
|
|
||||||
/* Reserve for ethernet and IP header */
|
/* Reserve for ethernet and IP header */
|
||||||
eth = (__u8 *) skb_push(skb, 14);
|
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));
|
iph = (struct ipv6hdr *)skb_put(skb, sizeof(struct ipv6hdr));
|
||||||
udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
|
udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
|
||||||
|
|
||||||
memcpy(eth, pkt_dev->hh, 12);
|
memcpy(eth, pkt_dev->hh, 12);
|
||||||
*(u16 *) & eth[12] = __constant_htons(ETH_P_IPV6);
|
*(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)) {
|
if (datalen < sizeof(struct pktgen_hdr)) {
|
||||||
datalen = sizeof(struct pktgen_hdr);
|
datalen = sizeof(struct pktgen_hdr);
|
||||||
|
@ -2320,8 +2456,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
|
||||||
ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr);
|
ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr);
|
||||||
ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr);
|
ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr);
|
||||||
|
|
||||||
skb->mac.raw = ((u8 *) iph) - 14;
|
skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
|
||||||
skb->protocol = __constant_htons(ETH_P_IPV6);
|
skb->protocol = protocol;
|
||||||
skb->dev = odev;
|
skb->dev = odev;
|
||||||
skb->pkt_type = PACKET_HOST;
|
skb->pkt_type = PACKET_HOST;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue