diff options
Diffstat (limited to 'net/core/pktgen.c')
-rw-r--r-- | net/core/pktgen.c | 83 |
1 files changed, 75 insertions, 8 deletions
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index c7d484f7e1c4..a756847e3814 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -168,7 +168,7 @@ | |||
168 | #include <asm/div64.h> /* do_div */ | 168 | #include <asm/div64.h> /* do_div */ |
169 | #include <asm/timex.h> | 169 | #include <asm/timex.h> |
170 | 170 | ||
171 | #define VERSION "pktgen v2.69: Packet Generator for packet performance testing.\n" | 171 | #define VERSION "pktgen v2.70: Packet Generator for packet performance testing.\n" |
172 | 172 | ||
173 | #define IP_NAME_SZ 32 | 173 | #define IP_NAME_SZ 32 |
174 | #define MAX_MPLS_LABELS 16 /* This is the max label stack depth */ | 174 | #define MAX_MPLS_LABELS 16 /* This is the max label stack depth */ |
@@ -189,6 +189,7 @@ | |||
189 | #define F_FLOW_SEQ (1<<11) /* Sequential flows */ | 189 | #define F_FLOW_SEQ (1<<11) /* Sequential flows */ |
190 | #define F_IPSEC_ON (1<<12) /* ipsec on for flows */ | 190 | #define F_IPSEC_ON (1<<12) /* ipsec on for flows */ |
191 | #define F_QUEUE_MAP_RND (1<<13) /* queue map Random */ | 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() */ | ||
192 | 193 | ||
193 | /* Thread control flag bits */ | 194 | /* Thread control flag bits */ |
194 | #define T_TERMINATE (1<<0) | 195 | #define T_TERMINATE (1<<0) |
@@ -621,6 +622,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v) | |||
621 | if (pkt_dev->flags & F_QUEUE_MAP_RND) | 622 | if (pkt_dev->flags & F_QUEUE_MAP_RND) |
622 | seq_printf(seq, "QUEUE_MAP_RND "); | 623 | seq_printf(seq, "QUEUE_MAP_RND "); |
623 | 624 | ||
625 | if (pkt_dev->flags & F_QUEUE_MAP_CPU) | ||
626 | seq_printf(seq, "QUEUE_MAP_CPU "); | ||
627 | |||
624 | if (pkt_dev->cflows) { | 628 | if (pkt_dev->cflows) { |
625 | if (pkt_dev->flags & F_FLOW_SEQ) | 629 | if (pkt_dev->flags & F_FLOW_SEQ) |
626 | seq_printf(seq, "FLOW_SEQ "); /*in sequence flows*/ | 630 | seq_printf(seq, "FLOW_SEQ "); /*in sequence flows*/ |
@@ -1134,6 +1138,12 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1134 | 1138 | ||
1135 | else if (strcmp(f, "!QUEUE_MAP_RND") == 0) | 1139 | else if (strcmp(f, "!QUEUE_MAP_RND") == 0) |
1136 | pkt_dev->flags &= ~F_QUEUE_MAP_RND; | 1140 | pkt_dev->flags &= ~F_QUEUE_MAP_RND; |
1141 | |||
1142 | else if (strcmp(f, "QUEUE_MAP_CPU") == 0) | ||
1143 | pkt_dev->flags |= F_QUEUE_MAP_CPU; | ||
1144 | |||
1145 | else if (strcmp(f, "!QUEUE_MAP_CPU") == 0) | ||
1146 | pkt_dev->flags &= ~F_QUEUE_MAP_CPU; | ||
1137 | #ifdef CONFIG_XFRM | 1147 | #ifdef CONFIG_XFRM |
1138 | else if (strcmp(f, "IPSEC") == 0) | 1148 | else if (strcmp(f, "IPSEC") == 0) |
1139 | pkt_dev->flags |= F_IPSEC_ON; | 1149 | pkt_dev->flags |= F_IPSEC_ON; |
@@ -1895,6 +1905,23 @@ static int pktgen_device_event(struct notifier_block *unused, | |||
1895 | return NOTIFY_DONE; | 1905 | return NOTIFY_DONE; |
1896 | } | 1906 | } |
1897 | 1907 | ||
1908 | static struct net_device *pktgen_dev_get_by_name(struct pktgen_dev *pkt_dev, const char *ifname) | ||
1909 | { | ||
1910 | char b[IFNAMSIZ+5]; | ||
1911 | int i = 0; | ||
1912 | |||
1913 | for(i=0; ifname[i] != '@'; i++) { | ||
1914 | if(i == IFNAMSIZ) | ||
1915 | break; | ||
1916 | |||
1917 | b[i] = ifname[i]; | ||
1918 | } | ||
1919 | b[i] = 0; | ||
1920 | |||
1921 | return dev_get_by_name(&init_net, b); | ||
1922 | } | ||
1923 | |||
1924 | |||
1898 | /* Associate pktgen_dev with a device. */ | 1925 | /* Associate pktgen_dev with a device. */ |
1899 | 1926 | ||
1900 | static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname) | 1927 | static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname) |
@@ -1908,7 +1935,7 @@ static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname) | |||
1908 | pkt_dev->odev = NULL; | 1935 | pkt_dev->odev = NULL; |
1909 | } | 1936 | } |
1910 | 1937 | ||
1911 | odev = dev_get_by_name(&init_net, ifname); | 1938 | odev = pktgen_dev_get_by_name(pkt_dev, ifname); |
1912 | if (!odev) { | 1939 | if (!odev) { |
1913 | printk(KERN_ERR "pktgen: no such netdevice: \"%s\"\n", ifname); | 1940 | printk(KERN_ERR "pktgen: no such netdevice: \"%s\"\n", ifname); |
1914 | return -ENODEV; | 1941 | return -ENODEV; |
@@ -1934,6 +1961,8 @@ static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname) | |||
1934 | */ | 1961 | */ |
1935 | static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) | 1962 | static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) |
1936 | { | 1963 | { |
1964 | int ntxq; | ||
1965 | |||
1937 | if (!pkt_dev->odev) { | 1966 | if (!pkt_dev->odev) { |
1938 | printk(KERN_ERR "pktgen: ERROR: pkt_dev->odev == NULL in " | 1967 | printk(KERN_ERR "pktgen: ERROR: pkt_dev->odev == NULL in " |
1939 | "setup_inject.\n"); | 1968 | "setup_inject.\n"); |
@@ -1942,6 +1971,33 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) | |||
1942 | return; | 1971 | return; |
1943 | } | 1972 | } |
1944 | 1973 | ||
1974 | /* make sure that we don't pick a non-existing transmit queue */ | ||
1975 | ntxq = pkt_dev->odev->real_num_tx_queues; | ||
1976 | if (ntxq <= num_online_cpus() && (pkt_dev->flags & F_QUEUE_MAP_CPU)) { | ||
1977 | printk(KERN_WARNING "pktgen: WARNING: QUEUE_MAP_CPU " | ||
1978 | "disabled because CPU count (%d) exceeds number ", | ||
1979 | num_online_cpus()); | ||
1980 | printk(KERN_WARNING "pktgen: WARNING: of tx queues " | ||
1981 | "(%d) on %s \n", ntxq, pkt_dev->odev->name); | ||
1982 | pkt_dev->flags &= ~F_QUEUE_MAP_CPU; | ||
1983 | } | ||
1984 | if (ntxq <= pkt_dev->queue_map_min) { | ||
1985 | printk(KERN_WARNING "pktgen: WARNING: Requested " | ||
1986 | "queue_map_min (%d) exceeds number of tx\n", | ||
1987 | pkt_dev->queue_map_min); | ||
1988 | printk(KERN_WARNING "pktgen: WARNING: queues (%d) on " | ||
1989 | "%s, resetting\n", ntxq, pkt_dev->odev->name); | ||
1990 | pkt_dev->queue_map_min = ntxq - 1; | ||
1991 | } | ||
1992 | if (ntxq <= pkt_dev->queue_map_max) { | ||
1993 | printk(KERN_WARNING "pktgen: WARNING: Requested " | ||
1994 | "queue_map_max (%d) exceeds number of tx\n", | ||
1995 | pkt_dev->queue_map_max); | ||
1996 | printk(KERN_WARNING "pktgen: WARNING: queues (%d) on " | ||
1997 | "%s, resetting\n", ntxq, pkt_dev->odev->name); | ||
1998 | pkt_dev->queue_map_max = ntxq - 1; | ||
1999 | } | ||
2000 | |||
1945 | /* Default to the interface's mac if not explicitly set. */ | 2001 | /* Default to the interface's mac if not explicitly set. */ |
1946 | 2002 | ||
1947 | if (is_zero_ether_addr(pkt_dev->src_mac)) | 2003 | if (is_zero_ether_addr(pkt_dev->src_mac)) |
@@ -2085,15 +2141,19 @@ static inline int f_pick(struct pktgen_dev *pkt_dev) | |||
2085 | if (pkt_dev->flows[flow].count >= pkt_dev->lflow) { | 2141 | if (pkt_dev->flows[flow].count >= pkt_dev->lflow) { |
2086 | /* reset time */ | 2142 | /* reset time */ |
2087 | pkt_dev->flows[flow].count = 0; | 2143 | pkt_dev->flows[flow].count = 0; |
2144 | pkt_dev->flows[flow].flags = 0; | ||
2088 | pkt_dev->curfl += 1; | 2145 | pkt_dev->curfl += 1; |
2089 | if (pkt_dev->curfl >= pkt_dev->cflows) | 2146 | if (pkt_dev->curfl >= pkt_dev->cflows) |
2090 | pkt_dev->curfl = 0; /*reset */ | 2147 | pkt_dev->curfl = 0; /*reset */ |
2091 | } | 2148 | } |
2092 | } else { | 2149 | } else { |
2093 | flow = random32() % pkt_dev->cflows; | 2150 | flow = random32() % pkt_dev->cflows; |
2151 | pkt_dev->curfl = flow; | ||
2094 | 2152 | ||
2095 | if (pkt_dev->flows[flow].count > pkt_dev->lflow) | 2153 | if (pkt_dev->flows[flow].count > pkt_dev->lflow) { |
2096 | pkt_dev->flows[flow].count = 0; | 2154 | pkt_dev->flows[flow].count = 0; |
2155 | pkt_dev->flows[flow].flags = 0; | ||
2156 | } | ||
2097 | } | 2157 | } |
2098 | 2158 | ||
2099 | return pkt_dev->curfl; | 2159 | return pkt_dev->curfl; |
@@ -2125,7 +2185,11 @@ static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow) | |||
2125 | #endif | 2185 | #endif |
2126 | static void set_cur_queue_map(struct pktgen_dev *pkt_dev) | 2186 | static void set_cur_queue_map(struct pktgen_dev *pkt_dev) |
2127 | { | 2187 | { |
2128 | if (pkt_dev->queue_map_min < pkt_dev->queue_map_max) { | 2188 | |
2189 | if (pkt_dev->flags & F_QUEUE_MAP_CPU) | ||
2190 | pkt_dev->cur_queue_map = smp_processor_id(); | ||
2191 | |||
2192 | else if (pkt_dev->queue_map_min < pkt_dev->queue_map_max) { | ||
2129 | __u16 t; | 2193 | __u16 t; |
2130 | if (pkt_dev->flags & F_QUEUE_MAP_RND) { | 2194 | if (pkt_dev->flags & F_QUEUE_MAP_RND) { |
2131 | t = random32() % | 2195 | t = random32() % |
@@ -2162,7 +2226,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) | |||
2162 | mc = random32() % pkt_dev->src_mac_count; | 2226 | mc = random32() % pkt_dev->src_mac_count; |
2163 | else { | 2227 | else { |
2164 | mc = pkt_dev->cur_src_mac_offset++; | 2228 | mc = pkt_dev->cur_src_mac_offset++; |
2165 | if (pkt_dev->cur_src_mac_offset > | 2229 | if (pkt_dev->cur_src_mac_offset >= |
2166 | pkt_dev->src_mac_count) | 2230 | pkt_dev->src_mac_count) |
2167 | pkt_dev->cur_src_mac_offset = 0; | 2231 | pkt_dev->cur_src_mac_offset = 0; |
2168 | } | 2232 | } |
@@ -2189,7 +2253,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) | |||
2189 | 2253 | ||
2190 | else { | 2254 | else { |
2191 | mc = pkt_dev->cur_dst_mac_offset++; | 2255 | mc = pkt_dev->cur_dst_mac_offset++; |
2192 | if (pkt_dev->cur_dst_mac_offset > | 2256 | if (pkt_dev->cur_dst_mac_offset >= |
2193 | pkt_dev->dst_mac_count) { | 2257 | pkt_dev->dst_mac_count) { |
2194 | pkt_dev->cur_dst_mac_offset = 0; | 2258 | pkt_dev->cur_dst_mac_offset = 0; |
2195 | } | 2259 | } |
@@ -3305,6 +3369,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
3305 | 3369 | ||
3306 | txq = netdev_get_tx_queue(odev, queue_map); | 3370 | txq = netdev_get_tx_queue(odev, queue_map); |
3307 | if (netif_tx_queue_stopped(txq) || | 3371 | if (netif_tx_queue_stopped(txq) || |
3372 | netif_tx_queue_frozen(txq) || | ||
3308 | need_resched()) { | 3373 | need_resched()) { |
3309 | idle_start = getCurUs(); | 3374 | idle_start = getCurUs(); |
3310 | 3375 | ||
@@ -3320,7 +3385,8 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
3320 | 3385 | ||
3321 | pkt_dev->idle_acc += getCurUs() - idle_start; | 3386 | pkt_dev->idle_acc += getCurUs() - idle_start; |
3322 | 3387 | ||
3323 | if (netif_tx_queue_stopped(txq)) { | 3388 | if (netif_tx_queue_stopped(txq) || |
3389 | netif_tx_queue_frozen(txq)) { | ||
3324 | pkt_dev->next_tx_us = getCurUs(); /* TODO */ | 3390 | pkt_dev->next_tx_us = getCurUs(); /* TODO */ |
3325 | pkt_dev->next_tx_ns = 0; | 3391 | pkt_dev->next_tx_ns = 0; |
3326 | goto out; /* Try the next interface */ | 3392 | goto out; /* Try the next interface */ |
@@ -3352,7 +3418,8 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
3352 | txq = netdev_get_tx_queue(odev, queue_map); | 3418 | txq = netdev_get_tx_queue(odev, queue_map); |
3353 | 3419 | ||
3354 | __netif_tx_lock_bh(txq); | 3420 | __netif_tx_lock_bh(txq); |
3355 | if (!netif_tx_queue_stopped(txq)) { | 3421 | if (!netif_tx_queue_stopped(txq) && |
3422 | !netif_tx_queue_frozen(txq)) { | ||
3356 | 3423 | ||
3357 | atomic_inc(&(pkt_dev->skb->users)); | 3424 | atomic_inc(&(pkt_dev->skb->users)); |
3358 | retry_now: | 3425 | retry_now: |