net/softnic: add command for default tmgr hierarchy
authorCristian Dumitrescu <cristian.dumitrescu@intel.com>
Wed, 25 Jul 2018 17:10:07 +0000 (18:10 +0100)
committerCristian Dumitrescu <cristian.dumitrescu@intel.com>
Wed, 25 Jul 2018 17:29:15 +0000 (19:29 +0200)
Add support for creating default Traffic Manager (TMGR) hierarchy through
firmware CLI script.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
drivers/net/softnic/rte_eth_softnic_cli.c

index 4bd792b..0c7448c 100644 (file)
@@ -502,6 +502,498 @@ cmd_tmgr_node(struct pmd_internals *softnic,
        }
 }
 
+static uint32_t
+root_node_id(uint32_t n_spp,
+       uint32_t n_pps)
+{
+       uint32_t n_queues = n_spp * n_pps * RTE_SCHED_QUEUES_PER_PIPE;
+       uint32_t n_tc = n_spp * n_pps * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
+       uint32_t n_pipes = n_spp * n_pps;
+
+       return n_queues + n_tc + n_pipes + n_spp;
+}
+
+static uint32_t
+subport_node_id(uint32_t n_spp,
+       uint32_t n_pps,
+       uint32_t subport_id)
+{
+       uint32_t n_pipes = n_spp * n_pps;
+       uint32_t n_tc = n_pipes * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
+       uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
+
+       return n_queues + n_tc + n_pipes + subport_id;
+}
+
+static uint32_t
+pipe_node_id(uint32_t n_spp,
+       uint32_t n_pps,
+       uint32_t subport_id,
+       uint32_t pipe_id)
+{
+       uint32_t n_pipes = n_spp * n_pps;
+       uint32_t n_tc = n_pipes * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
+       uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
+
+       return n_queues +
+               n_tc +
+               pipe_id +
+               subport_id * n_pps;
+}
+
+static uint32_t
+tc_node_id(uint32_t n_spp,
+       uint32_t n_pps,
+       uint32_t subport_id,
+       uint32_t pipe_id,
+       uint32_t tc_id)
+{
+       uint32_t n_pipes = n_spp * n_pps;
+       uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
+
+       return n_queues +
+               tc_id +
+               (pipe_id + subport_id * n_pps) * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
+}
+
+static uint32_t
+queue_node_id(uint32_t n_spp __rte_unused,
+       uint32_t n_pps,
+       uint32_t subport_id,
+       uint32_t pipe_id,
+       uint32_t tc_id,
+       uint32_t queue_id)
+{
+       return queue_id +
+               tc_id * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE +
+               (pipe_id + subport_id * n_pps) * RTE_SCHED_QUEUES_PER_PIPE;
+}
+
+struct tmgr_hierarchy_default_params {
+       uint32_t n_spp; /**< Number of subports per port. */
+       uint32_t n_pps; /**< Number of pipes per subport. */
+
+       struct {
+               uint32_t port;
+               uint32_t subport;
+               uint32_t pipe;
+               uint32_t tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
+       } shaper_profile_id;
+
+       struct {
+               uint32_t tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
+               uint32_t tc_valid[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
+       } shared_shaper_id;
+
+       struct {
+               uint32_t queue[RTE_SCHED_QUEUES_PER_PIPE];
+       } weight;
+};
+
+static int
+tmgr_hierarchy_default(struct pmd_internals *softnic,
+       struct tmgr_hierarchy_default_params *params)
+{
+       struct rte_tm_node_params root_node_params = {
+               .shaper_profile_id = params->shaper_profile_id.port,
+               .nonleaf = {
+                       .n_sp_priorities = 1,
+               },
+       };
+
+       struct rte_tm_node_params subport_node_params = {
+               .shaper_profile_id = params->shaper_profile_id.subport,
+               .nonleaf = {
+                       .n_sp_priorities = 1,
+               },
+       };
+
+       struct rte_tm_node_params pipe_node_params = {
+               .shaper_profile_id = params->shaper_profile_id.pipe,
+               .nonleaf = {
+                       .n_sp_priorities = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
+               },
+       };
+
+       struct rte_tm_node_params tc_node_params[] = {
+               [0] = {
+                       .shaper_profile_id = params->shaper_profile_id.tc[0],
+                       .shared_shaper_id = &params->shared_shaper_id.tc[0],
+                       .n_shared_shapers =
+                               (&params->shared_shaper_id.tc_valid[0]) ? 1 : 0,
+                       .nonleaf = {
+                               .n_sp_priorities = 1,
+                       },
+               },
+
+               [1] = {
+                       .shaper_profile_id = params->shaper_profile_id.tc[1],
+                       .shared_shaper_id = &params->shared_shaper_id.tc[1],
+                       .n_shared_shapers =
+                               (&params->shared_shaper_id.tc_valid[1]) ? 1 : 0,
+                       .nonleaf = {
+                               .n_sp_priorities = 1,
+                       },
+               },
+
+               [2] = {
+                       .shaper_profile_id = params->shaper_profile_id.tc[2],
+                       .shared_shaper_id = &params->shared_shaper_id.tc[2],
+                       .n_shared_shapers =
+                               (&params->shared_shaper_id.tc_valid[2]) ? 1 : 0,
+                       .nonleaf = {
+                               .n_sp_priorities = 1,
+                       },
+               },
+
+               [3] = {
+                       .shaper_profile_id = params->shaper_profile_id.tc[3],
+                       .shared_shaper_id = &params->shared_shaper_id.tc[3],
+                       .n_shared_shapers =
+                               (&params->shared_shaper_id.tc_valid[3]) ? 1 : 0,
+                       .nonleaf = {
+                               .n_sp_priorities = 1,
+                       },
+               },
+       };
+
+       struct rte_tm_node_params queue_node_params = {
+               .shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE,
+       };
+
+       struct rte_tm_error error;
+       uint32_t n_spp = params->n_spp, n_pps = params->n_pps, s;
+       int status;
+       uint16_t port_id;
+
+       status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
+       if (status)
+               return -1;
+
+       /* Hierarchy level 0: Root node */
+       status = rte_tm_node_add(port_id,
+               root_node_id(n_spp, n_pps),
+               RTE_TM_NODE_ID_NULL,
+               0,
+               1,
+               RTE_TM_NODE_LEVEL_ID_ANY,
+               &root_node_params,
+               &error);
+       if (status)
+               return -1;
+
+       /* Hierarchy level 1: Subport nodes */
+       for (s = 0; s < params->n_spp; s++) {
+               uint32_t p;
+
+               status = rte_tm_node_add(port_id,
+                       subport_node_id(n_spp, n_pps, s),
+                       root_node_id(n_spp, n_pps),
+                       0,
+                       1,
+                       RTE_TM_NODE_LEVEL_ID_ANY,
+                       &subport_node_params,
+                       &error);
+               if (status)
+                       return -1;
+
+               /* Hierarchy level 2: Pipe nodes */
+               for (p = 0; p < params->n_pps; p++) {
+                       uint32_t t;
+
+                       status = rte_tm_node_add(port_id,
+                               pipe_node_id(n_spp, n_pps, s, p),
+                               subport_node_id(n_spp, n_pps, s),
+                               0,
+                               1,
+                               RTE_TM_NODE_LEVEL_ID_ANY,
+                               &pipe_node_params,
+                               &error);
+                       if (status)
+                               return -1;
+
+                       /* Hierarchy level 3: Traffic class nodes */
+                       for (t = 0; t < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; t++) {
+                               uint32_t q;
+
+                               status = rte_tm_node_add(port_id,
+                                       tc_node_id(n_spp, n_pps, s, p, t),
+                                       pipe_node_id(n_spp, n_pps, s, p),
+                                       t,
+                                       1,
+                                       RTE_TM_NODE_LEVEL_ID_ANY,
+                                       &tc_node_params[t],
+                                       &error);
+                               if (status)
+                                       return -1;
+
+                               /* Hierarchy level 4: Queue nodes */
+                               for (q = 0; q < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; q++) {
+                                       status = rte_tm_node_add(port_id,
+                                               queue_node_id(n_spp, n_pps, s, p, t, q),
+                                               tc_node_id(n_spp, n_pps, s, p, t),
+                                               0,
+                                               params->weight.queue[q],
+                                               RTE_TM_NODE_LEVEL_ID_ANY,
+                                               &queue_node_params,
+                                               &error);
+                                       if (status)
+                                               return -1;
+                               } /* Queue */
+                       } /* TC */
+               } /* Pipe */
+       } /* Subport */
+
+       return 0;
+}
+
+
+/**
+ * tmgr hierarchy-default
+ *  spp <n_subports_per_port>
+ *  pps <n_pipes_per_subport>
+ *  shaper profile
+ *   port <profile_id>
+ *   subport <profile_id>
+ *   pipe <profile_id>
+ *   tc0 <profile_id>
+ *   tc1 <profile_id>
+ *   tc2 <profile_id>
+ *   tc3 <profile_id>
+ *  shared shaper
+ *   tc0 <id | none>
+ *   tc1 <id | none>
+ *   tc2 <id | none>
+ *   tc3 <id | none>
+ *  weight
+ *   queue  <q0> ... <q15>
+ */
+static void
+cmd_tmgr_hierarchy_default(struct pmd_internals *softnic,
+       char **tokens,
+       uint32_t n_tokens,
+       char *out,
+       size_t out_size)
+{
+       struct tmgr_hierarchy_default_params p;
+       int i, status;
+
+       memset(&p, 0, sizeof(p));
+
+       if (n_tokens != 50) {
+               snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+               return;
+       }
+
+       if (strcmp(tokens[1], "hierarchy-default") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "hierarchy-default");
+               return;
+       }
+
+       if (strcmp(tokens[2], "spp") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
+               return;
+       }
+
+       if (softnic_parser_read_uint32(&p.n_spp, tokens[3]) != 0) {
+               snprintf(out, out_size, MSG_ARG_INVALID, "n_subports_per_port");
+               return;
+       }
+
+       if (strcmp(tokens[4], "pps") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
+               return;
+       }
+
+       if (softnic_parser_read_uint32(&p.n_pps, tokens[5]) != 0) {
+               snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport");
+               return;
+       }
+
+       /* Shaper profile */
+
+       if (strcmp(tokens[6], "shaper") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
+               return;
+       }
+
+       if (strcmp(tokens[7], "profile") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
+               return;
+       }
+
+       if (strcmp(tokens[8], "port") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+               return;
+       }
+
+       if (softnic_parser_read_uint32(&p.shaper_profile_id.port, tokens[9]) != 0) {
+               snprintf(out, out_size, MSG_ARG_INVALID, "port profile id");
+               return;
+       }
+
+       if (strcmp(tokens[10], "subport") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "subport");
+               return;
+       }
+
+       if (softnic_parser_read_uint32(&p.shaper_profile_id.subport, tokens[11]) != 0) {
+               snprintf(out, out_size, MSG_ARG_INVALID, "subport profile id");
+               return;
+       }
+
+       if (strcmp(tokens[12], "pipe") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipe");
+               return;
+       }
+
+       if (softnic_parser_read_uint32(&p.shaper_profile_id.pipe, tokens[13]) != 0) {
+               snprintf(out, out_size, MSG_ARG_INVALID, "pipe_profile_id");
+               return;
+       }
+
+       if (strcmp(tokens[14], "tc0") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc0");
+               return;
+       }
+
+       if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[0], tokens[15]) != 0) {
+               snprintf(out, out_size, MSG_ARG_INVALID, "tc0 profile id");
+               return;
+       }
+
+       if (strcmp(tokens[16], "tc1") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc1");
+               return;
+       }
+
+       if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[1], tokens[17]) != 0) {
+               snprintf(out, out_size, MSG_ARG_INVALID, "tc1 profile id");
+               return;
+       }
+
+       if (strcmp(tokens[18], "tc2") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc2");
+               return;
+       }
+
+       if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[2], tokens[19]) != 0) {
+               snprintf(out, out_size, MSG_ARG_INVALID, "tc2 profile id");
+               return;
+       }
+
+       if (strcmp(tokens[20], "tc3") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc3");
+               return;
+       }
+
+       if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[3], tokens[21]) != 0) {
+               snprintf(out, out_size, MSG_ARG_INVALID, "tc3 profile id");
+               return;
+       }
+
+       /* Shared shaper */
+
+       if (strcmp(tokens[22], "shared") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shared");
+               return;
+       }
+
+       if (strcmp(tokens[23], "shaper") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
+               return;
+       }
+
+       if (strcmp(tokens[24], "tc0") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc0");
+               return;
+       }
+
+       if (strcmp(tokens[25], "none") == 0)
+               p.shared_shaper_id.tc_valid[0] = 0;
+       else {
+               if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[0], tokens[25]) != 0) {
+                       snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc0");
+                       return;
+               }
+
+               p.shared_shaper_id.tc_valid[0] = 1;
+       }
+
+       if (strcmp(tokens[26], "tc1") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc1");
+               return;
+       }
+
+       if (strcmp(tokens[27], "none") == 0)
+               p.shared_shaper_id.tc_valid[1] = 0;
+       else {
+               if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[1], tokens[27]) != 0) {
+                       snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc1");
+                       return;
+               }
+
+               p.shared_shaper_id.tc_valid[1] = 1;
+       }
+
+       if (strcmp(tokens[28], "tc2") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc2");
+               return;
+       }
+
+       if (strcmp(tokens[29], "none") == 0)
+               p.shared_shaper_id.tc_valid[2] = 0;
+       else {
+               if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[2], tokens[29]) != 0) {
+                       snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc2");
+                       return;
+               }
+
+               p.shared_shaper_id.tc_valid[2] = 1;
+       }
+
+       if (strcmp(tokens[30], "tc3") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc3");
+               return;
+       }
+
+       if (strcmp(tokens[31], "none") == 0)
+               p.shared_shaper_id.tc_valid[3] = 0;
+       else {
+               if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[3], tokens[31]) != 0) {
+                       snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc3");
+                       return;
+               }
+
+               p.shared_shaper_id.tc_valid[3] = 1;
+       }
+
+       /* Weight */
+
+       if (strcmp(tokens[32], "weight") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "weight");
+               return;
+       }
+
+       if (strcmp(tokens[33], "queue") != 0) {
+               snprintf(out, out_size, MSG_ARG_NOT_FOUND, "queue");
+               return;
+       }
+
+       for (i = 0; i < 16; i++) {
+               if (softnic_parser_read_uint32(&p.weight.queue[i], tokens[34 + i]) != 0) {
+                       snprintf(out, out_size, MSG_ARG_INVALID, "weight queue");
+                       return;
+               }
+       }
+
+       status = tmgr_hierarchy_default(softnic, &p);
+       if (status != 0) {
+               snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+               return;
+       }
+}
+
 /**
  * tmgr hierarchy commit
  */
@@ -4366,6 +4858,12 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
                        return;
                }
 
+               if (n_tokens >= 2 &&
+                       (strcmp(tokens[1], "hierarchy-default") == 0)) {
+                       cmd_tmgr_hierarchy_default(softnic, tokens, n_tokens, out, out_size);
+                       return;
+               }
+
                if (n_tokens >= 3 &&
                        (strcmp(tokens[1], "hierarchy") == 0) &&
                        (strcmp(tokens[2], "commit") == 0)) {