diff options
author | John Fastabend <john.fastabend@gmail.com> | 2016-07-02 17:12:54 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-07-04 19:07:34 -0400 |
commit | 0967f2445963b63269d7dd2f5b6f234ea57dd10e (patch) | |
tree | aa18225468533de8f2a4d32cb3de17d6245dc7f8 /net/core | |
parent | 4386f5662e639553552408c33014ca3e8d612b14 (diff) |
net: pktgen: support injecting packets for qdisc testing
Add another xmit_mode to pktgen to allow testing xmit functionality
of qdiscs. The new mode "queue_xmit" injects packets at
__dev_queue_xmit() so that qdisc is called.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/pktgen.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index f74ab9c3b38f..bbd118b19aef 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -213,6 +213,7 @@ | |||
213 | /* Xmit modes */ | 213 | /* Xmit modes */ |
214 | #define M_START_XMIT 0 /* Default normal TX */ | 214 | #define M_START_XMIT 0 /* Default normal TX */ |
215 | #define M_NETIF_RECEIVE 1 /* Inject packets into stack */ | 215 | #define M_NETIF_RECEIVE 1 /* Inject packets into stack */ |
216 | #define M_QUEUE_XMIT 2 /* Inject packet into qdisc */ | ||
216 | 217 | ||
217 | /* If lock -- protects updating of if_list */ | 218 | /* If lock -- protects updating of if_list */ |
218 | #define if_lock(t) spin_lock(&(t->if_lock)); | 219 | #define if_lock(t) spin_lock(&(t->if_lock)); |
@@ -626,6 +627,8 @@ static int pktgen_if_show(struct seq_file *seq, void *v) | |||
626 | 627 | ||
627 | if (pkt_dev->xmit_mode == M_NETIF_RECEIVE) | 628 | if (pkt_dev->xmit_mode == M_NETIF_RECEIVE) |
628 | seq_puts(seq, " xmit_mode: netif_receive\n"); | 629 | seq_puts(seq, " xmit_mode: netif_receive\n"); |
630 | else if (pkt_dev->xmit_mode == M_QUEUE_XMIT) | ||
631 | seq_puts(seq, " xmit_mode: xmit_queue\n"); | ||
629 | 632 | ||
630 | seq_puts(seq, " Flags: "); | 633 | seq_puts(seq, " Flags: "); |
631 | 634 | ||
@@ -1142,8 +1145,10 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1142 | return len; | 1145 | return len; |
1143 | 1146 | ||
1144 | i += len; | 1147 | i += len; |
1145 | if ((value > 1) && (pkt_dev->xmit_mode == M_START_XMIT) && | 1148 | if ((value > 1) && |
1146 | (!(pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING))) | 1149 | ((pkt_dev->xmit_mode == M_QUEUE_XMIT) || |
1150 | ((pkt_dev->xmit_mode == M_START_XMIT) && | ||
1151 | (!(pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING))))) | ||
1147 | return -ENOTSUPP; | 1152 | return -ENOTSUPP; |
1148 | pkt_dev->burst = value < 1 ? 1 : value; | 1153 | pkt_dev->burst = value < 1 ? 1 : value; |
1149 | sprintf(pg_result, "OK: burst=%d", pkt_dev->burst); | 1154 | sprintf(pg_result, "OK: burst=%d", pkt_dev->burst); |
@@ -1198,6 +1203,9 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1198 | * at module loading time | 1203 | * at module loading time |
1199 | */ | 1204 | */ |
1200 | pkt_dev->clone_skb = 0; | 1205 | pkt_dev->clone_skb = 0; |
1206 | } else if (strcmp(f, "queue_xmit") == 0) { | ||
1207 | pkt_dev->xmit_mode = M_QUEUE_XMIT; | ||
1208 | pkt_dev->last_ok = 1; | ||
1201 | } else { | 1209 | } else { |
1202 | sprintf(pg_result, | 1210 | sprintf(pg_result, |
1203 | "xmit_mode -:%s:- unknown\nAvailable modes: %s", | 1211 | "xmit_mode -:%s:- unknown\nAvailable modes: %s", |
@@ -3434,6 +3442,36 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
3434 | #endif | 3442 | #endif |
3435 | } while (--burst > 0); | 3443 | } while (--burst > 0); |
3436 | goto out; /* Skips xmit_mode M_START_XMIT */ | 3444 | goto out; /* Skips xmit_mode M_START_XMIT */ |
3445 | } else if (pkt_dev->xmit_mode == M_QUEUE_XMIT) { | ||
3446 | local_bh_disable(); | ||
3447 | atomic_inc(&pkt_dev->skb->users); | ||
3448 | |||
3449 | ret = dev_queue_xmit(pkt_dev->skb); | ||
3450 | switch (ret) { | ||
3451 | case NET_XMIT_SUCCESS: | ||
3452 | pkt_dev->sofar++; | ||
3453 | pkt_dev->seq_num++; | ||
3454 | pkt_dev->tx_bytes += pkt_dev->last_pkt_size; | ||
3455 | break; | ||
3456 | case NET_XMIT_DROP: | ||
3457 | case NET_XMIT_CN: | ||
3458 | /* These are all valid return codes for a qdisc but | ||
3459 | * indicate packets are being dropped or will likely | ||
3460 | * be dropped soon. | ||
3461 | */ | ||
3462 | case NETDEV_TX_BUSY: | ||
3463 | /* qdisc may call dev_hard_start_xmit directly in cases | ||
3464 | * where no queues exist e.g. loopback device, virtual | ||
3465 | * devices, etc. In this case we need to handle | ||
3466 | * NETDEV_TX_ codes. | ||
3467 | */ | ||
3468 | default: | ||
3469 | pkt_dev->errors++; | ||
3470 | net_info_ratelimited("%s xmit error: %d\n", | ||
3471 | pkt_dev->odevname, ret); | ||
3472 | break; | ||
3473 | } | ||
3474 | goto out; | ||
3437 | } | 3475 | } |
3438 | 3476 | ||
3439 | txq = skb_get_tx_queue(odev, pkt_dev->skb); | 3477 | txq = skb_get_tx_queue(odev, pkt_dev->skb); |