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)
{
struct cmd_config_dcb *res = parsed_result;
struct dcb_config dcb_conf;
portid_t port_id = res->port_id;
struct rte_port *port;
uint8_t pfc_en;
int ret;
port = &ports[port_id];
/** Check if the port is not started **/
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;
}
dcb_conf.num_tcs = (enum rte_eth_nb_tcs) res->num_tcs;
if ((dcb_conf.num_tcs != ETH_4_TCS) && (dcb_conf.num_tcs != ETH_8_TCS)){
printf("The invalid number of traffic class,only 4 or 8 allowed\n");
if ((res->num_tcs != ETH_4_TCS) && (res->num_tcs != ETH_8_TCS)) {
printf("The invalid number of traffic class,"
" only 4 or 8 allowed.\n");
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 */
if (!strncmp(res->vt_en, "on",2))
dcb_conf.dcb_mode = DCB_VT_ENABLED;
if (!strncmp(res->vt_en, "on", 2))
ret = init_port_dcb_config(port_id, DCB_VT_ENABLED,
(enum rte_eth_nb_tcs)res->num_tcs,
pfc_en);
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) {
printf("Cannot initialize network ports\n");
if (ret != 0) {
printf("Cannot initialize network ports.\n");
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
* queue.
* For the DCB forwarding test, each core is assigned on each traffic class.
*
* 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 TX queue of a TX port where to send forwarded packets.
* All packets received on the RX queue of index "RxQj" of the RX port "RxPi"
* are sent on the TX queue "TxQl" of the TX port "TxPk" according to the two
* following rules:
* 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.
* a TX queue of a TX port where to send forwarded packets. All RX and
* TX queues are mapping to the same traffic class.
* If VMDQ and DCB co-exist, each traffic class on different POOLs share
* the same core
*/
static void
dcb_fwd_config_setup(void)
{
portid_t rxp;
portid_t txp;
queueid_t rxq;
queueid_t nb_q;
struct rte_eth_dcb_info rxp_dcb_info, txp_dcb_info;
portid_t txp, rxp = 0;
queueid_t txq, rxq = 0;
lcoreid_t lc_id;
uint16_t sm_id;
nb_q = nb_rxq;
uint16_t nb_rx_queue, nb_tx_queue;
uint16_t i, j, k, sm_id = 0;
uint8_t tc = 0;
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_streams =
(streamid_t) (nb_q * cur_fwd_config.nb_fwd_ports);
(streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports);
/* reinitialize forwarding streams */
init_fwd_streams();
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++) {
/* a fwd core can run multi-streams */
for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++)
{
struct fwd_stream *fs;
fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id];
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);
for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) {
fwd_lcores[lc_id]->stream_nb = 0;
fwd_lcores[lc_id]->stream_idx = sm_id;
for (i = 0; i < ETH_MAX_VMDQ_POOL; i++) {
/* if the nb_queue is zero, means this tc is
* not enabled on the POOL
*/
if (rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue == 0)
break;
k = fwd_lcores[lc_id]->stream_nb +
fwd_lcores[lc_id]->stream_idx;
rxq = rxp_dcb_info.tc_queue.tc_rxq[i][tc].base;
txq = txp_dcb_info.tc_queue.tc_txq[i][tc].base;
nb_rx_queue = txp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue;
nb_tx_queue = txp_dcb_info.tc_queue.tc_txq[i][tc].nb_queue;
for (j = 0; j < nb_rx_queue; j++) {
struct fwd_stream *fs;
fs = fwd_streams[k + j];
fs->rx_port = fwd_ports_ids[rxp];
fs->rx_queue = rxq;
fs->rx_queue = rxq + j;
fs->tx_port = fwd_ports_ids[txp];
if (dcb_q_mapping == DCB_VT_Q_MAPPING)
fs->tx_queue = rxq;
else
dcb_rxq_2_txq_mapping(rxq, &fs->tx_queue);
fs->tx_queue = txq + j % nb_tx_queue;
fs->peer_addr = fs->tx_port;
rxq = (queueid_t) (rxq + 1);
if (rxq < nb_q)
}
fwd_lcores[lc_id]->stream_nb +=
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;
rxq = 0;
/* 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 = (portid_t) (rxp + 1);
}
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
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();
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 */
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.
*/
@ -1852,7 +1849,10 @@ const uint16_t vlan_tags[] = {
};
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;
@ -1860,107 +1860,120 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf, struct dcb_config *dcb_conf)
* 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.
*/
if (dcb_conf->dcb_mode == DCB_VT_ENABLED) {
struct rte_eth_vmdq_dcb_conf vmdq_rx_conf;
struct rte_eth_vmdq_dcb_tx_conf vmdq_tx_conf;
if (dcb_mode == DCB_VT_ENABLED) {
struct rte_eth_vmdq_dcb_conf *vmdq_rx_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_rx_conf.enable_default_pool = 0;
vmdq_rx_conf.default_pool = 0;
vmdq_rx_conf.nb_queue_pools =
(dcb_conf->num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS);
vmdq_tx_conf.nb_queue_pools =
(dcb_conf->num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS);
vmdq_rx_conf->enable_default_pool = 0;
vmdq_rx_conf->default_pool = 0;
vmdq_rx_conf->nb_queue_pools =
(num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS);
vmdq_tx_conf->nb_queue_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 ]);
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].pools = 1 << (i % vmdq_rx_conf.nb_queue_pools);
vmdq_rx_conf->nb_pool_maps = vmdq_rx_conf->nb_queue_pools;
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].pools =
1 << (i % vmdq_rx_conf->nb_queue_pools);
}
for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) {
vmdq_rx_conf.dcb_tc[i] = i;
vmdq_tx_conf.dcb_tc[i] = i;
vmdq_rx_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->txmode.mq_mode = ETH_MQ_TX_VMDQ_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;
} else {
struct rte_eth_dcb_rx_conf *rx_conf =
&eth_conf->rx_adv_conf.dcb_rx_conf;
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,
sizeof(struct rte_eth_vmdq_dcb_conf)));
(void)(rte_memcpy(&eth_conf->tx_adv_conf.vmdq_dcb_tx_conf, &vmdq_tx_conf,
sizeof(struct rte_eth_vmdq_dcb_tx_conf)));
rx_conf->nb_tcs = num_tcs;
tx_conf->nb_tcs = num_tcs;
for (i = 0; i < num_tcs; i++) {
rx_conf->dcb_tc[i] = i;
tx_conf->dcb_tc[i] = i;
}
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 */
if (dcb_conf->num_tcs == ETH_4_TCS)
dcb_q_mapping = DCB_4_TCS_Q_MAPPING;
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;
if (dcb_conf->pfc_en)
eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT|ETH_DCB_PFC_SUPPORT;
}
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;
(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)));
}
return 0;
}
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_dev_info dev_info;
struct rte_port *rte_port;
int retval;
uint16_t nb_vlan;
uint16_t i;
/* rxq and txq configuration in dcb mode */
nb_rxq = 128;
nb_txq = 128;
rte_eth_dev_info_get(pid, &dev_info);
/* 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;
memset(&port_conf,0,sizeof(struct rte_eth_conf));
memset(&port_conf, 0, sizeof(struct rte_eth_conf));
/* Enter DCB configuration status */
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*/
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)
return retval;
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);
/* VLAN filter */
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);
}
rte_eth_macaddr_get(pid, &rte_port->eth_addr);
map_port_queue_stats_mapping_registers(pid, rte_port);

View File

@ -255,25 +255,6 @@ enum dcb_mode_enable
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_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 set_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);
void stop_port(portid_t pid);
void close_port(portid_t pid);