From: Jasvinder Singh Date: Fri, 6 Jul 2018 17:21:16 +0000 (+0100) Subject: app/testpmd: rework softnic forward mode X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=0ad778b398c676b30096954f9badea3cc0afe644;p=dpdk.git app/testpmd: rework softnic forward mode Modied the testpmd softnic forwarding mode as per the changes in softnic PMD. To run testpmd application with softnic fwd mode, following command is used; $ ./testpmd -c 0xc -n 4 --vdev 'net_softnic0,firmware=script.cli' -- -i --forward-mode=softnic Signed-off-by: Jasvinder Singh Signed-off-by: Reshma Pattan --- diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile index a5a827bbd2..f788078372 100644 --- a/app/test-pmd/Makefile +++ b/app/test-pmd/Makefile @@ -35,8 +35,8 @@ SRCS-y += icmpecho.c SRCS-$(CONFIG_RTE_LIBRTE_IEEE1588) += ieee1588fwd.c SRCS-$(CONFIG_RTE_LIBRTE_BPF) += bpf_cmd.c -ifeq ($(CONFIG_RTE_LIBRTE_PMD_SOFTNIC)$(CONFIG_RTE_LIBRTE_SCHED),yy) -SRCS-y += tm.c +ifeq ($(CONFIG_RTE_LIBRTE_PMD_SOFTNIC), y) +SRCS-y += softnicfwd.c endif ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 15d35da1c3..46a9f49ef3 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -69,6 +69,9 @@ #ifdef RTE_LIBRTE_I40E_PMD #include #endif +#ifdef RTE_LIBRTE_PMD_SOFTNIC +#include +#endif #ifdef RTE_LIBRTE_BNXT_PMD #include #endif @@ -14817,20 +14820,14 @@ static void cmd_set_port_tm_hierarchy_default_parsed(void *parsed_result, p = &ports[port_id]; - /* Port tm flag */ - if (p->softport.tm_flag == 0) { - printf(" tm not enabled on port %u (error)\n", port_id); - return; - } - /* Forward mode: tm */ - if (strcmp(cur_fwd_config.fwd_eng->fwd_mode_name, "tm")) { - printf(" tm mode not enabled(error)\n"); + if (strcmp(cur_fwd_config.fwd_eng->fwd_mode_name, "softnic")) { + printf(" softnicfwd mode not enabled(error)\n"); return; } /* Set the default tm hierarchy */ - p->softport.tm.default_hierarchy_enable = 1; + p->softport.default_tm_hierarchy_enable = 1; } cmdline_parse_inst_t cmd_set_port_tm_hierarchy_default = { @@ -17554,15 +17551,50 @@ cmdline_read_from_file(const char *filename) void prompt(void) { + int status; + /* initialize non-constant commands */ cmd_set_fwd_mode_init(); cmd_set_fwd_retry_mode_init(); +#if defined RTE_LIBRTE_PMD_SOFTNIC + portid_t softnic_portid, pid; + uint8_t softnic_enable = 0; + + if (strcmp(cur_fwd_eng->fwd_mode_name, "softnic") == 0) { + RTE_ETH_FOREACH_DEV(pid) { + struct rte_port *port = &ports[pid]; + const char *driver = port->dev_info.driver_name; + + if (strcmp(driver, "net_softnic") == 0) { + softnic_portid = pid; + softnic_enable = 1; + break; + } + } + } +#endif + testpmd_cl = cmdline_stdin_new(main_ctx, "testpmd> "); if (testpmd_cl == NULL) return; - cmdline_interact(testpmd_cl); - cmdline_stdin_exit(testpmd_cl); + + for (;;) { + status = cmdline_poll(testpmd_cl); + if (status < 0) + rte_panic("CLI poll error (%" PRId32 ")\n", status); + else if (status == RDLINE_EXITED) { + cmdline_stdin_exit(testpmd_cl); + rte_exit(0, "\n"); + } + +#if defined RTE_LIBRTE_PMD_SOFTNIC + + if ((softnic_enable == 1) && + (strcmp(cur_fwd_eng->fwd_mode_name, "softnic") == 0)) + rte_pmd_softnic_manage(softnic_portid); +#endif + } } void diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index 97020fb3d7..a17a7b57a6 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -2332,6 +2332,55 @@ icmp_echo_config_setup(void) } } +#if defined RTE_LIBRTE_PMD_SOFTNIC +static void +softnic_fwd_config_setup(void) +{ + struct rte_port *port; + portid_t pid, softnic_portid; + queueid_t i; + uint8_t softnic_enable = 0; + + RTE_ETH_FOREACH_DEV(pid) { + port = &ports[pid]; + const char *driver = port->dev_info.driver_name; + + if (strcmp(driver, "net_softnic") == 0) { + softnic_portid = pid; + softnic_enable = 1; + break; + } + } + + if (softnic_enable == 0) { + printf("Softnic mode not configured(%s)!\n", __func__); + return; + } + + cur_fwd_config.nb_fwd_ports = 1; + cur_fwd_config.nb_fwd_streams = (streamid_t) nb_rxq; + + /* Re-initialize forwarding streams */ + init_fwd_streams(); + + /* + * In the softnic forwarding test, the number of forwarding cores + * is set to one and remaining are used for softnic packet processing. + */ + cur_fwd_config.nb_fwd_lcores = 1; + setup_fwd_config_of_each_lcore(&cur_fwd_config); + + for (i = 0; i < cur_fwd_config.nb_fwd_streams; i++) { + fwd_streams[i]->rx_port = softnic_portid; + fwd_streams[i]->rx_queue = i; + fwd_streams[i]->tx_port = softnic_portid; + fwd_streams[i]->tx_queue = i; + fwd_streams[i]->peer_addr = fwd_streams[i]->tx_port; + fwd_streams[i]->retry_enabled = retry_enabled; + } +} +#endif + void fwd_config_setup(void) { @@ -2340,6 +2389,14 @@ fwd_config_setup(void) icmp_echo_config_setup(); return; } + +#if defined RTE_LIBRTE_PMD_SOFTNIC + if (strcmp(cur_fwd_eng->fwd_mode_name, "softnic") == 0) { + softnic_fwd_config_setup(); + return; + } +#endif + if ((nb_rxq > 1) && (nb_txq > 1)){ if (dcb_config) dcb_fwd_config_setup(); diff --git a/app/test-pmd/meson.build b/app/test-pmd/meson.build index 4c9fbbfda7..55539baa9b 100644 --- a/app/test-pmd/meson.build +++ b/app/test-pmd/meson.build @@ -35,7 +35,7 @@ if dpdk_conf.has('RTE_LIBRTE_IXGBE_PMD') deps += 'pmd_ixgbe' endif if dpdk_conf.has('RTE_LIBRTE_SOFTNIC_PMD') - sources += files('tm.c') + sources += files('softnicfwd.c') deps += 'pmd_softnic' endif if dpdk_conf.has('RTE_LIBRTE_DPAA_PMD') diff --git a/app/test-pmd/softnicfwd.c b/app/test-pmd/softnicfwd.c new file mode 100644 index 0000000000..1f9eeaf40b --- /dev/null +++ b/app/test-pmd/softnicfwd.c @@ -0,0 +1,677 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017 Intel Corporation + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "testpmd.h" + +#define SUBPORT_NODES_PER_PORT 1 +#define PIPE_NODES_PER_SUBPORT 4096 +#define TC_NODES_PER_PIPE 4 +#define QUEUE_NODES_PER_TC 4 + +#define NUM_PIPE_NODES \ + (SUBPORT_NODES_PER_PORT * PIPE_NODES_PER_SUBPORT) + +#define NUM_TC_NODES \ + (NUM_PIPE_NODES * TC_NODES_PER_PIPE) + +#define ROOT_NODE_ID 1000000 +#define SUBPORT_NODES_START_ID 900000 +#define PIPE_NODES_START_ID 800000 +#define TC_NODES_START_ID 700000 + +#define STATS_MASK_DEFAULT \ + (RTE_TM_STATS_N_PKTS | \ + RTE_TM_STATS_N_BYTES | \ + RTE_TM_STATS_N_PKTS_GREEN_DROPPED | \ + RTE_TM_STATS_N_BYTES_GREEN_DROPPED) + +#define STATS_MASK_QUEUE \ + (STATS_MASK_DEFAULT | \ + RTE_TM_STATS_N_PKTS_QUEUED) + +#define BYTES_IN_MBPS (1000 * 1000 / 8) +#define TOKEN_BUCKET_SIZE 1000000 + +/* TM Hierarchy Levels */ +enum tm_hierarchy_level { + TM_NODE_LEVEL_PORT = 0, + TM_NODE_LEVEL_SUBPORT, + TM_NODE_LEVEL_PIPE, + TM_NODE_LEVEL_TC, + TM_NODE_LEVEL_QUEUE, + TM_NODE_LEVEL_MAX, +}; + +struct tm_hierarchy { + /* TM Nodes */ + uint32_t root_node_id; + uint32_t subport_node_id[SUBPORT_NODES_PER_PORT]; + uint32_t pipe_node_id[SUBPORT_NODES_PER_PORT][PIPE_NODES_PER_SUBPORT]; + uint32_t tc_node_id[NUM_PIPE_NODES][TC_NODES_PER_PIPE]; + uint32_t queue_node_id[NUM_TC_NODES][QUEUE_NODES_PER_TC]; + + /* TM Hierarchy Nodes Shaper Rates */ + uint32_t root_node_shaper_rate; + uint32_t subport_node_shaper_rate; + uint32_t pipe_node_shaper_rate; + uint32_t tc_node_shaper_rate; + uint32_t tc_node_shared_shaper_rate; + + uint32_t n_shapers; +}; + +static struct fwd_lcore *softnic_fwd_lcore; +static uint16_t softnic_port_id; +struct fwd_engine softnic_fwd_engine; + +/* + * Softnic packet forward + */ +static void +softnic_fwd(struct fwd_stream *fs) +{ + struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; + uint16_t nb_rx; + uint16_t nb_tx; + uint32_t retry; + +#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES + uint64_t start_tsc; + uint64_t end_tsc; + uint64_t core_cycles; +#endif + +#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES + start_tsc = rte_rdtsc(); +#endif + + /* Packets Receive */ + nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, + pkts_burst, nb_pkt_per_burst); + fs->rx_packets += nb_rx; + +#ifdef RTE_TEST_PMD_RECORD_BURST_STATS + fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; +#endif + + nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, + pkts_burst, nb_rx); + + /* Retry if necessary */ + if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) { + retry = 0; + while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) { + rte_delay_us(burst_tx_delay_time); + nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue, + &pkts_burst[nb_tx], nb_rx - nb_tx); + } + } + fs->tx_packets += nb_tx; + +#ifdef RTE_TEST_PMD_RECORD_BURST_STATS + fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; +#endif + + if (unlikely(nb_tx < nb_rx)) { + fs->fwd_dropped += (nb_rx - nb_tx); + do { + rte_pktmbuf_free(pkts_burst[nb_tx]); + } while (++nb_tx < nb_rx); + } +#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES + end_tsc = rte_rdtsc(); + core_cycles = (end_tsc - start_tsc); + fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); +#endif +} + +static void +softnic_fwd_run(struct fwd_stream *fs) +{ + rte_pmd_softnic_run(softnic_port_id); + softnic_fwd(fs); +} + +/** + * Softnic init + */ +static int +softnic_begin(void *arg __rte_unused) +{ + for (;;) { + if (!softnic_fwd_lcore->stopped) + break; + } + + do { + /* Run softnic */ + rte_pmd_softnic_run(softnic_port_id); + } while (!softnic_fwd_lcore->stopped); + + return 0; +} + +static void +set_tm_hiearchy_nodes_shaper_rate(portid_t port_id, + struct tm_hierarchy *h) +{ + struct rte_eth_link link_params; + uint64_t tm_port_rate; + + memset(&link_params, 0, sizeof(link_params)); + + rte_eth_link_get(port_id, &link_params); + tm_port_rate = (uint64_t)ETH_SPEED_NUM_10G * BYTES_IN_MBPS; + + if (tm_port_rate > UINT32_MAX) + tm_port_rate = UINT32_MAX; + + /* Set tm hierarchy shapers rate */ + h->root_node_shaper_rate = tm_port_rate; + h->subport_node_shaper_rate = + tm_port_rate / SUBPORT_NODES_PER_PORT; + h->pipe_node_shaper_rate + = h->subport_node_shaper_rate / PIPE_NODES_PER_SUBPORT; + h->tc_node_shaper_rate = h->pipe_node_shaper_rate; + h->tc_node_shared_shaper_rate = h->subport_node_shaper_rate; +} + +static int +softport_tm_root_node_add(portid_t port_id, struct tm_hierarchy *h, + struct rte_tm_error *error) +{ + struct rte_tm_node_params rnp; + struct rte_tm_shaper_params rsp; + uint32_t priority, weight, level_id, shaper_profile_id; + + memset(&rsp, 0, sizeof(struct rte_tm_shaper_params)); + memset(&rnp, 0, sizeof(struct rte_tm_node_params)); + + /* Shaper profile Parameters */ + rsp.peak.rate = h->root_node_shaper_rate; + rsp.peak.size = TOKEN_BUCKET_SIZE; + rsp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS; + shaper_profile_id = 0; + + if (rte_tm_shaper_profile_add(port_id, shaper_profile_id, + &rsp, error)) { + printf("%s ERROR(%d)-%s!(shaper_id %u)\n ", + __func__, error->type, error->message, + shaper_profile_id); + return -1; + } + + /* Root Node Parameters */ + h->root_node_id = ROOT_NODE_ID; + weight = 1; + priority = 0; + level_id = TM_NODE_LEVEL_PORT; + rnp.shaper_profile_id = shaper_profile_id; + rnp.nonleaf.n_sp_priorities = 1; + rnp.stats_mask = STATS_MASK_DEFAULT; + + /* Add Node to TM Hierarchy */ + if (rte_tm_node_add(port_id, h->root_node_id, RTE_TM_NODE_ID_NULL, + priority, weight, level_id, &rnp, error)) { + printf("%s ERROR(%d)-%s!(node_id %u, parent_id %u, level %u)\n", + __func__, error->type, error->message, + h->root_node_id, RTE_TM_NODE_ID_NULL, + level_id); + return -1; + } + /* Update */ + h->n_shapers++; + + printf(" Root node added (Start id %u, Count %u, level %u)\n", + h->root_node_id, 1, level_id); + + return 0; +} + +static int +softport_tm_subport_node_add(portid_t port_id, + struct tm_hierarchy *h, + struct rte_tm_error *error) +{ + uint32_t subport_parent_node_id, subport_node_id = 0; + struct rte_tm_node_params snp; + struct rte_tm_shaper_params ssp; + uint32_t priority, weight, level_id, shaper_profile_id; + uint32_t i; + + memset(&ssp, 0, sizeof(struct rte_tm_shaper_params)); + memset(&snp, 0, sizeof(struct rte_tm_node_params)); + + shaper_profile_id = h->n_shapers; + + /* Add Shaper Profile to TM Hierarchy */ + for (i = 0; i < SUBPORT_NODES_PER_PORT; i++) { + ssp.peak.rate = h->subport_node_shaper_rate; + ssp.peak.size = TOKEN_BUCKET_SIZE; + ssp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS; + + if (rte_tm_shaper_profile_add(port_id, shaper_profile_id, + &ssp, error)) { + printf("%s ERROR(%d)-%s!(shaper_id %u)\n ", + __func__, error->type, error->message, + shaper_profile_id); + return -1; + } + + /* Node Parameters */ + h->subport_node_id[i] = SUBPORT_NODES_START_ID + i; + subport_parent_node_id = h->root_node_id; + weight = 1; + priority = 0; + level_id = TM_NODE_LEVEL_SUBPORT; + snp.shaper_profile_id = shaper_profile_id; + snp.nonleaf.n_sp_priorities = 1; + snp.stats_mask = STATS_MASK_DEFAULT; + + /* Add Node to TM Hiearchy */ + if (rte_tm_node_add(port_id, + h->subport_node_id[i], + subport_parent_node_id, + priority, weight, + level_id, + &snp, + error)) { + printf("%s ERROR(%d)-%s!(node %u,parent %u,level %u)\n", + __func__, + error->type, + error->message, + h->subport_node_id[i], + subport_parent_node_id, + level_id); + return -1; + } + shaper_profile_id++; + subport_node_id++; + } + /* Update */ + h->n_shapers = shaper_profile_id; + + printf(" Subport nodes added (Start id %u, Count %u, level %u)\n", + h->subport_node_id[0], SUBPORT_NODES_PER_PORT, level_id); + + return 0; +} + +static int +softport_tm_pipe_node_add(portid_t port_id, + struct tm_hierarchy *h, + struct rte_tm_error *error) +{ + uint32_t pipe_parent_node_id; + struct rte_tm_node_params pnp; + struct rte_tm_shaper_params psp; + uint32_t priority, weight, level_id, shaper_profile_id; + uint32_t i, j; + + memset(&psp, 0, sizeof(struct rte_tm_shaper_params)); + memset(&pnp, 0, sizeof(struct rte_tm_node_params)); + + shaper_profile_id = h->n_shapers; + + /* Shaper Profile Parameters */ + psp.peak.rate = h->pipe_node_shaper_rate; + psp.peak.size = TOKEN_BUCKET_SIZE; + psp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS; + + /* Pipe Node Parameters */ + weight = 1; + priority = 0; + level_id = TM_NODE_LEVEL_PIPE; + pnp.nonleaf.n_sp_priorities = 4; + pnp.stats_mask = STATS_MASK_DEFAULT; + + /* Add Shaper Profiles and Nodes to TM Hierarchy */ + for (i = 0; i < SUBPORT_NODES_PER_PORT; i++) { + for (j = 0; j < PIPE_NODES_PER_SUBPORT; j++) { + if (rte_tm_shaper_profile_add(port_id, + shaper_profile_id, &psp, error)) { + printf("%s ERROR(%d)-%s!(shaper_id %u)\n ", + __func__, error->type, error->message, + shaper_profile_id); + return -1; + } + pnp.shaper_profile_id = shaper_profile_id; + pipe_parent_node_id = h->subport_node_id[i]; + h->pipe_node_id[i][j] = PIPE_NODES_START_ID + + (i * PIPE_NODES_PER_SUBPORT) + j; + + if (rte_tm_node_add(port_id, + h->pipe_node_id[i][j], + pipe_parent_node_id, + priority, weight, level_id, + &pnp, + error)) { + printf("%s ERROR(%d)-%s!(node %u,parent %u )\n", + __func__, + error->type, + error->message, + h->pipe_node_id[i][j], + pipe_parent_node_id); + + return -1; + } + shaper_profile_id++; + } + } + /* Update */ + h->n_shapers = shaper_profile_id; + + printf(" Pipe nodes added (Start id %u, Count %u, level %u)\n", + h->pipe_node_id[0][0], NUM_PIPE_NODES, level_id); + + return 0; +} + +static int +softport_tm_tc_node_add(portid_t port_id, + struct tm_hierarchy *h, + struct rte_tm_error *error) +{ + uint32_t tc_parent_node_id; + struct rte_tm_node_params tnp; + struct rte_tm_shaper_params tsp, tssp; + uint32_t shared_shaper_profile_id[TC_NODES_PER_PIPE]; + uint32_t priority, weight, level_id, shaper_profile_id; + uint32_t pos, n_tc_nodes, i, j, k; + + memset(&tsp, 0, sizeof(struct rte_tm_shaper_params)); + memset(&tssp, 0, sizeof(struct rte_tm_shaper_params)); + memset(&tnp, 0, sizeof(struct rte_tm_node_params)); + + shaper_profile_id = h->n_shapers; + + /* Private Shaper Profile (TC) Parameters */ + tsp.peak.rate = h->tc_node_shaper_rate; + tsp.peak.size = TOKEN_BUCKET_SIZE; + tsp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS; + + /* Shared Shaper Profile (TC) Parameters */ + tssp.peak.rate = h->tc_node_shared_shaper_rate; + tssp.peak.size = TOKEN_BUCKET_SIZE; + tssp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS; + + /* TC Node Parameters */ + weight = 1; + level_id = TM_NODE_LEVEL_TC; + tnp.n_shared_shapers = 1; + tnp.nonleaf.n_sp_priorities = 1; + tnp.stats_mask = STATS_MASK_DEFAULT; + + /* Add Shared Shaper Profiles to TM Hierarchy */ + for (i = 0; i < TC_NODES_PER_PIPE; i++) { + shared_shaper_profile_id[i] = shaper_profile_id; + + if (rte_tm_shaper_profile_add(port_id, + shared_shaper_profile_id[i], &tssp, error)) { + printf("%s ERROR(%d)-%s!(Shared shaper profileid %u)\n", + __func__, error->type, error->message, + shared_shaper_profile_id[i]); + + return -1; + } + if (rte_tm_shared_shaper_add_update(port_id, i, + shared_shaper_profile_id[i], error)) { + printf("%s ERROR(%d)-%s!(Shared shaper id %u)\n", + __func__, error->type, error->message, i); + + return -1; + } + shaper_profile_id++; + } + + /* Add Shaper Profiles and Nodes to TM Hierarchy */ + n_tc_nodes = 0; + for (i = 0; i < SUBPORT_NODES_PER_PORT; i++) { + for (j = 0; j < PIPE_NODES_PER_SUBPORT; j++) { + for (k = 0; k < TC_NODES_PER_PIPE ; k++) { + priority = k; + tc_parent_node_id = h->pipe_node_id[i][j]; + tnp.shared_shaper_id = + (uint32_t *)calloc(1, sizeof(uint32_t)); + if (tnp.shared_shaper_id == NULL) { + printf("Shared shaper mem alloc err\n"); + return -1; + } + tnp.shared_shaper_id[0] = k; + pos = j + (i * PIPE_NODES_PER_SUBPORT); + h->tc_node_id[pos][k] = + TC_NODES_START_ID + n_tc_nodes; + + if (rte_tm_shaper_profile_add(port_id, + shaper_profile_id, &tsp, error)) { + printf("%s ERROR(%d)-%s!(shaper %u)\n", + __func__, error->type, + error->message, + shaper_profile_id); + + return -1; + } + tnp.shaper_profile_id = shaper_profile_id; + if (rte_tm_node_add(port_id, + h->tc_node_id[pos][k], + tc_parent_node_id, + priority, weight, + level_id, + &tnp, error)) { + printf("%s ERROR(%d)-%s!(node id %u)\n", + __func__, + error->type, + error->message, + h->tc_node_id[pos][k]); + + return -1; + } + shaper_profile_id++; + n_tc_nodes++; + } + } + } + /* Update */ + h->n_shapers = shaper_profile_id; + + printf(" TC nodes added (Start id %u, Count %u, level %u)\n", + h->tc_node_id[0][0], n_tc_nodes, level_id); + + return 0; +} + +static int +softport_tm_queue_node_add(portid_t port_id, struct tm_hierarchy *h, + struct rte_tm_error *error) +{ + uint32_t queue_parent_node_id; + struct rte_tm_node_params qnp; + uint32_t priority, weight, level_id, pos; + uint32_t n_queue_nodes, i, j, k; + + memset(&qnp, 0, sizeof(struct rte_tm_node_params)); + + /* Queue Node Parameters */ + priority = 0; + weight = 1; + level_id = TM_NODE_LEVEL_QUEUE; + qnp.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE; + qnp.leaf.cman = RTE_TM_CMAN_TAIL_DROP; + qnp.stats_mask = STATS_MASK_QUEUE; + + /* Add Queue Nodes to TM Hierarchy */ + n_queue_nodes = 0; + for (i = 0; i < NUM_PIPE_NODES; i++) { + for (j = 0; j < TC_NODES_PER_PIPE; j++) { + queue_parent_node_id = h->tc_node_id[i][j]; + for (k = 0; k < QUEUE_NODES_PER_TC; k++) { + pos = j + (i * TC_NODES_PER_PIPE); + h->queue_node_id[pos][k] = n_queue_nodes; + if (rte_tm_node_add(port_id, + h->queue_node_id[pos][k], + queue_parent_node_id, + priority, + weight, + level_id, + &qnp, error)) { + printf("%s ERROR(%d)-%s!(node %u)\n", + __func__, + error->type, + error->message, + h->queue_node_id[pos][k]); + + return -1; + } + n_queue_nodes++; + } + } + } + printf(" Queue nodes added (Start id %u, Count %u, level %u)\n", + h->queue_node_id[0][0], n_queue_nodes, level_id); + + return 0; +} + +static int +softport_tm_hierarchy_specify(portid_t port_id, + struct rte_tm_error *error) +{ + + struct tm_hierarchy h; + int status; + + memset(&h, 0, sizeof(struct tm_hierarchy)); + + /* TM hierarchy shapers rate */ + set_tm_hiearchy_nodes_shaper_rate(port_id, &h); + + /* Add root node (level 0) */ + status = softport_tm_root_node_add(port_id, &h, error); + if (status) + return status; + + /* Add subport node (level 1) */ + status = softport_tm_subport_node_add(port_id, &h, error); + if (status) + return status; + + /* Add pipe nodes (level 2) */ + status = softport_tm_pipe_node_add(port_id, &h, error); + if (status) + return status; + + /* Add traffic class nodes (level 3) */ + status = softport_tm_tc_node_add(port_id, &h, error); + if (status) + return status; + + /* Add queue nodes (level 4) */ + status = softport_tm_queue_node_add(port_id, &h, error); + if (status) + return status; + + return 0; +} + +/* + * Softnic TM default configuration + */ +static void +softnic_tm_default_config(portid_t pi) +{ + struct rte_port *port = &ports[pi]; + struct rte_tm_error error; + int status; + + /* Stop port */ + rte_eth_dev_stop(pi); + + /* TM hierarchy specification */ + status = softport_tm_hierarchy_specify(pi, &error); + if (status) { + printf(" TM Hierarchy built error(%d) - %s\n", + error.type, error.message); + return; + } + printf("\n TM Hierarchy Specified!\n"); + + /* TM hierarchy commit */ + status = rte_tm_hierarchy_commit(pi, 0, &error); + if (status) { + printf(" Hierarchy commit error(%d) - %s\n", + error.type, error.message); + return; + } + printf(" Hierarchy Committed (port %u)!\n", pi); + + /* Start port */ + status = rte_eth_dev_start(pi); + if (status) { + printf("\n Port %u start error!\n", pi); + return; + } + + /* Reset the default hierarchy flag */ + port->softport.default_tm_hierarchy_enable = 0; +} + +/* + * Softnic forwarding init + */ +static void +softnic_fwd_begin(portid_t pi) +{ + struct rte_port *port = &ports[pi]; + uint32_t lcore, fwd_core_present = 0, softnic_run_launch = 0; + int status; + + softnic_fwd_lcore = port->softport.fwd_lcore_arg[0]; + softnic_port_id = pi; + + /* Launch softnic_run function on lcores */ + for (lcore = 0; lcore < RTE_MAX_LCORE; lcore++) { + if (!rte_lcore_is_enabled(lcore)) + continue; + + if (lcore == rte_get_master_lcore()) + continue; + + if (fwd_core_present == 0) { + fwd_core_present++; + continue; + } + + status = rte_eal_remote_launch(softnic_begin, NULL, lcore); + if (status) + printf("softnic launch on lcore %u failed (%d)\n", + lcore, status); + + softnic_run_launch = 1; + } + + if (!softnic_run_launch) + softnic_fwd_engine.packet_fwd = softnic_fwd_run; + + /* Softnic TM default configuration */ + if (port->softport.default_tm_hierarchy_enable == 1) + softnic_tm_default_config(pi); +} + +struct fwd_engine softnic_fwd_engine = { + .fwd_mode_name = "softnic", + .port_fwd_begin = softnic_fwd_begin, + .port_fwd_end = NULL, + .packet_fwd = softnic_fwd, +}; diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 31e9f9543a..d3ce92f3c5 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -155,9 +155,8 @@ struct fwd_engine * fwd_engines[] = { &tx_only_engine, &csum_fwd_engine, &icmp_echo_engine, -#if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED - &softnic_tm_engine, - &softnic_tm_bypass_engine, +#if defined RTE_LIBRTE_PMD_SOFTNIC + &softnic_fwd_engine, #endif #ifdef RTE_LIBRTE_IEEE1588 &ieee1588_fwd_engine, @@ -815,6 +814,19 @@ init_config(void) "rte_gro_ctx_create() failed\n"); } } + +#if defined RTE_LIBRTE_PMD_SOFTNIC + if (strcmp(cur_fwd_eng->fwd_mode_name, "softnic") == 0) { + RTE_ETH_FOREACH_DEV(pid) { + port = &ports[pid]; + const char *driver = port->dev_info.driver_name; + + if (strcmp(driver, "net_softnic") == 0) + port->softport.fwd_lcore_arg = fwd_lcores; + } + } +#endif + } @@ -2390,17 +2402,6 @@ init_port_config(void) (rte_eth_devices[pid].data->dev_flags & RTE_ETH_DEV_INTR_RMV)) port->dev_conf.intr_conf.rmv = 1; - -#if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED - /* Detect softnic port */ - if (!strcmp(port->dev_info.driver_name, "net_softnic")) { - port->softnic_enable = 1; - memset(&port->softport, 0, sizeof(struct softnic_port)); - - if (!strcmp(cur_fwd_eng->fwd_mode_name, "tm")) - port->softport.tm_flag = 1; - } -#endif } } diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index f51cd9dd9b..4fc30a8ba6 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -57,10 +57,10 @@ typedef uint16_t streamid_t; #define MAX_QUEUE_ID ((1 << (sizeof(queueid_t) * 8)) - 1) -#if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED -#define TM_MODE 1 +#if defined RTE_LIBRTE_PMD_SOFTNIC +#define SOFTNIC 1 #else -#define TM_MODE 0 +#define SOFTNIC 0 #endif enum { @@ -135,35 +135,13 @@ struct port_flow { uint8_t data[]; /**< Storage for pattern/actions. */ }; -#ifdef TM_MODE -/** - * Soft port tm related parameters - */ -struct softnic_port_tm { - uint32_t default_hierarchy_enable; /**< def hierarchy enable flag */ - uint32_t hierarchy_config; /**< set to 1 if hierarchy configured */ - - uint32_t n_subports_per_port; /**< Num of subport nodes per port */ - uint32_t n_pipes_per_subport; /**< Num of pipe nodes per subport */ - - uint64_t tm_pktfield0_slabpos; /**< Pkt field position for subport */ - uint64_t tm_pktfield0_slabmask; /**< Pkt field mask for the subport */ - uint64_t tm_pktfield0_slabshr; - uint64_t tm_pktfield1_slabpos; /**< Pkt field position for the pipe */ - uint64_t tm_pktfield1_slabmask; /**< Pkt field mask for the pipe */ - uint64_t tm_pktfield1_slabshr; - uint64_t tm_pktfield2_slabpos; /**< Pkt field position table index */ - uint64_t tm_pktfield2_slabmask; /**< Pkt field mask for tc table idx */ - uint64_t tm_pktfield2_slabshr; - uint64_t tm_tc_table[64]; /**< TC translation table */ -}; - +#ifdef SOFTNIC /** * The data structure associate with softnic port */ struct softnic_port { - unsigned int tm_flag; /**< set to 1 if tm feature is enabled */ - struct softnic_port_tm tm; /**< softnic port tm parameters */ + uint32_t default_tm_hierarchy_enable; /**< default tm hierarchy */ + struct fwd_lcore **fwd_lcore_arg; /**< softnic fwd core parameters */ }; #endif @@ -202,9 +180,8 @@ struct rte_port { uint32_t mc_addr_nb; /**< nb. of addr. in mc_addr_pool */ uint8_t slave_flag; /**< bonding slave port */ struct port_flow *flow_list; /**< Associated flows. */ -#ifdef TM_MODE - unsigned int softnic_enable; /**< softnic flag */ - struct softnic_port softport; /**< softnic port params */ +#ifdef SOFTNIC + struct softnic_port softport; /**< softnic params */ #endif }; @@ -266,9 +243,8 @@ extern struct fwd_engine rx_only_engine; extern struct fwd_engine tx_only_engine; extern struct fwd_engine csum_fwd_engine; extern struct fwd_engine icmp_echo_engine; -#ifdef TM_MODE -extern struct fwd_engine softnic_tm_engine; -extern struct fwd_engine softnic_tm_bypass_engine; +#ifdef SOFTNIC +extern struct fwd_engine softnic_fwd_engine; #endif #ifdef RTE_LIBRTE_IEEE1588 extern struct fwd_engine ieee1588_fwd_engine; diff --git a/app/test-pmd/tm.c b/app/test-pmd/tm.c deleted file mode 100644 index 7231552a41..0000000000 --- a/app/test-pmd/tm.c +++ /dev/null @@ -1,840 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2017 Intel Corporation - */ -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "testpmd.h" - -#define SUBPORT_NODES_PER_PORT 1 -#define PIPE_NODES_PER_SUBPORT 4096 -#define TC_NODES_PER_PIPE 4 -#define QUEUE_NODES_PER_TC 4 - -#define NUM_PIPE_NODES \ - (SUBPORT_NODES_PER_PORT * PIPE_NODES_PER_SUBPORT) - -#define NUM_TC_NODES \ - (NUM_PIPE_NODES * TC_NODES_PER_PIPE) - -#define ROOT_NODE_ID 1000000 -#define SUBPORT_NODES_START_ID 900000 -#define PIPE_NODES_START_ID 800000 -#define TC_NODES_START_ID 700000 - -#define STATS_MASK_DEFAULT \ - (RTE_TM_STATS_N_PKTS | \ - RTE_TM_STATS_N_BYTES | \ - RTE_TM_STATS_N_PKTS_GREEN_DROPPED | \ - RTE_TM_STATS_N_BYTES_GREEN_DROPPED) - -#define STATS_MASK_QUEUE \ - (STATS_MASK_DEFAULT | \ - RTE_TM_STATS_N_PKTS_QUEUED) - -#define BYTES_IN_MBPS (1000 * 1000 / 8) -#define TOKEN_BUCKET_SIZE 1000000 - -/* TM Hierarchy Levels */ -enum tm_hierarchy_level { - TM_NODE_LEVEL_PORT = 0, - TM_NODE_LEVEL_SUBPORT, - TM_NODE_LEVEL_PIPE, - TM_NODE_LEVEL_TC, - TM_NODE_LEVEL_QUEUE, - TM_NODE_LEVEL_MAX, -}; - -struct tm_hierarchy { - /* TM Nodes */ - uint32_t root_node_id; - uint32_t subport_node_id[SUBPORT_NODES_PER_PORT]; - uint32_t pipe_node_id[SUBPORT_NODES_PER_PORT][PIPE_NODES_PER_SUBPORT]; - uint32_t tc_node_id[NUM_PIPE_NODES][TC_NODES_PER_PIPE]; - uint32_t queue_node_id[NUM_TC_NODES][QUEUE_NODES_PER_TC]; - - /* TM Hierarchy Nodes Shaper Rates */ - uint32_t root_node_shaper_rate; - uint32_t subport_node_shaper_rate; - uint32_t pipe_node_shaper_rate; - uint32_t tc_node_shaper_rate; - uint32_t tc_node_shared_shaper_rate; - - uint32_t n_shapers; -}; - -#define BITFIELD(byte_array, slab_pos, slab_mask, slab_shr) \ -({ \ - uint64_t slab = *((uint64_t *) &byte_array[slab_pos]); \ - uint64_t val = \ - (rte_be_to_cpu_64(slab) & slab_mask) >> slab_shr; \ - val; \ -}) - -#define RTE_SCHED_PORT_HIERARCHY(subport, pipe, \ - traffic_class, queue, color) \ - ((((uint64_t) (queue)) & 0x3) | \ - ((((uint64_t) (traffic_class)) & 0x3) << 2) | \ - ((((uint64_t) (color)) & 0x3) << 4) | \ - ((((uint64_t) (subport)) & 0xFFFF) << 16) | \ - ((((uint64_t) (pipe)) & 0xFFFFFFFF) << 32)) - - -static void -pkt_metadata_set(struct rte_port *p, struct rte_mbuf **pkts, - uint32_t n_pkts) -{ - struct softnic_port_tm *tm = &p->softport.tm; - uint32_t i; - - for (i = 0; i < (n_pkts & (~0x3)); i += 4) { - struct rte_mbuf *pkt0 = pkts[i]; - struct rte_mbuf *pkt1 = pkts[i + 1]; - struct rte_mbuf *pkt2 = pkts[i + 2]; - struct rte_mbuf *pkt3 = pkts[i + 3]; - - uint8_t *pkt0_data = rte_pktmbuf_mtod(pkt0, uint8_t *); - uint8_t *pkt1_data = rte_pktmbuf_mtod(pkt1, uint8_t *); - uint8_t *pkt2_data = rte_pktmbuf_mtod(pkt2, uint8_t *); - uint8_t *pkt3_data = rte_pktmbuf_mtod(pkt3, uint8_t *); - - uint64_t pkt0_subport = BITFIELD(pkt0_data, - tm->tm_pktfield0_slabpos, - tm->tm_pktfield0_slabmask, - tm->tm_pktfield0_slabshr); - uint64_t pkt0_pipe = BITFIELD(pkt0_data, - tm->tm_pktfield1_slabpos, - tm->tm_pktfield1_slabmask, - tm->tm_pktfield1_slabshr); - uint64_t pkt0_dscp = BITFIELD(pkt0_data, - tm->tm_pktfield2_slabpos, - tm->tm_pktfield2_slabmask, - tm->tm_pktfield2_slabshr); - uint32_t pkt0_tc = tm->tm_tc_table[pkt0_dscp & 0x3F] >> 2; - uint32_t pkt0_tc_q = tm->tm_tc_table[pkt0_dscp & 0x3F] & 0x3; - uint64_t pkt1_subport = BITFIELD(pkt1_data, - tm->tm_pktfield0_slabpos, - tm->tm_pktfield0_slabmask, - tm->tm_pktfield0_slabshr); - uint64_t pkt1_pipe = BITFIELD(pkt1_data, - tm->tm_pktfield1_slabpos, - tm->tm_pktfield1_slabmask, - tm->tm_pktfield1_slabshr); - uint64_t pkt1_dscp = BITFIELD(pkt1_data, - tm->tm_pktfield2_slabpos, - tm->tm_pktfield2_slabmask, - tm->tm_pktfield2_slabshr); - uint32_t pkt1_tc = tm->tm_tc_table[pkt1_dscp & 0x3F] >> 2; - uint32_t pkt1_tc_q = tm->tm_tc_table[pkt1_dscp & 0x3F] & 0x3; - - uint64_t pkt2_subport = BITFIELD(pkt2_data, - tm->tm_pktfield0_slabpos, - tm->tm_pktfield0_slabmask, - tm->tm_pktfield0_slabshr); - uint64_t pkt2_pipe = BITFIELD(pkt2_data, - tm->tm_pktfield1_slabpos, - tm->tm_pktfield1_slabmask, - tm->tm_pktfield1_slabshr); - uint64_t pkt2_dscp = BITFIELD(pkt2_data, - tm->tm_pktfield2_slabpos, - tm->tm_pktfield2_slabmask, - tm->tm_pktfield2_slabshr); - uint32_t pkt2_tc = tm->tm_tc_table[pkt2_dscp & 0x3F] >> 2; - uint32_t pkt2_tc_q = tm->tm_tc_table[pkt2_dscp & 0x3F] & 0x3; - - uint64_t pkt3_subport = BITFIELD(pkt3_data, - tm->tm_pktfield0_slabpos, - tm->tm_pktfield0_slabmask, - tm->tm_pktfield0_slabshr); - uint64_t pkt3_pipe = BITFIELD(pkt3_data, - tm->tm_pktfield1_slabpos, - tm->tm_pktfield1_slabmask, - tm->tm_pktfield1_slabshr); - uint64_t pkt3_dscp = BITFIELD(pkt3_data, - tm->tm_pktfield2_slabpos, - tm->tm_pktfield2_slabmask, - tm->tm_pktfield2_slabshr); - uint32_t pkt3_tc = tm->tm_tc_table[pkt3_dscp & 0x3F] >> 2; - uint32_t pkt3_tc_q = tm->tm_tc_table[pkt3_dscp & 0x3F] & 0x3; - - uint64_t pkt0_sched = RTE_SCHED_PORT_HIERARCHY(pkt0_subport, - pkt0_pipe, - pkt0_tc, - pkt0_tc_q, - 0); - uint64_t pkt1_sched = RTE_SCHED_PORT_HIERARCHY(pkt1_subport, - pkt1_pipe, - pkt1_tc, - pkt1_tc_q, - 0); - uint64_t pkt2_sched = RTE_SCHED_PORT_HIERARCHY(pkt2_subport, - pkt2_pipe, - pkt2_tc, - pkt2_tc_q, - 0); - uint64_t pkt3_sched = RTE_SCHED_PORT_HIERARCHY(pkt3_subport, - pkt3_pipe, - pkt3_tc, - pkt3_tc_q, - 0); - - pkt0->hash.sched.lo = pkt0_sched & 0xFFFFFFFF; - pkt0->hash.sched.hi = pkt0_sched >> 32; - pkt1->hash.sched.lo = pkt1_sched & 0xFFFFFFFF; - pkt1->hash.sched.hi = pkt1_sched >> 32; - pkt2->hash.sched.lo = pkt2_sched & 0xFFFFFFFF; - pkt2->hash.sched.hi = pkt2_sched >> 32; - pkt3->hash.sched.lo = pkt3_sched & 0xFFFFFFFF; - pkt3->hash.sched.hi = pkt3_sched >> 32; - } - - for (; i < n_pkts; i++) { - struct rte_mbuf *pkt = pkts[i]; - - uint8_t *pkt_data = rte_pktmbuf_mtod(pkt, uint8_t *); - - uint64_t pkt_subport = BITFIELD(pkt_data, - tm->tm_pktfield0_slabpos, - tm->tm_pktfield0_slabmask, - tm->tm_pktfield0_slabshr); - uint64_t pkt_pipe = BITFIELD(pkt_data, - tm->tm_pktfield1_slabpos, - tm->tm_pktfield1_slabmask, - tm->tm_pktfield1_slabshr); - uint64_t pkt_dscp = BITFIELD(pkt_data, - tm->tm_pktfield2_slabpos, - tm->tm_pktfield2_slabmask, - tm->tm_pktfield2_slabshr); - uint32_t pkt_tc = tm->tm_tc_table[pkt_dscp & 0x3F] >> 2; - uint32_t pkt_tc_q = tm->tm_tc_table[pkt_dscp & 0x3F] & 0x3; - - uint64_t pkt_sched = RTE_SCHED_PORT_HIERARCHY(pkt_subport, - pkt_pipe, - pkt_tc, - pkt_tc_q, - 0); - - pkt->hash.sched.lo = pkt_sched & 0xFFFFFFFF; - pkt->hash.sched.hi = pkt_sched >> 32; - } -} - -/* - * Soft port packet forward - */ -static void -softport_packet_fwd(struct fwd_stream *fs) -{ - struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; - struct rte_port *rte_tx_port = &ports[fs->tx_port]; - uint16_t nb_rx; - uint16_t nb_tx; - uint32_t retry; - -#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES - uint64_t start_tsc; - uint64_t end_tsc; - uint64_t core_cycles; -#endif - -#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES - start_tsc = rte_rdtsc(); -#endif - - /* Packets Receive */ - nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, - pkts_burst, nb_pkt_per_burst); - fs->rx_packets += nb_rx; - -#ifdef RTE_TEST_PMD_RECORD_BURST_STATS - fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; -#endif - - if (rte_tx_port->softnic_enable) { - /* Set packet metadata if tm flag enabled */ - if (rte_tx_port->softport.tm_flag) - pkt_metadata_set(rte_tx_port, pkts_burst, nb_rx); - - /* Softport run */ - rte_pmd_softnic_run(fs->tx_port); - } - nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, - pkts_burst, nb_rx); - - /* Retry if necessary */ - if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) { - retry = 0; - while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) { - rte_delay_us(burst_tx_delay_time); - nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue, - &pkts_burst[nb_tx], nb_rx - nb_tx); - } - } - fs->tx_packets += nb_tx; - -#ifdef RTE_TEST_PMD_RECORD_BURST_STATS - fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; -#endif - - if (unlikely(nb_tx < nb_rx)) { - fs->fwd_dropped += (nb_rx - nb_tx); - do { - rte_pktmbuf_free(pkts_burst[nb_tx]); - } while (++nb_tx < nb_rx); - } -#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES - end_tsc = rte_rdtsc(); - core_cycles = (end_tsc - start_tsc); - fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); -#endif -} - -static void -set_tm_hiearchy_nodes_shaper_rate(portid_t port_id, struct tm_hierarchy *h) -{ - struct rte_eth_link link_params; - uint64_t tm_port_rate; - - memset(&link_params, 0, sizeof(link_params)); - - rte_eth_link_get(port_id, &link_params); - tm_port_rate = (uint64_t)link_params.link_speed * BYTES_IN_MBPS; - - if (tm_port_rate > UINT32_MAX) - tm_port_rate = UINT32_MAX; - - /* Set tm hierarchy shapers rate */ - h->root_node_shaper_rate = tm_port_rate; - h->subport_node_shaper_rate = - tm_port_rate / SUBPORT_NODES_PER_PORT; - h->pipe_node_shaper_rate - = h->subport_node_shaper_rate / PIPE_NODES_PER_SUBPORT; - h->tc_node_shaper_rate = h->pipe_node_shaper_rate; - h->tc_node_shared_shaper_rate = h->subport_node_shaper_rate; -} - -static int -softport_tm_root_node_add(portid_t port_id, struct tm_hierarchy *h, - struct rte_tm_error *error) -{ - struct rte_tm_node_params rnp; - struct rte_tm_shaper_params rsp; - uint32_t priority, weight, level_id, shaper_profile_id; - - memset(&rsp, 0, sizeof(struct rte_tm_shaper_params)); - memset(&rnp, 0, sizeof(struct rte_tm_node_params)); - - /* Shaper profile Parameters */ - rsp.peak.rate = h->root_node_shaper_rate; - rsp.peak.size = TOKEN_BUCKET_SIZE; - rsp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS; - shaper_profile_id = 0; - - if (rte_tm_shaper_profile_add(port_id, shaper_profile_id, - &rsp, error)) { - printf("%s ERROR(%d)-%s!(shaper_id %u)\n ", - __func__, error->type, error->message, - shaper_profile_id); - return -1; - } - - /* Root Node Parameters */ - h->root_node_id = ROOT_NODE_ID; - weight = 1; - priority = 0; - level_id = TM_NODE_LEVEL_PORT; - rnp.shaper_profile_id = shaper_profile_id; - rnp.nonleaf.n_sp_priorities = 1; - rnp.stats_mask = STATS_MASK_DEFAULT; - - /* Add Node to TM Hierarchy */ - if (rte_tm_node_add(port_id, h->root_node_id, RTE_TM_NODE_ID_NULL, - priority, weight, level_id, &rnp, error)) { - printf("%s ERROR(%d)-%s!(node_id %u, parent_id %u, level %u)\n", - __func__, error->type, error->message, - h->root_node_id, RTE_TM_NODE_ID_NULL, - level_id); - return -1; - } - /* Update */ - h->n_shapers++; - - printf(" Root node added (Start id %u, Count %u, level %u)\n", - h->root_node_id, 1, level_id); - - return 0; -} - -static int -softport_tm_subport_node_add(portid_t port_id, struct tm_hierarchy *h, - struct rte_tm_error *error) -{ - uint32_t subport_parent_node_id, subport_node_id = 0; - struct rte_tm_node_params snp; - struct rte_tm_shaper_params ssp; - uint32_t priority, weight, level_id, shaper_profile_id; - uint32_t i; - - memset(&ssp, 0, sizeof(struct rte_tm_shaper_params)); - memset(&snp, 0, sizeof(struct rte_tm_node_params)); - - shaper_profile_id = h->n_shapers; - - /* Add Shaper Profile to TM Hierarchy */ - for (i = 0; i < SUBPORT_NODES_PER_PORT; i++) { - ssp.peak.rate = h->subport_node_shaper_rate; - ssp.peak.size = TOKEN_BUCKET_SIZE; - ssp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS; - - if (rte_tm_shaper_profile_add(port_id, shaper_profile_id, - &ssp, error)) { - printf("%s ERROR(%d)-%s!(shaper_id %u)\n ", - __func__, error->type, error->message, - shaper_profile_id); - return -1; - } - - /* Node Parameters */ - h->subport_node_id[i] = SUBPORT_NODES_START_ID + i; - subport_parent_node_id = h->root_node_id; - weight = 1; - priority = 0; - level_id = TM_NODE_LEVEL_SUBPORT; - snp.shaper_profile_id = shaper_profile_id; - snp.nonleaf.n_sp_priorities = 1; - snp.stats_mask = STATS_MASK_DEFAULT; - - /* Add Node to TM Hiearchy */ - if (rte_tm_node_add(port_id, - h->subport_node_id[i], - subport_parent_node_id, - priority, weight, - level_id, - &snp, - error)) { - printf("%s ERROR(%d)-%s!(node %u,parent %u,level %u)\n", - __func__, - error->type, - error->message, - h->subport_node_id[i], - subport_parent_node_id, - level_id); - return -1; - } - shaper_profile_id++; - subport_node_id++; - } - /* Update */ - h->n_shapers = shaper_profile_id; - - printf(" Subport nodes added (Start id %u, Count %u, level %u)\n", - h->subport_node_id[0], SUBPORT_NODES_PER_PORT, level_id); - - return 0; -} - -static int -softport_tm_pipe_node_add(portid_t port_id, struct tm_hierarchy *h, - struct rte_tm_error *error) -{ - uint32_t pipe_parent_node_id; - struct rte_tm_node_params pnp; - struct rte_tm_shaper_params psp; - uint32_t priority, weight, level_id, shaper_profile_id; - uint32_t i, j; - - memset(&psp, 0, sizeof(struct rte_tm_shaper_params)); - memset(&pnp, 0, sizeof(struct rte_tm_node_params)); - - shaper_profile_id = h->n_shapers; - - /* Shaper Profile Parameters */ - psp.peak.rate = h->pipe_node_shaper_rate; - psp.peak.size = TOKEN_BUCKET_SIZE; - psp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS; - - /* Pipe Node Parameters */ - weight = 1; - priority = 0; - level_id = TM_NODE_LEVEL_PIPE; - pnp.nonleaf.n_sp_priorities = 4; - pnp.stats_mask = STATS_MASK_DEFAULT; - - /* Add Shaper Profiles and Nodes to TM Hierarchy */ - for (i = 0; i < SUBPORT_NODES_PER_PORT; i++) { - for (j = 0; j < PIPE_NODES_PER_SUBPORT; j++) { - if (rte_tm_shaper_profile_add(port_id, - shaper_profile_id, &psp, error)) { - printf("%s ERROR(%d)-%s!(shaper_id %u)\n ", - __func__, error->type, error->message, - shaper_profile_id); - return -1; - } - pnp.shaper_profile_id = shaper_profile_id; - pipe_parent_node_id = h->subport_node_id[i]; - h->pipe_node_id[i][j] = PIPE_NODES_START_ID + - (i * PIPE_NODES_PER_SUBPORT) + j; - - if (rte_tm_node_add(port_id, - h->pipe_node_id[i][j], - pipe_parent_node_id, - priority, weight, level_id, - &pnp, - error)) { - printf("%s ERROR(%d)-%s!(node %u,parent %u )\n", - __func__, - error->type, - error->message, - h->pipe_node_id[i][j], - pipe_parent_node_id); - - return -1; - } - shaper_profile_id++; - } - } - /* Update */ - h->n_shapers = shaper_profile_id; - - printf(" Pipe nodes added (Start id %u, Count %u, level %u)\n", - h->pipe_node_id[0][0], NUM_PIPE_NODES, level_id); - - return 0; -} - -static int -softport_tm_tc_node_add(portid_t port_id, struct tm_hierarchy *h, - struct rte_tm_error *error) -{ - uint32_t tc_parent_node_id; - struct rte_tm_node_params tnp; - struct rte_tm_shaper_params tsp, tssp; - uint32_t shared_shaper_profile_id[TC_NODES_PER_PIPE]; - uint32_t priority, weight, level_id, shaper_profile_id; - uint32_t pos, n_tc_nodes, i, j, k; - - memset(&tsp, 0, sizeof(struct rte_tm_shaper_params)); - memset(&tssp, 0, sizeof(struct rte_tm_shaper_params)); - memset(&tnp, 0, sizeof(struct rte_tm_node_params)); - - shaper_profile_id = h->n_shapers; - - /* Private Shaper Profile (TC) Parameters */ - tsp.peak.rate = h->tc_node_shaper_rate; - tsp.peak.size = TOKEN_BUCKET_SIZE; - tsp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS; - - /* Shared Shaper Profile (TC) Parameters */ - tssp.peak.rate = h->tc_node_shared_shaper_rate; - tssp.peak.size = TOKEN_BUCKET_SIZE; - tssp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS; - - /* TC Node Parameters */ - weight = 1; - level_id = TM_NODE_LEVEL_TC; - tnp.n_shared_shapers = 1; - tnp.nonleaf.n_sp_priorities = 1; - tnp.stats_mask = STATS_MASK_DEFAULT; - - /* Add Shared Shaper Profiles to TM Hierarchy */ - for (i = 0; i < TC_NODES_PER_PIPE; i++) { - shared_shaper_profile_id[i] = shaper_profile_id; - - if (rte_tm_shaper_profile_add(port_id, - shared_shaper_profile_id[i], &tssp, error)) { - printf("%s ERROR(%d)-%s!(Shared shaper profileid %u)\n", - __func__, error->type, error->message, - shared_shaper_profile_id[i]); - - return -1; - } - if (rte_tm_shared_shaper_add_update(port_id, i, - shared_shaper_profile_id[i], error)) { - printf("%s ERROR(%d)-%s!(Shared shaper id %u)\n", - __func__, error->type, error->message, i); - - return -1; - } - shaper_profile_id++; - } - - /* Add Shaper Profiles and Nodes to TM Hierarchy */ - n_tc_nodes = 0; - for (i = 0; i < SUBPORT_NODES_PER_PORT; i++) { - for (j = 0; j < PIPE_NODES_PER_SUBPORT; j++) { - for (k = 0; k < TC_NODES_PER_PIPE ; k++) { - priority = k; - tc_parent_node_id = h->pipe_node_id[i][j]; - tnp.shared_shaper_id = - (uint32_t *)calloc(1, sizeof(uint32_t)); - if (tnp.shared_shaper_id == NULL) { - printf("Shared shaper mem alloc err\n"); - return -1; - } - tnp.shared_shaper_id[0] = k; - pos = j + (i * PIPE_NODES_PER_SUBPORT); - h->tc_node_id[pos][k] = - TC_NODES_START_ID + n_tc_nodes; - - if (rte_tm_shaper_profile_add(port_id, - shaper_profile_id, &tsp, error)) { - printf("%s ERROR(%d)-%s!(shaper %u)\n", - __func__, error->type, - error->message, - shaper_profile_id); - - return -1; - } - tnp.shaper_profile_id = shaper_profile_id; - if (rte_tm_node_add(port_id, - h->tc_node_id[pos][k], - tc_parent_node_id, - priority, weight, - level_id, - &tnp, error)) { - printf("%s ERROR(%d)-%s!(node id %u)\n", - __func__, - error->type, - error->message, - h->tc_node_id[pos][k]); - - return -1; - } - shaper_profile_id++; - n_tc_nodes++; - } - } - } - /* Update */ - h->n_shapers = shaper_profile_id; - - printf(" TC nodes added (Start id %u, Count %u, level %u)\n", - h->tc_node_id[0][0], n_tc_nodes, level_id); - - return 0; -} - -static int -softport_tm_queue_node_add(portid_t port_id, struct tm_hierarchy *h, - struct rte_tm_error *error) -{ - uint32_t queue_parent_node_id; - struct rte_tm_node_params qnp; - uint32_t priority, weight, level_id, pos; - uint32_t n_queue_nodes, i, j, k; - - memset(&qnp, 0, sizeof(struct rte_tm_node_params)); - - /* Queue Node Parameters */ - priority = 0; - weight = 1; - level_id = TM_NODE_LEVEL_QUEUE; - qnp.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE; - qnp.leaf.cman = RTE_TM_CMAN_TAIL_DROP; - qnp.stats_mask = STATS_MASK_QUEUE; - - /* Add Queue Nodes to TM Hierarchy */ - n_queue_nodes = 0; - for (i = 0; i < NUM_PIPE_NODES; i++) { - for (j = 0; j < TC_NODES_PER_PIPE; j++) { - queue_parent_node_id = h->tc_node_id[i][j]; - for (k = 0; k < QUEUE_NODES_PER_TC; k++) { - pos = j + (i * TC_NODES_PER_PIPE); - h->queue_node_id[pos][k] = n_queue_nodes; - if (rte_tm_node_add(port_id, - h->queue_node_id[pos][k], - queue_parent_node_id, - priority, - weight, - level_id, - &qnp, error)) { - printf("%s ERROR(%d)-%s!(node %u)\n", - __func__, - error->type, - error->message, - h->queue_node_id[pos][k]); - - return -1; - } - n_queue_nodes++; - } - } - } - printf(" Queue nodes added (Start id %u, Count %u, level %u)\n", - h->queue_node_id[0][0], n_queue_nodes, level_id); - - return 0; -} - -/* - * TM Packet Field Setup - */ -static void -softport_tm_pktfield_setup(portid_t port_id) -{ - struct rte_port *p = &ports[port_id]; - uint64_t pktfield0_mask = 0; - uint64_t pktfield1_mask = 0x0000000FFF000000LLU; - uint64_t pktfield2_mask = 0x00000000000000FCLLU; - - p->softport.tm = (struct softnic_port_tm) { - .n_subports_per_port = SUBPORT_NODES_PER_PORT, - .n_pipes_per_subport = PIPE_NODES_PER_SUBPORT, - - /* Packet field to identify subport - * - * Default configuration assumes only one subport, thus - * the subport ID is hardcoded to 0 - */ - .tm_pktfield0_slabpos = 0, - .tm_pktfield0_slabmask = pktfield0_mask, - .tm_pktfield0_slabshr = - __builtin_ctzll(pktfield0_mask), - - /* Packet field to identify pipe. - * - * Default value assumes Ethernet/IPv4/UDP packets, - * UDP payload bits 12 .. 23 - */ - .tm_pktfield1_slabpos = 40, - .tm_pktfield1_slabmask = pktfield1_mask, - .tm_pktfield1_slabshr = - __builtin_ctzll(pktfield1_mask), - - /* Packet field used as index into TC translation table - * to identify the traffic class and queue. - * - * Default value assumes Ethernet/IPv4 packets, IPv4 - * DSCP field - */ - .tm_pktfield2_slabpos = 8, - .tm_pktfield2_slabmask = pktfield2_mask, - .tm_pktfield2_slabshr = - __builtin_ctzll(pktfield2_mask), - - .tm_tc_table = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - }, /**< TC translation table */ - }; -} - -static int -softport_tm_hierarchy_specify(portid_t port_id, struct rte_tm_error *error) -{ - - struct tm_hierarchy h; - int status; - - memset(&h, 0, sizeof(struct tm_hierarchy)); - - /* TM hierarchy shapers rate */ - set_tm_hiearchy_nodes_shaper_rate(port_id, &h); - - /* Add root node (level 0) */ - status = softport_tm_root_node_add(port_id, &h, error); - if (status) - return status; - - /* Add subport node (level 1) */ - status = softport_tm_subport_node_add(port_id, &h, error); - if (status) - return status; - - /* Add pipe nodes (level 2) */ - status = softport_tm_pipe_node_add(port_id, &h, error); - if (status) - return status; - - /* Add traffic class nodes (level 3) */ - status = softport_tm_tc_node_add(port_id, &h, error); - if (status) - return status; - - /* Add queue nodes (level 4) */ - status = softport_tm_queue_node_add(port_id, &h, error); - if (status) - return status; - - /* TM packet fields setup */ - softport_tm_pktfield_setup(port_id); - - return 0; -} - -/* - * Soft port Init - */ -static void -softport_tm_begin(portid_t pi) -{ - struct rte_port *port = &ports[pi]; - - /* Soft port TM flag */ - if (port->softport.tm_flag == 1) { - printf("\n\n TM feature available on port %u\n", pi); - - /* Soft port TM hierarchy configuration */ - if ((port->softport.tm.hierarchy_config == 0) && - (port->softport.tm.default_hierarchy_enable == 1)) { - struct rte_tm_error error; - int status; - - /* Stop port */ - rte_eth_dev_stop(pi); - - /* TM hierarchy specification */ - status = softport_tm_hierarchy_specify(pi, &error); - if (status) { - printf(" TM Hierarchy built error(%d) - %s\n", - error.type, error.message); - return; - } - printf("\n TM Hierarchy Specified!\n\v"); - - /* TM hierarchy commit */ - status = rte_tm_hierarchy_commit(pi, 0, &error); - if (status) { - printf(" Hierarchy commit error(%d) - %s\n", - error.type, error.message); - return; - } - printf(" Hierarchy Committed (port %u)!", pi); - port->softport.tm.hierarchy_config = 1; - - /* Start port */ - status = rte_eth_dev_start(pi); - if (status) { - printf("\n Port %u start error!\n", pi); - return; - } - printf("\n Port %u started!\n", pi); - return; - } - } - printf("\n TM feature not available on port %u", pi); -} - -struct fwd_engine softnic_tm_engine = { - .fwd_mode_name = "tm", - .port_fwd_begin = softport_tm_begin, - .port_fwd_end = NULL, - .packet_fwd = softport_packet_fwd, -}; - -struct fwd_engine softnic_tm_bypass_engine = { - .fwd_mode_name = "tm-bypass", - .port_fwd_begin = NULL, - .port_fwd_end = NULL, - .packet_fwd = softport_packet_fwd, -};