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>
This commit is contained in:
Родитель
4386f5662e
Коммит
0967f24459
|
@ -213,6 +213,7 @@
|
||||||
/* Xmit modes */
|
/* Xmit modes */
|
||||||
#define M_START_XMIT 0 /* Default normal TX */
|
#define M_START_XMIT 0 /* Default normal TX */
|
||||||
#define M_NETIF_RECEIVE 1 /* Inject packets into stack */
|
#define M_NETIF_RECEIVE 1 /* Inject packets into stack */
|
||||||
|
#define M_QUEUE_XMIT 2 /* Inject packet into qdisc */
|
||||||
|
|
||||||
/* If lock -- protects updating of if_list */
|
/* If lock -- protects updating of if_list */
|
||||||
#define if_lock(t) spin_lock(&(t->if_lock));
|
#define if_lock(t) spin_lock(&(t->if_lock));
|
||||||
|
@ -626,6 +627,8 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
|
||||||
|
|
||||||
if (pkt_dev->xmit_mode == M_NETIF_RECEIVE)
|
if (pkt_dev->xmit_mode == M_NETIF_RECEIVE)
|
||||||
seq_puts(seq, " xmit_mode: netif_receive\n");
|
seq_puts(seq, " xmit_mode: netif_receive\n");
|
||||||
|
else if (pkt_dev->xmit_mode == M_QUEUE_XMIT)
|
||||||
|
seq_puts(seq, " xmit_mode: xmit_queue\n");
|
||||||
|
|
||||||
seq_puts(seq, " Flags: ");
|
seq_puts(seq, " Flags: ");
|
||||||
|
|
||||||
|
@ -1142,8 +1145,10 @@ static ssize_t pktgen_if_write(struct file *file,
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
i += len;
|
i += len;
|
||||||
if ((value > 1) && (pkt_dev->xmit_mode == M_START_XMIT) &&
|
if ((value > 1) &&
|
||||||
(!(pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING)))
|
((pkt_dev->xmit_mode == M_QUEUE_XMIT) ||
|
||||||
|
((pkt_dev->xmit_mode == M_START_XMIT) &&
|
||||||
|
(!(pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING)))))
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
pkt_dev->burst = value < 1 ? 1 : value;
|
pkt_dev->burst = value < 1 ? 1 : value;
|
||||||
sprintf(pg_result, "OK: burst=%d", pkt_dev->burst);
|
sprintf(pg_result, "OK: burst=%d", pkt_dev->burst);
|
||||||
|
@ -1198,6 +1203,9 @@ static ssize_t pktgen_if_write(struct file *file,
|
||||||
* at module loading time
|
* at module loading time
|
||||||
*/
|
*/
|
||||||
pkt_dev->clone_skb = 0;
|
pkt_dev->clone_skb = 0;
|
||||||
|
} else if (strcmp(f, "queue_xmit") == 0) {
|
||||||
|
pkt_dev->xmit_mode = M_QUEUE_XMIT;
|
||||||
|
pkt_dev->last_ok = 1;
|
||||||
} else {
|
} else {
|
||||||
sprintf(pg_result,
|
sprintf(pg_result,
|
||||||
"xmit_mode -:%s:- unknown\nAvailable modes: %s",
|
"xmit_mode -:%s:- unknown\nAvailable modes: %s",
|
||||||
|
@ -3434,6 +3442,36 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
|
||||||
#endif
|
#endif
|
||||||
} while (--burst > 0);
|
} while (--burst > 0);
|
||||||
goto out; /* Skips xmit_mode M_START_XMIT */
|
goto out; /* Skips xmit_mode M_START_XMIT */
|
||||||
|
} else if (pkt_dev->xmit_mode == M_QUEUE_XMIT) {
|
||||||
|
local_bh_disable();
|
||||||
|
atomic_inc(&pkt_dev->skb->users);
|
||||||
|
|
||||||
|
ret = dev_queue_xmit(pkt_dev->skb);
|
||||||
|
switch (ret) {
|
||||||
|
case NET_XMIT_SUCCESS:
|
||||||
|
pkt_dev->sofar++;
|
||||||
|
pkt_dev->seq_num++;
|
||||||
|
pkt_dev->tx_bytes += pkt_dev->last_pkt_size;
|
||||||
|
break;
|
||||||
|
case NET_XMIT_DROP:
|
||||||
|
case NET_XMIT_CN:
|
||||||
|
/* These are all valid return codes for a qdisc but
|
||||||
|
* indicate packets are being dropped or will likely
|
||||||
|
* be dropped soon.
|
||||||
|
*/
|
||||||
|
case NETDEV_TX_BUSY:
|
||||||
|
/* qdisc may call dev_hard_start_xmit directly in cases
|
||||||
|
* where no queues exist e.g. loopback device, virtual
|
||||||
|
* devices, etc. In this case we need to handle
|
||||||
|
* NETDEV_TX_ codes.
|
||||||
|
*/
|
||||||
|
default:
|
||||||
|
pkt_dev->errors++;
|
||||||
|
net_info_ratelimited("%s xmit error: %d\n",
|
||||||
|
pkt_dev->odevname, ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
txq = skb_get_tx_queue(odev, pkt_dev->skb);
|
txq = skb_get_tx_queue(odev, pkt_dev->skb);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче