/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2010-2018 Intel Corporation
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <rte_common.h>
#include <rte_cycles.h>
#include <rte_string_fns.h>
#include <rte_cryptodev.h>
#include "rte_eth_softnic_internals.h"
#include "parser.h"
#ifndef CMD_MAX_TOKENS
#define CMD_MAX_TOKENS 256
#endif
#define MSG_OUT_OF_MEMORY "Not enough memory.\n"
#define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n"
#define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n"
#define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n"
#define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n"
#define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n"
#define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n"
#define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n"
#define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n"
#define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
#define MSG_CMD_FAIL "Command \"%s\" failed.\n"
static int
is_comment(char *in)
{
if ((strlen(in) && index("!#%;", in[0])) ||
(strncmp(in, "//", 2) == 0) ||
(strncmp(in, "--", 2) == 0))
return 1;
return 0;
}
/**
* mempool <mempool_name>
* buffer <buffer_size>
* pool <pool_size>
* cache <cache_size>
*/
static void
cmd_mempool(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
struct softnic_mempool_params p;
char *name;
struct softnic_mempool *mempool;
if (n_tokens != 8) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
name = tokens[1];
if (strcmp(tokens[2], "buffer") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer");
return;
}
if (softnic_parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size");
return;
}
if (strcmp(tokens[4], "pool") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool");
return;
}
if (softnic_parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "pool_size");
return;
}
if (strcmp(tokens[6], "cache") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache");
return;
}
if (softnic_parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "cache_size");
return;
}
mempool = softnic_mempool_create(softnic, name, &p);
if (mempool == NULL) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
/**
* link <link_name>
* dev <device_name> | port <port_id>
*/
static void
cmd_link(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
struct softnic_link_params p;
struct softnic_link *link;
char *name;
memset(&p, 0, sizeof(p));
if (n_tokens != 4) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
name = tokens[1];
if (strcmp(tokens[2], "dev") == 0) {
p.dev_name = tokens[3];
} else if (strcmp(tokens[2], "port") == 0) {
p.dev_name = NULL;
if (softnic_parser_read_uint16(&p.port_id, tokens[3]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
return;
}
} else {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port");
return;
}
link = softnic_link_create(softnic, name, &p);
if (link == NULL) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
/**
* swq <swq_name>
* size <size>
*/
static void
cmd_swq(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
struct softnic_swq_params p;
char *name;
struct softnic_swq *swq;
if (n_tokens != 4) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
name = tokens[1];
if (strcmp(tokens[2], "size") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
return;
}
if (softnic_parser_read_uint32(&p.size, tokens[3]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "size");
return;
}
swq = softnic_swq_create(softnic, name, &p);
if (swq == NULL) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
/**
* tmgr shaper profile
* id <profile_id>
* rate <tb_rate> size <tb_size>
* adj <packet_length_adjust>
*/
static void
cmd_tmgr_shaper_profile(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
struct rte_tm_shaper_params sp;
struct rte_tm_error error;
uint32_t shaper_profile_id;
uint16_t port_id;
int status;
memset(&sp, 0, sizeof(struct rte_tm_shaper_params));
if (n_tokens != 11) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (strcmp(tokens[1], "shaper") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
return;
}
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;
}
}
/**
* tmgr shared shaper
* id <shared_shaper_id>
* profile <shaper_profile_id>
*/
static void
cmd_tmgr_shared_shaper(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
struct rte_tm_error error;
uint32_t shared_shaper_id, shaper_profile_id;
uint16_t port_id;
int status;
if (n_tokens != 7) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (strcmp(tokens[1], "shared") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shared");
return;
}
if (strcmp(tokens[2], "shaper") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
return;
}
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;
}
if (softnic_parser_read_uint32(&shaper_profile_id, tokens[6]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shaper_profile_id");
return;
}
status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
if (status)
return;
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;
}
}
/**
* 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;
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 (n_tokens < 10) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (strcmp(tokens[1], "node") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "node");
return;
}
if (strcmp(tokens[2], "id") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
return;
}
if (softnic_parser_read_uint32(&node_id, tokens[3]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "node_id");
return;
}
if (strcmp(tokens[4], "parent") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "parent");
return;
}
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[6], "priority") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority");
return;
}
if (softnic_parser_read_uint32(&priority, tokens[7]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "priority");
return;
}
if (strcmp(tokens[8], "weight") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "weight");
return;
}
if (softnic_parser_read_uint32(&weight, tokens[9]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "weight");
return;
}
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[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;
}
}
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 (softnic_parser_read_uint32(&shared_shaper_id, tokens[2]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shared_shaper_id");
return;
}
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 (softnic_parser_read_uint32(&np.nonleaf.n_sp_priorities, tokens[2]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "n_sp_priorities");
return;
}
tokens += 3;
n_tokens -= 3;
} /* nonleaf sp <n_sp_priorities> */
if (n_tokens) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
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;
}
}
static uint32_t
root_node_id(uint32_t n_spp,
uint32_t n_pps)
{
uint32_t n_queues = n_spp * n_pps * RTE_SCHED_QUEUES_PER_PIPE;
uint32_t n_tc = n_spp * n_pps * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
uint32_t n_pipes = n_spp * n_pps;
return n_queues + n_tc + n_pipes + n_spp;
}
static uint32_t
subport_node_id(uint32_t n_spp,
uint32_t n_pps,
uint32_t subport_id)
{
uint32_t n_pipes = n_spp * n_pps;
uint32_t n_tc = n_pipes * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
return n_queues + n_tc + n_pipes + subport_id;
}
static uint32_t
pipe_node_id(uint32_t n_spp,
uint32_t n_pps,
uint32_t subport_id,
uint32_t pipe_id)
{
uint32_t n_pipes = n_spp * n_pps;
uint32_t n_tc = n_pipes * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
return n_queues +
n_tc +
pipe_id +
subport_id * n_pps;
}
static uint32_t
tc_node_id(uint32_t n_spp,
uint32_t n_pps,
uint32_t subport_id,
uint32_t pipe_id,
uint32_t tc_id)
{
uint32_t n_pipes = n_spp * n_pps;
uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
return n_queues +
tc_id +
(pipe_id + subport_id * n_pps) * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
}
static uint32_t
queue_node_id(uint32_t n_spp __rte_unused,
uint32_t n_pps,
uint32_t subport_id,
uint32_t pipe_id,
uint32_t tc_id,
uint32_t queue_id)
{
return queue_id + tc_id +
(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,
},
};
uint32_t *shared_shaper_id =
(uint32_t *)calloc(RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
sizeof(uint32_t));
if (shared_shaper_id == NULL)
return -1;
memcpy(shared_shaper_id, params->shared_shaper_id.tc,
sizeof(params->shared_shaper_id.tc));
struct rte_tm_node_params tc_node_params[] = {
[0] = {
.shaper_profile_id = params->shaper_profile_id.tc[0],
.shared_shaper_id = &shared_shaper_id[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 = &shared_shaper_id[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 = &shared_shaper_id[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 = &shared_shaper_id[3],
.n_shared_shapers =
(¶ms->shared_shaper_id.tc_valid[3]) ? 1 : 0,
.nonleaf = {
.n_sp_priorities = 1,
},
},
[4] = {
.shaper_profile_id = params->shaper_profile_id.tc[4],
.shared_shaper_id = &shared_shaper_id[4],
.n_shared_shapers =
(¶ms->shared_shaper_id.tc_valid[4]) ? 1 : 0,
.nonleaf = {
.n_sp_priorities = 1,
},
},
[5] = {
.shaper_profile_id = params->shaper_profile_id.tc[5],
.shared_shaper_id = &shared_shaper_id[5],
.n_shared_shapers =
(¶ms->shared_shaper_id.tc_valid[5]) ? 1 : 0,
.nonleaf = {
.n_sp_priorities = 1,
},
},
[6] = {
.shaper_profile_id = params->shaper_profile_id.tc[6],
.shared_shaper_id = &shared_shaper_id[6],
.n_shared_shapers =
(¶ms->shared_shaper_id.tc_valid[6]) ? 1 : 0,
.nonleaf = {
.n_sp_priorities = 1,
},
},
[7] = {
.shaper_profile_id = params->shaper_profile_id.tc[7],
.shared_shaper_id = &shared_shaper_id[7],
.n_shared_shapers =
(¶ms->shared_shaper_id.tc_valid[7]) ? 1 : 0,
.nonleaf = {
.n_sp_priorities = 1,
},
},
[8] = {
.shaper_profile_id = params->shaper_profile_id.tc[8],
.shared_shaper_id = &shared_shaper_id[8],
.n_shared_shapers =
(¶ms->shared_shaper_id.tc_valid[8]) ? 1 : 0,
.nonleaf = {
.n_sp_priorities = 1,
},
},
[9] = {
.shaper_profile_id = params->shaper_profile_id.tc[9],
.shared_shaper_id = &shared_shaper_id[9],
.n_shared_shapers =
(¶ms->shared_shaper_id.tc_valid[9]) ? 1 : 0,
.nonleaf = {
.n_sp_priorities = 1,
},
},
[10] = {
.shaper_profile_id = params->shaper_profile_id.tc[10],
.shared_shaper_id = &shared_shaper_id[10],
.n_shared_shapers =
(¶ms->shared_shaper_id.tc_valid[10]) ? 1 : 0,
.nonleaf = {
.n_sp_priorities = 1,
},
},
[11] = {
.shaper_profile_id = params->shaper_profile_id.tc[11],
.shared_shaper_id = &shared_shaper_id[11],
.n_shared_shapers =
(¶ms->shared_shaper_id.tc_valid[11]) ? 1 : 0,
.nonleaf = {
.n_sp_priorities = 1,
},
},
[12] = {
.shaper_profile_id = params->shaper_profile_id.tc[12],
.shared_shaper_id = &shared_shaper_id[12],
.n_shared_shapers =
(¶ms->shared_shaper_id.tc_valid[12]) ? 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 */
if (t < RTE_SCHED_TRAFFIC_CLASS_BE) {
/* Strict-priority traffic class queues */
q = 0;
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;
continue;
}
/* Best-effort traffic class queues */
for (q = 0; q < RTE_SCHED_BE_QUEUES_PER_PIPE; 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;
}
} /* 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>
* tc4 <profile_id>
* tc5 <profile_id>
* tc6 <profile_id>
* tc7 <profile_id>
* tc8 <profile_id>
* tc9 <profile_id>
* tc10 <profile_id>
* tc11 <profile_id>
* tc12 <profile_id>
* shared shaper
* tc0 <id | none>
* tc1 <id | none>
* tc2 <id | none>
* tc3 <id | none>
* tc4 <id | none>
* tc5 <id | none>
* tc6 <id | none>
* tc7 <id | none>
* tc8 <id | none>
* tc9 <id | none>
* tc10 <id | none>
* tc11 <id | none>
* tc12 <id | none>
* weight
* queue <q12> ... <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, j, status;
memset(&p, 0, sizeof(p));
if (n_tokens != 74) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (strcmp(tokens[1], "hierarchy-default") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "hierarchy-default");
return;
}
if (strcmp(tokens[2], "spp") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
return;
}
if (softnic_parser_read_uint32(&p.n_spp, tokens[3]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "n_subports_per_port");
return;
}
if (strcmp(tokens[4], "pps") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
return;
}
if (softnic_parser_read_uint32(&p.n_pps, tokens[5]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport");
return;
}
/* Shaper profile */
if (strcmp(tokens[6], "shaper") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
return;
}
if (strcmp(tokens[7], "profile") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
return;
}
if (strcmp(tokens[8], "port") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.port, tokens[9]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "port profile id");
return;
}
if (strcmp(tokens[10], "subport") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "subport");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.subport, tokens[11]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "subport profile id");
return;
}
if (strcmp(tokens[12], "pipe") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipe");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.pipe, tokens[13]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipe_profile_id");
return;
}
if (strcmp(tokens[14], "tc0") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc0");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[0], tokens[15]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "tc0 profile id");
return;
}
if (strcmp(tokens[16], "tc1") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc1");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[1], tokens[17]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "tc1 profile id");
return;
}
if (strcmp(tokens[18], "tc2") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc2");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[2], tokens[19]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "tc2 profile id");
return;
}
if (strcmp(tokens[20], "tc3") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc3");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[3], tokens[21]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "tc3 profile id");
return;
}
if (strcmp(tokens[22], "tc4") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc4");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[4], tokens[23]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "tc4 profile id");
return;
}
if (strcmp(tokens[24], "tc5") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc5");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[5], tokens[25]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "tc5 profile id");
return;
}
if (strcmp(tokens[26], "tc6") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc6");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[6], tokens[27]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "tc6 profile id");
return;
}
if (strcmp(tokens[28], "tc7") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc7");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[7], tokens[29]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "tc7 profile id");
return;
}
if (strcmp(tokens[30], "tc8") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc8");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[8], tokens[31]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "tc8 profile id");
return;
}
if (strcmp(tokens[32], "tc9") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc9");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[9], tokens[33]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "tc9 profile id");
return;
}
if (strcmp(tokens[34], "tc10") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc10");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[10], tokens[35]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "tc10 profile id");
return;
}
if (strcmp(tokens[36], "tc11") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc11");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[11], tokens[37]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "tc11 profile id");
return;
}
if (strcmp(tokens[38], "tc12") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc12");
return;
}
if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[12], tokens[39]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "tc12 profile id");
return;
}
/* Shared shaper */
if (strcmp(tokens[40], "shared") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shared");
return;
}
if (strcmp(tokens[41], "shaper") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
return;
}
if (strcmp(tokens[42], "tc0") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc0");
return;
}
if (strcmp(tokens[43], "none") == 0)
p.shared_shaper_id.tc_valid[0] = 0;
else {
if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[0],
tokens[43]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc0");
return;
}
p.shared_shaper_id.tc_valid[0] = 1;
}
if (strcmp(tokens[44], "tc1") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc1");
return;
}
if (strcmp(tokens[45], "none") == 0)
p.shared_shaper_id.tc_valid[1] = 0;
else {
if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[1],
tokens[45]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc1");
return;
}
p.shared_shaper_id.tc_valid[1] = 1;
}
if (strcmp(tokens[46], "tc2") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc2");
return;
}
if (strcmp(tokens[47], "none") == 0)
p.shared_shaper_id.tc_valid[2] = 0;
else {
if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[2],
tokens[47]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc2");
return;
}
p.shared_shaper_id.tc_valid[2] = 1;
}
if (strcmp(tokens[48], "tc3") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc3");
return;
}
if (strcmp(tokens[49], "none") == 0)
p.shared_shaper_id.tc_valid[3] = 0;
else {
if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[3],
tokens[49]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc3");
return;
}
p.shared_shaper_id.tc_valid[3] = 1;
}
if (strcmp(tokens[50], "tc4") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc4");
return;
}
if (strcmp(tokens[51], "none") == 0) {
p.shared_shaper_id.tc_valid[4] = 0;
} else {
if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[4],
tokens[51]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc4");
return;
}
p.shared_shaper_id.tc_valid[4] = 1;
}
if (strcmp(tokens[52], "tc5") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc5");
return;
}
if (strcmp(tokens[53], "none") == 0) {
p.shared_shaper_id.tc_valid[5] = 0;
} else {
if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[5],
tokens[53]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc5");
return;
}
p.shared_shaper_id.tc_valid[5] = 1;
}
if (strcmp(tokens[54], "tc6") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc6");
return;
}
if (strcmp(tokens[55], "none") == 0) {
p.shared_shaper_id.tc_valid[6] = 0;
} else {
if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[6],
tokens[55]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc6");
return;
}
p.shared_shaper_id.tc_valid[6] = 1;
}
if (strcmp(tokens[56], "tc7") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc7");
return;
}
if (strcmp(tokens[57], "none") == 0) {
p.shared_shaper_id.tc_valid[7] = 0;
} else {
if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[7],
tokens[57]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc7");
return;
}
p.shared_shaper_id.tc_valid[7] = 1;
}
if (strcmp(tokens[58], "tc8") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc8");
return;
}
if (strcmp(tokens[59], "none") == 0) {
p.shared_shaper_id.tc_valid[8] = 0;
} else {
if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[8],
tokens[59]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc8");
return;
}
p.shared_shaper_id.tc_valid[8] = 1;
}
if (strcmp(tokens[60], "tc9") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc9");
return;
}
if (strcmp(tokens[61], "none") == 0) {
p.shared_shaper_id.tc_valid[9] = 0;
} else {
if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[9],
tokens[61]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc9");
return;
}
p.shared_shaper_id.tc_valid[9] = 1;
}
if (strcmp(tokens[62], "tc10") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc10");
return;
}
if (strcmp(tokens[63], "none") == 0) {
p.shared_shaper_id.tc_valid[10] = 0;
} else {
if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[10],
tokens[63]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc10");
return;
}
p.shared_shaper_id.tc_valid[10] = 1;
}
if (strcmp(tokens[64], "tc11") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc11");
return;
}
if (strcmp(tokens[65], "none") == 0) {
p.shared_shaper_id.tc_valid[11] = 0;
} else {
if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[11],
tokens[65]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc11");
return;
}
p.shared_shaper_id.tc_valid[11] = 1;
}
if (strcmp(tokens[66], "tc12") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc12");
return;
}
if (strcmp(tokens[67], "none") == 0) {
p.shared_shaper_id.tc_valid[12] = 0;
} else {
if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[12],
tokens[67]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc12");
return;
}
p.shared_shaper_id.tc_valid[12] = 1;
}
/* Weight */
if (strcmp(tokens[68], "weight") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "weight");
return;
}
if (strcmp(tokens[69], "queue") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "queue");
return;
}
for (i = 0, j = 0; i < 16; i++) {
if (i < RTE_SCHED_TRAFFIC_CLASS_BE) {
p.weight.queue[i] = 1;
} else {
if (softnic_parser_read_uint32(&p.weight.queue[i],
tokens[70 + j]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "weight queue");
return;
}
j++;
}
}
status = tmgr_hierarchy_default(softnic, &p);
if (status != 0) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
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;
if (n_tokens != 3) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (strcmp(tokens[1], "hierarchy") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "hierarchy");
return;
}
if (strcmp(tokens[2], "commit") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "commit");
return;
}
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;
}
}
/**
* tmgr <tmgr_name>
*/
static void
cmd_tmgr(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
char *name;
struct softnic_tmgr_port *tmgr_port;
if (n_tokens != 2) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
name = tokens[1];
tmgr_port = softnic_tmgr_port_create(softnic, name);
if (tmgr_port == NULL) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
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 (n_tokens != 2) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
name = tokens[1];
tap = softnic_tap_create(softnic, name);
if (tap == NULL) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
/**
* cryptodev <tap_name> dev <device_name> | dev_id <device_id>
* queue <n_queues> <queue_size> max_sessions <n_sessions>
**/
static void
cmd_cryptodev(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
struct softnic_cryptodev_params params;
char *name;
memset(¶ms, 0, sizeof(params));
if (n_tokens != 9) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
name = tokens[1];
if (strcmp(tokens[2], "dev") == 0)
params.dev_name = tokens[3];
else if (strcmp(tokens[2], "dev_id") == 0) {
if (softnic_parser_read_uint32(¶ms.dev_id, tokens[3]) < 0) {
snprintf(out, out_size, MSG_ARG_INVALID,
"dev_id");
return;
}
} else {
snprintf(out, out_size, MSG_ARG_INVALID,
"cryptodev");
return;
}
if (strcmp(tokens[4], "queue")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
"4");
return;
}
if (softnic_parser_read_uint32(¶ms.n_queues, tokens[5]) < 0) {
snprintf(out, out_size, MSG_ARG_INVALID,
"q");
return;
}
if (softnic_parser_read_uint32(¶ms.queue_size, tokens[6]) < 0) {
snprintf(out, out_size, MSG_ARG_INVALID,
"queue_size");
return;
}
if (strcmp(tokens[7], "max_sessions")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
"4");
return;
}
if (softnic_parser_read_uint32(¶ms.session_pool_size, tokens[8])
< 0) {
snprintf(out, out_size, MSG_ARG_INVALID,
"q");
return;
}
if (softnic_cryptodev_create(softnic, name, ¶ms) == NULL) {
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>]
*/
static void
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_action_profile_params p;
struct softnic_port_in_action_profile *ap;
char *name;
uint32_t t0;
memset(&p, 0, sizeof(p));
if (n_tokens < 5) {
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");
return;
}
if (strcmp(tokens[2], "action") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
return;
}
if (strcmp(tokens[3], "profile") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
return;
}
name = tokens[4];
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;
}
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], "offset") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
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[t0 + 4], "mask") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
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 (strcmp(tokens[t0 + 6], "key") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
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");
return;
}
if (strcmp(tokens[t0 + 8], "port") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
return;
}
if (softnic_parser_read_uint32(&p.fltr.port_id,
tokens[t0 + 9]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
return;
}
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,
"port in action profile balance");
return;
}
if (strcmp(tokens[t0 + 1], "offset") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
return;
}
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[t0 + 3], "mask") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
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[t0 + 5], "port") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
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 */
if (t0 < 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) {
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 | qinq_pppoe |
* vxlan offset <ether_offset> ipv4 | ipv6 vlan on | off]
* [nat src | dst
* proto udp | tcp]
* [ttl drop | fwd
* stats none | pkts]
* [stats pkts | bytes | both]
* [time]
* [tag]
* [decap]
*
*/
static void
cmd_table_action_profile(struct pmd_internals *softnic,
char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size)
{
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 < 8) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (strcmp(tokens[1], "action") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
return;
}
if (strcmp(tokens[2], "profile") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
return;
}
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 (strcmp(tokens[5], "offset") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
return;
}
if (softnic_parser_read_uint32(&p.common.ip_offset,
tokens[6]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset");
return;
}
if (strcmp(tokens[7], "fwd") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd");
return;
}
p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
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 (strcmp(tokens[t0 + 1], "offset") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
return;
}
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[t0 + 3], "mask") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
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[t0 + 5], "outoffset") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset");
return;
}
if (softnic_parser_read_uint32(&p.lb.out_offset,
tokens[t0 + 6]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "out_offset");
return;
}
p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB;
t0 += 7;
} /* balance */
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[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 (strcmp(tokens[t0 + 2], "tc") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc");
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 (strcmp(tokens[t0 + 4], "stats") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
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;
}
p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR;
t0 += 6;
} /* meter */
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 (strcmp(tokens[t0 + 1], "spp") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
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 (strcmp(tokens[t0 + 3], "pps") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
return;
}
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");
return;
}
p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM;
t0 += 5;
} /* tm */
if (t0 < n_tokens &&
(strcmp(tokens[t0], "encap") == 0)) {
uint32_t n_extra_tokens = 0;
if (n_tokens < t0 + 2) {
snprintf(out, out_size, MSG_ARG_MISMATCH,
"action profile encap");
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 if (strcmp(tokens[t0 + 1], "vxlan") == 0) {
if (n_tokens < t0 + 2 + 5) {
snprintf(out, out_size, MSG_ARG_MISMATCH,
"action profile encap vxlan");
return;
}
if (strcmp(tokens[t0 + 2], "offset") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
"vxlan: offset");
return;
}
if (softnic_parser_read_uint32(&p.encap.vxlan.data_offset,
tokens[t0 + 2 + 1]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID,
"vxlan: ether_offset");
return;
}
if (strcmp(tokens[t0 + 2 + 2], "ipv4") == 0)
p.encap.vxlan.ip_version = 1;
else if (strcmp(tokens[t0 + 2 + 2], "ipv6") == 0)
p.encap.vxlan.ip_version = 0;
else {
snprintf(out, out_size, MSG_ARG_INVALID,
"vxlan: ipv4 or ipv6");
return;
}
if (strcmp(tokens[t0 + 2 + 3], "vlan") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND,
"vxlan: vlan");
return;
}
if (strcmp(tokens[t0 + 2 + 4], "on") == 0)
p.encap.vxlan.vlan = 1;
else if (strcmp(tokens[t0 + 2 + 4], "off") == 0)
p.encap.vxlan.vlan = 0;
else {
snprintf(out, out_size, MSG_ARG_INVALID,
"vxlan: on or off");
return;
}
p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VXLAN;
n_extra_tokens = 5;
} else if (strcmp(tokens[t0 + 1], "qinq_pppoe") == 0) {
p.encap.encap_mask =
1LLU << RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE;
} else {
snprintf(out, out_size, MSG_ARG_MISMATCH, "encap");
return;
}
p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP;
t0 += 2 + n_extra_tokens;
} /* 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 (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 */
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 (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 + 2], "stats") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
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");
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;
}
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;
}
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;
} /* time */
if (t0 < n_tokens &&
(strcmp(tokens[t0], "tag") == 0)) {
p.action_mask |= 1LLU << RTE_TABLE_ACTION_TAG;
t0 += 1;
} /* tag */
if (t0 < n_tokens &&
(strcmp(tokens[t0], "decap") == 0)) {
p.action_mask |= 1LLU << RTE_TABLE_ACTION_DECAP;
t0 += 1;
} /* decap */
if (t0 < n_tokens && (strcmp(tokens[t0], "sym_crypto") == 0)) {
struct softnic_cryptodev *cryptodev;
if (n_tokens < t0 + 5 ||
strcmp(tokens[t0 + 1], "dev") ||
strcmp(tokens[t0 + 3], "offset")) {
snprintf(out, out_size, MSG_ARG_MISMATCH,
"table action profile sym_crypto");
return;
}
cryptodev = softnic_cryptodev_find(softnic, tokens[t0 + 2]);
if (cryptodev == NULL) {
snprintf(out, out_size, MSG_ARG_INVALID,
"table action profile sym_crypto");
return;
}
p.sym_crypto.cryptodev_id = cryptodev->dev_id;
if (softnic_parser_read_uint32(&p.sym_crypto.op_offset,
tokens[t0 + 4]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID,
"table action profile sym_crypto");
return;
}
p.sym_crypto.mp_create = cryptodev->mp_create;
p.sym_crypto.mp_init = cryptodev->mp_init;
p.action_mask |= 1LLU << RTE_TABLE_ACTION_SYM_CRYPTO;
t0 += 5;
} /* sym_crypto */
if (t0 < n_tokens) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
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>
* period <timer_period_ms>
* offset_port_id <offset_port_id>
*/
static void
cmd_pipeline(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;
if (n_tokens != 6) {
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");
return;
}
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[4], "offset_port_id") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id");
return;
}
if (softnic_parser_read_uint32(&p.offset_port_id,
tokens[5]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id");
return;
}
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
* 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>
* | cryptodev <cryptodev_name> rxq <queue_id>
* [action <port_in_action_profile_name>]
* [disabled]
*/
static void
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 t0;
int enabled, 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], "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");
return;
}
if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
return;
}
t0 = 6;
if (strcmp(tokens[t0], "link") == 0) {
if (n_tokens < t0 + 4) {
snprintf(out, out_size, MSG_ARG_MISMATCH,
"pipeline port in link");
return;
}
p.type = PORT_IN_RXQ;
strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
if (strcmp(tokens[t0 + 2], "rxq") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
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;
}
p.type = PORT_IN_SWQ;
strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
t0 += 2;
} else if (strcmp(tokens[t0], "tmgr") == 0) {
if (n_tokens<