app/testpmd: add qinq stripping and insertion
If double vlan is detected, its stripped flag and vlan tags can be printed on rxonly mode. Test command of 'tx_vlan set' is expanded to set both single and double vlan tags on TX side for each packets to be sent out. Signed-off-by: Helin Zhang <helin.zhang@intel.com> Acked-by: Jingjing Wu <jingjing.wu@intel.com>
This commit is contained in:
parent
4fa5e9f59b
commit
92ebda07ee
@ -304,9 +304,9 @@ static void cmd_help_long_parsed(void *parsed_result,
|
||||
"rx_vxlan_port rm (udp_port) (port_id)\n"
|
||||
" Remove an UDP port for VXLAN packet filter on a port\n\n"
|
||||
|
||||
"tx_vlan set vlan_id (port_id)\n"
|
||||
" Set hardware insertion of VLAN ID in packets sent"
|
||||
" on a port.\n\n"
|
||||
"tx_vlan set (port_id) vlan_id[, vlan_id_outer]\n"
|
||||
" Set hardware insertion of VLAN IDs (single or double VLAN "
|
||||
"depends on the number of VLAN IDs) in packets sent on a port.\n\n"
|
||||
|
||||
"tx_vlan set pvid port_id vlan_id (on|off)\n"
|
||||
" Set port based TX VLAN insertion.\n\n"
|
||||
@ -2799,8 +2799,8 @@ cmdline_parse_inst_t cmd_rx_vlan_filter = {
|
||||
struct cmd_tx_vlan_set_result {
|
||||
cmdline_fixed_string_t tx_vlan;
|
||||
cmdline_fixed_string_t set;
|
||||
uint16_t vlan_id;
|
||||
uint8_t port_id;
|
||||
uint16_t vlan_id;
|
||||
};
|
||||
|
||||
static void
|
||||
@ -2809,6 +2809,13 @@ cmd_tx_vlan_set_parsed(void *parsed_result,
|
||||
__attribute__((unused)) void *data)
|
||||
{
|
||||
struct cmd_tx_vlan_set_result *res = parsed_result;
|
||||
int vlan_offload = rte_eth_dev_get_vlan_offload(res->port_id);
|
||||
|
||||
if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD) {
|
||||
printf("Error, as QinQ has been enabled.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
tx_vlan_set(res->port_id, res->vlan_id);
|
||||
}
|
||||
|
||||
@ -2828,13 +2835,69 @@ cmdline_parse_token_num_t cmd_tx_vlan_set_portid =
|
||||
cmdline_parse_inst_t cmd_tx_vlan_set = {
|
||||
.f = cmd_tx_vlan_set_parsed,
|
||||
.data = NULL,
|
||||
.help_str = "enable hardware insertion of a VLAN header with a given "
|
||||
"TAG Identifier in packets sent on a port",
|
||||
.help_str = "enable hardware insertion of a single VLAN header "
|
||||
"with a given TAG Identifier in packets sent on a port",
|
||||
.tokens = {
|
||||
(void *)&cmd_tx_vlan_set_tx_vlan,
|
||||
(void *)&cmd_tx_vlan_set_set,
|
||||
(void *)&cmd_tx_vlan_set_vlanid,
|
||||
(void *)&cmd_tx_vlan_set_portid,
|
||||
(void *)&cmd_tx_vlan_set_vlanid,
|
||||
NULL,
|
||||
},
|
||||
};
|
||||
|
||||
/* *** ENABLE HARDWARE INSERTION OF Double VLAN HEADER IN TX PACKETS *** */
|
||||
struct cmd_tx_vlan_set_qinq_result {
|
||||
cmdline_fixed_string_t tx_vlan;
|
||||
cmdline_fixed_string_t set;
|
||||
uint8_t port_id;
|
||||
uint16_t vlan_id;
|
||||
uint16_t vlan_id_outer;
|
||||
};
|
||||
|
||||
static void
|
||||
cmd_tx_vlan_set_qinq_parsed(void *parsed_result,
|
||||
__attribute__((unused)) struct cmdline *cl,
|
||||
__attribute__((unused)) void *data)
|
||||
{
|
||||
struct cmd_tx_vlan_set_qinq_result *res = parsed_result;
|
||||
int vlan_offload = rte_eth_dev_get_vlan_offload(res->port_id);
|
||||
|
||||
if (!(vlan_offload & ETH_VLAN_EXTEND_OFFLOAD)) {
|
||||
printf("Error, as QinQ hasn't been enabled.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
tx_qinq_set(res->port_id, res->vlan_id, res->vlan_id_outer);
|
||||
}
|
||||
|
||||
cmdline_parse_token_string_t cmd_tx_vlan_set_qinq_tx_vlan =
|
||||
TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
|
||||
tx_vlan, "tx_vlan");
|
||||
cmdline_parse_token_string_t cmd_tx_vlan_set_qinq_set =
|
||||
TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
|
||||
set, "set");
|
||||
cmdline_parse_token_num_t cmd_tx_vlan_set_qinq_portid =
|
||||
TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
|
||||
port_id, UINT8);
|
||||
cmdline_parse_token_num_t cmd_tx_vlan_set_qinq_vlanid =
|
||||
TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
|
||||
vlan_id, UINT16);
|
||||
cmdline_parse_token_num_t cmd_tx_vlan_set_qinq_vlanid_outer =
|
||||
TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
|
||||
vlan_id_outer, UINT16);
|
||||
|
||||
cmdline_parse_inst_t cmd_tx_vlan_set_qinq = {
|
||||
.f = cmd_tx_vlan_set_qinq_parsed,
|
||||
.data = NULL,
|
||||
.help_str = "enable hardware insertion of double VLAN header "
|
||||
"with given TAG Identifiers in packets sent on a port",
|
||||
.tokens = {
|
||||
(void *)&cmd_tx_vlan_set_qinq_tx_vlan,
|
||||
(void *)&cmd_tx_vlan_set_qinq_set,
|
||||
(void *)&cmd_tx_vlan_set_qinq_portid,
|
||||
(void *)&cmd_tx_vlan_set_qinq_vlanid,
|
||||
(void *)&cmd_tx_vlan_set_qinq_vlanid_outer,
|
||||
NULL,
|
||||
},
|
||||
};
|
||||
@ -8834,6 +8897,7 @@ cmdline_parse_ctx_t main_ctx[] = {
|
||||
(cmdline_parse_inst_t *)&cmd_rx_vlan_filter_all,
|
||||
(cmdline_parse_inst_t *)&cmd_rx_vlan_filter,
|
||||
(cmdline_parse_inst_t *)&cmd_tx_vlan_set,
|
||||
(cmdline_parse_inst_t *)&cmd_tx_vlan_set_qinq,
|
||||
(cmdline_parse_inst_t *)&cmd_tx_vlan_reset,
|
||||
(cmdline_parse_inst_t *)&cmd_tx_vlan_set_pvid,
|
||||
(cmdline_parse_inst_t *)&cmd_csum_set,
|
||||
|
@ -1732,16 +1732,35 @@ tx_vlan_set(portid_t port_id, uint16_t vlan_id)
|
||||
return;
|
||||
if (vlan_id_is_invalid(vlan_id))
|
||||
return;
|
||||
tx_vlan_reset(port_id);
|
||||
ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_INSERT_VLAN;
|
||||
ports[port_id].tx_vlan_id = vlan_id;
|
||||
}
|
||||
|
||||
void
|
||||
tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer)
|
||||
{
|
||||
if (port_id_is_invalid(port_id, ENABLED_WARN))
|
||||
return;
|
||||
if (vlan_id_is_invalid(vlan_id))
|
||||
return;
|
||||
if (vlan_id_is_invalid(vlan_id_outer))
|
||||
return;
|
||||
tx_vlan_reset(port_id);
|
||||
ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_INSERT_QINQ;
|
||||
ports[port_id].tx_vlan_id = vlan_id;
|
||||
ports[port_id].tx_vlan_id_outer = vlan_id_outer;
|
||||
}
|
||||
|
||||
void
|
||||
tx_vlan_reset(portid_t port_id)
|
||||
{
|
||||
if (port_id_is_invalid(port_id, ENABLED_WARN))
|
||||
return;
|
||||
ports[port_id].tx_ol_flags &= ~TESTPMD_TX_OFFLOAD_INSERT_VLAN;
|
||||
ports[port_id].tx_ol_flags &= ~(TESTPMD_TX_OFFLOAD_INSERT_VLAN |
|
||||
TESTPMD_TX_OFFLOAD_INSERT_QINQ);
|
||||
ports[port_id].tx_vlan_id = 0;
|
||||
ports[port_id].tx_vlan_id_outer = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -136,7 +136,7 @@ pkt_burst_flow_gen(struct fwd_stream *fs)
|
||||
struct ether_hdr *eth_hdr;
|
||||
struct ipv4_hdr *ip_hdr;
|
||||
struct udp_hdr *udp_hdr;
|
||||
uint16_t vlan_tci;
|
||||
uint16_t vlan_tci, vlan_tci_outer;
|
||||
uint16_t ol_flags;
|
||||
uint16_t nb_rx;
|
||||
uint16_t nb_tx;
|
||||
@ -163,6 +163,7 @@ pkt_burst_flow_gen(struct fwd_stream *fs)
|
||||
|
||||
mbp = current_fwd_lcore()->mbp;
|
||||
vlan_tci = ports[fs->tx_port].tx_vlan_id;
|
||||
vlan_tci_outer = ports[fs->tx_port].tx_vlan_id_outer;
|
||||
ol_flags = ports[fs->tx_port].tx_ol_flags;
|
||||
|
||||
for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
|
||||
@ -208,6 +209,7 @@ pkt_burst_flow_gen(struct fwd_stream *fs)
|
||||
pkt->pkt_len = pkt_size;
|
||||
pkt->ol_flags = ol_flags;
|
||||
pkt->vlan_tci = vlan_tci;
|
||||
pkt->vlan_tci_outer = vlan_tci_outer;
|
||||
pkt->l2_len = sizeof(struct ether_hdr);
|
||||
pkt->l3_len = sizeof(struct ipv4_hdr);
|
||||
pkts_burst[nb_pkt] = pkt;
|
||||
|
@ -110,6 +110,8 @@ pkt_burst_mac_forward(struct fwd_stream *fs)
|
||||
txp = &ports[fs->tx_port];
|
||||
if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_VLAN)
|
||||
ol_flags = PKT_TX_VLAN_PKT;
|
||||
if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_QINQ)
|
||||
ol_flags |= PKT_TX_QINQ_PKT;
|
||||
for (i = 0; i < nb_rx; i++) {
|
||||
mb = pkts_burst[i];
|
||||
eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *);
|
||||
@ -121,6 +123,7 @@ pkt_burst_mac_forward(struct fwd_stream *fs)
|
||||
mb->l2_len = sizeof(struct ether_hdr);
|
||||
mb->l3_len = sizeof(struct ipv4_hdr);
|
||||
mb->vlan_tci = txp->tx_vlan_id;
|
||||
mb->vlan_tci_outer = txp->tx_vlan_id_outer;
|
||||
}
|
||||
nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx);
|
||||
fs->tx_packets += nb_tx;
|
||||
|
@ -110,6 +110,8 @@ pkt_burst_mac_swap(struct fwd_stream *fs)
|
||||
txp = &ports[fs->tx_port];
|
||||
if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_VLAN)
|
||||
ol_flags = PKT_TX_VLAN_PKT;
|
||||
if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_QINQ)
|
||||
ol_flags |= PKT_TX_QINQ_PKT;
|
||||
for (i = 0; i < nb_rx; i++) {
|
||||
mb = pkts_burst[i];
|
||||
eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *);
|
||||
@ -123,6 +125,7 @@ pkt_burst_mac_swap(struct fwd_stream *fs)
|
||||
mb->l2_len = sizeof(struct ether_hdr);
|
||||
mb->l3_len = sizeof(struct ipv4_hdr);
|
||||
mb->vlan_tci = txp->tx_vlan_id;
|
||||
mb->vlan_tci_outer = txp->tx_vlan_id_outer;
|
||||
}
|
||||
nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx);
|
||||
fs->tx_packets += nb_tx;
|
||||
|
@ -160,6 +160,9 @@ pkt_burst_receive(struct fwd_stream *fs)
|
||||
}
|
||||
if (ol_flags & PKT_RX_VLAN_PKT)
|
||||
printf(" - VLAN tci=0x%x", mb->vlan_tci);
|
||||
if (ol_flags & PKT_RX_QINQ_PKT)
|
||||
printf(" - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x",
|
||||
mb->vlan_tci, mb->vlan_tci_outer);
|
||||
if (is_encapsulation) {
|
||||
struct ipv4_hdr *ipv4_hdr;
|
||||
struct ipv6_hdr *ipv6_hdr;
|
||||
|
@ -133,6 +133,8 @@ struct fwd_stream {
|
||||
#define TESTPMD_TX_OFFLOAD_PARSE_TUNNEL 0x0020
|
||||
/** Insert VLAN header in forward engine */
|
||||
#define TESTPMD_TX_OFFLOAD_INSERT_VLAN 0x0040
|
||||
/** Insert double VLAN header in forward engine */
|
||||
#define TESTPMD_TX_OFFLOAD_INSERT_QINQ 0x0080
|
||||
|
||||
/**
|
||||
* The data structure associated with each port.
|
||||
@ -149,7 +151,8 @@ struct rte_port {
|
||||
unsigned int socket_id; /**< For NUMA support */
|
||||
uint16_t tx_ol_flags;/**< TX Offload Flags (TESTPMD_TX_OFFLOAD...). */
|
||||
uint16_t tso_segsz; /**< MSS for segmentation offload. */
|
||||
uint16_t tx_vlan_id; /**< Tag Id. in TX VLAN packets. */
|
||||
uint16_t tx_vlan_id;/**< The tag ID */
|
||||
uint16_t tx_vlan_id_outer;/**< The outer tag ID */
|
||||
void *fwd_ctx; /**< Forwarding mode context */
|
||||
uint64_t rx_bad_ip_csum; /**< rx pkts with bad ip checksum */
|
||||
uint64_t rx_bad_l4_csum; /**< rx pkts with bad l4 checksum */
|
||||
@ -515,6 +518,7 @@ int rx_vft_set(portid_t port_id, uint16_t vlan_id, int on);
|
||||
void vlan_extend_set(portid_t port_id, int on);
|
||||
void vlan_tpid_set(portid_t port_id, uint16_t tp_id);
|
||||
void tx_vlan_set(portid_t port_id, uint16_t vlan_id);
|
||||
void tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer);
|
||||
void tx_vlan_reset(portid_t port_id);
|
||||
void tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on);
|
||||
|
||||
|
@ -202,7 +202,7 @@ pkt_burst_transmit(struct fwd_stream *fs)
|
||||
struct ether_hdr eth_hdr;
|
||||
uint16_t nb_tx;
|
||||
uint16_t nb_pkt;
|
||||
uint16_t vlan_tci;
|
||||
uint16_t vlan_tci, vlan_tci_outer;
|
||||
uint64_t ol_flags = 0;
|
||||
uint8_t i;
|
||||
#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
|
||||
@ -218,8 +218,11 @@ pkt_burst_transmit(struct fwd_stream *fs)
|
||||
mbp = current_fwd_lcore()->mbp;
|
||||
txp = &ports[fs->tx_port];
|
||||
vlan_tci = txp->tx_vlan_id;
|
||||
vlan_tci_outer = txp->tx_vlan_id_outer;
|
||||
if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_VLAN)
|
||||
ol_flags = PKT_TX_VLAN_PKT;
|
||||
if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_QINQ)
|
||||
ol_flags |= PKT_TX_QINQ_PKT;
|
||||
for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
|
||||
pkt = tx_mbuf_alloc(mbp);
|
||||
if (pkt == NULL) {
|
||||
@ -266,7 +269,8 @@ pkt_burst_transmit(struct fwd_stream *fs)
|
||||
pkt->nb_segs = tx_pkt_nb_segs;
|
||||
pkt->pkt_len = tx_pkt_length;
|
||||
pkt->ol_flags = ol_flags;
|
||||
pkt->vlan_tci = vlan_tci;
|
||||
pkt->vlan_tci = vlan_tci;
|
||||
pkt->vlan_tci_outer = vlan_tci_outer;
|
||||
pkt->l2_len = sizeof(struct ether_hdr);
|
||||
pkt->l3_len = sizeof(struct ipv4_hdr);
|
||||
pkts_burst[nb_pkt] = pkt;
|
||||
|
@ -503,9 +503,19 @@ rx_vxlan_port rm (udp_port) (port_id)
|
||||
tx_vlan set
|
||||
~~~~~~~~~~~
|
||||
|
||||
Set hardware insertion of VLAN ID in packets sent on a port:
|
||||
Set hardware insertion of VLAN IDs in packets sent on a port:
|
||||
|
||||
tx_vlan set (vlan_id) (port_id)
|
||||
tx_vlan set (port_id) vlan_id[, vlan_id_outer]
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
Set a single VLAN ID (5) insertion on port 0.
|
||||
|
||||
tx_vlan set 0 5
|
||||
|
||||
Set double VLAN ID (inner: 2, outer: 3) insertion on port 1.
|
||||
|
||||
tx_vlan set 1 2 3
|
||||
|
||||
tx_vlan set pvid
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
Loading…
x
Reference in New Issue
Block a user