[PKTGEN]: Multiqueue support.

Below some pktgen support to send into different TX queues.
This can of course be feed into input queues on other machines

Signed-off-by: Robert Olsson <robert.olsson@its.uu.se>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Robert Olsson 2007-08-28 15:45:55 -07:00 committed by David S. Miller
parent 32b21e034b
commit 45b270f880
1 changed files with 59 additions and 0 deletions

View File

@ -189,6 +189,7 @@
#define F_SVID_RND (1<<10) /* Random SVLAN ID */ #define F_SVID_RND (1<<10) /* Random SVLAN ID */
#define F_FLOW_SEQ (1<<11) /* Sequential flows */ #define F_FLOW_SEQ (1<<11) /* Sequential flows */
#define F_IPSEC_ON (1<<12) /* ipsec on for flows */ #define F_IPSEC_ON (1<<12) /* ipsec on for flows */
#define F_QUEUE_MAP_RND (1<<13) /* queue map Random */
/* Thread control flag bits */ /* Thread control flag bits */
#define T_TERMINATE (1<<0) #define T_TERMINATE (1<<0)
@ -331,6 +332,7 @@ struct pktgen_dev {
__be32 cur_daddr; __be32 cur_daddr;
__u16 cur_udp_dst; __u16 cur_udp_dst;
__u16 cur_udp_src; __u16 cur_udp_src;
__u16 cur_queue_map;
__u32 cur_pkt_size; __u32 cur_pkt_size;
__u8 hh[14]; __u8 hh[14];
@ -358,6 +360,10 @@ struct pktgen_dev {
unsigned lflow; /* Flow length (config) */ unsigned lflow; /* Flow length (config) */
unsigned nflows; /* accumulated flows (stats) */ unsigned nflows; /* accumulated flows (stats) */
unsigned curfl; /* current sequenced flow (state)*/ unsigned curfl; /* current sequenced flow (state)*/
u16 queue_map_min;
u16 queue_map_max;
#ifdef CONFIG_XFRM #ifdef CONFIG_XFRM
__u8 ipsmode; /* IPSEC mode (config) */ __u8 ipsmode; /* IPSEC mode (config) */
__u8 ipsproto; /* IPSEC type (config) */ __u8 ipsproto; /* IPSEC type (config) */
@ -613,6 +619,11 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
seq_printf(seq, " flows: %u flowlen: %u\n", pkt_dev->cflows, seq_printf(seq, " flows: %u flowlen: %u\n", pkt_dev->cflows,
pkt_dev->lflow); pkt_dev->lflow);
seq_printf(seq,
" queue_map_min: %u queue_map_max: %u\n",
pkt_dev->queue_map_min,
pkt_dev->queue_map_max);
if (pkt_dev->flags & F_IPV6) { if (pkt_dev->flags & F_IPV6) {
char b1[128], b2[128], b3[128]; char b1[128], b2[128], b3[128];
fmt_ip6(b1, pkt_dev->in6_saddr.s6_addr); fmt_ip6(b1, pkt_dev->in6_saddr.s6_addr);
@ -709,6 +720,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
if (pkt_dev->flags & F_MPLS_RND) if (pkt_dev->flags & F_MPLS_RND)
seq_printf(seq, "MPLS_RND "); seq_printf(seq, "MPLS_RND ");
if (pkt_dev->flags & F_QUEUE_MAP_RND)
seq_printf(seq, "QUEUE_MAP_RND ");
if (pkt_dev->cflows) { if (pkt_dev->cflows) {
if (pkt_dev->flags & F_FLOW_SEQ) if (pkt_dev->flags & F_FLOW_SEQ)
seq_printf(seq, "FLOW_SEQ "); /*in sequence flows*/ seq_printf(seq, "FLOW_SEQ "); /*in sequence flows*/
@ -764,6 +778,8 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
seq_printf(seq, " cur_udp_dst: %d cur_udp_src: %d\n", seq_printf(seq, " cur_udp_dst: %d cur_udp_src: %d\n",
pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src); pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
seq_printf(seq, " cur_queue_map: %u\n", pkt_dev->cur_queue_map);
seq_printf(seq, " flows: %u\n", pkt_dev->nflows); seq_printf(seq, " flows: %u\n", pkt_dev->nflows);
if (pkt_dev->result[0]) if (pkt_dev->result[0])
@ -1215,6 +1231,11 @@ static ssize_t pktgen_if_write(struct file *file,
else if (strcmp(f, "FLOW_SEQ") == 0) else if (strcmp(f, "FLOW_SEQ") == 0)
pkt_dev->flags |= F_FLOW_SEQ; pkt_dev->flags |= F_FLOW_SEQ;
else if (strcmp(f, "QUEUE_MAP_RND") == 0)
pkt_dev->flags |= F_QUEUE_MAP_RND;
else if (strcmp(f, "!QUEUE_MAP_RND") == 0)
pkt_dev->flags &= ~F_QUEUE_MAP_RND;
#ifdef CONFIG_XFRM #ifdef CONFIG_XFRM
else if (strcmp(f, "IPSEC") == 0) else if (strcmp(f, "IPSEC") == 0)
pkt_dev->flags |= F_IPSEC_ON; pkt_dev->flags |= F_IPSEC_ON;
@ -1526,6 +1547,28 @@ static ssize_t pktgen_if_write(struct file *file,
return count; return count;
} }
if (!strcmp(name, "queue_map_min")) {
len = num_arg(&user_buffer[i], 5, &value);
if (len < 0) {
return len;
}
i += len;
pkt_dev->queue_map_min = value;
sprintf(pg_result, "OK: queue_map_min=%u", pkt_dev->queue_map_min);
return count;
}
if (!strcmp(name, "queue_map_max")) {
len = num_arg(&user_buffer[i], 5, &value);
if (len < 0) {
return len;
}
i += len;
pkt_dev->queue_map_max = value;
sprintf(pg_result, "OK: queue_map_max=%u", pkt_dev->queue_map_max);
return count;
}
if (!strcmp(name, "mpls")) { if (!strcmp(name, "mpls")) {
unsigned n, offset; unsigned n, offset;
len = get_labels(&user_buffer[i], pkt_dev); len = get_labels(&user_buffer[i], pkt_dev);
@ -2387,6 +2430,20 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
pkt_dev->cur_pkt_size = t; pkt_dev->cur_pkt_size = t;
} }
if (pkt_dev->queue_map_min < pkt_dev->queue_map_max) {
__u16 t;
if (pkt_dev->flags & F_QUEUE_MAP_RND) {
t = random32() %
(pkt_dev->queue_map_max - pkt_dev->queue_map_min + 1)
+ pkt_dev->queue_map_min;
} else {
t = pkt_dev->cur_queue_map + 1;
if (t > pkt_dev->queue_map_max)
t = pkt_dev->queue_map_min;
}
pkt_dev->cur_queue_map = t;
}
pkt_dev->flows[flow].count++; pkt_dev->flows[flow].count++;
} }
@ -2557,6 +2614,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
skb->network_header = skb->tail; skb->network_header = skb->tail;
skb->transport_header = skb->network_header + sizeof(struct iphdr); skb->transport_header = skb->network_header + sizeof(struct iphdr);
skb_put(skb, sizeof(struct iphdr) + sizeof(struct udphdr)); skb_put(skb, sizeof(struct iphdr) + sizeof(struct udphdr));
skb->queue_mapping = pkt_dev->cur_queue_map;
iph = ip_hdr(skb); iph = ip_hdr(skb);
udph = udp_hdr(skb); udph = udp_hdr(skb);
@ -2898,6 +2956,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
skb->network_header = skb->tail; skb->network_header = skb->tail;
skb->transport_header = skb->network_header + sizeof(struct ipv6hdr); skb->transport_header = skb->network_header + sizeof(struct ipv6hdr);
skb_put(skb, sizeof(struct ipv6hdr) + sizeof(struct udphdr)); skb_put(skb, sizeof(struct ipv6hdr) + sizeof(struct udphdr));
skb->queue_mapping = pkt_dev->cur_queue_map;
iph = ipv6_hdr(skb); iph = ipv6_hdr(skb);
udph = udp_hdr(skb); udph = udp_hdr(skb);