app/testpmd: setup DCB forwarding based on traffic class

This patch changes the testpmd DCB forwarding stream to make it
based on traffic class.
It also fixes some coding style issues.

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
Acked-by: Jijiang Liu <jijiang.liu@intel.com>
Acked-by: Helin Zhang <helin.zhang@intel.com>
This commit is contained in:
Jingjing Wu 2015-10-31 23:57:30 +08:00 committed by Thomas Monjalon
parent 89d6728c78
commit 1a572499be
4 changed files with 173 additions and 193 deletions

View File

@ -2032,37 +2032,46 @@ cmd_config_dcb_parsed(void *parsed_result,
__attribute__((unused)) void *data) __attribute__((unused)) void *data)
{ {
struct cmd_config_dcb *res = parsed_result; struct cmd_config_dcb *res = parsed_result;
struct dcb_config dcb_conf;
portid_t port_id = res->port_id; portid_t port_id = res->port_id;
struct rte_port *port; struct rte_port *port;
uint8_t pfc_en;
int ret;
port = &ports[port_id]; port = &ports[port_id];
/** Check if the port is not started **/ /** Check if the port is not started **/
if (port->port_status != RTE_PORT_STOPPED) { if (port->port_status != RTE_PORT_STOPPED) {
printf("Please stop port %d first\n",port_id); printf("Please stop port %d first\n", port_id);
return; return;
} }
dcb_conf.num_tcs = (enum rte_eth_nb_tcs) res->num_tcs; if ((res->num_tcs != ETH_4_TCS) && (res->num_tcs != ETH_8_TCS)) {
if ((dcb_conf.num_tcs != ETH_4_TCS) && (dcb_conf.num_tcs != ETH_8_TCS)){ printf("The invalid number of traffic class,"
printf("The invalid number of traffic class,only 4 or 8 allowed\n"); " only 4 or 8 allowed.\n");
return; return;
} }
if (nb_fwd_lcores < res->num_tcs) {
printf("nb_cores shouldn't be less than number of TCs.\n");
return;
}
if (!strncmp(res->pfc_en, "on", 2))
pfc_en = 1;
else
pfc_en = 0;
/* DCB in VT mode */ /* DCB in VT mode */
if (!strncmp(res->vt_en, "on",2)) if (!strncmp(res->vt_en, "on", 2))
dcb_conf.dcb_mode = DCB_VT_ENABLED; ret = init_port_dcb_config(port_id, DCB_VT_ENABLED,
(enum rte_eth_nb_tcs)res->num_tcs,
pfc_en);
else else
dcb_conf.dcb_mode = DCB_ENABLED; ret = init_port_dcb_config(port_id, DCB_ENABLED,
(enum rte_eth_nb_tcs)res->num_tcs,
pfc_en);
if (!strncmp(res->pfc_en, "on",2)) {
dcb_conf.pfc_en = 1;
}
else
dcb_conf.pfc_en = 0;
if (init_port_dcb_config(port_id,&dcb_conf) != 0) { if (ret != 0) {
printf("Cannot initialize network ports\n"); printf("Cannot initialize network ports.\n");
return; return;
} }

View File

@ -1145,113 +1145,92 @@ rss_fwd_config_setup(void)
} }
} }
/*
* In DCB and VT on,the mapping of 128 receive queues to 128 transmit queues.
*/
static void
dcb_rxq_2_txq_mapping(queueid_t rxq, queueid_t *txq)
{
if(dcb_q_mapping == DCB_4_TCS_Q_MAPPING) {
if (rxq < 32)
/* tc0: 0-31 */
*txq = rxq;
else if (rxq < 64) {
/* tc1: 64-95 */
*txq = (uint16_t)(rxq + 32);
}
else {
/* tc2: 96-111;tc3:112-127 */
*txq = (uint16_t)(rxq/2 + 64);
}
}
else {
if (rxq < 16)
/* tc0 mapping*/
*txq = rxq;
else if (rxq < 32) {
/* tc1 mapping*/
*txq = (uint16_t)(rxq + 16);
}
else if (rxq < 64) {
/*tc2,tc3 mapping */
*txq = (uint16_t)(rxq + 32);
}
else {
/* tc4,tc5,tc6 and tc7 mapping */
*txq = (uint16_t)(rxq/2 + 64);
}
}
}
/** /**
* For the DCB forwarding test, each core is assigned on every port multi-transmit * For the DCB forwarding test, each core is assigned on each traffic class.
* queue.
* *
* Each core is assigned a multi-stream, each stream being composed of * Each core is assigned a multi-stream, each stream being composed of
* a RX queue to poll on a RX port for input messages, associated with * a RX queue to poll on a RX port for input messages, associated with
* a TX queue of a TX port where to send forwarded packets. * a TX queue of a TX port where to send forwarded packets. All RX and
* All packets received on the RX queue of index "RxQj" of the RX port "RxPi" * TX queues are mapping to the same traffic class.
* are sent on the TX queue "TxQl" of the TX port "TxPk" according to the two * If VMDQ and DCB co-exist, each traffic class on different POOLs share
* following rules: * the same core
* In VT mode,
* - TxPk = (RxPi + 1) if RxPi is even, (RxPi - 1) if RxPi is odd
* - TxQl = RxQj
* In non-VT mode,
* - TxPk = (RxPi + 1) if RxPi is even, (RxPi - 1) if RxPi is odd
* There is a mapping of RxQj to TxQl to be required,and the mapping was implemented
* in dcb_rxq_2_txq_mapping function.
*/ */
static void static void
dcb_fwd_config_setup(void) dcb_fwd_config_setup(void)
{ {
portid_t rxp; struct rte_eth_dcb_info rxp_dcb_info, txp_dcb_info;
portid_t txp; portid_t txp, rxp = 0;
queueid_t rxq; queueid_t txq, rxq = 0;
queueid_t nb_q;
lcoreid_t lc_id; lcoreid_t lc_id;
uint16_t sm_id; uint16_t nb_rx_queue, nb_tx_queue;
uint16_t i, j, k, sm_id = 0;
nb_q = nb_rxq; uint8_t tc = 0;
cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores;
cur_fwd_config.nb_fwd_ports = nb_fwd_ports; cur_fwd_config.nb_fwd_ports = nb_fwd_ports;
cur_fwd_config.nb_fwd_streams = cur_fwd_config.nb_fwd_streams =
(streamid_t) (nb_q * cur_fwd_config.nb_fwd_ports); (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports);
/* reinitialize forwarding streams */ /* reinitialize forwarding streams */
init_fwd_streams(); init_fwd_streams();
sm_id = 0;
if ((rxp & 0x1) == 0)
txp = (portid_t) (rxp + 1);
else
txp = (portid_t) (rxp - 1);
/* get the dcb info on the first RX and TX ports */
(void)rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info);
(void)rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info);
setup_fwd_config_of_each_lcore(&cur_fwd_config);
rxp = 0; rxq = 0;
for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) { for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) {
/* a fwd core can run multi-streams */ fwd_lcores[lc_id]->stream_nb = 0;
for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) fwd_lcores[lc_id]->stream_idx = sm_id;
{ for (i = 0; i < ETH_MAX_VMDQ_POOL; i++) {
struct fwd_stream *fs; /* if the nb_queue is zero, means this tc is
fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id]; * not enabled on the POOL
if ((rxp & 0x1) == 0) */
txp = (portid_t) (rxp + 1); if (rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue == 0)
else break;
txp = (portid_t) (rxp - 1); k = fwd_lcores[lc_id]->stream_nb +
fs->rx_port = fwd_ports_ids[rxp]; fwd_lcores[lc_id]->stream_idx;
fs->rx_queue = rxq; rxq = rxp_dcb_info.tc_queue.tc_rxq[i][tc].base;
fs->tx_port = fwd_ports_ids[txp]; txq = txp_dcb_info.tc_queue.tc_txq[i][tc].base;
if (dcb_q_mapping == DCB_VT_Q_MAPPING) nb_rx_queue = txp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue;
fs->tx_queue = rxq; nb_tx_queue = txp_dcb_info.tc_queue.tc_txq[i][tc].nb_queue;
else for (j = 0; j < nb_rx_queue; j++) {
dcb_rxq_2_txq_mapping(rxq, &fs->tx_queue); struct fwd_stream *fs;
fs->peer_addr = fs->tx_port;
rxq = (queueid_t) (rxq + 1); fs = fwd_streams[k + j];
if (rxq < nb_q) fs->rx_port = fwd_ports_ids[rxp];
continue; fs->rx_queue = rxq + j;
rxq = 0; fs->tx_port = fwd_ports_ids[txp];
if (numa_support && (nb_fwd_ports <= (nb_ports >> 1))) fs->tx_queue = txq + j % nb_tx_queue;
rxp = (portid_t) fs->peer_addr = fs->tx_port;
(rxp + ((nb_ports >> 1) / nb_fwd_ports)); }
else fwd_lcores[lc_id]->stream_nb +=
rxp = (portid_t) (rxp + 1); rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue;
} }
sm_id = (streamid_t) (sm_id + fwd_lcores[lc_id]->stream_nb);
tc++;
if (tc < rxp_dcb_info.nb_tcs)
continue;
/* Restart from TC 0 on next RX port */
tc = 0;
if (numa_support && (nb_fwd_ports <= (nb_ports >> 1)))
rxp = (portid_t)
(rxp + ((nb_ports >> 1) / nb_fwd_ports));
else
rxp++;
if (rxp >= nb_fwd_ports)
return;
/* get the dcb information on next RX and TX ports */
if ((rxp & 0x1) == 0)
txp = (portid_t) (rxp + 1);
else
txp = (portid_t) (rxp - 1);
rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info);
rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info);
} }
} }
@ -1371,10 +1350,6 @@ pkt_fwd_config_display(struct fwd_config *cfg)
void void
fwd_config_display(void) fwd_config_display(void)
{ {
if((dcb_config) && (nb_fwd_lcores == 1)) {
printf("In DCB mode,the nb forwarding cores should be larger than 1\n");
return;
}
fwd_config_setup(); fwd_config_setup();
pkt_fwd_config_display(&cur_fwd_config); pkt_fwd_config_display(&cur_fwd_config);
} }

View File

@ -182,9 +182,6 @@ uint8_t dcb_config = 0;
/* Whether the dcb is in testing status */ /* Whether the dcb is in testing status */
uint8_t dcb_test = 0; uint8_t dcb_test = 0;
/* DCB on and VT on mapping is default */
enum dcb_queue_mapping_mode dcb_q_mapping = DCB_VT_Q_MAPPING;
/* /*
* Configurable number of RX/TX queues. * Configurable number of RX/TX queues.
*/ */
@ -1852,115 +1849,131 @@ const uint16_t vlan_tags[] = {
}; };
static int static int
get_eth_dcb_conf(struct rte_eth_conf *eth_conf, struct dcb_config *dcb_conf) get_eth_dcb_conf(struct rte_eth_conf *eth_conf,
enum dcb_mode_enable dcb_mode,
enum rte_eth_nb_tcs num_tcs,
uint8_t pfc_en)
{ {
uint8_t i; uint8_t i;
/* /*
* Builds up the correct configuration for dcb+vt based on the vlan tags array * Builds up the correct configuration for dcb+vt based on the vlan tags array
* given above, and the number of traffic classes available for use. * given above, and the number of traffic classes available for use.
*/ */
if (dcb_conf->dcb_mode == DCB_VT_ENABLED) { if (dcb_mode == DCB_VT_ENABLED) {
struct rte_eth_vmdq_dcb_conf vmdq_rx_conf; struct rte_eth_vmdq_dcb_conf *vmdq_rx_conf =
struct rte_eth_vmdq_dcb_tx_conf vmdq_tx_conf; &eth_conf->rx_adv_conf.vmdq_dcb_conf;
struct rte_eth_vmdq_dcb_tx_conf *vmdq_tx_conf =
&eth_conf->tx_adv_conf.vmdq_dcb_tx_conf;
/* VMDQ+DCB RX and TX configrations */ /* VMDQ+DCB RX and TX configrations */
vmdq_rx_conf.enable_default_pool = 0; vmdq_rx_conf->enable_default_pool = 0;
vmdq_rx_conf.default_pool = 0; vmdq_rx_conf->default_pool = 0;
vmdq_rx_conf.nb_queue_pools = vmdq_rx_conf->nb_queue_pools =
(dcb_conf->num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS); (num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS);
vmdq_tx_conf.nb_queue_pools = vmdq_tx_conf->nb_queue_pools =
(dcb_conf->num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS); (num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS);
vmdq_rx_conf.nb_pool_maps = sizeof( vlan_tags )/sizeof( vlan_tags[ 0 ]); vmdq_rx_conf->nb_pool_maps = vmdq_rx_conf->nb_queue_pools;
for (i = 0; i < vmdq_rx_conf.nb_pool_maps; i++) { for (i = 0; i < vmdq_rx_conf->nb_pool_maps; i++) {
vmdq_rx_conf.pool_map[i].vlan_id = vlan_tags[ i ]; vmdq_rx_conf->pool_map[i].vlan_id = vlan_tags[i];
vmdq_rx_conf.pool_map[i].pools = 1 << (i % vmdq_rx_conf.nb_queue_pools); vmdq_rx_conf->pool_map[i].pools =
1 << (i % vmdq_rx_conf->nb_queue_pools);
} }
for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) { for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) {
vmdq_rx_conf.dcb_tc[i] = i; vmdq_rx_conf->dcb_tc[i] = i;
vmdq_tx_conf.dcb_tc[i] = i; vmdq_tx_conf->dcb_tc[i] = i;
} }
/*set DCB mode of RX and TX of multiple queues*/ /* set DCB mode of RX and TX of multiple queues */
eth_conf->rxmode.mq_mode = ETH_MQ_RX_VMDQ_DCB; eth_conf->rxmode.mq_mode = ETH_MQ_RX_VMDQ_DCB;
eth_conf->txmode.mq_mode = ETH_MQ_TX_VMDQ_DCB; eth_conf->txmode.mq_mode = ETH_MQ_TX_VMDQ_DCB;
if (dcb_conf->pfc_en) } else {
eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT|ETH_DCB_PFC_SUPPORT; struct rte_eth_dcb_rx_conf *rx_conf =
else &eth_conf->rx_adv_conf.dcb_rx_conf;
eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT; struct rte_eth_dcb_tx_conf *tx_conf =
&eth_conf->tx_adv_conf.dcb_tx_conf;
(void)(rte_memcpy(&eth_conf->rx_adv_conf.vmdq_dcb_conf, &vmdq_rx_conf, rx_conf->nb_tcs = num_tcs;
sizeof(struct rte_eth_vmdq_dcb_conf))); tx_conf->nb_tcs = num_tcs;
(void)(rte_memcpy(&eth_conf->tx_adv_conf.vmdq_dcb_tx_conf, &vmdq_tx_conf,
sizeof(struct rte_eth_vmdq_dcb_tx_conf)));
}
else {
struct rte_eth_dcb_rx_conf rx_conf;
struct rte_eth_dcb_tx_conf tx_conf;
/* queue mapping configuration of DCB RX and TX */ for (i = 0; i < num_tcs; i++) {
if (dcb_conf->num_tcs == ETH_4_TCS) rx_conf->dcb_tc[i] = i;
dcb_q_mapping = DCB_4_TCS_Q_MAPPING; tx_conf->dcb_tc[i] = i;
else
dcb_q_mapping = DCB_8_TCS_Q_MAPPING;
rx_conf.nb_tcs = dcb_conf->num_tcs;
tx_conf.nb_tcs = dcb_conf->num_tcs;
for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++){
rx_conf.dcb_tc[i] = i;
tx_conf.dcb_tc[i] = i;
} }
eth_conf->rxmode.mq_mode = ETH_MQ_RX_DCB; eth_conf->rxmode.mq_mode = ETH_MQ_RX_DCB_RSS;
eth_conf->rx_adv_conf.rss_conf.rss_hf = rss_hf;
eth_conf->txmode.mq_mode = ETH_MQ_TX_DCB; eth_conf->txmode.mq_mode = ETH_MQ_TX_DCB;
if (dcb_conf->pfc_en)
eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT|ETH_DCB_PFC_SUPPORT;
else
eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT;
(void)(rte_memcpy(&eth_conf->rx_adv_conf.dcb_rx_conf, &rx_conf,
sizeof(struct rte_eth_dcb_rx_conf)));
(void)(rte_memcpy(&eth_conf->tx_adv_conf.dcb_tx_conf, &tx_conf,
sizeof(struct rte_eth_dcb_tx_conf)));
} }
if (pfc_en)
eth_conf->dcb_capability_en =
ETH_DCB_PG_SUPPORT | ETH_DCB_PFC_SUPPORT;
else
eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT;
return 0; return 0;
} }
int int
init_port_dcb_config(portid_t pid,struct dcb_config *dcb_conf) init_port_dcb_config(portid_t pid,
enum dcb_mode_enable dcb_mode,
enum rte_eth_nb_tcs num_tcs,
uint8_t pfc_en)
{ {
struct rte_eth_conf port_conf; struct rte_eth_conf port_conf;
struct rte_eth_dev_info dev_info;
struct rte_port *rte_port; struct rte_port *rte_port;
int retval; int retval;
uint16_t nb_vlan;
uint16_t i; uint16_t i;
/* rxq and txq configuration in dcb mode */ rte_eth_dev_info_get(pid, &dev_info);
nb_rxq = 128;
nb_txq = 128; /* If dev_info.vmdq_pool_base is greater than 0,
* the queue id of vmdq pools is started after pf queues.
*/
if (dcb_mode == DCB_VT_ENABLED && dev_info.vmdq_pool_base > 0) {
printf("VMDQ_DCB multi-queue mode is nonsensical"
" for port %d.", pid);
return -1;
}
/* Assume the ports in testpmd have the same dcb capability
* and has the same number of rxq and txq in dcb mode
*/
if (dcb_mode == DCB_VT_ENABLED) {
nb_rxq = dev_info.max_rx_queues;
nb_txq = dev_info.max_tx_queues;
} else {
/*if vt is disabled, use all pf queues */
if (dev_info.vmdq_pool_base == 0) {
nb_rxq = dev_info.max_rx_queues;
nb_txq = dev_info.max_tx_queues;
} else {
nb_rxq = (queueid_t)num_tcs;
nb_txq = (queueid_t)num_tcs;
}
}
rx_free_thresh = 64; rx_free_thresh = 64;
memset(&port_conf,0,sizeof(struct rte_eth_conf)); memset(&port_conf, 0, sizeof(struct rte_eth_conf));
/* Enter DCB configuration status */ /* Enter DCB configuration status */
dcb_config = 1; dcb_config = 1;
nb_vlan = sizeof( vlan_tags )/sizeof( vlan_tags[ 0 ]);
/*set configuration of DCB in vt mode and DCB in non-vt mode*/ /*set configuration of DCB in vt mode and DCB in non-vt mode*/
retval = get_eth_dcb_conf(&port_conf, dcb_conf); retval = get_eth_dcb_conf(&port_conf, dcb_mode, num_tcs, pfc_en);
if (retval < 0) if (retval < 0)
return retval; return retval;
rte_port = &ports[pid]; rte_port = &ports[pid];
memcpy(&rte_port->dev_conf, &port_conf,sizeof(struct rte_eth_conf)); memcpy(&rte_port->dev_conf, &port_conf, sizeof(struct rte_eth_conf));
rxtx_port_config(rte_port); rxtx_port_config(rte_port);
/* VLAN filter */ /* VLAN filter */
rte_port->dev_conf.rxmode.hw_vlan_filter = 1; rte_port->dev_conf.rxmode.hw_vlan_filter = 1;
for (i = 0; i < nb_vlan; i++){ for (i = 0; i < RTE_DIM(vlan_tags); i++)
rx_vft_set(pid, vlan_tags[i], 1); rx_vft_set(pid, vlan_tags[i], 1);
}
rte_eth_macaddr_get(pid, &rte_port->eth_addr); rte_eth_macaddr_get(pid, &rte_port->eth_addr);
map_port_queue_stats_mapping_registers(pid, rte_port); map_port_queue_stats_mapping_registers(pid, rte_port);

View File

@ -255,25 +255,6 @@ enum dcb_mode_enable
DCB_ENABLED DCB_ENABLED
}; };
/*
* DCB general config info
*/
struct dcb_config {
enum dcb_mode_enable dcb_mode;
uint8_t vt_en;
enum rte_eth_nb_tcs num_tcs;
uint8_t pfc_en;
};
/*
* In DCB io FWD mode, 128 RX queue to 128 TX queue mapping
*/
enum dcb_queue_mapping_mode {
DCB_VT_Q_MAPPING = 0,
DCB_4_TCS_Q_MAPPING,
DCB_8_TCS_Q_MAPPING
};
#define MAX_TX_QUEUE_STATS_MAPPINGS 1024 /* MAX_PORT of 32 @ 32 tx_queues/port */ #define MAX_TX_QUEUE_STATS_MAPPINGS 1024 /* MAX_PORT of 32 @ 32 tx_queues/port */
#define MAX_RX_QUEUE_STATS_MAPPINGS 4096 /* MAX_PORT of 32 @ 128 rx_queues/port */ #define MAX_RX_QUEUE_STATS_MAPPINGS 4096 /* MAX_PORT of 32 @ 128 rx_queues/port */
@ -536,7 +517,9 @@ void dev_set_link_down(portid_t pid);
void init_port_config(void); void init_port_config(void);
void set_port_slave_flag(portid_t slave_pid); void set_port_slave_flag(portid_t slave_pid);
void clear_port_slave_flag(portid_t slave_pid); void clear_port_slave_flag(portid_t slave_pid);
int init_port_dcb_config(portid_t pid,struct dcb_config *dcb_conf); int init_port_dcb_config(portid_t pid, enum dcb_mode_enable dcb_mode,
enum rte_eth_nb_tcs num_tcs,
uint8_t pfc_en);
int start_port(portid_t pid); int start_port(portid_t pid);
void stop_port(portid_t pid); void stop_port(portid_t pid);
void close_port(portid_t pid); void close_port(portid_t pid);