app/testpmd: rework softnic forward mode
authorJasvinder Singh <jasvinder.singh@intel.com>
Fri, 6 Jul 2018 17:21:16 +0000 (18:21 +0100)
committerCristian Dumitrescu <cristian.dumitrescu@intel.com>
Thu, 12 Jul 2018 11:55:56 +0000 (13:55 +0200)
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 <jasvinder.singh@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
app/test-pmd/Makefile
app/test-pmd/cmdline.c
app/test-pmd/config.c
app/test-pmd/meson.build
app/test-pmd/softnicfwd.c [new file with mode: 0644]
app/test-pmd/testpmd.c
app/test-pmd/testpmd.h
app/test-pmd/tm.c [deleted file]

index a5a827b..f788078 100644 (file)
@@ -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)
index 15d35da..46a9f49 100644 (file)
@@ -69,6 +69,9 @@
 #ifdef RTE_LIBRTE_I40E_PMD
 #include <rte_pmd_i40e.h>
 #endif
+#ifdef RTE_LIBRTE_PMD_SOFTNIC
+#include <rte_eth_softnic.h>
+#endif
 #ifdef RTE_LIBRTE_BNXT_PMD
 #include <rte_pmd_bnxt.h>
 #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
index 97020fb..a17a7b5 100644 (file)
@@ -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();
index 4c9fbbf..55539ba 100644 (file)
@@ -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 (file)
index 0000000..1f9eeaf
--- /dev/null
@@ -0,0 +1,677 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include <rte_cycles.h>
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+#include <rte_ethdev.h>
+#include <rte_flow.h>
+#include <rte_meter.h>
+#include <rte_eth_softnic.h>
+#include <rte_tm.h>
+
+#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,
+};
index 31e9f95..d3ce92f 100644 (file)
@@ -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
        }
 }
 
index f51cd9d..4fc30a8 100644 (file)
@@ -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 (file)
index 7231552..0000000
+++ /dev/null
@@ -1,840 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017 Intel Corporation
- */
-#include <stdio.h>
-#include <sys/stat.h>
-
-#include <rte_cycles.h>
-#include <rte_mbuf.h>
-#include <rte_ethdev.h>
-#include <rte_flow.h>
-#include <rte_meter.h>
-#include <rte_eth_softnic.h>
-#include <rte_tm.h>
-
-#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,
-};