}
/**
- * tap <tap_name>
+ * tmgr shaper profile
+ * id <profile_id>
+ * rate <tb_rate> size <tb_size>
+ * adj <packet_length_adjust>
*/
static void
-cmd_tap(struct pmd_internals *softnic,
+cmd_tmgr_shaper_profile(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
- char *name;
- struct softnic_tap *tap;
+ struct rte_tm_shaper_params sp;
+ struct rte_tm_error error;
+ uint32_t shaper_profile_id;
+ uint16_t port_id;
+ int status;
- if (n_tokens != 2) {
+ memset(&sp, 0, sizeof(struct rte_tm_shaper_params));
+
+ if (n_tokens != 11) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
- name = tokens[1];
+ if (strcmp(tokens[1], "shaper") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
+ return;
+ }
- tap = softnic_tap_create(softnic, name);
- if (tap == NULL) {
+ if (strcmp(tokens[2], "profile") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
+ return;
+ }
+
+ if (strcmp(tokens[3], "id") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&shaper_profile_id, tokens[4]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "profile_id");
+ return;
+ }
+
+ if (strcmp(tokens[5], "rate") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rate");
+ return;
+ }
+
+ if (softnic_parser_read_uint64(&sp.peak.rate, tokens[6]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate");
+ return;
+ }
+
+ if (strcmp(tokens[7], "size") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
+ return;
+ }
+
+ if (softnic_parser_read_uint64(&sp.peak.size, tokens[8]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "tb_size");
+ return;
+ }
+
+ if (strcmp(tokens[9], "adj") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "adj");
+ return;
+ }
+
+ if (softnic_parser_read_int32(&sp.pkt_length_adjust, tokens[10]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "packet_length_adjust");
+ return;
+ }
+
+ status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
+ if (status)
+ return;
+
+ status = rte_tm_shaper_profile_add(port_id, shaper_profile_id, &sp, &error);
+ if (status != 0) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
/**
- * port in action profile <profile_name>
- * [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]
- * [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>]
+ * tmgr shared shaper
+ * id <shared_shaper_id>
+ * profile <shaper_profile_id>
*/
static void
-cmd_port_in_action_profile(struct pmd_internals *softnic,
+cmd_tmgr_shared_shaper(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
- struct softnic_port_in_action_profile_params p;
- struct softnic_port_in_action_profile *ap;
- char *name;
- uint32_t t0;
-
- memset(&p, 0, sizeof(p));
+ struct rte_tm_error error;
+ uint32_t shared_shaper_id, shaper_profile_id;
+ uint16_t port_id;
+ int status;
- if (n_tokens < 5) {
+ if (n_tokens != 7) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
- if (strcmp(tokens[1], "in") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
+ if (strcmp(tokens[1], "shared") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shared");
return;
}
- if (strcmp(tokens[2], "action") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
+ if (strcmp(tokens[2], "shaper") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
return;
}
- if (strcmp(tokens[3], "profile") != 0) {
+ if (strcmp(tokens[3], "id") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&shared_shaper_id, tokens[4]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "shared_shaper_id");
+ return;
+ }
+
+ if (strcmp(tokens[5], "profile") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
return;
}
- name = tokens[4];
+ if (softnic_parser_read_uint32(&shaper_profile_id, tokens[6]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "shaper_profile_id");
+ return;
+ }
- t0 = 5;
+ status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
+ if (status)
+ return;
- if (t0 < n_tokens &&
- (strcmp(tokens[t0], "filter") == 0)) {
- uint32_t size;
+ status = rte_tm_shared_shaper_add_update(port_id,
+ shared_shaper_id,
+ shaper_profile_id,
+ &error);
+ if (status != 0) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+ return;
+ }
+}
- if (n_tokens < t0 + 10) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter");
- return;
- }
+/**
+ * tmgr node
+ * id <node_id>
+ * parent <parent_node_id | none>
+ * priority <priority>
+ * weight <weight>
+ * [shaper profile <shaper_profile_id>]
+ * [shared shaper <shared_shaper_id>]
+ * [nonleaf sp <n_sp_priorities>]
+ */
+static void
+cmd_tmgr_node(struct pmd_internals *softnic,
+ char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size)
+{
+ struct rte_tm_error error;
+ struct rte_tm_node_params np;
+ uint32_t node_id, parent_node_id, priority, weight, shared_shaper_id;
+ uint16_t port_id;
+ int status;
- if (strcmp(tokens[t0 + 1], "match") == 0) {
- p.fltr.filter_on_match = 1;
- } else if (strcmp(tokens[t0 + 1], "mismatch") == 0) {
- p.fltr.filter_on_match = 0;
- } else {
- snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch");
- return;
- }
+ memset(&np, 0, sizeof(struct rte_tm_node_params));
+ np.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE;
+ np.nonleaf.n_sp_priorities = 1;
- if (strcmp(tokens[t0 + 2], "offset") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
- return;
- }
+ if (n_tokens < 10) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
- if (softnic_parser_read_uint32(&p.fltr.key_offset,
- tokens[t0 + 3]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
- return;
- }
+ if (strcmp(tokens[1], "node") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "node");
+ return;
+ }
- if (strcmp(tokens[t0 + 4], "mask") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
- return;
- }
+ if (strcmp(tokens[2], "id") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
+ return;
+ }
- size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
- if ((softnic_parse_hex_string(tokens[t0 + 5],
- p.fltr.key_mask, &size) != 0) ||
- size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) {
- snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
- return;
- }
+ if (softnic_parser_read_uint32(&node_id, tokens[3]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "node_id");
+ return;
+ }
- if (strcmp(tokens[t0 + 6], "key") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
- return;
- }
+ if (strcmp(tokens[4], "parent") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "parent");
+ return;
+ }
- size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
- if ((softnic_parse_hex_string(tokens[t0 + 7],
- p.fltr.key, &size) != 0) ||
- size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) {
- snprintf(out, out_size, MSG_ARG_INVALID, "key_value");
+ if (strcmp(tokens[5], "none") == 0)
+ parent_node_id = RTE_TM_NODE_ID_NULL;
+ else {
+ if (softnic_parser_read_uint32(&parent_node_id, tokens[5]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "parent_node_id");
return;
}
+ }
- if (strcmp(tokens[t0 + 8], "port") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
- return;
- }
+ if (strcmp(tokens[6], "priority") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority");
+ return;
+ }
- if (softnic_parser_read_uint32(&p.fltr.port_id,
- tokens[t0 + 9]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
- return;
- }
+ if (softnic_parser_read_uint32(&priority, tokens[7]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "priority");
+ return;
+ }
- p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR;
- t0 += 10;
- } /* filter */
+ if (strcmp(tokens[8], "weight") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "weight");
+ return;
+ }
- if (t0 < n_tokens &&
- (strcmp(tokens[t0], "balance") == 0)) {
- uint32_t i;
+ if (softnic_parser_read_uint32(&weight, tokens[9]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "weight");
+ return;
+ }
- if (n_tokens < t0 + 22) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "port in action profile balance");
+ tokens += 10;
+ n_tokens -= 10;
+
+ if (n_tokens >= 2 &&
+ (strcmp(tokens[0], "shaper") == 0) &&
+ (strcmp(tokens[1], "profile") == 0)) {
+ if (n_tokens < 3) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
return;
}
- if (strcmp(tokens[t0 + 1], "offset") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
- return;
+ if (strcmp(tokens[2], "none") == 0) {
+ np.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE;
+ } else {
+ if (softnic_parser_read_uint32(&np.shaper_profile_id, tokens[2]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "shaper_profile_id");
+ return;
+ }
}
- if (softnic_parser_read_uint32(&p.lb.key_offset,
- tokens[t0 + 2]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
+ tokens += 3;
+ n_tokens -= 3;
+ } /* shaper profile */
+
+ if (n_tokens >= 2 &&
+ (strcmp(tokens[0], "shared") == 0) &&
+ (strcmp(tokens[1], "shaper") == 0)) {
+ if (n_tokens < 3) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
return;
}
- if (strcmp(tokens[t0 + 3], "mask") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
+ if (softnic_parser_read_uint32(&shared_shaper_id, tokens[2]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "shared_shaper_id");
return;
}
- p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
- if (softnic_parse_hex_string(tokens[t0 + 4],
- p.lb.key_mask, &p.lb.key_size) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
+ np.shared_shaper_id = &shared_shaper_id;
+ np.n_shared_shapers = 1;
+
+ tokens += 3;
+ n_tokens -= 3;
+ } /* shared shaper */
+
+ if (n_tokens >= 2 &&
+ (strcmp(tokens[0], "nonleaf") == 0) &&
+ (strcmp(tokens[1], "sp") == 0)) {
+ if (n_tokens < 3) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
return;
}
- if (strcmp(tokens[t0 + 5], "port") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+ if (softnic_parser_read_uint32(&np.nonleaf.n_sp_priorities, tokens[2]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "n_sp_priorities");
return;
}
- for (i = 0; i < 16; i++)
- if (softnic_parser_read_uint32(&p.lb.port_id[i],
- tokens[t0 + 6 + i]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
- return;
- }
-
- p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB;
- t0 += 22;
- } /* balance */
+ tokens += 3;
+ n_tokens -= 3;
+ } /* nonleaf sp <n_sp_priorities> */
- if (t0 < n_tokens) {
+ if (n_tokens) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
- ap = softnic_port_in_action_profile_create(softnic, name, &p);
- if (ap == NULL) {
+ status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
+ if (status != 0)
+ return;
+
+ status = rte_tm_node_add(port_id,
+ node_id,
+ parent_node_id,
+ priority,
+ weight,
+ RTE_TM_NODE_LEVEL_ID_ANY,
+ &np,
+ &error);
+ if (status != 0) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
-/**
- * table action profile <profile_name>
- * ipv4 | ipv6
- * offset <ip_offset>
- * fwd
- * [balance offset <key_offset> mask <key_mask> outoffset <out_offset>]
- * [meter srtcm | trtcm
- * tc <n_tc>
- * stats none | pkts | bytes | both]
- * [tm spp <n_subports_per_port> pps <n_pipes_per_subport>]
- * [encap ether | vlan | qinq | mpls | pppoe]
- * [nat src | dst
- * proto udp | tcp]
- * [ttl drop | fwd
- * stats none | pkts]
- * [stats pkts | bytes | both]
- * [time]
- */
-static void
-cmd_table_action_profile(struct pmd_internals *softnic,
- char **tokens,
- uint32_t n_tokens,
- char *out,
- size_t out_size)
+static uint32_t
+root_node_id(uint32_t n_spp,
+ uint32_t n_pps)
{
- struct softnic_table_action_profile_params p;
- struct softnic_table_action_profile *ap;
- char *name;
- uint32_t t0;
-
- memset(&p, 0, sizeof(p));
+ 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;
- if (n_tokens < 8) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
+ return n_queues + n_tc + n_pipes + n_spp;
+}
- if (strcmp(tokens[1], "action") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
- return;
- }
+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;
- if (strcmp(tokens[2], "profile") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
- return;
- }
+ return n_queues + n_tc + n_pipes + subport_id;
+}
- name = tokens[3];
+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;
+}
- if (strcmp(tokens[4], "ipv4") == 0) {
- p.common.ip_version = 1;
- } else if (strcmp(tokens[4], "ipv6") == 0) {
- p.common.ip_version = 0;
- } else {
- snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6");
+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 = ¶ms->shared_shaper_id.tc[0],
+ .n_shared_shapers =
+ (¶ms->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 = ¶ms->shared_shaper_id.tc[1],
+ .n_shared_shapers =
+ (¶ms->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 = ¶ms->shared_shaper_id.tc[2],
+ .n_shared_shapers =
+ (¶ms->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 = ¶ms->shared_shaper_id.tc[3],
+ .n_shared_shapers =
+ (¶ms->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[5], "offset") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
+ if (strcmp(tokens[1], "hierarchy-default") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "hierarchy-default");
return;
}
- if (softnic_parser_read_uint32(&p.common.ip_offset,
- tokens[6]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset");
+ if (strcmp(tokens[2], "spp") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
return;
}
- if (strcmp(tokens[7], "fwd") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd");
+ if (softnic_parser_read_uint32(&p.n_spp, tokens[3]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "n_subports_per_port");
return;
}
- p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
+ if (strcmp(tokens[4], "pps") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
+ return;
+ }
- t0 = 8;
- if (t0 < n_tokens &&
- (strcmp(tokens[t0], "balance") == 0)) {
- if (n_tokens < t0 + 7) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, "table action profile balance");
- return;
- }
+ if (softnic_parser_read_uint32(&p.n_pps, tokens[5]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport");
+ return;
+ }
- if (strcmp(tokens[t0 + 1], "offset") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
- return;
- }
+ /* Shaper profile */
- if (softnic_parser_read_uint32(&p.lb.key_offset,
- tokens[t0 + 2]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
- return;
- }
+ if (strcmp(tokens[6], "shaper") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
+ return;
+ }
- if (strcmp(tokens[t0 + 3], "mask") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
- return;
- }
+ if (strcmp(tokens[7], "profile") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
+ return;
+ }
- p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
- if (softnic_parse_hex_string(tokens[t0 + 4],
- p.lb.key_mask, &p.lb.key_size) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
- return;
- }
+ if (strcmp(tokens[8], "port") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+ return;
+ }
- if (strcmp(tokens[t0 + 5], "outoffset") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset");
- 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 (softnic_parser_read_uint32(&p.lb.out_offset,
- tokens[t0 + 6]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "out_offset");
- return;
- }
+ if (strcmp(tokens[10], "subport") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "subport");
+ return;
+ }
- p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB;
- t0 += 7;
- } /* balance */
+ 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 (t0 < n_tokens &&
- (strcmp(tokens[t0], "meter") == 0)) {
- if (n_tokens < t0 + 6) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "table action profile meter");
- return;
- }
+ if (strcmp(tokens[12], "pipe") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipe");
+ return;
+ }
- if (strcmp(tokens[t0 + 1], "srtcm") == 0) {
- p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM;
- } else if (strcmp(tokens[t0 + 1], "trtcm") == 0) {
- p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM;
- } else {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "srtcm or trtcm");
- 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[t0 + 2], "tc") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc");
- return;
- }
+ if (strcmp(tokens[14], "tc0") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc0");
+ return;
+ }
- if (softnic_parser_read_uint32(&p.mtr.n_tc,
- tokens[t0 + 3]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "n_tc");
- 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[t0 + 4], "stats") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
- return;
- }
+ if (strcmp(tokens[16], "tc1") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc1");
+ return;
+ }
- if (strcmp(tokens[t0 + 5], "none") == 0) {
- p.mtr.n_packets_enabled = 0;
- p.mtr.n_bytes_enabled = 0;
- } else if (strcmp(tokens[t0 + 5], "pkts") == 0) {
- p.mtr.n_packets_enabled = 1;
- p.mtr.n_bytes_enabled = 0;
- } else if (strcmp(tokens[t0 + 5], "bytes") == 0) {
- p.mtr.n_packets_enabled = 0;
- p.mtr.n_bytes_enabled = 1;
- } else if (strcmp(tokens[t0 + 5], "both") == 0) {
- p.mtr.n_packets_enabled = 1;
- p.mtr.n_bytes_enabled = 1;
- } else {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "none or pkts or bytes or both");
- 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;
+ }
- p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR;
- t0 += 6;
- } /* meter */
+ if (strcmp(tokens[18], "tc2") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc2");
+ return;
+ }
- if (t0 < n_tokens &&
- (strcmp(tokens[t0], "tm") == 0)) {
- if (n_tokens < t0 + 5) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "table action profile tm");
- 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[t0 + 1], "spp") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
- return;
- }
+ if (strcmp(tokens[20], "tc3") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc3");
+ return;
+ }
- if (softnic_parser_read_uint32(&p.tm.n_subports_per_port,
- tokens[t0 + 2]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "n_subports_per_port");
- 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;
+ }
- if (strcmp(tokens[t0 + 3], "pps") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
- return;
- }
+ /* Shared shaper */
- if (softnic_parser_read_uint32(&p.tm.n_pipes_per_subport,
- tokens[t0 + 4]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "n_pipes_per_subport");
+ 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.action_mask |= 1LLU << RTE_TABLE_ACTION_TM;
- t0 += 5;
- } /* tm */
+ p.shared_shaper_id.tc_valid[0] = 1;
+ }
- if (t0 < n_tokens &&
- (strcmp(tokens[t0], "encap") == 0)) {
- if (n_tokens < t0 + 2) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "action profile encap");
+ 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;
}
- if (strcmp(tokens[t0 + 1], "ether") == 0) {
- p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER;
- } else if (strcmp(tokens[t0 + 1], "vlan") == 0) {
- p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN;
- } else if (strcmp(tokens[t0 + 1], "qinq") == 0) {
- p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ;
- } else if (strcmp(tokens[t0 + 1], "mpls") == 0) {
- p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS;
- } else if (strcmp(tokens[t0 + 1], "pppoe") == 0) {
- p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE;
- } else {
- snprintf(out, out_size, MSG_ARG_MISMATCH, "encap");
+ 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.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP;
- t0 += 2;
- } /* encap */
+ p.shared_shaper_id.tc_valid[2] = 1;
+ }
- if (t0 < n_tokens &&
- (strcmp(tokens[t0], "nat") == 0)) {
- if (n_tokens < t0 + 4) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "table action profile nat");
+ 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;
}
- if (strcmp(tokens[t0 + 1], "src") == 0) {
- p.nat.source_nat = 1;
- } else if (strcmp(tokens[t0 + 1], "dst") == 0) {
- p.nat.source_nat = 0;
- } else {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "src or dst");
- return;
- }
-
- if (strcmp(tokens[t0 + 2], "proto") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto");
- return;
- }
-
- if (strcmp(tokens[t0 + 3], "tcp") == 0) {
- p.nat.proto = 0x06;
- } else if (strcmp(tokens[t0 + 3], "udp") == 0) {
- p.nat.proto = 0x11;
- } else {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "tcp or udp");
- return;
- }
-
- p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT;
- t0 += 4;
- } /* nat */
+ p.shared_shaper_id.tc_valid[3] = 1;
+ }
- if (t0 < n_tokens &&
- (strcmp(tokens[t0], "ttl") == 0)) {
- if (n_tokens < t0 + 4) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "table action profile ttl");
- return;
- }
+ /* Weight */
- if (strcmp(tokens[t0 + 1], "drop") == 0) {
- p.ttl.drop = 1;
- } else if (strcmp(tokens[t0 + 1], "fwd") == 0) {
- p.ttl.drop = 0;
- } else {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "drop or fwd");
- return;
- }
+ if (strcmp(tokens[32], "weight") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "weight");
+ return;
+ }
- if (strcmp(tokens[t0 + 2], "stats") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
- return;
- }
+ if (strcmp(tokens[33], "queue") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "queue");
+ return;
+ }
- if (strcmp(tokens[t0 + 3], "none") == 0) {
- p.ttl.n_packets_enabled = 0;
- } else if (strcmp(tokens[t0 + 3], "pkts") == 0) {
- p.ttl.n_packets_enabled = 1;
- } else {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "none or pkts");
+ 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;
}
+ }
- p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL;
- t0 += 4;
- } /* ttl */
-
- if (t0 < n_tokens &&
- (strcmp(tokens[t0], "stats") == 0)) {
- if (n_tokens < t0 + 2) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "table action profile stats");
- return;
- }
+ status = tmgr_hierarchy_default(softnic, &p);
+ if (status != 0) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+ return;
+ }
+}
- if (strcmp(tokens[t0 + 1], "pkts") == 0) {
- p.stats.n_packets_enabled = 1;
- p.stats.n_bytes_enabled = 0;
- } else if (strcmp(tokens[t0 + 1], "bytes") == 0) {
- p.stats.n_packets_enabled = 0;
- p.stats.n_bytes_enabled = 1;
- } else if (strcmp(tokens[t0 + 1], "both") == 0) {
- p.stats.n_packets_enabled = 1;
- p.stats.n_bytes_enabled = 1;
- } else {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "pkts or bytes or both");
- return;
- }
+/**
+ * tmgr hierarchy commit
+ */
+static void
+cmd_tmgr_hierarchy_commit(struct pmd_internals *softnic,
+ char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size)
+{
+ struct rte_tm_error error;
+ uint16_t port_id;
+ int status;
- p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS;
- t0 += 2;
- } /* stats */
+ if (n_tokens != 3) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
- if (t0 < n_tokens &&
- (strcmp(tokens[t0], "time") == 0)) {
- p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME;
- t0 += 1;
- } /* time */
+ if (strcmp(tokens[1], "hierarchy") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "hierarchy");
+ return;
+ }
- if (t0 < n_tokens) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ if (strcmp(tokens[2], "commit") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "commit");
return;
}
- ap = softnic_table_action_profile_create(softnic, name, &p);
- if (ap == NULL) {
+ status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
+ if (status != 0)
+ return;
+
+ status = rte_tm_hierarchy_commit(port_id, 1, &error);
+ if (status) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
/**
- * pipeline <pipeline_name>
- * period <timer_period_ms>
- * offset_port_id <offset_port_id>
+ * tmgr <tmgr_name>
*/
static void
-cmd_pipeline(struct pmd_internals *softnic,
+cmd_tmgr(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
- struct pipeline_params p;
char *name;
- struct pipeline *pipeline;
+ struct softnic_tmgr_port *tmgr_port;
- if (n_tokens != 6) {
+ if (n_tokens != 2) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
name = tokens[1];
- if (strcmp(tokens[2], "period") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period");
+ tmgr_port = softnic_tmgr_port_create(softnic, name);
+ if (tmgr_port == NULL) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
+}
- if (softnic_parser_read_uint32(&p.timer_period_ms,
- tokens[3]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms");
- return;
- }
+/**
+ * tap <tap_name>
+ */
+static void
+cmd_tap(struct pmd_internals *softnic,
+ char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size)
+{
+ char *name;
+ struct softnic_tap *tap;
- if (strcmp(tokens[4], "offset_port_id") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id");
+ if (n_tokens != 2) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
- if (softnic_parser_read_uint32(&p.offset_port_id,
- tokens[5]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id");
- return;
- }
+ name = tokens[1];
- pipeline = softnic_pipeline_create(softnic, name, &p);
- if (pipeline == NULL) {
+ tap = softnic_tap_create(softnic, name);
+ if (tap == NULL) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
/**
- * pipeline <pipeline_name> port in
- * bsz <burst_size>
- * link <link_name> rxq <queue_id>
- * | swq <swq_name>
- * | tmgr <tmgr_name>
- * | tap <tap_name> mempool <mempool_name> mtu <mtu>
- * | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
- * [action <port_in_action_profile_name>]
- * [disabled]
+ * port in action profile <profile_name>
+ * [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]
+ * [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>]
*/
static void
-cmd_pipeline_port_in(struct pmd_internals *softnic,
+cmd_port_in_action_profile(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
- struct softnic_port_in_params p;
- char *pipeline_name;
+ struct softnic_port_in_action_profile_params p;
+ struct softnic_port_in_action_profile *ap;
+ char *name;
uint32_t t0;
- int enabled, status;
-
- if (n_tokens < 7) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
- pipeline_name = tokens[1];
+ memset(&p, 0, sizeof(p));
- if (strcmp(tokens[2], "port") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+ if (n_tokens < 5) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
- if (strcmp(tokens[3], "in") != 0) {
+ if (strcmp(tokens[1], "in") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
return;
}
- if (strcmp(tokens[4], "bsz") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
+ if (strcmp(tokens[2], "action") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
return;
}
- if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
+ if (strcmp(tokens[3], "profile") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
return;
}
- t0 = 6;
+ name = tokens[4];
- if (strcmp(tokens[t0], "link") == 0) {
- if (n_tokens < t0 + 4) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port in link");
+ t0 = 5;
+
+ if (t0 < n_tokens &&
+ (strcmp(tokens[t0], "filter") == 0)) {
+ uint32_t size;
+
+ if (n_tokens < t0 + 10) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter");
return;
}
- p.type = PORT_IN_RXQ;
-
- p.dev_name = tokens[t0 + 1];
+ if (strcmp(tokens[t0 + 1], "match") == 0) {
+ p.fltr.filter_on_match = 1;
+ } else if (strcmp(tokens[t0 + 1], "mismatch") == 0) {
+ p.fltr.filter_on_match = 0;
+ } else {
+ snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch");
+ return;
+ }
- if (strcmp(tokens[t0 + 2], "rxq") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
+ if (strcmp(tokens[t0 + 2], "offset") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
return;
}
- if (softnic_parser_read_uint16(&p.rxq.queue_id,
+ if (softnic_parser_read_uint32(&p.fltr.key_offset,
tokens[t0 + 3]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "queue_id");
+ snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
return;
}
- t0 += 4;
- } else if (strcmp(tokens[t0], "swq") == 0) {
- if (n_tokens < t0 + 2) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port in swq");
+
+ if (strcmp(tokens[t0 + 4], "mask") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
return;
}
- p.type = PORT_IN_SWQ;
-
- p.dev_name = tokens[t0 + 1];
-
- t0 += 2;
- } else if (strcmp(tokens[t0], "tmgr") == 0) {
- if (n_tokens < t0 + 2) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port in tmgr");
+ size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
+ if ((softnic_parse_hex_string(tokens[t0 + 5],
+ p.fltr.key_mask, &size) != 0) ||
+ size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
return;
}
- p.type = PORT_IN_TMGR;
-
- p.dev_name = tokens[t0 + 1];
-
- t0 += 2;
- } else if (strcmp(tokens[t0], "tap") == 0) {
- if (n_tokens < t0 + 6) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port in tap");
+ if (strcmp(tokens[t0 + 6], "key") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
return;
}
- p.type = PORT_IN_TAP;
-
- p.dev_name = tokens[t0 + 1];
-
- if (strcmp(tokens[t0 + 2], "mempool") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "mempool");
+ size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
+ if ((softnic_parse_hex_string(tokens[t0 + 7],
+ p.fltr.key, &size) != 0) ||
+ size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "key_value");
return;
}
- p.tap.mempool_name = tokens[t0 + 3];
-
- if (strcmp(tokens[t0 + 4], "mtu") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "mtu");
+ if (strcmp(tokens[t0 + 8], "port") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
return;
}
- if (softnic_parser_read_uint32(&p.tap.mtu,
- tokens[t0 + 5]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
+ if (softnic_parser_read_uint32(&p.fltr.port_id,
+ tokens[t0 + 9]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
return;
}
- t0 += 6;
- } else if (strcmp(tokens[t0], "source") == 0) {
- if (n_tokens < t0 + 6) {
+ p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR;
+ t0 += 10;
+ } /* filter */
+
+ if (t0 < n_tokens &&
+ (strcmp(tokens[t0], "balance") == 0)) {
+ uint32_t i;
+
+ if (n_tokens < t0 + 22) {
snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port in source");
+ "port in action profile balance");
return;
}
- p.type = PORT_IN_SOURCE;
-
- p.dev_name = NULL;
-
- if (strcmp(tokens[t0 + 1], "mempool") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "mempool");
+ if (strcmp(tokens[t0 + 1], "offset") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
return;
}
- p.source.mempool_name = tokens[t0 + 2];
-
- if (strcmp(tokens[t0 + 3], "file") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "file");
+ if (softnic_parser_read_uint32(&p.lb.key_offset,
+ tokens[t0 + 2]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
return;
}
- p.source.file_name = tokens[t0 + 4];
-
- if (strcmp(tokens[t0 + 5], "bpp") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "bpp");
+ if (strcmp(tokens[t0 + 3], "mask") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
return;
}
- if (softnic_parser_read_uint32(&p.source.n_bytes_per_pkt,
- tokens[t0 + 6]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "n_bytes_per_pkt");
+ p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
+ if (softnic_parse_hex_string(tokens[t0 + 4],
+ p.lb.key_mask, &p.lb.key_size) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
return;
}
- t0 += 7;
- } else {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
- return;
- }
-
- p.action_profile_name = NULL;
- if (n_tokens > t0 &&
- (strcmp(tokens[t0], "action") == 0)) {
- if (n_tokens < t0 + 2) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
+ if (strcmp(tokens[t0 + 5], "port") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
return;
}
- p.action_profile_name = tokens[t0 + 1];
-
- t0 += 2;
- }
-
- enabled = 1;
- if (n_tokens > t0 &&
- (strcmp(tokens[t0], "disabled") == 0)) {
- enabled = 0;
+ for (i = 0; i < 16; i++)
+ if (softnic_parser_read_uint32(&p.lb.port_id[i],
+ tokens[t0 + 6 + i]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
+ return;
+ }
- t0 += 1;
- }
+ p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB;
+ t0 += 22;
+ } /* balance */
- if (n_tokens != t0) {
+ if (t0 < n_tokens) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
- status = softnic_pipeline_port_in_create(softnic,
- pipeline_name,
- &p,
- enabled);
- if (status) {
+ ap = softnic_port_in_action_profile_create(softnic, name, &p);
+ if (ap == NULL) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
/**
- * pipeline <pipeline_name> port out
- * bsz <burst_size>
- * link <link_name> txq <txq_id>
- * | swq <swq_name>
- * | tmgr <tmgr_name>
- * | tap <tap_name>
- * | sink [file <file_name> pkts <max_n_pkts>]
+ * table action profile <profile_name>
+ * ipv4 | ipv6
+ * offset <ip_offset>
+ * fwd
+ * [balance offset <key_offset> mask <key_mask> outoffset <out_offset>]
+ * [meter srtcm | trtcm
+ * tc <n_tc>
+ * stats none | pkts | bytes | both]
+ * [tm spp <n_subports_per_port> pps <n_pipes_per_subport>]
+ * [encap ether | vlan | qinq | mpls | pppoe]
+ * [nat src | dst
+ * proto udp | tcp]
+ * [ttl drop | fwd
+ * stats none | pkts]
+ * [stats pkts | bytes | both]
+ * [time]
*/
static void
-cmd_pipeline_port_out(struct pmd_internals *softnic,
+cmd_table_action_profile(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
- struct softnic_port_out_params p;
- char *pipeline_name;
- int status;
+ struct softnic_table_action_profile_params p;
+ struct softnic_table_action_profile *ap;
+ char *name;
+ uint32_t t0;
memset(&p, 0, sizeof(p));
- if (n_tokens < 7) {
+ if (n_tokens < 8) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
- pipeline_name = tokens[1];
-
- if (strcmp(tokens[2], "port") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+ if (strcmp(tokens[1], "action") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
return;
}
- if (strcmp(tokens[3], "out") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
+ if (strcmp(tokens[2], "profile") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
return;
}
- if (strcmp(tokens[4], "bsz") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
+ name = tokens[3];
+
+ if (strcmp(tokens[4], "ipv4") == 0) {
+ p.common.ip_version = 1;
+ } else if (strcmp(tokens[4], "ipv6") == 0) {
+ p.common.ip_version = 0;
+ } else {
+ snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6");
return;
}
- if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
+ if (strcmp(tokens[5], "offset") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
return;
}
- if (strcmp(tokens[6], "link") == 0) {
- if (n_tokens != 10) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port out link");
- return;
- }
+ if (softnic_parser_read_uint32(&p.common.ip_offset,
+ tokens[6]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset");
+ return;
+ }
- p.type = PORT_OUT_TXQ;
+ if (strcmp(tokens[7], "fwd") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd");
+ return;
+ }
- p.dev_name = tokens[7];
+ p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
- if (strcmp(tokens[8], "txq") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
+ t0 = 8;
+ if (t0 < n_tokens &&
+ (strcmp(tokens[t0], "balance") == 0)) {
+ if (n_tokens < t0 + 7) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, "table action profile balance");
return;
}
- if (softnic_parser_read_uint16(&p.txq.queue_id,
- tokens[9]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
+ if (strcmp(tokens[t0 + 1], "offset") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
return;
}
- } else if (strcmp(tokens[6], "swq") == 0) {
- if (n_tokens != 8) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port out swq");
+
+ if (softnic_parser_read_uint32(&p.lb.key_offset,
+ tokens[t0 + 2]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
return;
}
- p.type = PORT_OUT_SWQ;
-
- p.dev_name = tokens[7];
- } else if (strcmp(tokens[6], "tmgr") == 0) {
- if (n_tokens != 8) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port out tmgr");
+ if (strcmp(tokens[t0 + 3], "mask") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
return;
}
- p.type = PORT_OUT_TMGR;
-
- p.dev_name = tokens[7];
- } else if (strcmp(tokens[6], "tap") == 0) {
- if (n_tokens != 8) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port out tap");
+ p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
+ if (softnic_parse_hex_string(tokens[t0 + 4],
+ p.lb.key_mask, &p.lb.key_size) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
return;
}
- p.type = PORT_OUT_TAP;
+ if (strcmp(tokens[t0 + 5], "outoffset") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset");
+ return;
+ }
- p.dev_name = tokens[7];
- } else if (strcmp(tokens[6], "sink") == 0) {
- if ((n_tokens != 7) && (n_tokens != 11)) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port out sink");
+ if (softnic_parser_read_uint32(&p.lb.out_offset,
+ tokens[t0 + 6]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "out_offset");
return;
}
- p.type = PORT_OUT_SINK;
+ p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB;
+ t0 += 7;
+ } /* balance */
- p.dev_name = NULL;
-
- if (n_tokens == 7) {
- p.sink.file_name = NULL;
- p.sink.max_n_pkts = 0;
- } else {
- if (strcmp(tokens[7], "file") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "file");
- return;
- }
-
- p.sink.file_name = tokens[8];
-
- if (strcmp(tokens[9], "pkts") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts");
- return;
- }
-
- if (softnic_parser_read_uint32(&p.sink.max_n_pkts,
- tokens[10]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts");
- return;
- }
- }
- } else {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
- return;
- }
-
- status = softnic_pipeline_port_out_create(softnic, pipeline_name, &p);
- if (status) {
- snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
- return;
- }
-}
-
-/**
- * pipeline <pipeline_name> table
- * match
- * acl
- * ipv4 | ipv6
- * offset <ip_header_offset>
- * size <n_rules>
- * | array
- * offset <key_offset>
- * size <n_keys>
- * | hash
- * ext | lru
- * key <key_size>
- * mask <key_mask>
- * offset <key_offset>
- * buckets <n_buckets>
- * size <n_keys>
- * | lpm
- * ipv4 | ipv6
- * offset <ip_header_offset>
- * size <n_rules>
- * | stub
- * [action <table_action_profile_name>]
- */
-static void
-cmd_pipeline_table(struct pmd_internals *softnic,
- char **tokens,
- uint32_t n_tokens,
- char *out,
- size_t out_size)
-{
- uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX];
- struct softnic_table_params p;
- char *pipeline_name;
- uint32_t t0;
- int status;
-
- if (n_tokens < 5) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-
- pipeline_name = tokens[1];
-
- if (strcmp(tokens[2], "table") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
- return;
- }
-
- if (strcmp(tokens[3], "match") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
- return;
- }
-
- t0 = 4;
- if (strcmp(tokens[t0], "acl") == 0) {
+ if (t0 < n_tokens &&
+ (strcmp(tokens[t0], "meter") == 0)) {
if (n_tokens < t0 + 6) {
snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline table acl");
+ "table action profile meter");
return;
}
- p.match_type = TABLE_ACL;
-
- if (strcmp(tokens[t0 + 1], "ipv4") == 0) {
- p.match.acl.ip_version = 1;
- } else if (strcmp(tokens[t0 + 1], "ipv6") == 0) {
- p.match.acl.ip_version = 0;
+ if (strcmp(tokens[t0 + 1], "srtcm") == 0) {
+ p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM;
+ } else if (strcmp(tokens[t0 + 1], "trtcm") == 0) {
+ p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM;
} else {
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "ipv4 or ipv6");
+ "srtcm or trtcm");
return;
}
- if (strcmp(tokens[t0 + 2], "offset") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
+ if (strcmp(tokens[t0 + 2], "tc") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc");
return;
}
- if (softnic_parser_read_uint32(&p.match.acl.ip_header_offset,
+ if (softnic_parser_read_uint32(&p.mtr.n_tc,
tokens[t0 + 3]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "ip_header_offset");
+ snprintf(out, out_size, MSG_ARG_INVALID, "n_tc");
return;
}
- if (strcmp(tokens[t0 + 4], "size") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
+ if (strcmp(tokens[t0 + 4], "stats") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
return;
}
- if (softnic_parser_read_uint32(&p.match.acl.n_rules,
- tokens[t0 + 5]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
+ if (strcmp(tokens[t0 + 5], "none") == 0) {
+ p.mtr.n_packets_enabled = 0;
+ p.mtr.n_bytes_enabled = 0;
+ } else if (strcmp(tokens[t0 + 5], "pkts") == 0) {
+ p.mtr.n_packets_enabled = 1;
+ p.mtr.n_bytes_enabled = 0;
+ } else if (strcmp(tokens[t0 + 5], "bytes") == 0) {
+ p.mtr.n_packets_enabled = 0;
+ p.mtr.n_bytes_enabled = 1;
+ } else if (strcmp(tokens[t0 + 5], "both") == 0) {
+ p.mtr.n_packets_enabled = 1;
+ p.mtr.n_bytes_enabled = 1;
+ } else {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND,
+ "none or pkts or bytes or both");
return;
}
+ p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR;
t0 += 6;
- } else if (strcmp(tokens[t0], "array") == 0) {
+ } /* meter */
+
+ if (t0 < n_tokens &&
+ (strcmp(tokens[t0], "tm") == 0)) {
if (n_tokens < t0 + 5) {
snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline table array");
+ "table action profile tm");
return;
}
- p.match_type = TABLE_ARRAY;
-
- if (strcmp(tokens[t0 + 1], "offset") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
+ if (strcmp(tokens[t0 + 1], "spp") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
return;
}
- if (softnic_parser_read_uint32(&p.match.array.key_offset,
+ if (softnic_parser_read_uint32(&p.tm.n_subports_per_port,
tokens[t0 + 2]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "n_subports_per_port");
return;
}
- if (strcmp(tokens[t0 + 3], "size") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
+ if (strcmp(tokens[t0 + 3], "pps") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
return;
}
- if (softnic_parser_read_uint32(&p.match.array.n_keys,
+ if (softnic_parser_read_uint32(&p.tm.n_pipes_per_subport,
tokens[t0 + 4]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "n_pipes_per_subport");
return;
}
+ p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM;
t0 += 5;
- } else if (strcmp(tokens[t0], "hash") == 0) {
- uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX;
+ } /* tm */
- if (n_tokens < t0 + 12) {
+ if (t0 < n_tokens &&
+ (strcmp(tokens[t0], "encap") == 0)) {
+ if (n_tokens < t0 + 2) {
snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline table hash");
+ "action profile encap");
return;
}
- p.match_type = TABLE_HASH;
-
- if (strcmp(tokens[t0 + 1], "ext") == 0) {
- p.match.hash.extendable_bucket = 1;
- } else if (strcmp(tokens[t0 + 1], "lru") == 0) {
- p.match.hash.extendable_bucket = 0;
+ if (strcmp(tokens[t0 + 1], "ether") == 0) {
+ p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER;
+ } else if (strcmp(tokens[t0 + 1], "vlan") == 0) {
+ p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN;
+ } else if (strcmp(tokens[t0 + 1], "qinq") == 0) {
+ p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ;
+ } else if (strcmp(tokens[t0 + 1], "mpls") == 0) {
+ p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS;
+ } else if (strcmp(tokens[t0 + 1], "pppoe") == 0) {
+ p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE;
} else {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "ext or lru");
+ snprintf(out, out_size, MSG_ARG_MISMATCH, "encap");
return;
}
- if (strcmp(tokens[t0 + 2], "key") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
+ p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP;
+ t0 += 2;
+ } /* encap */
+
+ if (t0 < n_tokens &&
+ (strcmp(tokens[t0], "nat") == 0)) {
+ if (n_tokens < t0 + 4) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "table action profile nat");
return;
}
- if ((softnic_parser_read_uint32(&p.match.hash.key_size,
- tokens[t0 + 3]) != 0) ||
- p.match.hash.key_size == 0 ||
- p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX) {
- snprintf(out, out_size, MSG_ARG_INVALID, "key_size");
+ if (strcmp(tokens[t0 + 1], "src") == 0) {
+ p.nat.source_nat = 1;
+ } else if (strcmp(tokens[t0 + 1], "dst") == 0) {
+ p.nat.source_nat = 0;
+ } else {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND,
+ "src or dst");
return;
}
- if (strcmp(tokens[t0 + 4], "mask") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
+ if (strcmp(tokens[t0 + 2], "proto") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto");
return;
}
- if ((softnic_parse_hex_string(tokens[t0 + 5],
- key_mask, &key_mask_size) != 0) ||
- key_mask_size != p.match.hash.key_size) {
- snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
+ if (strcmp(tokens[t0 + 3], "tcp") == 0) {
+ p.nat.proto = 0x06;
+ } else if (strcmp(tokens[t0 + 3], "udp") == 0) {
+ p.nat.proto = 0x11;
+ } else {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND,
+ "tcp or udp");
return;
}
- p.match.hash.key_mask = key_mask;
- if (strcmp(tokens[t0 + 6], "offset") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
+ p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT;
+ t0 += 4;
+ } /* nat */
+
+ if (t0 < n_tokens &&
+ (strcmp(tokens[t0], "ttl") == 0)) {
+ if (n_tokens < t0 + 4) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "table action profile ttl");
return;
}
- if (softnic_parser_read_uint32(&p.match.hash.key_offset,
- tokens[t0 + 7]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
+ if (strcmp(tokens[t0 + 1], "drop") == 0) {
+ p.ttl.drop = 1;
+ } else if (strcmp(tokens[t0 + 1], "fwd") == 0) {
+ p.ttl.drop = 0;
+ } else {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND,
+ "drop or fwd");
return;
}
- if (strcmp(tokens[t0 + 8], "buckets") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets");
- return;
- }
-
- if (softnic_parser_read_uint32(&p.match.hash.n_buckets,
- tokens[t0 + 9]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets");
- return;
- }
-
- if (strcmp(tokens[t0 + 10], "size") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
- return;
- }
-
- if (softnic_parser_read_uint32(&p.match.hash.n_keys,
- tokens[t0 + 11]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
- return;
- }
-
- t0 += 12;
- } else if (strcmp(tokens[t0], "lpm") == 0) {
- if (n_tokens < t0 + 6) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline table lpm");
+ if (strcmp(tokens[t0 + 2], "stats") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
return;
}
- p.match_type = TABLE_LPM;
-
- if (strcmp(tokens[t0 + 1], "ipv4") == 0) {
- p.match.lpm.key_size = 4;
- } else if (strcmp(tokens[t0 + 1], "ipv6") == 0) {
- p.match.lpm.key_size = 16;
+ if (strcmp(tokens[t0 + 3], "none") == 0) {
+ p.ttl.n_packets_enabled = 0;
+ } else if (strcmp(tokens[t0 + 3], "pkts") == 0) {
+ p.ttl.n_packets_enabled = 1;
} else {
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "ipv4 or ipv6");
- return;
- }
-
- if (strcmp(tokens[t0 + 2], "offset") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
+ "none or pkts");
return;
}
- if (softnic_parser_read_uint32(&p.match.lpm.key_offset,
- tokens[t0 + 3]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
- return;
- }
+ p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL;
+ t0 += 4;
+ } /* ttl */
- if (strcmp(tokens[t0 + 4], "size") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
+ if (t0 < n_tokens &&
+ (strcmp(tokens[t0], "stats") == 0)) {
+ if (n_tokens < t0 + 2) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "table action profile stats");
return;
}
- if (softnic_parser_read_uint32(&p.match.lpm.n_rules,
- tokens[t0 + 5]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
+ if (strcmp(tokens[t0 + 1], "pkts") == 0) {
+ p.stats.n_packets_enabled = 1;
+ p.stats.n_bytes_enabled = 0;
+ } else if (strcmp(tokens[t0 + 1], "bytes") == 0) {
+ p.stats.n_packets_enabled = 0;
+ p.stats.n_bytes_enabled = 1;
+ } else if (strcmp(tokens[t0 + 1], "both") == 0) {
+ p.stats.n_packets_enabled = 1;
+ p.stats.n_bytes_enabled = 1;
+ } else {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND,
+ "pkts or bytes or both");
return;
}
- t0 += 6;
- } else if (strcmp(tokens[t0], "stub") == 0) {
- p.match_type = TABLE_STUB;
+ p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS;
+ t0 += 2;
+ } /* stats */
+ if (t0 < n_tokens &&
+ (strcmp(tokens[t0], "time") == 0)) {
+ p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME;
t0 += 1;
- } else {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
- return;
- }
-
- p.action_profile_name = NULL;
- if (n_tokens > t0 &&
- (strcmp(tokens[t0], "action") == 0)) {
- if (n_tokens < t0 + 2) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
- return;
- }
-
- p.action_profile_name = tokens[t0 + 1];
-
- t0 += 2;
- }
+ } /* time */
- if (n_tokens > t0) {
+ if (t0 < n_tokens) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
- status = softnic_pipeline_table_create(softnic, pipeline_name, &p);
- if (status) {
+ ap = softnic_table_action_profile_create(softnic, name, &p);
+ if (ap == NULL) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
/**
- * pipeline <pipeline_name> port in <port_id> table <table_id>
+ * pipeline <pipeline_name>
+ * period <timer_period_ms>
+ * offset_port_id <offset_port_id>
*/
static void
-cmd_pipeline_port_in_table(struct pmd_internals *softnic,
+cmd_pipeline(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
- char *pipeline_name;
- uint32_t port_id, table_id;
- int status;
+ struct pipeline_params p;
+ char *name;
+ struct pipeline *pipeline;
- if (n_tokens != 7) {
+ if (n_tokens != 6) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
- pipeline_name = tokens[1];
-
- if (strcmp(tokens[2], "port") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
- return;
- }
+ name = tokens[1];
- if (strcmp(tokens[3], "in") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
+ if (strcmp(tokens[2], "period") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period");
return;
}
- if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
+ if (softnic_parser_read_uint32(&p.timer_period_ms,
+ tokens[3]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms");
return;
}
- if (strcmp(tokens[5], "table") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
+ if (strcmp(tokens[4], "offset_port_id") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id");
return;
}
- if (softnic_parser_read_uint32(&table_id, tokens[6]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
+ if (softnic_parser_read_uint32(&p.offset_port_id,
+ tokens[5]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id");
return;
}
- status = softnic_pipeline_port_in_connect_to_table(softnic,
- pipeline_name,
- port_id,
- table_id);
- if (status) {
+ pipeline = softnic_pipeline_create(softnic, name, &p);
+ if (pipeline == NULL) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
/**
- * pipeline <pipeline_name> port in <port_id> enable
+ * pipeline <pipeline_name> port in
+ * bsz <burst_size>
+ * link <link_name> rxq <queue_id>
+ * | swq <swq_name>
+ * | tmgr <tmgr_name>
+ * | tap <tap_name> mempool <mempool_name> mtu <mtu>
+ * | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
+ * [action <port_in_action_profile_name>]
+ * [disabled]
*/
static void
-cmd_softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
+cmd_pipeline_port_in(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
+ struct softnic_port_in_params p;
char *pipeline_name;
- uint32_t port_id;
- int status;
+ uint32_t t0;
+ int enabled, status;
- if (n_tokens != 6) {
+ if (n_tokens < 7) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
return;
}
- if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
+ if (strcmp(tokens[4], "bsz") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
return;
}
- if (strcmp(tokens[5], "enable") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
+ if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
return;
}
- status = softnic_pipeline_port_in_enable(softnic, pipeline_name, port_id);
- if (status) {
- snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
- return;
- }
-}
+ t0 = 6;
-/**
- * pipeline <pipeline_name> port in <port_id> disable
- */
-static void
-cmd_softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
- char **tokens,
- uint32_t n_tokens,
- char *out,
- size_t out_size)
-{
- char *pipeline_name;
- uint32_t port_id;
- int status;
+ if (strcmp(tokens[t0], "link") == 0) {
+ if (n_tokens < t0 + 4) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "pipeline port in link");
+ return;
+ }
- if (n_tokens != 6) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
+ p.type = PORT_IN_RXQ;
- pipeline_name = tokens[1];
+ p.dev_name = tokens[t0 + 1];
- if (strcmp(tokens[2], "port") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
- return;
- }
+ if (strcmp(tokens[t0 + 2], "rxq") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
+ return;
+ }
- if (strcmp(tokens[3], "in") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
- return;
- }
+ if (softnic_parser_read_uint16(&p.rxq.queue_id,
+ tokens[t0 + 3]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "queue_id");
+ return;
+ }
+ t0 += 4;
+ } else if (strcmp(tokens[t0], "swq") == 0) {
+ if (n_tokens < t0 + 2) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "pipeline port in swq");
+ return;
+ }
- if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
- return;
- }
+ p.type = PORT_IN_SWQ;
- if (strcmp(tokens[5], "disable") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
- return;
- }
+ p.dev_name = tokens[t0 + 1];
- status = softnic_pipeline_port_in_disable(softnic, pipeline_name, port_id);
- if (status) {
- snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
- return;
- }
-}
+ t0 += 2;
+ } else if (strcmp(tokens[t0], "tmgr") == 0) {
+ if (n_tokens < t0 + 2) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "pipeline port in tmgr");
+ return;
+ }
+
+ p.type = PORT_IN_TMGR;
+
+ p.dev_name = tokens[t0 + 1];
+
+ t0 += 2;
+ } else if (strcmp(tokens[t0], "tap") == 0) {
+ if (n_tokens < t0 + 6) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "pipeline port in tap");
+ return;
+ }
+
+ p.type = PORT_IN_TAP;
+
+ p.dev_name = tokens[t0 + 1];
+
+ if (strcmp(tokens[t0 + 2], "mempool") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND,
+ "mempool");
+ return;
+ }
+
+ p.tap.mempool_name = tokens[t0 + 3];
+
+ if (strcmp(tokens[t0 + 4], "mtu") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND,
+ "mtu");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&p.tap.mtu,
+ tokens[t0 + 5]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
+ return;
+ }
+
+ t0 += 6;
+ } else if (strcmp(tokens[t0], "source") == 0) {
+ if (n_tokens < t0 + 6) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "pipeline port in source");
+ return;
+ }
+
+ p.type = PORT_IN_SOURCE;
+
+ p.dev_name = NULL;
+
+ if (strcmp(tokens[t0 + 1], "mempool") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND,
+ "mempool");
+ return;
+ }
+
+ p.source.mempool_name = tokens[t0 + 2];
+
+ if (strcmp(tokens[t0 + 3], "file") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND,
+ "file");
+ return;
+ }
+
+ p.source.file_name = tokens[t0 + 4];
+
+ if (strcmp(tokens[t0 + 5], "bpp") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND,
+ "bpp");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&p.source.n_bytes_per_pkt,
+ tokens[t0 + 6]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "n_bytes_per_pkt");
+ return;
+ }
+
+ t0 += 7;
+ } else {
+ snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
+ return;
+ }
+
+ p.action_profile_name = NULL;
+ if (n_tokens > t0 &&
+ (strcmp(tokens[t0], "action") == 0)) {
+ if (n_tokens < t0 + 2) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
+ return;
+ }
+
+ p.action_profile_name = tokens[t0 + 1];
+
+ t0 += 2;
+ }
+
+ enabled = 1;
+ if (n_tokens > t0 &&
+ (strcmp(tokens[t0], "disabled") == 0)) {
+ enabled = 0;
+
+ t0 += 1;
+ }
+
+ if (n_tokens != t0) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ status = softnic_pipeline_port_in_create(softnic,
+ pipeline_name,
+ &p,
+ enabled);
+ if (status) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+ return;
+ }
+}
+
+/**
+ * pipeline <pipeline_name> port out
+ * bsz <burst_size>
+ * link <link_name> txq <txq_id>
+ * | swq <swq_name>
+ * | tmgr <tmgr_name>
+ * | tap <tap_name>
+ * | sink [file <file_name> pkts <max_n_pkts>]
+ */
+static void
+cmd_pipeline_port_out(struct pmd_internals *softnic,
+ char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size)
+{
+ struct softnic_port_out_params p;
+ char *pipeline_name;
+ int status;
+
+ memset(&p, 0, sizeof(p));
+
+ if (n_tokens < 7) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ pipeline_name = tokens[1];
+
+ if (strcmp(tokens[2], "port") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+ return;
+ }
+
+ if (strcmp(tokens[3], "out") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
+ return;
+ }
+
+ if (strcmp(tokens[4], "bsz") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
+ return;
+ }
+
+ if (strcmp(tokens[6], "link") == 0) {
+ if (n_tokens != 10) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "pipeline port out link");
+ return;
+ }
+
+ p.type = PORT_OUT_TXQ;
+
+ p.dev_name = tokens[7];
+
+ if (strcmp(tokens[8], "txq") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
+ return;
+ }
+
+ if (softnic_parser_read_uint16(&p.txq.queue_id,
+ tokens[9]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
+ return;
+ }
+ } else if (strcmp(tokens[6], "swq") == 0) {
+ if (n_tokens != 8) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "pipeline port out swq");
+ return;
+ }
+
+ p.type = PORT_OUT_SWQ;
+
+ p.dev_name = tokens[7];
+ } else if (strcmp(tokens[6], "tmgr") == 0) {
+ if (n_tokens != 8) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "pipeline port out tmgr");
+ return;
+ }
+
+ p.type = PORT_OUT_TMGR;
+
+ p.dev_name = tokens[7];
+ } else if (strcmp(tokens[6], "tap") == 0) {
+ if (n_tokens != 8) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "pipeline port out tap");
+ return;
+ }
+
+ p.type = PORT_OUT_TAP;
+
+ p.dev_name = tokens[7];
+ } else if (strcmp(tokens[6], "sink") == 0) {
+ if ((n_tokens != 7) && (n_tokens != 11)) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "pipeline port out sink");
+ return;
+ }
+
+ p.type = PORT_OUT_SINK;
+
+ p.dev_name = NULL;
+
+ if (n_tokens == 7) {
+ p.sink.file_name = NULL;
+ p.sink.max_n_pkts = 0;
+ } else {
+ if (strcmp(tokens[7], "file") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND,
+ "file");
+ return;
+ }
+
+ p.sink.file_name = tokens[8];
+
+ if (strcmp(tokens[9], "pkts") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&p.sink.max_n_pkts,
+ tokens[10]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts");
+ return;
+ }
+ }
+ } else {
+ snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
+ return;
+ }
+
+ status = softnic_pipeline_port_out_create(softnic, pipeline_name, &p);
+ if (status) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+ return;
+ }
+}
+
+/**
+ * pipeline <pipeline_name> table
+ * match
+ * acl
+ * ipv4 | ipv6
+ * offset <ip_header_offset>
+ * size <n_rules>
+ * | array
+ * offset <key_offset>
+ * size <n_keys>
+ * | hash
+ * ext | lru
+ * key <key_size>
+ * mask <key_mask>
+ * offset <key_offset>
+ * buckets <n_buckets>
+ * size <n_keys>
+ * | lpm
+ * ipv4 | ipv6
+ * offset <ip_header_offset>
+ * size <n_rules>
+ * | stub
+ * [action <table_action_profile_name>]
+ */
+static void
+cmd_pipeline_table(struct pmd_internals *softnic,
+ char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size)
+{
+ uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX];
+ struct softnic_table_params p;
+ char *pipeline_name;
+ uint32_t t0;
+ int status;
+
+ if (n_tokens < 5) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ pipeline_name = tokens[1];
+
+ if (strcmp(tokens[2], "table") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
+ return;
+ }
+
+ if (strcmp(tokens[3], "match") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
+ return;
+ }
+
+ t0 = 4;
+ if (strcmp(tokens[t0], "acl") == 0) {
+ if (n_tokens < t0 + 6) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "pipeline table acl");
+ return;
+ }
+
+ p.match_type = TABLE_ACL;
+
+ if (strcmp(tokens[t0 + 1], "ipv4") == 0) {
+ p.match.acl.ip_version = 1;
+ } else if (strcmp(tokens[t0 + 1], "ipv6") == 0) {
+ p.match.acl.ip_version = 0;
+ } else {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND,
+ "ipv4 or ipv6");
+ return;
+ }
+
+ if (strcmp(tokens[t0 + 2], "offset") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&p.match.acl.ip_header_offset,
+ tokens[t0 + 3]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "ip_header_offset");
+ return;
+ }
+
+ if (strcmp(tokens[t0 + 4], "size") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&p.match.acl.n_rules,
+ tokens[t0 + 5]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
+ return;
+ }
+
+ t0 += 6;
+ } else if (strcmp(tokens[t0], "array") == 0) {
+ if (n_tokens < t0 + 5) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "pipeline table array");
+ return;
+ }
+
+ p.match_type = TABLE_ARRAY;
+
+ if (strcmp(tokens[t0 + 1], "offset") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&p.match.array.key_offset,
+ tokens[t0 + 2]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
+ return;
+ }
+
+ if (strcmp(tokens[t0 + 3], "size") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&p.match.array.n_keys,
+ tokens[t0 + 4]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
+ return;
+ }
+
+ t0 += 5;
+ } else if (strcmp(tokens[t0], "hash") == 0) {
+ uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX;
+
+ if (n_tokens < t0 + 12) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "pipeline table hash");
+ return;
+ }
+
+ p.match_type = TABLE_HASH;
+
+ if (strcmp(tokens[t0 + 1], "ext") == 0) {
+ p.match.hash.extendable_bucket = 1;
+ } else if (strcmp(tokens[t0 + 1], "lru") == 0) {
+ p.match.hash.extendable_bucket = 0;
+ } else {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND,
+ "ext or lru");
+ return;
+ }
+
+ if (strcmp(tokens[t0 + 2], "key") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
+ return;
+ }
+
+ if ((softnic_parser_read_uint32(&p.match.hash.key_size,
+ tokens[t0 + 3]) != 0) ||
+ p.match.hash.key_size == 0 ||
+ p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "key_size");
+ return;
+ }
+
+ if (strcmp(tokens[t0 + 4], "mask") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
+ return;
+ }
+
+ if ((softnic_parse_hex_string(tokens[t0 + 5],
+ key_mask, &key_mask_size) != 0) ||
+ key_mask_size != p.match.hash.key_size) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
+ return;
+ }
+ p.match.hash.key_mask = key_mask;
+
+ if (strcmp(tokens[t0 + 6], "offset") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&p.match.hash.key_offset,
+ tokens[t0 + 7]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
+ return;
+ }
+
+ if (strcmp(tokens[t0 + 8], "buckets") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&p.match.hash.n_buckets,
+ tokens[t0 + 9]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets");
+ return;
+ }
+
+ if (strcmp(tokens[t0 + 10], "size") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&p.match.hash.n_keys,
+ tokens[t0 + 11]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
+ return;
+ }
+
+ t0 += 12;
+ } else if (strcmp(tokens[t0], "lpm") == 0) {
+ if (n_tokens < t0 + 6) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ "pipeline table lpm");
+ return;
+ }
+
+ p.match_type = TABLE_LPM;
+
+ if (strcmp(tokens[t0 + 1], "ipv4") == 0) {
+ p.match.lpm.key_size = 4;
+ } else if (strcmp(tokens[t0 + 1], "ipv6") == 0) {
+ p.match.lpm.key_size = 16;
+ } else {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND,
+ "ipv4 or ipv6");
+ return;
+ }
+
+ if (strcmp(tokens[t0 + 2], "offset") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&p.match.lpm.key_offset,
+ tokens[t0 + 3]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
+ return;
+ }
+
+ if (strcmp(tokens[t0 + 4], "size") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&p.match.lpm.n_rules,
+ tokens[t0 + 5]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
+ return;
+ }
+
+ t0 += 6;
+ } else if (strcmp(tokens[t0], "stub") == 0) {
+ p.match_type = TABLE_STUB;
+
+ t0 += 1;
+ } else {
+ snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
+ return;
+ }
+
+ p.action_profile_name = NULL;
+ if (n_tokens > t0 &&
+ (strcmp(tokens[t0], "action") == 0)) {
+ if (n_tokens < t0 + 2) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
+ return;
+ }
+
+ p.action_profile_name = tokens[t0 + 1];
+
+ t0 += 2;
+ }
+
+ if (n_tokens > t0) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ status = softnic_pipeline_table_create(softnic, pipeline_name, &p);
+ if (status) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+ return;
+ }
+}
+
+/**
+ * pipeline <pipeline_name> port in <port_id> table <table_id>
+ */
+static void
+cmd_pipeline_port_in_table(struct pmd_internals *softnic,
+ char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size)
+{
+ char *pipeline_name;
+ uint32_t port_id, table_id;
+ int status;
+
+ if (n_tokens != 7) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ pipeline_name = tokens[1];
+
+ if (strcmp(tokens[2], "port") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+ return;
+ }
+
+ if (strcmp(tokens[3], "in") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
+ return;
+ }
+
+ if (strcmp(tokens[5], "table") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&table_id, tokens[6]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
+ return;
+ }
+
+ status = softnic_pipeline_port_in_connect_to_table(softnic,
+ pipeline_name,
+ port_id,
+ table_id);
+ if (status) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+ return;
+ }
+}
+
+/**
+ * pipeline <pipeline_name> port in <port_id> stats read [clear]
+ */
+
+#define MSG_PIPELINE_PORT_IN_STATS \
+ "Pkts in: %" PRIu64 "\n" \
+ "Pkts dropped by AH: %" PRIu64 "\n" \
+ "Pkts dropped by other: %" PRIu64 "\n"
+
+static void
+cmd_pipeline_port_in_stats(struct pmd_internals *softnic,
+ char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size)
+{
+ struct rte_pipeline_port_in_stats stats;
+ char *pipeline_name;
+ uint32_t port_id;
+ int clear, status;
+
+ if (n_tokens != 7 &&
+ n_tokens != 8) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ pipeline_name = tokens[1];
+
+ if (strcmp(tokens[2], "port") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+ return;
+ }
+
+ if (strcmp(tokens[3], "in") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
+ return;
+ }
+
+ if (strcmp(tokens[5], "stats") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
+ return;
+ }
+
+ if (strcmp(tokens[6], "read") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
+ return;
+ }
+
+ clear = 0;
+ if (n_tokens == 8) {
+ if (strcmp(tokens[7], "clear") != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "clear");
+ return;
+ }
+
+ clear = 1;
+ }
+
+ status = softnic_pipeline_port_in_stats_read(softnic,
+ pipeline_name,
+ port_id,
+ &stats,
+ clear);
+ if (status) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+ return;
+ }
+
+ snprintf(out, out_size, MSG_PIPELINE_PORT_IN_STATS,
+ stats.stats.n_pkts_in,
+ stats.n_pkts_dropped_by_ah,
+ stats.stats.n_pkts_drop);
+}
+
+/**
+ * pipeline <pipeline_name> port in <port_id> enable
+ */
+static void
+cmd_softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
+ char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size)
+{
+ char *pipeline_name;
+ uint32_t port_id;
+ int status;
+
+ if (n_tokens != 6) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ pipeline_name = tokens[1];
+
+ if (strcmp(tokens[2], "port") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+ return;
+ }
+
+ if (strcmp(tokens[3], "in") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
+ return;
+ }
+
+ if (strcmp(tokens[5], "enable") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
+ return;
+ }
+
+ status = softnic_pipeline_port_in_enable(softnic, pipeline_name, port_id);
+ if (status) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+ return;
+ }
+}
+
+/**
+ * pipeline <pipeline_name> port in <port_id> disable
+ */
+static void
+cmd_softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
+ char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size)
+{
+ char *pipeline_name;
+ uint32_t port_id;
+ int status;
+
+ if (n_tokens != 6) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ pipeline_name = tokens[1];
+
+ if (strcmp(tokens[2], "port") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+ return;
+ }
+
+ if (strcmp(tokens[3], "in") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
+ return;
+ }
+
+ if (strcmp(tokens[5], "disable") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
+ return;
+ }
+
+ status = softnic_pipeline_port_in_disable(softnic, pipeline_name, port_id);
+ if (status) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+ return;
+ }
+}
+
+/**
+ * pipeline <pipeline_name> port out <port_id> stats read [clear]
+ */
+#define MSG_PIPELINE_PORT_OUT_STATS \
+ "Pkts in: %" PRIu64 "\n" \
+ "Pkts dropped by AH: %" PRIu64 "\n" \
+ "Pkts dropped by other: %" PRIu64 "\n"
+
+static void
+cmd_pipeline_port_out_stats(struct pmd_internals *softnic,
+ char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size)
+{
+ struct rte_pipeline_port_out_stats stats;
+ char *pipeline_name;
+ uint32_t port_id;
+ int clear, status;
+
+ if (n_tokens != 7 &&
+ n_tokens != 8) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ pipeline_name = tokens[1];
+
+ if (strcmp(tokens[2], "port") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+ return;
+ }
+
+ if (strcmp(tokens[3], "out") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
+ return;
+ }
+
+ if (strcmp(tokens[5], "stats") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
+ return;
+ }
+
+ if (strcmp(tokens[6], "read") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
+ return;
+ }
+
+ clear = 0;
+ if (n_tokens == 8) {
+ if (strcmp(tokens[7], "clear") != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "clear");
+ return;
+ }
+
+ clear = 1;
+ }
+
+ status = softnic_pipeline_port_out_stats_read(softnic,
+ pipeline_name,
+ port_id,
+ &stats,
+ clear);
+ if (status) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+ return;
+ }
+
+ snprintf(out, out_size, MSG_PIPELINE_PORT_OUT_STATS,
+ stats.stats.n_pkts_in,
+ stats.n_pkts_dropped_by_ah,
+ stats.stats.n_pkts_drop);
+}
+
+/**
+ * pipeline <pipeline_name> table <table_id> stats read [clear]
+ */
+#define MSG_PIPELINE_TABLE_STATS \
+ "Pkts in: %" PRIu64 "\n" \
+ "Pkts in with lookup miss: %" PRIu64 "\n" \
+ "Pkts in with lookup hit dropped by AH: %" PRIu64 "\n" \
+ "Pkts in with lookup hit dropped by others: %" PRIu64 "\n" \
+ "Pkts in with lookup miss dropped by AH: %" PRIu64 "\n" \
+ "Pkts in with lookup miss dropped by others: %" PRIu64 "\n"
+
+static void
+cmd_pipeline_table_stats(struct pmd_internals *softnic,
+ char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size)
+{
+ struct rte_pipeline_table_stats stats;
+ char *pipeline_name;
+ uint32_t table_id;
+ int clear, status;
+
+ if (n_tokens != 6 &&
+ n_tokens != 7) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ pipeline_name = tokens[1];
+
+ if (strcmp(tokens[2], "table") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
+ return;
+ }
+
+ if (strcmp(tokens[4], "stats") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
+ return;
+ }
+
+ if (strcmp(tokens[5], "read") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
+ return;
+ }
+
+ clear = 0;
+ if (n_tokens == 7) {
+ if (strcmp(tokens[6], "clear") != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "clear");
+ return;
+ }
+
+ clear = 1;
+ }
+
+ status = softnic_pipeline_table_stats_read(softnic,
+ pipeline_name,
+ table_id,
+ &stats,
+ clear);
+ if (status) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+ return;
+ }
+
+ snprintf(out, out_size, MSG_PIPELINE_TABLE_STATS,
+ stats.stats.n_pkts_in,
+ stats.stats.n_pkts_lookup_miss,
+ stats.n_pkts_dropped_by_lkp_hit_ah,
+ stats.n_pkts_dropped_lkp_hit,
+ stats.n_pkts_dropped_by_lkp_miss_ah,
+ stats.n_pkts_dropped_lkp_miss);
+}
/**
* <match> ::=
parse_table_action(char **tokens,
uint32_t n_tokens,
char *out,
- size_t out_size,
- struct softnic_table_rule_action *a)
+ size_t out_size,
+ struct softnic_table_rule_action *a)
+{
+ uint32_t n_tokens0 = n_tokens;
+
+ memset(a, 0, sizeof(*a));
+
+ if (n_tokens < 2 ||
+ strcmp(tokens[0], "action"))
+ return 0;
+
+ tokens++;
+ n_tokens--;
+
+ if (n_tokens && (strcmp(tokens[0], "fwd") == 0)) {
+ uint32_t n;
+
+ n = parse_table_action_fwd(tokens, n_tokens, a);
+ if (n == 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "action fwd");
+ return 0;
+ }
+
+ tokens += n;
+ n_tokens -= n;
+ }
+
+ if (n_tokens && (strcmp(tokens[0], "balance") == 0)) {
+ uint32_t n;
+
+ n = parse_table_action_balance(tokens, n_tokens, a);
+ if (n == 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "action balance");
+ return 0;
+ }
+
+ tokens += n;
+ n_tokens -= n;
+ }
+
+ if (n_tokens && (strcmp(tokens[0], "meter") == 0)) {
+ uint32_t n;
+
+ n = parse_table_action_meter(tokens, n_tokens, a);
+ if (n == 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "action meter");
+ return 0;
+ }
+
+ tokens += n;
+ n_tokens -= n;
+ }
+
+ if (n_tokens && (strcmp(tokens[0], "tm") == 0)) {
+ uint32_t n;
+
+ n = parse_table_action_tm(tokens, n_tokens, a);
+ if (n == 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "action tm");
+ return 0;
+ }
+
+ tokens += n;
+ n_tokens -= n;
+ }
+
+ if (n_tokens && (strcmp(tokens[0], "encap") == 0)) {
+ uint32_t n;
+
+ n = parse_table_action_encap(tokens, n_tokens, a);
+ if (n == 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "action encap");
+ return 0;
+ }
+
+ tokens += n;
+ n_tokens -= n;
+ }
+
+ if (n_tokens && (strcmp(tokens[0], "nat") == 0)) {
+ uint32_t n;
+
+ n = parse_table_action_nat(tokens, n_tokens, a);
+ if (n == 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "action nat");
+ return 0;
+ }
+
+ tokens += n;
+ n_tokens -= n;
+ }
+
+ if (n_tokens && (strcmp(tokens[0], "ttl") == 0)) {
+ uint32_t n;
+
+ n = parse_table_action_ttl(tokens, n_tokens, a);
+ if (n == 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "action ttl");
+ return 0;
+ }
+
+ tokens += n;
+ n_tokens -= n;
+ }
+
+ if (n_tokens && (strcmp(tokens[0], "stats") == 0)) {
+ uint32_t n;
+
+ n = parse_table_action_stats(tokens, n_tokens, a);
+ if (n == 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "action stats");
+ return 0;
+ }
+
+ tokens += n;
+ n_tokens -= n;
+ }
+
+ if (n_tokens && (strcmp(tokens[0], "time") == 0)) {
+ uint32_t n;
+
+ n = parse_table_action_time(tokens, n_tokens, a);
+ if (n == 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "action time");
+ return 0;
+ }
+
+ tokens += n;
+ n_tokens -= n;
+ }
+
+ if (n_tokens0 - n_tokens == 1) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "action");
+ return 0;
+ }
+
+ return n_tokens0 - n_tokens;
+}
+
+/**
+ * pipeline <pipeline_name> table <table_id> rule add
+ * match <match>
+ * action <table_action>
+ */
+static void
+cmd_softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
+ char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size)
+{
+ struct softnic_table_rule_match m;
+ struct softnic_table_rule_action a;
+ char *pipeline_name;
+ void *data;
+ uint32_t table_id, t0, n_tokens_parsed;
+ int status;
+
+ if (n_tokens < 8) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ pipeline_name = tokens[1];
+
+ if (strcmp(tokens[2], "table") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
+ return;
+ }
+
+ if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
+ return;
+ }
+
+ if (strcmp(tokens[4], "rule") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
+ return;
+ }
+
+ if (strcmp(tokens[5], "add") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
+ return;
+ }
+
+ t0 = 6;
+
+ /* match */
+ n_tokens_parsed = parse_match(tokens + t0,
+ n_tokens - t0,
+ out,
+ out_size,
+ &m);
+ if (n_tokens_parsed == 0)
+ return;
+ t0 += n_tokens_parsed;
+
+ /* action */
+ n_tokens_parsed = parse_table_action(tokens + t0,
+ n_tokens - t0,
+ out,
+ out_size,
+ &a);
+ if (n_tokens_parsed == 0)
+ return;
+ t0 += n_tokens_parsed;
+
+ if (t0 != n_tokens) {
+ snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
+ return;
+ }
+
+ status = softnic_pipeline_table_rule_add(softnic,
+ pipeline_name,
+ table_id,
+ &m,
+ &a,
+ &data);
+ if (status) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+ return;
+ }
+}
+
+/**
+ * pipeline <pipeline_name> table <table_id> rule add
+ * match
+ * default
+ * action
+ * fwd
+ * drop
+ * | port <port_id>
+ * | meta
+ * | table <table_id>
+ */
+static void
+cmd_softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
+ char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size)
{
- uint32_t n_tokens0 = n_tokens;
+ struct softnic_table_rule_action action;
+ void *data;
+ char *pipeline_name;
+ uint32_t table_id;
+ int status;
- memset(a, 0, sizeof(*a));
+ if (n_tokens != 11 &&
+ n_tokens != 12) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
- if (n_tokens < 2 ||
- strcmp(tokens[0], "action"))
- return 0;
+ pipeline_name = tokens[1];
- tokens++;
- n_tokens--;
+ if (strcmp(tokens[2], "table") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
+ return;
+ }
- if (n_tokens && (strcmp(tokens[0], "fwd") == 0)) {
- uint32_t n;
+ if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
+ return;
+ }
- n = parse_table_action_fwd(tokens, n_tokens, a);
- if (n == 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "action fwd");
- return 0;
- }
+ if (strcmp(tokens[4], "rule") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
+ return;
+ }
- tokens += n;
- n_tokens -= n;
+ if (strcmp(tokens[5], "add") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
+ return;
}
- if (n_tokens && (strcmp(tokens[0], "balance") == 0)) {
- uint32_t n;
+ if (strcmp(tokens[6], "match") != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "match");
+ return;
+ }
- n = parse_table_action_balance(tokens, n_tokens, a);
- if (n == 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "action balance");
- return 0;
- }
+ if (strcmp(tokens[7], "default") != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "default");
+ return;
+ }
- tokens += n;
- n_tokens -= n;
+ if (strcmp(tokens[8], "action") != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "action");
+ return;
}
- if (n_tokens && (strcmp(tokens[0], "meter") == 0)) {
- uint32_t n;
+ if (strcmp(tokens[9], "fwd") != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "fwd");
+ return;
+ }
- n = parse_table_action_meter(tokens, n_tokens, a);
- if (n == 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "action meter");
- return 0;
+ action.action_mask = 1 << RTE_TABLE_ACTION_FWD;
+
+ if (strcmp(tokens[10], "drop") == 0) {
+ if (n_tokens != 11) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
}
- tokens += n;
- n_tokens -= n;
- }
+ action.fwd.action = RTE_PIPELINE_ACTION_DROP;
+ } else if (strcmp(tokens[10], "port") == 0) {
+ uint32_t id;
- if (n_tokens && (strcmp(tokens[0], "tm") == 0)) {
- uint32_t n;
+ if (n_tokens != 12) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
- n = parse_table_action_tm(tokens, n_tokens, a);
- if (n == 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "action tm");
- return 0;
+ if (softnic_parser_read_uint32(&id, tokens[11]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
+ return;
}
- tokens += n;
- n_tokens -= n;
- }
+ action.fwd.action = RTE_PIPELINE_ACTION_PORT;
+ action.fwd.id = id;
+ } else if (strcmp(tokens[10], "meta") == 0) {
+ if (n_tokens != 11) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
- if (n_tokens && (strcmp(tokens[0], "encap") == 0)) {
- uint32_t n;
+ action.fwd.action = RTE_PIPELINE_ACTION_PORT_META;
+ } else if (strcmp(tokens[10], "table") == 0) {
+ uint32_t id;
- n = parse_table_action_encap(tokens, n_tokens, a);
- if (n == 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "action encap");
- return 0;
+ if (n_tokens != 12) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
}
- tokens += n;
- n_tokens -= n;
+ if (softnic_parser_read_uint32(&id, tokens[11]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
+ return;
+ }
+
+ action.fwd.action = RTE_PIPELINE_ACTION_TABLE;
+ action.fwd.id = id;
+ } else {
+ snprintf(out, out_size, MSG_ARG_INVALID,
+ "drop or port or meta or table");
+ return;
}
- if (n_tokens && (strcmp(tokens[0], "nat") == 0)) {
- uint32_t n;
+ status = softnic_pipeline_table_rule_add_default(softnic,
+ pipeline_name,
+ table_id,
+ &action,
+ &data);
+ if (status) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+ return;
+ }
+}
- n = parse_table_action_nat(tokens, n_tokens, a);
- if (n == 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "action nat");
- return 0;
- }
+/**
+ * pipeline <pipeline_name> table <table_id> rule add bulk <file_name> <n_rules>
+ *
+ * File <file_name>:
+ * - line format: match <match> action <action>
+ */
+static int
+cli_rule_file_process(const char *file_name,
+ size_t line_len_max,
+ struct softnic_table_rule_match *m,
+ struct softnic_table_rule_action *a,
+ uint32_t *n_rules,
+ uint32_t *line_number,
+ char *out,
+ size_t out_size);
- tokens += n;
- n_tokens -= n;
+static void
+cmd_softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
+ char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size)
+{
+ struct softnic_table_rule_match *match;
+ struct softnic_table_rule_action *action;
+ void **data;
+ char *pipeline_name, *file_name;
+ uint32_t table_id, n_rules, n_rules_parsed, line_number;
+ int status;
+
+ if (n_tokens != 9) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
}
- if (n_tokens && (strcmp(tokens[0], "ttl") == 0)) {
- uint32_t n;
+ pipeline_name = tokens[1];
- n = parse_table_action_ttl(tokens, n_tokens, a);
- if (n == 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "action ttl");
- return 0;
- }
+ if (strcmp(tokens[2], "table") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
+ return;
+ }
- tokens += n;
- n_tokens -= n;
+ if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
+ return;
}
- if (n_tokens && (strcmp(tokens[0], "stats") == 0)) {
- uint32_t n;
+ if (strcmp(tokens[4], "rule") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
+ return;
+ }
- n = parse_table_action_stats(tokens, n_tokens, a);
- if (n == 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "action stats");
- return 0;
- }
+ if (strcmp(tokens[5], "add") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
+ return;
+ }
- tokens += n;
- n_tokens -= n;
+ if (strcmp(tokens[6], "bulk") != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "bulk");
+ return;
}
- if (n_tokens && (strcmp(tokens[0], "time") == 0)) {
- uint32_t n;
+ file_name = tokens[7];
- n = parse_table_action_time(tokens, n_tokens, a);
- if (n == 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "action time");
- return 0;
- }
+ if ((softnic_parser_read_uint32(&n_rules, tokens[8]) != 0) ||
+ n_rules == 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
+ return;
+ }
+
+ /* Memory allocation. */
+ match = calloc(n_rules, sizeof(struct softnic_table_rule_match));
+ action = calloc(n_rules, sizeof(struct softnic_table_rule_action));
+ data = calloc(n_rules, sizeof(void *));
+ if (match == NULL ||
+ action == NULL ||
+ data == NULL) {
+ snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+ free(data);
+ free(action);
+ free(match);
+ return;
+ }
- tokens += n;
- n_tokens -= n;
+ /* Load rule file */
+ n_rules_parsed = n_rules;
+ status = cli_rule_file_process(file_name,
+ 1024,
+ match,
+ action,
+ &n_rules_parsed,
+ &line_number,
+ out,
+ out_size);
+ if (status) {
+ snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
+ free(data);
+ free(action);
+ free(match);
+ return;
+ }
+ if (n_rules_parsed != n_rules) {
+ snprintf(out, out_size, MSG_FILE_NOT_ENOUGH, file_name);
+ free(data);
+ free(action);
+ free(match);
+ return;
}
- if (n_tokens0 - n_tokens == 1) {
- snprintf(out, out_size, MSG_ARG_INVALID, "action");
- return 0;
+ /* Rule bulk add */
+ status = softnic_pipeline_table_rule_add_bulk(softnic,
+ pipeline_name,
+ table_id,
+ match,
+ action,
+ data,
+ &n_rules);
+ if (status) {
+ snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+ free(data);
+ free(action);
+ free(match);
+ return;
}
- return n_tokens0 - n_tokens;
+ /* Memory free */
+ free(data);
+ free(action);
+ free(match);
}
/**
- * pipeline <pipeline_name> table <table_id> rule add
+ * pipeline <pipeline_name> table <table_id> rule delete
* match <match>
- * action <table_action>
*/
static void
-cmd_softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
+cmd_softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
struct softnic_table_rule_match m;
- struct softnic_table_rule_action a;
char *pipeline_name;
- void *data;
- uint32_t table_id, t0, n_tokens_parsed;
+ uint32_t table_id, n_tokens_parsed, t0;
int status;
if (n_tokens < 8) {
return;
}
- if (strcmp(tokens[5], "add") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
+ if (strcmp(tokens[5], "delete") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
return;
}
return;
t0 += n_tokens_parsed;
- /* action */
- n_tokens_parsed = parse_table_action(tokens + t0,
- n_tokens - t0,
- out,
- out_size,
- &a);
- if (n_tokens_parsed == 0)
- return;
- t0 += n_tokens_parsed;
-
- if (t0 != n_tokens) {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
+ if (n_tokens != t0) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
- status = softnic_pipeline_table_rule_add(softnic,
+ status = softnic_pipeline_table_rule_delete(softnic,
pipeline_name,
table_id,
- &m,
- &a,
- &data);
+ &m);
if (status) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
/**
- * pipeline <pipeline_name> table <table_id> rule add
+ * pipeline <pipeline_name> table <table_id> rule delete
* match
* default
- * action
- * fwd
- * drop
- * | port <port_id>
- * | meta
- * | table <table_id>
*/
static void
-cmd_softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
+cmd_softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
- struct softnic_table_rule_action action;
- void *data;
char *pipeline_name;
uint32_t table_id;
int status;
- if (n_tokens != 11 &&
- n_tokens != 12) {
+ if (n_tokens != 8) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
return;
}
- if (strcmp(tokens[5], "add") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
+ if (strcmp(tokens[5], "delete") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
return;
}
return;
}
- if (strcmp(tokens[8], "action") != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "action");
- return;
- }
-
- if (strcmp(tokens[9], "fwd") != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "fwd");
- return;
- }
-
- action.action_mask = 1 << RTE_TABLE_ACTION_FWD;
-
- if (strcmp(tokens[10], "drop") == 0) {
- if (n_tokens != 11) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-
- action.fwd.action = RTE_PIPELINE_ACTION_DROP;
- } else if (strcmp(tokens[10], "port") == 0) {
- uint32_t id;
-
- if (n_tokens != 12) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-
- if (softnic_parser_read_uint32(&id, tokens[11]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
- return;
- }
-
- action.fwd.action = RTE_PIPELINE_ACTION_PORT;
- action.fwd.id = id;
- } else if (strcmp(tokens[10], "meta") == 0) {
- if (n_tokens != 11) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-
- action.fwd.action = RTE_PIPELINE_ACTION_PORT_META;
- } else if (strcmp(tokens[10], "table") == 0) {
- uint32_t id;
-
- if (n_tokens != 12) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-
- if (softnic_parser_read_uint32(&id, tokens[11]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
- return;
- }
-
- action.fwd.action = RTE_PIPELINE_ACTION_TABLE;
- action.fwd.id = id;
- } else {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "drop or port or meta or table");
- return;
- }
-
- status = softnic_pipeline_table_rule_add_default(softnic,
+ status = softnic_pipeline_table_rule_delete_default(softnic,
pipeline_name,
- table_id,
- &action,
- &data);
+ table_id);
if (status) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
/**
- * pipeline <pipeline_name> table <table_id> rule add bulk <file_name> <n_rules>
- *
- * File <file_name>:
- * - line format: match <match> action <action>
+ * pipeline <pipeline_name> table <table_id> rule read stats [clear]
*/
-static int
-cli_rule_file_process(const char *file_name,
- size_t line_len_max,
- struct softnic_table_rule_match *m,
- struct softnic_table_rule_action *a,
- uint32_t *n_rules,
- uint32_t *line_number,
+static void
+cmd_softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic __rte_unused,
+ char **tokens,
+ uint32_t n_tokens __rte_unused,
char *out,
- size_t out_size);
+ size_t out_size)
+{
+ snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
+}
+/**
+ * pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id>
+ * add srtcm cir <cir> cbs <cbs> ebs <ebs>
+ * | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs>
+ */
static void
-cmd_softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
+cmd_pipeline_table_meter_profile_add(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
- struct softnic_table_rule_match *match;
- struct softnic_table_rule_action *action;
- void **data;
- char *pipeline_name, *file_name;
- uint32_t table_id, n_rules, n_rules_parsed, line_number;
+ struct rte_table_action_meter_profile p;
+ char *pipeline_name;
+ uint32_t table_id, meter_profile_id;
int status;
- if (n_tokens != 9) {
+ if (n_tokens < 9) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (strcmp(tokens[2], "table") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
return;
}
return;
}
- if (strcmp(tokens[4], "rule") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
+ if (strcmp(tokens[4], "meter") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
return;
}
- if (strcmp(tokens[5], "add") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
+ if (strcmp(tokens[5], "profile") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
return;
}
- if (strcmp(tokens[6], "bulk") != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "bulk");
+ if (softnic_parser_read_uint32(&meter_profile_id, tokens[6]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id");
return;
}
- file_name = tokens[7];
-
- if ((softnic_parser_read_uint32(&n_rules, tokens[8]) != 0) ||
- n_rules == 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
+ if (strcmp(tokens[7], "add") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
return;
}
- /* Memory allocation. */
- match = calloc(n_rules, sizeof(struct softnic_table_rule_match));
- action = calloc(n_rules, sizeof(struct softnic_table_rule_action));
- data = calloc(n_rules, sizeof(void *));
- if (match == NULL ||
- action == NULL ||
- data == NULL) {
- snprintf(out, out_size, MSG_OUT_OF_MEMORY);
- free(data);
- free(action);
- free(match);
- return;
- }
+ if (strcmp(tokens[8], "srtcm") == 0) {
+ if (n_tokens != 15) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH,
+ tokens[0]);
+ return;
+ }
+
+ p.alg = RTE_TABLE_ACTION_METER_SRTCM;
+
+ if (strcmp(tokens[9], "cir") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
+ return;
+ }
+
+ if (softnic_parser_read_uint64(&p.srtcm.cir, tokens[10]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "cir");
+ return;
+ }
+
+ if (strcmp(tokens[11], "cbs") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
+ return;
+ }
+
+ if (softnic_parser_read_uint64(&p.srtcm.cbs, tokens[12]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
+ return;
+ }
+
+ if (strcmp(tokens[13], "ebs") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ebs");
+ return;
+ }
+
+ if (softnic_parser_read_uint64(&p.srtcm.ebs, tokens[14]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "ebs");
+ return;
+ }
+ } else if (strcmp(tokens[8], "trtcm") == 0) {
+ if (n_tokens != 17) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ p.alg = RTE_TABLE_ACTION_METER_TRTCM;
+
+ if (strcmp(tokens[9], "cir") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
+ return;
+ }
+
+ if (softnic_parser_read_uint64(&p.trtcm.cir, tokens[10]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "cir");
+ return;
+ }
+
+ if (strcmp(tokens[11], "pir") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir");
+ return;
+ }
+
+ if (softnic_parser_read_uint64(&p.trtcm.pir, tokens[12]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "pir");
+ return;
+ }
+ if (strcmp(tokens[13], "cbs") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
+ return;
+ }
+
+ if (softnic_parser_read_uint64(&p.trtcm.cbs, tokens[14]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
+ return;
+ }
+
+ if (strcmp(tokens[15], "pbs") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs");
+ return;
+ }
- /* Load rule file */
- n_rules_parsed = n_rules;
- status = cli_rule_file_process(file_name,
- 1024,
- match,
- action,
- &n_rules_parsed,
- &line_number,
- out,
- out_size);
- if (status) {
- snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
- free(data);
- free(action);
- free(match);
- return;
- }
- if (n_rules_parsed != n_rules) {
- snprintf(out, out_size, MSG_FILE_NOT_ENOUGH, file_name);
- free(data);
- free(action);
- free(match);
+ if (softnic_parser_read_uint64(&p.trtcm.pbs, tokens[16]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "pbs");
+ return;
+ }
+ } else {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
- /* Rule bulk add */
- status = softnic_pipeline_table_rule_add_bulk(softnic,
+ status = softnic_pipeline_table_mtr_profile_add(softnic,
pipeline_name,
table_id,
- match,
- action,
- data,
- &n_rules);
+ meter_profile_id,
+ &p);
if (status) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
- free(data);
- free(action);
- free(match);
return;
}
-
- /* Memory free */
- free(data);
- free(action);
- free(match);
}
/**
- * pipeline <pipeline_name> table <table_id> rule delete
- * match <match>
+ * pipeline <pipeline_name> table <table_id>
+ * meter profile <meter_profile_id> delete
*/
static void
-cmd_softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
+cmd_pipeline_table_meter_profile_delete(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
- struct softnic_table_rule_match m;
char *pipeline_name;
- uint32_t table_id, n_tokens_parsed, t0;
+ uint32_t table_id, meter_profile_id;
int status;
- if (n_tokens < 8) {
+ if (n_tokens != 8) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (strcmp(tokens[2], "table") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
return;
}
return;
}
- if (strcmp(tokens[4], "rule") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
+ if (strcmp(tokens[4], "meter") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
return;
}
- if (strcmp(tokens[5], "delete") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
+ if (strcmp(tokens[5], "profile") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
return;
}
- t0 = 6;
-
- /* match */
- n_tokens_parsed = parse_match(tokens + t0,
- n_tokens - t0,
- out,
- out_size,
- &m);
- if (n_tokens_parsed == 0)
+ if (softnic_parser_read_uint32(&meter_profile_id, tokens[6]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id");
return;
- t0 += n_tokens_parsed;
+ }
- if (n_tokens != t0) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ if (strcmp(tokens[7], "delete") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
return;
}
- status = softnic_pipeline_table_rule_delete(softnic,
+ status = softnic_pipeline_table_mtr_profile_delete(softnic,
pipeline_name,
table_id,
- &m);
+ meter_profile_id);
if (status) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
/**
- * pipeline <pipeline_name> table <table_id> rule delete
- * match
- * default
+ * pipeline <pipeline_name> table <table_id> rule read meter [clear]
*/
static void
-cmd_softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
+cmd_pipeline_table_rule_meter_read(struct pmd_internals *softnic __rte_unused,
+ char **tokens,
+ uint32_t n_tokens __rte_unused,
+ char *out,
+ size_t out_size)
+{
+ snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
+}
+
+/**
+ * pipeline <pipeline_name> table <table_id> dscp <file_name>
+ *
+ * File <file_name>:
+ * - exactly 64 lines
+ * - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r
+ */
+static int
+load_dscp_table(struct rte_table_action_dscp_table *dscp_table,
+ const char *file_name,
+ uint32_t *line_number)
+{
+ FILE *f = NULL;
+ uint32_t dscp, l;
+
+ /* Check input arguments */
+ if (dscp_table == NULL ||
+ file_name == NULL ||
+ line_number == NULL) {
+ if (line_number)
+ *line_number = 0;
+ return -EINVAL;
+ }
+
+ /* Open input file */
+ f = fopen(file_name, "r");
+ if (f == NULL) {
+ *line_number = 0;
+ return -EINVAL;
+ }
+
+ /* Read file */
+ for (dscp = 0, l = 1; ; l++) {
+ char line[64];
+ char *tokens[3];
+ enum rte_meter_color color;
+ uint32_t tc_id, tc_queue_id, n_tokens = RTE_DIM(tokens);
+
+ if (fgets(line, sizeof(line), f) == NULL)
+ break;
+
+ if (is_comment(line))
+ continue;
+
+ if (softnic_parse_tokenize_string(line, tokens, &n_tokens)) {
+ *line_number = l;
+ fclose(f);
+ return -EINVAL;
+ }
+
+ if (n_tokens == 0)
+ continue;
+
+ if (dscp >= RTE_DIM(dscp_table->entry) ||
+ n_tokens != RTE_DIM(tokens) ||
+ softnic_parser_read_uint32(&tc_id, tokens[0]) ||
+ tc_id >= RTE_TABLE_ACTION_TC_MAX ||
+ softnic_parser_read_uint32(&tc_queue_id, tokens[1]) ||
+ tc_queue_id >= RTE_TABLE_ACTION_TC_QUEUE_MAX ||
+ (strlen(tokens[2]) != 1)) {
+ *line_number = l;
+ fclose(f);
+ return -EINVAL;
+ }
+
+ switch (tokens[2][0]) {
+ case 'g':
+ case 'G':
+ color = e_RTE_METER_GREEN;
+ break;
+
+ case 'y':
+ case 'Y':
+ color = e_RTE_METER_YELLOW;
+ break;
+
+ case 'r':
+ case 'R':
+ color = e_RTE_METER_RED;
+ break;
+
+ default:
+ *line_number = l;
+ fclose(f);
+ return -EINVAL;
+ }
+
+ dscp_table->entry[dscp].tc_id = tc_id;
+ dscp_table->entry[dscp].tc_queue_id = tc_queue_id;
+ dscp_table->entry[dscp].color = color;
+ dscp++;
+ }
+
+ /* Close file */
+ fclose(f);
+ return 0;
+}
+
+static void
+cmd_pipeline_table_dscp(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
- char *pipeline_name;
- uint32_t table_id;
+ struct rte_table_action_dscp_table dscp_table;
+ char *pipeline_name, *file_name;
+ uint32_t table_id, line_number;
int status;
- if (n_tokens != 8) {
+ if (n_tokens != 6) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (strcmp(tokens[2], "table") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
return;
}
return;
}
- if (strcmp(tokens[4], "rule") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
- return;
- }
-
- if (strcmp(tokens[5], "delete") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
+ if (strcmp(tokens[4], "dscp") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dscp");
return;
}
- if (strcmp(tokens[6], "match") != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "match");
- return;
- }
+ file_name = tokens[5];
- if (strcmp(tokens[7], "default") != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "default");
+ status = load_dscp_table(&dscp_table, file_name, &line_number);
+ if (status) {
+ snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
return;
}
- status = softnic_pipeline_table_rule_delete_default(softnic,
+ status = softnic_pipeline_table_dscp_table_update(softnic,
pipeline_name,
- table_id);
+ table_id,
+ UINT64_MAX,
+ &dscp_table);
if (status) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
+/**
+ * pipeline <pipeline_name> table <table_id> rule read ttl [clear]
+ */
+static void
+cmd_softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic __rte_unused,
+ char **tokens,
+ uint32_t n_tokens __rte_unused,
+ char *out,
+ size_t out_size)
+{
+ snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
+}
+
/**
* thread <thread_id> pipeline <pipeline_name> enable
*/
return;
}
+ if (strcmp(tokens[0], "tmgr") == 0) {
+ if (n_tokens == 2) {
+ cmd_tmgr(softnic, tokens, n_tokens, out, out_size);
+ return;
+ }
+
+ if (n_tokens >= 3 &&
+ (strcmp(tokens[1], "shaper") == 0) &&
+ (strcmp(tokens[2], "profile") == 0)) {
+ cmd_tmgr_shaper_profile(softnic, tokens, n_tokens, out, out_size);
+ return;
+ }
+
+ if (n_tokens >= 3 &&
+ (strcmp(tokens[1], "shared") == 0) &&
+ (strcmp(tokens[2], "shaper") == 0)) {
+ cmd_tmgr_shared_shaper(softnic, tokens, n_tokens, out, out_size);
+ return;
+ }
+
+ if (n_tokens >= 2 &&
+ (strcmp(tokens[1], "node") == 0)) {
+ cmd_tmgr_node(softnic, tokens, n_tokens, out, out_size);
+ 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)) {
+ cmd_tmgr_hierarchy_commit(softnic, tokens, n_tokens, out, out_size);
+ return;
+ }
+ }
+
if (strcmp(tokens[0], "tap") == 0) {
cmd_tap(softnic, tokens, n_tokens, out, out_size);
return;
return;
}
+ if (n_tokens >= 6 &&
+ (strcmp(tokens[2], "port") == 0) &&
+ (strcmp(tokens[3], "in") == 0) &&
+ (strcmp(tokens[5], "stats") == 0)) {
+ cmd_pipeline_port_in_stats(softnic, tokens, n_tokens,
+ out, out_size);
+ return;
+ }
+
if (n_tokens >= 6 &&
(strcmp(tokens[2], "port") == 0) &&
(strcmp(tokens[3], "in") == 0) &&
return;
}
+ if (n_tokens >= 6 &&
+ (strcmp(tokens[2], "port") == 0) &&
+ (strcmp(tokens[3], "out") == 0) &&
+ (strcmp(tokens[5], "stats") == 0)) {
+ cmd_pipeline_port_out_stats(softnic, tokens, n_tokens,
+ out, out_size);
+ return;
+ }
+
+ if (n_tokens >= 5 &&
+ (strcmp(tokens[2], "table") == 0) &&
+ (strcmp(tokens[4], "stats") == 0)) {
+ cmd_pipeline_table_stats(softnic, tokens, n_tokens,
+ out, out_size);
+ return;
+ }
+
if (n_tokens >= 7 &&
(strcmp(tokens[2], "table") == 0) &&
(strcmp(tokens[4], "rule") == 0) &&
out, out_size);
return;
}
+
+ if (n_tokens >= 7 &&
+ (strcmp(tokens[2], "table") == 0) &&
+ (strcmp(tokens[4], "rule") == 0) &&
+ (strcmp(tokens[5], "read") == 0) &&
+ (strcmp(tokens[6], "stats") == 0)) {
+ cmd_softnic_pipeline_table_rule_stats_read(softnic, tokens, n_tokens,
+ out, out_size);
+ return;
+ }
+
+ if (n_tokens >= 8 &&
+ (strcmp(tokens[2], "table") == 0) &&
+ (strcmp(tokens[4], "meter") == 0) &&
+ (strcmp(tokens[5], "profile") == 0) &&
+ (strcmp(tokens[7], "add") == 0)) {
+ cmd_pipeline_table_meter_profile_add(softnic, tokens, n_tokens,
+ out, out_size);
+ return;
+ }
+
+ if (n_tokens >= 8 &&
+ (strcmp(tokens[2], "table") == 0) &&
+ (strcmp(tokens[4], "meter") == 0) &&
+ (strcmp(tokens[5], "profile") == 0) &&
+ (strcmp(tokens[7], "delete") == 0)) {
+ cmd_pipeline_table_meter_profile_delete(softnic, tokens,
+ n_tokens, out, out_size);
+ return;
+ }
+
+ if (n_tokens >= 7 &&
+ (strcmp(tokens[2], "table") == 0) &&
+ (strcmp(tokens[4], "rule") == 0) &&
+ (strcmp(tokens[5], "read") == 0) &&
+ (strcmp(tokens[6], "meter") == 0)) {
+ cmd_pipeline_table_rule_meter_read(softnic, tokens, n_tokens,
+ out, out_size);
+ return;
+ }
+
+ if (n_tokens >= 5 &&
+ (strcmp(tokens[2], "table") == 0) &&
+ (strcmp(tokens[4], "dscp") == 0)) {
+ cmd_pipeline_table_dscp(softnic, tokens, n_tokens,
+ out, out_size);
+ return;
+ }
+
+ if (n_tokens >= 7 &&
+ (strcmp(tokens[2], "table") == 0) &&
+ (strcmp(tokens[4], "rule") == 0) &&
+ (strcmp(tokens[5], "read") == 0) &&
+ (strcmp(tokens[6], "ttl") == 0)) {
+ cmd_softnic_pipeline_table_rule_ttl_read(softnic, tokens, n_tokens,
+ out, out_size);
+ return;
+ }
}
if (strcmp(tokens[0], "thread") == 0) {