pktgen: multiqueue etc.

Sofar far pktgen have had a restriction to only use one device per kernel
thread. With the new multiqueue architecture this is no longer adequate.

The patch below is an effort to remove this by in pktgen configuration
adding a tag to the device name a la eth0@0 etc. The tag is used for
usual device config just as before. Also a new flag is introduced to mirror
queue_map with sending threads smp_processor_id() QUEUE_MAP_CPU.

An example: We use 4 CPU's to send to one 10g interface (eth0)
and we use the new tagging to send a mix of packet sizes, 64, 576 and
1500 bytes. Also we use TX queues according to smp_processor_id()

PGDEV=/proc/net/pktgen/kpktgend_0
pgset "add_device eth0@0"

PGDEV=/proc/net/pktgen/kpktgend_1
pgset "add_device eth0@1"

PGDEV=/proc/net/pktgen/kpktgend_2
pgset "add_device eth0@2"

PGDEV=/proc/net/pktgen/kpktgend_3
pgset "add_device eth0@3"
....
PGDEV=/proc/net/pktgen/eth0@0
pgset "pkt_size 64"
pgset "flag QUEUE_MAP_CPU"

PGDEV=/proc/net/pktgen/eth0@1
pgset "pkt_size 572"
pgset "flag QUEUE_MAP_CPU"

PGDEV=/proc/net/pktgen/eth0@2
pgset "pkt_size 1496"

PGDEV=/proc/net/pktgen/eth0@3
pgset "pkt_size 1496"
pgset "flag QUEUE_MAP_CPU"

Signed-off-by: Robert Olsson <robert.olsson@its.uu.se>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Robert Olsson and committed by David S. Miller e6fce5b9 32bb93b0

+34 -3
+34 -3
net/core/pktgen.c
··· 168 #include <asm/div64.h> /* do_div */ 169 #include <asm/timex.h> 170 171 - #define VERSION "pktgen v2.69: Packet Generator for packet performance testing.\n" 172 173 #define IP_NAME_SZ 32 174 #define MAX_MPLS_LABELS 16 /* This is the max label stack depth */ ··· 189 #define F_FLOW_SEQ (1<<11) /* Sequential flows */ 190 #define F_IPSEC_ON (1<<12) /* ipsec on for flows */ 191 #define F_QUEUE_MAP_RND (1<<13) /* queue map Random */ 192 193 /* Thread control flag bits */ 194 #define T_TERMINATE (1<<0) ··· 621 622 if (pkt_dev->flags & F_QUEUE_MAP_RND) 623 seq_printf(seq, "QUEUE_MAP_RND "); 624 625 if (pkt_dev->cflows) { 626 if (pkt_dev->flags & F_FLOW_SEQ) ··· 1138 1139 else if (strcmp(f, "!QUEUE_MAP_RND") == 0) 1140 pkt_dev->flags &= ~F_QUEUE_MAP_RND; 1141 #ifdef CONFIG_XFRM 1142 else if (strcmp(f, "IPSEC") == 0) 1143 pkt_dev->flags |= F_IPSEC_ON; ··· 1905 return NOTIFY_DONE; 1906 } 1907 1908 /* Associate pktgen_dev with a device. */ 1909 1910 static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname) ··· 1935 pkt_dev->odev = NULL; 1936 } 1937 1938 - odev = dev_get_by_name(&init_net, ifname); 1939 if (!odev) { 1940 printk(KERN_ERR "pktgen: no such netdevice: \"%s\"\n", ifname); 1941 return -ENODEV; ··· 2156 #endif 2157 static void set_cur_queue_map(struct pktgen_dev *pkt_dev) 2158 { 2159 - if (pkt_dev->queue_map_min < pkt_dev->queue_map_max) { 2160 __u16 t; 2161 if (pkt_dev->flags & F_QUEUE_MAP_RND) { 2162 t = random32() %
··· 168 #include <asm/div64.h> /* do_div */ 169 #include <asm/timex.h> 170 171 + #define VERSION "pktgen v2.70: Packet Generator for packet performance testing.\n" 172 173 #define IP_NAME_SZ 32 174 #define MAX_MPLS_LABELS 16 /* This is the max label stack depth */ ··· 189 #define F_FLOW_SEQ (1<<11) /* Sequential flows */ 190 #define F_IPSEC_ON (1<<12) /* ipsec on for flows */ 191 #define F_QUEUE_MAP_RND (1<<13) /* queue map Random */ 192 + #define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */ 193 194 /* Thread control flag bits */ 195 #define T_TERMINATE (1<<0) ··· 620 621 if (pkt_dev->flags & F_QUEUE_MAP_RND) 622 seq_printf(seq, "QUEUE_MAP_RND "); 623 + 624 + if (pkt_dev->flags & F_QUEUE_MAP_CPU) 625 + seq_printf(seq, "QUEUE_MAP_CPU "); 626 627 if (pkt_dev->cflows) { 628 if (pkt_dev->flags & F_FLOW_SEQ) ··· 1134 1135 else if (strcmp(f, "!QUEUE_MAP_RND") == 0) 1136 pkt_dev->flags &= ~F_QUEUE_MAP_RND; 1137 + 1138 + else if (strcmp(f, "QUEUE_MAP_CPU") == 0) 1139 + pkt_dev->flags |= F_QUEUE_MAP_CPU; 1140 + 1141 + else if (strcmp(f, "!QUEUE_MAP_CPU") == 0) 1142 + pkt_dev->flags &= ~F_QUEUE_MAP_CPU; 1143 #ifdef CONFIG_XFRM 1144 else if (strcmp(f, "IPSEC") == 0) 1145 pkt_dev->flags |= F_IPSEC_ON; ··· 1895 return NOTIFY_DONE; 1896 } 1897 1898 + static struct net_device *pktgen_dev_get_by_name(struct pktgen_dev *pkt_dev, const char *ifname) 1899 + { 1900 + char b[IFNAMSIZ+5]; 1901 + int i = 0; 1902 + 1903 + for(i=0; ifname[i] != '@'; i++) { 1904 + if(i == IFNAMSIZ) 1905 + break; 1906 + 1907 + b[i] = ifname[i]; 1908 + } 1909 + b[i] = 0; 1910 + 1911 + return dev_get_by_name(&init_net, b); 1912 + } 1913 + 1914 + 1915 /* Associate pktgen_dev with a device. */ 1916 1917 static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname) ··· 1908 pkt_dev->odev = NULL; 1909 } 1910 1911 + odev = pktgen_dev_get_by_name(pkt_dev, ifname); 1912 if (!odev) { 1913 printk(KERN_ERR "pktgen: no such netdevice: \"%s\"\n", ifname); 1914 return -ENODEV; ··· 2129 #endif 2130 static void set_cur_queue_map(struct pktgen_dev *pkt_dev) 2131 { 2132 + 2133 + if (pkt_dev->flags & F_QUEUE_MAP_CPU) 2134 + pkt_dev->cur_queue_map = smp_processor_id(); 2135 + 2136 + else if (pkt_dev->queue_map_min < pkt_dev->queue_map_max) { 2137 __u16 t; 2138 if (pkt_dev->flags & F_QUEUE_MAP_RND) { 2139 t = random32() %