#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "cli.h"
#include "obj.h"
#include "thread.h"
#ifndef CMD_MAX_TOKENS
#define CMD_MAX_TOKENS 256
#endif
#ifndef MAX_LINE_SIZE
#define MAX_LINE_SIZE 2048
#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"
#define skip_white_spaces(pos) \
({ \
__typeof__(pos) _p = (pos); \
for ( ; isspace(*_p); _p++) \
; \
_p; \
})
static int
parser_read_uint64(uint64_t *value, const char *p)
{
char *next;
uint64_t val;
p = skip_white_spaces(p);
if (!isdigit(*p))
return -EINVAL;
val = strtoul(p, &next, 0);
if (p == next)
return -EINVAL;
p = next;
switch (*p) {
case 'T':
val *= 1024ULL;
case 'G':
val *= 1024ULL;
case 'M':
val *= 1024ULL;
case 'k':
case 'K':
val *= 1024ULL;
p++;
break;
}
p = skip_white_spaces(p);
if (*p != '\0')
return -EINVAL;
*value = val;
return 0;
}
static int
parser_read_uint32(uint32_t *value, const char *p)
{
uint64_t val = 0;
int ret = parser_read_uint64(&val, p);
if (ret < 0)
return ret;
if (val > UINT32_MAX)
return -ERANGE;
*value = val;
return 0;
}
#define PARSE_DELIMITER " \f\n\r\t\v"
static int
parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
{
uint32_t i;
if ((string == NULL) ||
(tokens == NULL) ||
(*n_tokens < 1))
return -EINVAL;
for (i = 0; i < *n_tokens; i++) {
tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
if (tokens[i] == NULL)
break;
}
if ((i == *n_tokens) && strtok_r(string, PARSE_DELIMITER, &string))
return -E2BIG;
*n_tokens = i;
return 0;
}
static int
is_comment(char *in)
{
if ((strlen(in) && index("!#%;", in[0])) ||
(strncmp(in, "//", 2) == 0) ||
(strncmp(in, "--", 2) == 0))
return 1;
return 0;
}
static void
{
if (!entry)
return;
free(entry);
}
parse_table_entry(struct rte_swx_ctl_pipeline *p,
char *table_name,
char **tokens,
uint32_t n_tokens)
{
char *line;
uint32_t i;
line = malloc(MAX_LINE_SIZE);
if (!line)
return NULL;
line[0] = 0;
for (i = 0; i < n_tokens; i++) {
if (i)
strcat(line, " ");
strcat(line, tokens[i]);
}
free(line);
return entry;
}
static const char cmd_mempool_help[] =
"mempool <mempool_name>\n"
" buffer <buffer_size>\n"
" pool <pool_size>\n"
" cache <cache_size>\n"
" cpu <cpu_id>\n";
static void
cmd_mempool(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
void *obj)
{
struct mempool_params p;
char *name;
struct mempool *mempool;
if (n_tokens != 10) {
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 (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 (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 (parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "cache_size");
return;
}
if (strcmp(tokens[8], "cpu") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
return;
}
if (parser_read_uint32(&p.cpu_id, tokens[9]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
return;
}
mempool = mempool_create(obj, name, &p);
if (mempool == NULL) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
static const char cmd_ethdev_help[] =
"ethdev <ethdev_name>\n"
" rxq <n_queues> <queue_size> <mempool_name>\n"
" txq <n_queues> <queue_size>\n"
" promiscuous on | off\n"
" [rss <qid_0> ... <qid_n>]\n";
static void
cmd_ethdev(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
void *obj)
{
struct link_params p;
struct link_params_rss rss;
struct link *link;
char *name;
memset(&p, 0, sizeof(p));
if ((n_tokens < 11) || (n_tokens > 12 + LINK_RXQ_RSS_MAX)) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
name = tokens[1];
if (strcmp(tokens[2], "rxq") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
return;
}
if (parser_read_uint32(&p.rx.n_queues, tokens[3]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
return;
}
if (parser_read_uint32(&p.rx.queue_size, tokens[4]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
return;
}
p.rx.mempool_name = tokens[5];
if (strcmp(tokens[6], "txq") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
return;
}
if (parser_read_uint32(&p.tx.n_queues, tokens[7]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
return;
}
if (parser_read_uint32(&p.tx.queue_size, tokens[8]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
return;
}
if (strcmp(tokens[9], "promiscuous") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous");
return;
}
if (strcmp(tokens[10], "on") == 0)
p.promiscuous = 1;
else if (strcmp(tokens[10], "off") == 0)
p.promiscuous = 0;
else {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off");
return;
}
p.rx.rss = NULL;
if (n_tokens > 11) {
uint32_t queue_id, i;
if (strcmp(tokens[11], "rss") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss");
return;
}
p.rx.rss = &rss;
rss.n_queues = 0;
for (i = 12; i < n_tokens; i++) {
if (parser_read_uint32(&queue_id, tokens[i]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID,
"queue_id");
return;
}
rss.queue_id[rss.n_queues] = queue_id;
rss.n_queues++;
}
}
link = link_create(obj, name, &p);
if (link == NULL) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
static void
print_link_info(struct link *link, char *out, size_t out_size)
{
uint16_t mtu;
int ret;
memset(&stats, 0, sizeof(stats));
if (ret != 0) {
snprintf(out, out_size, "\n%s: MAC address get failed: %s",
return;
}
if (ret < 0) {
snprintf(out, out_size, "\n%s: link get failed: %s",
return;
}
snprintf(out, out_size,
"\n"
"%s: flags=<%s> mtu %u\n"
"\tport# %u speed %s\n"
"\tRX packets %" PRIu64" bytes %" PRIu64"\n"
"\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n"
"\tTX packets %" PRIu64" bytes %" PRIu64"\n"
"\tTX errors %" PRIu64"\n",
link->name,
mtu,
link->n_rxq,
link->n_txq,
link->port_id,
}
static void
cmd_ethdev_show(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
void *obj)
{
struct link *link;
char *link_name;
if (n_tokens != 2 && n_tokens != 3) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (n_tokens == 2) {
link = link_next(obj, NULL);
while (link != NULL) {
out_size = out_size - strlen(out);
out = &out[strlen(out)];
print_link_info(link, out, out_size);
link = link_next(obj, link);
}
} else {
out_size = out_size - strlen(out);
out = &out[strlen(out)];
link_name = tokens[2];
link = link_find(obj, link_name);
if (link == NULL) {
snprintf(out, out_size, MSG_ARG_INVALID,
"Link does not exist");
return;
}
print_link_info(link, out, out_size);
}
}
static const char cmd_ring_help[] =
"ring <ring_name> size <size> numa <numa_node>\n";
static void
cmd_ring(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
void *obj)
{
struct ring_params p;
char *name;
struct ring *ring;
if (n_tokens != 6) {
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 (parser_read_uint32(&p.size, tokens[3]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "size");
return;
}
if (strcmp(tokens[4], "numa") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa");
return;
}
if (parser_read_uint32(&p.numa_node, tokens[5]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
return;
}
ring = ring_create(obj, name, &p);
if (!ring) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
return;
}
}
static const char cmd_pipeline_codegen_help[] =
"pipeline codegen <spec_file> <code_file>\n";
static void
cmd_pipeline_codegen(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
FILE *spec_file = NULL;
FILE *code_file = NULL;
uint32_t err_line;
const char *err_msg;
int status;
if (n_tokens != 4) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
spec_file = fopen(tokens[2], "r");
if (!spec_file) {
snprintf(out, out_size, "Cannot open file %s.\n", tokens[2]);
return;
}
code_file = fopen(tokens[3], "w");
if (!code_file) {
snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
fclose(spec_file);
return;
}
code_file,
&err_line,
&err_msg);
fclose(spec_file);
fclose(code_file);
if (status) {
snprintf(out, out_size, "Error %d at line %u: %s\n.",
status, err_line, err_msg);
return;
}
}
static const char cmd_pipeline_libbuild_help[] =
"pipeline libbuild <code_file> <lib_file>\n";
static void
cmd_pipeline_libbuild(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
char *code_file, *lib_file, *obj_file = NULL, *log_file = NULL;
char *install_dir, *cwd = NULL, *buffer = NULL;
size_t length;
int status = 0;
if (n_tokens != 4) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
goto free;
}
install_dir = getenv("RTE_INSTALL_DIR");
if (!install_dir) {
cwd = malloc(MAX_LINE_SIZE);
if (!cwd) {
snprintf(out, out_size, MSG_OUT_OF_MEMORY);
goto free;
}
install_dir = getcwd(cwd, MAX_LINE_SIZE);
if (!install_dir) {
snprintf(out, out_size, "Error: Path too long.\n");
goto free;
}
}
snprintf(out, out_size, "Using DPDK source code from \"%s\".\n", install_dir);
out_size -= strlen(out);
out += strlen(out);
code_file = tokens[2];
length = strnlen(code_file, MAX_LINE_SIZE);
if ((length < 3) ||
(code_file[length - 2] != '.') ||
(code_file[length - 1] != 'c')) {
snprintf(out, out_size, MSG_ARG_INVALID, "code_file");
goto free;
}
lib_file = tokens[3];
length = strnlen(lib_file, MAX_LINE_SIZE);
if ((length < 4) ||
(lib_file[length - 3] != '.') ||
(lib_file[length - 2] != 's') ||
(lib_file[length - 1] != 'o')) {
snprintf(out, out_size, MSG_ARG_INVALID, "lib_file");
goto free;
}
obj_file = malloc(length);
log_file = malloc(length + 2);
if (!obj_file || !log_file) {
snprintf(out, out_size, MSG_OUT_OF_MEMORY);
goto free;
}
memcpy(obj_file, lib_file, length - 2);
obj_file[length - 2] = 'o';
obj_file[length - 1] = 0;
memcpy(log_file, lib_file, length - 2);
log_file[length - 2] = 'l';
log_file[length - 1] = 'o';
log_file[length] = 'g';
log_file[length + 1] = 0;
buffer = malloc(MAX_LINE_SIZE);
if (!buffer) {
snprintf(out, out_size, MSG_OUT_OF_MEMORY);
goto free;
}
snprintf(buffer,
MAX_LINE_SIZE,
"gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s %s "
"-I %s/lib/pipeline "
"-I %s/lib/eal/include "
"-I %s/lib/eal/x86/include "
"-I %s/lib/eal/include/generic "
"-I %s/lib/meter "
"-I %s/lib/port "
"-I %s/lib/table "
"-I %s/lib/pipeline "
"-I %s/config "
"-I %s/build "
"-I %s/lib/eal/linux/include "
">%s 2>&1 "
"&& "
"gcc -shared %s -o %s "
">>%s 2>&1",
obj_file,
code_file,
install_dir,
install_dir,
install_dir,
install_dir,
install_dir,
install_dir,
install_dir,
install_dir,
install_dir,
install_dir,
install_dir,
log_file,
obj_file,
lib_file,
log_file);
status = system(buffer);
if (status) {
snprintf(out,
out_size,
"Library build failed, see file \"%s\" for details.\n",
log_file);
goto free;
}
free:
free(cwd);
free(obj_file);
free(log_file);
free(buffer);
}
static const char cmd_pipeline_build_help[] =
"pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>\n";
static void
cmd_pipeline_build(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_pipeline *p = NULL;
struct rte_swx_ctl_pipeline *ctl = NULL;
char *pipeline_name, *lib_file_name, *iospec_file_name;
FILE *iospec_file = NULL;
uint32_t numa_node = 0;
int status = 0;
if (n_tokens != 9) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (strcmp(tokens[2], "build")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "build");
return;
}
if (strcmp(tokens[3], "lib")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "lib");
return;
}
lib_file_name = tokens[4];
if (strcmp(tokens[5], "io")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "io");
return;
}
iospec_file_name = tokens[6];
if (strcmp(tokens[7], "numa")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa");
return;
}
if (parser_read_uint32(&numa_node, tokens[8])) {
snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
return;
}
iospec_file = fopen(iospec_file_name, "r");
if (!iospec_file) {
snprintf(out, out_size, "Cannot open file \"%s\".\n", iospec_file_name);
return;
}
pipeline_name,
lib_file_name,
iospec_file,
(int)numa_node);
if (status) {
snprintf(out, out_size, "Pipeline build failed (%d).", status);
goto free;
}
if (!ctl) {
snprintf(out, out_size, "Pipeline control create failed.");
goto free;
}
free:
if (status)
if (iospec_file)
fclose(iospec_file);
}
static int
pipeline_table_entries_add(struct rte_swx_ctl_pipeline *p,
const char *table_name,
FILE *file,
uint32_t *file_line_number)
{
char *line = NULL;
uint32_t line_id = 0;
int status = 0;
line = malloc(MAX_LINE_SIZE);
if (!line)
return -ENOMEM;
for (line_id = 1; ; line_id++) {
int is_blank_or_comment;
if (fgets(line, MAX_LINE_SIZE, file) == NULL)
break;
table_name,
line,
&is_blank_or_comment);
if (!entry) {
if (is_blank_or_comment)
continue;
status = -EINVAL;
goto error;
}
table_name,
entry);
table_entry_free(entry);
if (status)
goto error;
}
error:
free(line);
*file_line_number = line_id;
return status;
}
static const char cmd_pipeline_table_add_help[] =
"pipeline <pipeline_name> table <table_name> add <file_name>\n";
static void
cmd_pipeline_table_add(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *table_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
int status;
if (n_tokens != 6) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
table_name = tokens[3];
file_name = tokens[5];
file = fopen(file_name, "r");
if (!file) {
snprintf(out, out_size, "Cannot open file %s.\n", file_name);
return;
}
status = pipeline_table_entries_add(ctl,
table_name,
file,
&file_line_number);
if (status)
snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
file_name,
file_line_number);
fclose(file);
}
static int
pipeline_table_entries_delete(struct rte_swx_ctl_pipeline *p,
const char *table_name,
FILE *file,
uint32_t *file_line_number)
{
char *line = NULL;
uint32_t line_id = 0;
int status = 0;
line = malloc(MAX_LINE_SIZE);
if (!line)
return -ENOMEM;
for (line_id = 1; ; line_id++) {
int is_blank_or_comment;
if (fgets(line, MAX_LINE_SIZE, file) == NULL)
break;
table_name,
line,
&is_blank_or_comment);
if (!entry) {
if (is_blank_or_comment)
continue;
status = -EINVAL;
goto error;
}
table_name,
entry);
table_entry_free(entry);
if (status)
goto error;
}
error:
*file_line_number = line_id;
free(line);
return status;
}
static const char cmd_pipeline_table_delete_help[] =
"pipeline <pipeline_name> table <table_name> delete <file_name>\n";
static void
cmd_pipeline_table_delete(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *table_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
int status;
if (n_tokens != 6) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
table_name = tokens[3];
file_name = tokens[5];
file = fopen(file_name, "r");
if (!file) {
snprintf(out, out_size, "Cannot open file %s.\n", file_name);
return;
}
status = pipeline_table_entries_delete(ctl,
table_name,
file,
&file_line_number);
if (status)
snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
file_name,
file_line_number);
fclose(file);
}
static int
pipeline_table_default_entry_add(struct rte_swx_ctl_pipeline *p,
const char *table_name,
FILE *file,
uint32_t *file_line_number)
{
char *line = NULL;
uint32_t line_id = 0;
int status = 0;
line = malloc(MAX_LINE_SIZE);
if (!line)
return -ENOMEM;
for (line_id = 1; ; line_id++) {
int is_blank_or_comment;
if (fgets(line, MAX_LINE_SIZE, file) == NULL)
break;
table_name,
line,
&is_blank_or_comment);
if (!entry) {
if (is_blank_or_comment)
continue;
status = -EINVAL;
goto error;
}
table_name,
entry);
table_entry_free(entry);
if (status)
goto error;
}
error:
*file_line_number = line_id;
free(line);
return status;
}
static const char cmd_pipeline_table_default_help[] =
"pipeline <pipeline_name> table <table_name> default <file_name>\n";
static void
cmd_pipeline_table_default(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *table_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
int status;
if (n_tokens != 6) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
table_name = tokens[3];
file_name = tokens[5];
file = fopen(file_name, "r");
if (!file) {
snprintf(out, out_size, "Cannot open file %s.\n", file_name);
return;
}
status = pipeline_table_default_entry_add(ctl,
table_name,
file,
&file_line_number);
if (status)
snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
file_name,
file_line_number);
fclose(file);
}
static const char cmd_pipeline_table_show_help[] =
"pipeline <pipeline_name> table <table_name> show [filename]\n";
static void
cmd_pipeline_table_show(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *table_name;
FILE *file = NULL;
int status;
if (n_tokens != 5 && n_tokens != 6) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
table_name = tokens[3];
file = (n_tokens == 6) ? fopen(tokens[5], "w") : stdout;
if (!file) {
snprintf(out, out_size, "Cannot open file %s.\n", tokens[5]);
return;
}
if (status)
snprintf(out, out_size, MSG_ARG_INVALID, "table_name");
if (file)
fclose(file);
}
static const char cmd_pipeline_selector_group_add_help[] =
"pipeline <pipeline_name> selector <selector_name> group add\n";
static void
cmd_pipeline_selector_group_add(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name;
uint32_t group_id;
int status;
if (n_tokens != 6) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[2], "selector") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
return;
}
selector_name = tokens[3];
if (strcmp(tokens[4], "group") ||
strcmp(tokens[5], "add")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group add");
return;
}
selector_name,
&group_id);
if (status)
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
else
snprintf(out, out_size, "Group ID: %u\n", group_id);
}
static const char cmd_pipeline_selector_group_delete_help[] =
"pipeline <pipeline_name> selector <selector_name> group delete <group_id>\n";
static void
cmd_pipeline_selector_group_delete(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name;
uint32_t group_id;
int status;
if (n_tokens != 7) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[2], "selector") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
return;
}
selector_name = tokens[3];
if (strcmp(tokens[4], "group") ||
strcmp(tokens[5], "delete")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group delete");
return;
}
if (parser_read_uint32(&group_id, tokens[6]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "group_id");
return;
}
selector_name,
group_id);
if (status)
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
}
#define GROUP_MEMBER_INFO_TOKENS_MAX 6
static int
token_is_comment(const char *token)
{
if ((token[0] == '#') ||
(token[0] == ';') ||
((token[0] == '/') && (token[1] == '/')))
return 1;
return 0;
}
static int
pipeline_selector_group_member_read(const char *string,
uint32_t *group_id,
uint32_t *member_id,
uint32_t *weight,
int *is_blank_or_comment)
{
char *token_array[GROUP_MEMBER_INFO_TOKENS_MAX], **tokens;
char *s0 = NULL, *s;
uint32_t n_tokens = 0, group_id_val = 0, member_id_val = 0, weight_val = 0;
int blank_or_comment = 0;
if (!string || !string[0])
goto error;
s0 = strdup(string);
if (!s0)
goto error;
for (s = s0; ; ) {
char *token;
token = strtok_r(s, " \f\n\r\t\v", &s);
if (!token || token_is_comment(token))
break;
if (n_tokens >= GROUP_MEMBER_INFO_TOKENS_MAX)
goto error;
token_array[n_tokens] = token;
n_tokens++;
}
if (!n_tokens) {
blank_or_comment = 1;
goto error;
}
tokens = token_array;
if (n_tokens < 4 ||
strcmp(tokens[0], "group") ||
strcmp(tokens[2], "member"))
goto error;
if (parser_read_uint32(&group_id_val, tokens[1]) != 0)
goto error;
*group_id = group_id_val;
if (parser_read_uint32(&member_id_val, tokens[3]) != 0)
goto error;
*member_id = member_id_val;
tokens += 4;
n_tokens -= 4;
if (n_tokens && !strcmp(tokens[0], "weight")) {
if (n_tokens < 2)
goto error;
if (parser_read_uint32(&weight_val, tokens[1]) != 0)
goto error;
*weight = weight_val;
tokens += 2;
n_tokens -= 2;
}
if (n_tokens)
goto error;
free(s0);
return 0;
error:
free(s0);
if (is_blank_or_comment)
*is_blank_or_comment = blank_or_comment;
return -EINVAL;
}
static int
pipeline_selector_group_members_add(struct rte_swx_ctl_pipeline *p,
const char *selector_name,
FILE *file,
uint32_t *file_line_number)
{
char *line = NULL;
uint32_t line_id = 0;
int status = 0;
line = malloc(MAX_LINE_SIZE);
if (!line)
return -ENOMEM;
for (line_id = 1; ; line_id++) {
uint32_t group_id, member_id, weight;
int is_blank_or_comment;
if (fgets(line, MAX_LINE_SIZE, file) == NULL)
break;
status = pipeline_selector_group_member_read(line,
&group_id,
&member_id,
&weight,
&is_blank_or_comment);
if (status) {
if (is_blank_or_comment)
continue;
goto error;
}
selector_name,
group_id,
member_id,
weight);
if (status)
goto error;
}
error:
free(line);
*file_line_number = line_id;
return status;
}
static const char cmd_pipeline_selector_group_member_add_help[] =
"pipeline <pipeline_name> selector <selector_name> group member add <file_name>";
static void
cmd_pipeline_selector_group_member_add(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
int status;
if (n_tokens != 8) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[2], "selector") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
return;
}
selector_name = tokens[3];
if (strcmp(tokens[4], "group") ||
strcmp(tokens[5], "member") ||
strcmp(tokens[6], "add")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group member add");
return;
}
file_name = tokens[7];
file = fopen(file_name, "r");
if (!file) {
snprintf(out, out_size, "Cannot open file %s.\n", file_name);
return;
}
status = pipeline_selector_group_members_add(ctl,
selector_name,
file,
&file_line_number);
if (status)
snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
file_name,
file_line_number);
fclose(file);
}
static int
pipeline_selector_group_members_delete(struct rte_swx_ctl_pipeline *p,
const char *selector_name,
FILE *file,
uint32_t *file_line_number)
{
char *line = NULL;
uint32_t line_id = 0;
int status = 0;
line = malloc(MAX_LINE_SIZE);
if (!line)
return -ENOMEM;
for (line_id = 1; ; line_id++) {
uint32_t group_id, member_id, weight;
int is_blank_or_comment;
if (fgets(line, MAX_LINE_SIZE, file) == NULL)
break;
status = pipeline_selector_group_member_read(line,
&group_id,
&member_id,
&weight,
&is_blank_or_comment);
if (status) {
if (is_blank_or_comment)
continue;
goto error;
}
selector_name,
group_id,
member_id);
if (status)
goto error;
}
error:
free(line);
*file_line_number = line_id;
return status;
}
static const char cmd_pipeline_selector_group_member_delete_help[] =
"pipeline <pipeline_name> selector <selector_name> group member delete <file_name>";
static void
cmd_pipeline_selector_group_member_delete(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
int status;
if (n_tokens != 8) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[2], "selector") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
return;
}
selector_name = tokens[3];
if (strcmp(tokens[4], "group") ||
strcmp(tokens[5], "member") ||
strcmp(tokens[6], "delete")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group member delete");
return;
}
file_name = tokens[7];
file = fopen(file_name, "r");
if (!file) {
snprintf(out, out_size, "Cannot open file %s.\n", file_name);
return;
}
status = pipeline_selector_group_members_delete(ctl,
selector_name,
file,
&file_line_number);
if (status)
snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
file_name,
file_line_number);
fclose(file);
}
static const char cmd_pipeline_selector_show_help[] =
"pipeline <pipeline_name> selector <selector_name> show [filename]\n";
static void
cmd_pipeline_selector_show(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name;
FILE *file = NULL;
int status;
if (n_tokens != 5 && n_tokens != 6) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
selector_name = tokens[3];
file = (n_tokens == 6) ? fopen(tokens[5], "w") : stdout;
if (!file) {
snprintf(out, out_size, "Cannot open file %s.\n", tokens[5]);
return;
}
if (status)
snprintf(out, out_size, MSG_ARG_INVALID, "selector_name");
if (file)
fclose(file);
}
static int
pipeline_learner_default_entry_add(struct rte_swx_ctl_pipeline *p,
const char *learner_name,
FILE *file,
uint32_t *file_line_number)
{
char *line = NULL;
uint32_t line_id = 0;
int status = 0;
line = malloc(MAX_LINE_SIZE);
if (!line)
return -ENOMEM;
for (line_id = 1; ; line_id++) {
int is_blank_or_comment;
if (fgets(line, MAX_LINE_SIZE, file) == NULL)
break;
learner_name,
line,
&is_blank_or_comment);
if (!entry) {
if (is_blank_or_comment)
continue;
status = -EINVAL;
goto error;
}
learner_name,
entry);
table_entry_free(entry);
if (status)
goto error;
}
error:
*file_line_number = line_id;
free(line);
return status;
}
static const char cmd_pipeline_learner_default_help[] =
"pipeline <pipeline_name> learner <learner_name> default <file_name>\n";
static void
cmd_pipeline_learner_default(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *learner_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
int status;
if (n_tokens != 6) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
learner_name = tokens[3];
file_name = tokens[5];
file = fopen(file_name, "r");
if (!file) {
snprintf(out, out_size, "Cannot open file %s.\n", file_name);
return;
}
status = pipeline_learner_default_entry_add(ctl,
learner_name,
file,
&file_line_number);
if (status)
snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
file_name,
file_line_number);
fclose(file);
}
static const char cmd_pipeline_commit_help[] =
"pipeline <pipeline_name> commit\n";
static void
cmd_pipeline_commit(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name;
int status;
if (n_tokens != 3) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (status)
snprintf(out, out_size, "Commit failed. "
"Use \"commit\" to retry or \"abort\" to discard the pending work.\n");
}
static const char cmd_pipeline_abort_help[] =
"pipeline <pipeline_name> abort\n";
static void
cmd_pipeline_abort(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name;
if (n_tokens != 3) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
}
static const char cmd_pipeline_regrd_help[] =
"pipeline <pipeline_name> regrd <register_array_name>\n"
"index <index>\n"
" | table <table_name> match <field0> ...\n";
static void
cmd_pipeline_regrd(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_pipeline *p;
struct rte_swx_ctl_pipeline *ctl;
const char *pipeline_name, *name;
uint64_t value;
int status;
if (n_tokens < 5) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!p || !ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[2], "regrd")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regrd");
return;
}
name = tokens[3];
if (!strcmp(tokens[4], "index")) {
uint32_t idx = 0;
if (n_tokens != 6) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (parser_read_uint32(&idx, tokens[5])) {
snprintf(out, out_size, MSG_ARG_INVALID, "index");
return;
}
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
}
snprintf(out, out_size, "0x%" PRIx64 "\n", value);
return;
}
if (!strcmp(tokens[4], "table")) {
char *table_name;
if (n_tokens < 8) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
table_name = tokens[5];
if (strcmp(tokens[6], "match")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
return;
}
entry = parse_table_entry(ctl, table_name, &tokens[6], n_tokens - 6);
if (!entry) {
snprintf(out, out_size, "Invalid match tokens.\n");
return;
}
name,
table_name,
&value);
table_entry_free(entry);
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
}
snprintf(out, out_size, "0x%" PRIx64 "\n", value);
return;
}
snprintf(out, out_size, "Invalid token %s\n.", tokens[4]);
return;
}
static const char cmd_pipeline_regwr_help[] =
"pipeline <pipeline_name> regwr <register_array_name> value <value>\n"
"index <index>\n"
" | table <table_name> match <field0> ...\n";
static void
cmd_pipeline_regwr(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_pipeline *p;
struct rte_swx_ctl_pipeline *ctl;
const char *pipeline_name, *name;
uint64_t value = 0;
int status;
if (n_tokens < 7) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!p || !ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[2], "regwr")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regwr");
return;
}
name = tokens[3];
if (strcmp(tokens[4], "value")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "value");
return;
}
if (parser_read_uint64(&value, tokens[5])) {
snprintf(out, out_size, MSG_ARG_INVALID, "value");
return;
}
if (!strcmp(tokens[6], "index")) {
uint32_t idx = 0;
if (n_tokens != 8) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (parser_read_uint32(&idx, tokens[7])) {
snprintf(out, out_size, MSG_ARG_INVALID, "index");
return;
}
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
}
snprintf(out, out_size, "0x%" PRIx64 "\n", value);
return;
}
if (!strcmp(tokens[6], "table")) {
char *table_name;
if (n_tokens < 10) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
table_name = tokens[7];
if (strcmp(tokens[8], "match")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
return;
}
entry = parse_table_entry(ctl, table_name, &tokens[8], n_tokens - 8);
if (!entry) {
snprintf(out, out_size, "Invalid match tokens.\n");
return;
}
name,
table_name,
value);
table_entry_free(entry);
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
}
return;
}
snprintf(out, out_size, "Invalid token %s\n.", tokens[6]);
return;
}
static const char cmd_pipeline_meter_profile_add_help[] =
"pipeline <pipeline_name> meter profile <profile_name> add "
"cir <cir> pir <pir> cbs <cbs> pbs <pbs>\n";
static void
cmd_pipeline_meter_profile_add(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_pipeline *p;
const char *profile_name;
int status;
if (n_tokens != 14) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[2], "meter")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
return;
}
if (strcmp(tokens[3], "profile")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
return;
}
profile_name = tokens[4];
if (strcmp(tokens[5], "add")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
return;
}
if (strcmp(tokens[6], "cir")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
return;
}
if (parser_read_uint64(¶ms.
cir, tokens[7])) {
snprintf(out, out_size, MSG_ARG_INVALID, "cir");
return;
}
if (strcmp(tokens[8], "pir")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir");
return;
}
if (parser_read_uint64(¶ms.
pir, tokens[9])) {
snprintf(out, out_size, MSG_ARG_INVALID, "pir");
return;
}
if (strcmp(tokens[10], "cbs")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
return;
}
if (parser_read_uint64(¶ms.
cbs, tokens[11])) {
snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
return;
}
if (strcmp(tokens[12], "pbs")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs");
return;
}
if (parser_read_uint64(¶ms.
pbs, tokens[13])) {
snprintf(out, out_size, MSG_ARG_INVALID, "pbs");
return;
}
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
}
}
static const char cmd_pipeline_meter_profile_delete_help[] =
"pipeline <pipeline_name> meter profile <profile_name> delete\n";
static void
cmd_pipeline_meter_profile_delete(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_pipeline *p;
const char *profile_name;
int status;
if (n_tokens != 6) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[2], "meter")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
return;
}
if (strcmp(tokens[3], "profile")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
return;
}
profile_name = tokens[4];
if (strcmp(tokens[5], "delete")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
return;
}
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
}
}
static const char cmd_pipeline_meter_reset_help[] =
"pipeline <pipeline_name> meter <meter_array_name> reset\n"
"index from <index0> to <index1>\n"
" | table <table_name> match <field0> ...\n";
static void
cmd_pipeline_meter_reset(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_pipeline *p;
struct rte_swx_ctl_pipeline *ctl;
const char *pipeline_name, *name;
if (n_tokens < 6) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!p || !ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[2], "meter")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
return;
}
name = tokens[3];
if (strcmp(tokens[4], "reset")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "reset");
return;
}
if (!strcmp(tokens[5], "index")) {
uint32_t idx0 = 0, idx1 = 0;
if (n_tokens != 10) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (strcmp(tokens[6], "from")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
return;
}
if (parser_read_uint32(&idx0, tokens[7])) {
snprintf(out, out_size, MSG_ARG_INVALID, "index0");
return;
}
if (strcmp(tokens[8], "to")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
return;
}
if (parser_read_uint32(&idx1, tokens[9]) || (idx1 < idx0)) {
snprintf(out, out_size, MSG_ARG_INVALID, "index1");
return;
}
for ( ; idx0 <= idx1; idx0++) {
int status;
if (status) {
snprintf(out, out_size, "Command failed for index %u.\n", idx0);
return;
}
}
return;
}
if (!strcmp(tokens[5], "table")) {
char *table_name;
int status;
if (n_tokens < 9) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
table_name = tokens[6];
if (strcmp(tokens[7], "match")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
return;
}
entry = parse_table_entry(ctl, table_name, &tokens[7], n_tokens - 7);
if (!entry) {
snprintf(out, out_size, "Invalid match tokens.\n");
return;
}
table_entry_free(entry);
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
}
return;
}
snprintf(out, out_size, "Invalid token %s\n.", tokens[5]);
return;
}
static const char cmd_pipeline_meter_set_help[] =
"pipeline <pipeline_name> meter <meter_array_name> set profile <profile_name>\n"
"index from <index0> to <index1>\n"
" | table <table_name> match <field0> ...\n";
static void
cmd_pipeline_meter_set(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_pipeline *p;
struct rte_swx_ctl_pipeline *ctl;
const char *pipeline_name, *name, *profile_name;
if (n_tokens < 8) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!p || !ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[2], "meter")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
return;
}
name = tokens[3];
if (strcmp(tokens[4], "set")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "set");
return;
}
if (strcmp(tokens[5], "profile")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
return;
}
profile_name = tokens[6];
if (!strcmp(tokens[7], "index")) {
uint32_t idx0 = 0, idx1 = 0;
if (n_tokens != 12) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (strcmp(tokens[8], "from")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
return;
}
if (parser_read_uint32(&idx0, tokens[9])) {
snprintf(out, out_size, MSG_ARG_INVALID, "index0");
return;
}
if (strcmp(tokens[10], "to")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
return;
}
if (parser_read_uint32(&idx1, tokens[11]) || (idx1 < idx0)) {
snprintf(out, out_size, MSG_ARG_INVALID, "index1");
return;
}
for ( ; idx0 <= idx1; idx0++) {
int status;
if (status) {
snprintf(out, out_size, "Command failed for index %u.\n", idx0);
return;
}
}
return;
}
if (!strcmp(tokens[7], "table")) {
char *table_name;
int status;
if (n_tokens < 11) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
table_name = tokens[8];
if (strcmp(tokens[9], "match")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
return;
}
entry = parse_table_entry(ctl, table_name, &tokens[9], n_tokens - 9);
if (!entry) {
snprintf(out, out_size, "Invalid match tokens.\n");
return;
}
name,
table_name,
profile_name);
table_entry_free(entry);
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
}
return;
}
snprintf(out, out_size, "Invalid token %s\n.", tokens[7]);
return;
}
static const char cmd_pipeline_meter_stats_help[] =
"pipeline <pipeline_name> meter <meter_array_name> stats\n"
"index from <index0> to <index1>\n"
" | table <table_name> match <field0> ...\n";
static void
cmd_pipeline_meter_stats(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_pipeline *p;
struct rte_swx_ctl_pipeline *ctl;
const char *pipeline_name, *name;
if (n_tokens < 6) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
pipeline_name = tokens[1];
if (!p || !ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[2], "meter")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
return;
}
name = tokens[3];
if (strcmp(tokens[4], "stats")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
return;
}
if (!strcmp(tokens[5], "index")) {
uint32_t idx0 = 0, idx1 = 0;
if (n_tokens != 10) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (strcmp(tokens[6], "from")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
return;
}
if (parser_read_uint32(&idx0, tokens[7])) {
snprintf(out, out_size, MSG_ARG_INVALID, "index0");
return;
}
if (strcmp(tokens[8], "to")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
return;
}
if (parser_read_uint32(&idx1, tokens[9]) || (idx1 < idx0)) {
snprintf(out, out_size, MSG_ARG_INVALID, "index1");
return;
}
snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
"-------",
"----------------", "----------------", "----------------",
"----------------", "----------------", "----------------");
out_size -= strlen(out);
out += strlen(out);
snprintf(out, out_size, "| %4s | %16s | %16s | %16s | %16s | %16s | %16s |\n",
"METER #",
"GREEN (packets)", "YELLOW (packets)", "RED (packets)",
"GREEN (bytes)", "YELLOW (bytes)", "RED (bytes)");
out_size -= strlen(out);
out += strlen(out);
snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
"-------",
"----------------", "----------------", "----------------",
"----------------", "----------------", "----------------");
out_size -= strlen(out);
out += strlen(out);
for ( ; idx0 <= idx1; idx0++) {
int status;
if (status) {
snprintf(out, out_size, "Meter stats error at index %u.\n", idx0);
out_size -= strlen(out);
out += strlen(out);
return;
}
snprintf(out, out_size, "| %7d | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64
" | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 " |\n",
idx0,
out_size -= strlen(out);
out += strlen(out);
}
return;
}
if (!strcmp(tokens[5], "table")) {
char *table_name;
int status;
if (n_tokens < 9) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
table_name = tokens[6];
if (strcmp(tokens[7], "match")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
return;
}
entry = parse_table_entry(ctl, table_name, &tokens[7], n_tokens - 7);
if (!entry) {
snprintf(out, out_size, "Invalid match tokens.\n");
return;
}
name,
table_name,
&stats);
table_entry_free(entry);
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
}
snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
"-------",
"----------------", "----------------", "----------------",
"----------------", "----------------", "----------------");
out_size -= strlen(out);
out += strlen(out);
snprintf(out, out_size, "| %4s | %16s | %16s | %16s | %16s | %16s | %16s |\n",
"METER #",
"GREEN (packets)", "YELLOW (packets)", "RED (packets)",
"GREEN (bytes)", "YELLOW (bytes)", "RED (bytes)");
out_size -= strlen(out);
out += strlen(out);
snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
"-------",
"----------------", "----------------", "----------------",
"----------------", "----------------", "----------------");
out_size -= strlen(out);
out += strlen(out);
snprintf(out, out_size, "| %7d | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64
" | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 " |\n",
0,
out_size -= strlen(out);
out += strlen(out);
return;
}
snprintf(out, out_size, "Invalid token %s\n.", tokens[5]);
return;
}
static const char cmd_pipeline_stats_help[] =
"pipeline <pipeline_name> stats\n";
static void
cmd_pipeline_stats(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_pipeline *p;
uint32_t i;
int status;
if (n_tokens != 3) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[2], "stats")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
return;
}
if (status) {
snprintf(out, out_size, "Pipeline info get error.");
return;
}
snprintf(out, out_size, "Input ports:\n");
out_size -= strlen(out);
out += strlen(out);
snprintf(out, out_size, "\tPort %u:"
" packets %" PRIu64
" bytes %" PRIu64
" empty %" PRIu64 "\n",
out_size -= strlen(out);
out += strlen(out);
}
snprintf(out, out_size, "\nOutput ports:\n");
out_size -= strlen(out);
out += strlen(out);
snprintf(out, out_size, "\tPort %u:", i);
else
snprintf(out, out_size, "\tDROP:");
out_size -= strlen(out);
out += strlen(out);
snprintf(out,
out_size,
" packets %" PRIu64
" bytes %" PRIu64
" packets dropped %" PRIu64
" bytes dropped %" PRIu64
" clone %" PRIu64
" clonerr %" PRIu64 "\n",
out_size -= strlen(out);
out += strlen(out);
}
snprintf(out, out_size, "\nTables:\n");
out_size -= strlen(out);
out += strlen(out);
.n_pkts_miss = 0,
};
uint32_t j;
if (status) {
snprintf(out, out_size, "Table info get error.");
return;
}
if (status) {
snprintf(out, out_size, "Table stats read error.");
return;
}
snprintf(out, out_size, "\tTable %s:\n"
"\t\tHit (packets): %" PRIu64 "\n"
"\t\tMiss (packets): %" PRIu64 "\n",
out_size -= strlen(out);
out += strlen(out);
if (status) {
snprintf(out, out_size, "Action info get error.");
return;
}
snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n",
out_size -= strlen(out);
out += strlen(out);
}
}
snprintf(out, out_size, "\nLearner tables:\n");
out_size -= strlen(out);
out += strlen(out);
.n_pkts_miss = 0,
};
uint32_t j;
if (status) {
snprintf(out, out_size, "Learner table info get error.");
return;
}
if (status) {
snprintf(out, out_size, "Learner table stats read error.");
return;
}
snprintf(out, out_size, "\tLearner table %s:\n"
"\t\tHit (packets): %" PRIu64 "\n"
"\t\tMiss (packets): %" PRIu64 "\n"
"\t\tLearn OK (packets): %" PRIu64 "\n"
"\t\tLearn error (packets): %" PRIu64 "\n"
"\t\tRearm (packets): %" PRIu64 "\n"
"\t\tForget (packets): %" PRIu64 "\n",
out_size -= strlen(out);
out += strlen(out);
if (status) {
snprintf(out, out_size, "Action info get error.");
return;
}
snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n",
out_size -= strlen(out);
out += strlen(out);
}
}
}
static const char cmd_pipeline_mirror_session_help[] =
"pipeline <pipeline_name> mirror session <session_id> port <port_id> clone fast | slow "
"truncate <truncation_length>\n";
static void
cmd_pipeline_mirror_session(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_pipeline *p;
uint32_t session_id = 0;
int status;
if (n_tokens != 11) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (strcmp(tokens[0], "pipeline")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
return;
}
if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[2], "mirror")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mirror");
return;
}
if (strcmp(tokens[3], "session")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "session");
return;
}
if (parser_read_uint32(&session_id, tokens[4])) {
snprintf(out, out_size, MSG_ARG_INVALID, "session_id");
return;
}
if (strcmp(tokens[5], "port")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
return;
}
if (parser_read_uint32(¶ms.
port_id, tokens[6])) {
snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
return;
}
if (strcmp(tokens[7], "clone")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "clone");
return;
}
if (!strcmp(tokens[8], "fast"))
else if (!strcmp(tokens[8], "slow"))
else {
snprintf(out, out_size, MSG_ARG_INVALID, "clone");
return;
}
if (strcmp(tokens[9], "truncate")) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "truncate");
return;
}
snprintf(out, out_size, MSG_ARG_INVALID, "truncation_length");
return;
}
if (status) {
snprintf(out, out_size, "Command failed!\n");
return;
}
}
static const char cmd_thread_pipeline_enable_help[] =
"thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]\n";
#ifndef TIMER_PERIOD_MS_DEFAULT
#define TIMER_PERIOD_MS_DEFAULT 10
#endif
static void
cmd_thread_pipeline_enable(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
char *pipeline_name;
struct rte_swx_pipeline *p;
uint32_t thread_id, timer_period_ms = TIMER_PERIOD_MS_DEFAULT;
int status;
if ((n_tokens != 5) && (n_tokens != 7)) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
return;
}
if (strcmp(tokens[2], "pipeline") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
return;
}
pipeline_name = tokens[3];
if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[4], "enable") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
return;
}
if (n_tokens == 7) {
if (strcmp(tokens[5], "period") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period");
return;
}
if (parser_read_uint32(&timer_period_ms, tokens[6]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms");
return;
}
}
status = thread_pipeline_enable(thread_id, p, timer_period_ms);
if (status) {
snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable");
return;
}
}
static const char cmd_thread_pipeline_disable_help[] =
"thread <thread_id> pipeline <pipeline_name> disable\n";
static void
cmd_thread_pipeline_disable(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
struct rte_swx_pipeline *p;
char *pipeline_name;
uint32_t thread_id;
int status;
if (n_tokens != 5) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
return;
}
if (strcmp(tokens[2], "pipeline") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
return;
}
pipeline_name = tokens[3];
if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
if (strcmp(tokens[4], "disable") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
return;
}
status = thread_pipeline_disable(thread_id, p);
if (status) {
snprintf(out, out_size, MSG_CMD_FAIL,
"thread pipeline disable");
return;
}
}
static void
cmd_help(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
{
tokens++;
n_tokens--;
if (n_tokens == 0) {
snprintf(out, out_size,
"Type 'help <command>' for command details.\n\n"
"List of commands:\n"
"\tmempool\n"
"\tethdev\n"
"\tpipeline codegen\n"
"\tpipeline libbuild\n"
"\tpipeline build\n"
"\tpipeline table add\n"
"\tpipeline table delete\n"
"\tpipeline table default\n"
"\tpipeline table show\n"
"\tpipeline selector group add\n"
"\tpipeline selector group delete\n"
"\tpipeline selector group member add\n"
"\tpipeline selector group member delete\n"
"\tpipeline selector show\n"
"\tpipeline learner default\n"
"\tpipeline commit\n"
"\tpipeline abort\n"
"\tpipeline regrd\n"
"\tpipeline regwr\n"
"\tpipeline meter profile add\n"
"\tpipeline meter profile delete\n"
"\tpipeline meter reset\n"
"\tpipeline meter set\n"
"\tpipeline meter stats\n"
"\tpipeline stats\n"
"\tpipeline mirror session\n"
"\tthread pipeline enable\n"
"\tthread pipeline disable\n\n");
return;
}
if (strcmp(tokens[0], "mempool") == 0) {
snprintf(out, out_size, "\n%s\n", cmd_mempool_help);
return;
}
if (strcmp(tokens[0], "ethdev") == 0) {
snprintf(out, out_size, "\n%s\n", cmd_ethdev_help);
return;
}
if (strcmp(tokens[0], "ring") == 0) {
snprintf(out, out_size, "\n%s\n", cmd_ring_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "codegen") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_codegen_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "libbuild") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_libbuild_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 3) &&
(strcmp(tokens[1], "table") == 0) &&
(strcmp(tokens[2], "add") == 0)) {
snprintf(out, out_size, "\n%s\n",
cmd_pipeline_table_add_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 3) &&
(strcmp(tokens[1], "table") == 0) &&
(strcmp(tokens[2], "delete") == 0)) {
snprintf(out, out_size, "\n%s\n",
cmd_pipeline_table_delete_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 3) &&
(strcmp(tokens[1], "table") == 0) &&
(strcmp(tokens[2], "default") == 0)) {
snprintf(out, out_size, "\n%s\n",
cmd_pipeline_table_default_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 3) &&
(strcmp(tokens[1], "table") == 0) &&
(strcmp(tokens[2], "show") == 0)) {
snprintf(out, out_size, "\n%s\n",
cmd_pipeline_table_show_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 4) &&
(strcmp(tokens[1], "selector") == 0) &&
(strcmp(tokens[2], "group") == 0) &&
(strcmp(tokens[3], "add") == 0)) {
snprintf(out, out_size, "\n%s\n",
cmd_pipeline_selector_group_add_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 4) &&
(strcmp(tokens[1], "selector") == 0) &&
(strcmp(tokens[2], "group") == 0) &&
(strcmp(tokens[3], "delete") == 0)) {
snprintf(out, out_size, "\n%s\n",
cmd_pipeline_selector_group_delete_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 5) &&
(strcmp(tokens[1], "selector") == 0) &&
(strcmp(tokens[2], "group") == 0) &&
(strcmp(tokens[3], "member") == 0) &&
(strcmp(tokens[4], "add") == 0)) {
snprintf(out, out_size, "\n%s\n",
cmd_pipeline_selector_group_member_add_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 5) &&
(strcmp(tokens[1], "selector") == 0) &&
(strcmp(tokens[2], "group") == 0) &&
(strcmp(tokens[3], "member") == 0) &&
(strcmp(tokens[4], "delete") == 0)) {
snprintf(out, out_size, "\n%s\n",
cmd_pipeline_selector_group_member_delete_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 3) &&
(strcmp(tokens[1], "selector") == 0) &&
(strcmp(tokens[2], "show") == 0)) {
snprintf(out, out_size, "\n%s\n",
cmd_pipeline_selector_show_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 3) &&
(strcmp(tokens[1], "learner") == 0) &&
(strcmp(tokens[2], "default") == 0)) {
snprintf(out, out_size, "\n%s\n",
cmd_pipeline_learner_default_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) &&
(strcmp(tokens[1], "commit") == 0)) {
snprintf(out, out_size, "\n%s\n",
cmd_pipeline_commit_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) &&
(strcmp(tokens[1], "abort") == 0)) {
snprintf(out, out_size, "\n%s\n",
cmd_pipeline_abort_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "regrd") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_regrd_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "regwr") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_regwr_help);
return;
}
if (!strcmp(tokens[0], "pipeline") &&
(n_tokens == 4) && !strcmp(tokens[1], "meter")
&& !strcmp(tokens[2], "profile")
&& !strcmp(tokens[3], "add")) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_profile_add_help);
return;
}
if (!strcmp(tokens[0], "pipeline") &&
(n_tokens == 4) && !strcmp(tokens[1], "meter")
&& !strcmp(tokens[2], "profile")
&& !strcmp(tokens[3], "delete")) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_profile_delete_help);
return;
}
if (!strcmp(tokens[0], "pipeline") &&
(n_tokens == 3) && !strcmp(tokens[1], "meter")
&& !strcmp(tokens[2], "reset")) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_reset_help);
return;
}
if (!strcmp(tokens[0], "pipeline") &&
(n_tokens == 3) && !strcmp(tokens[1], "meter")
&& !strcmp(tokens[2], "set")) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_set_help);
return;
}
if (!strcmp(tokens[0], "pipeline") &&
(n_tokens == 3) && !strcmp(tokens[1], "meter")
&& !strcmp(tokens[2], "stats")) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_meter_stats_help);
return;
}
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "stats") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_stats_help);
return;
}
if (!strcmp(tokens[0], "pipeline") &&
(n_tokens == 3) && !strcmp(tokens[1], "mirror")
&& !strcmp(tokens[2], "session")) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_mirror_session_help);
return;
}
if ((n_tokens == 3) &&
(strcmp(tokens[0], "thread") == 0) &&
(strcmp(tokens[1], "pipeline") == 0)) {
if (strcmp(tokens[2], "enable") == 0) {
snprintf(out, out_size, "\n%s\n",
cmd_thread_pipeline_enable_help);
return;
}
if (strcmp(tokens[2], "disable") == 0) {
snprintf(out, out_size, "\n%s\n",
cmd_thread_pipeline_disable_help);
return;
}
}
snprintf(out, out_size, "Invalid command\n");
}
void
cli_process(char *in, char *out, size_t out_size, void *obj)
{
char *tokens[CMD_MAX_TOKENS];
uint32_t n_tokens =
RTE_DIM(tokens);
int status;
if (is_comment(in))
return;
status = parse_tokenize_string(in, tokens, &n_tokens);
if (status) {
snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
return;
}
if (n_tokens == 0)
return;
if (strcmp(tokens[0], "help") == 0) {
cmd_help(tokens, n_tokens, out, out_size, obj);
return;
}
if (strcmp(tokens[0], "mempool") == 0) {
cmd_mempool(tokens, n_tokens, out, out_size, obj);
return;
}
if (strcmp(tokens[0], "ethdev") == 0) {
if ((n_tokens >= 2) && (strcmp(tokens[1], "show") == 0)) {
cmd_ethdev_show(tokens, n_tokens, out, out_size, obj);
return;
}
cmd_ethdev(tokens, n_tokens, out, out_size, obj);
return;
}
if (strcmp(tokens[0], "ring") == 0) {
cmd_ring(tokens, n_tokens, out, out_size, obj);
return;
}
if (strcmp(tokens[0], "pipeline") == 0) {
if ((n_tokens >= 3) &&
(strcmp(tokens[1], "codegen") == 0)) {
cmd_pipeline_codegen(tokens, n_tokens, out, out_size,
obj);
return;
}
if ((n_tokens >= 3) &&
(strcmp(tokens[1], "libbuild") == 0)) {
cmd_pipeline_libbuild(tokens, n_tokens, out, out_size,
obj);
return;
}
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "build") == 0)) {
cmd_pipeline_build(tokens, n_tokens, out, out_size,
obj);
return;
}
if ((n_tokens >= 5) &&
(strcmp(tokens[2], "table") == 0) &&
(strcmp(tokens[4], "add") == 0)) {
cmd_pipeline_table_add(tokens, n_tokens, out,
out_size, obj);
return;
}
if ((n_tokens >= 5) &&
(strcmp(tokens[2], "table") == 0) &&
(strcmp(tokens[4], "delete") == 0)) {
cmd_pipeline_table_delete(tokens, n_tokens, out,
out_size, obj);
return;
}
if ((n_tokens >= 5) &&
(strcmp(tokens[2], "table") == 0) &&
(strcmp(tokens[4], "default") == 0)) {
cmd_pipeline_table_default(tokens, n_tokens, out,
out_size, obj);
return;
}
if ((n_tokens >= 5) &&
(strcmp(tokens[2], "table") == 0) &&
(strcmp(tokens[4], "show") == 0)) {
cmd_pipeline_table_show(tokens, n_tokens, out,
out_size, obj);
return;
}
if ((n_tokens >= 6) &&
(strcmp(tokens[2], "selector") == 0) &&
(strcmp(tokens[4], "group") == 0) &&
(strcmp(tokens[5], "add") == 0)) {
cmd_pipeline_selector_group_add(tokens, n_tokens, out,
out_size, obj);
return;
}
if ((n_tokens >= 6) &&
(strcmp(tokens[2], "selector") == 0) &&
(strcmp(tokens[4], "group") == 0) &&
(strcmp(tokens[5], "delete") == 0)) {
cmd_pipeline_selector_group_delete(tokens, n_tokens, out,
out_size, obj);
return;
}
if ((n_tokens >= 7) &&
(strcmp(tokens[2], "selector") == 0) &&
(strcmp(tokens[4], "group") == 0) &&
(strcmp(tokens[5], "member") == 0) &&
(strcmp(tokens[6], "add") == 0)) {
cmd_pipeline_selector_group_member_add(tokens, n_tokens, out,
out_size, obj);
return;
}
if ((n_tokens >= 7) &&
(strcmp(tokens[2], "selector") == 0) &&
(strcmp(tokens[4], "group") == 0) &&
(strcmp(tokens[5], "member") == 0) &&
(strcmp(tokens[6], "delete") == 0)) {
cmd_pipeline_selector_group_member_delete(tokens, n_tokens, out,
out_size, obj);
return;
}
if ((n_tokens >= 5) &&
(strcmp(tokens[2], "selector") == 0) &&
(strcmp(tokens[4], "show") == 0)) {
cmd_pipeline_selector_show(tokens, n_tokens, out,
out_size, obj);
return;
}
if ((n_tokens >= 5) &&
(strcmp(tokens[2], "learner") == 0) &&
(strcmp(tokens[4], "default") == 0)) {
cmd_pipeline_learner_default(tokens, n_tokens, out,
out_size, obj);
return;
}
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "commit") == 0)) {
cmd_pipeline_commit(tokens, n_tokens, out,
out_size, obj);
return;
}
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "abort") == 0)) {
cmd_pipeline_abort(tokens, n_tokens, out,
out_size, obj);
return;
}
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "regrd") == 0)) {
cmd_pipeline_regrd(tokens, n_tokens, out, out_size, obj);
return;
}
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "regwr") == 0)) {
cmd_pipeline_regwr(tokens, n_tokens, out, out_size, obj);
return;
}
if ((n_tokens >= 6) &&
(strcmp(tokens[2], "meter") == 0) &&
(strcmp(tokens[3], "profile") == 0) &&
(strcmp(tokens[5], "add") == 0)) {
cmd_pipeline_meter_profile_add(tokens, n_tokens, out, out_size, obj);
return;
}
if ((n_tokens >= 6) &&
(strcmp(tokens[2], "meter") == 0) &&
(strcmp(tokens[3], "profile") == 0) &&
(strcmp(tokens[5], "delete") == 0)) {
cmd_pipeline_meter_profile_delete(tokens, n_tokens, out, out_size, obj);
return;
}
if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[4], "reset")) {
cmd_pipeline_meter_reset(tokens, n_tokens, out, out_size, obj);
return;
}
if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[4], "set")) {
cmd_pipeline_meter_set(tokens, n_tokens, out, out_size, obj);
return;
}
if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[4], "stats")) {
cmd_pipeline_meter_stats(tokens, n_tokens, out, out_size, obj);
return;
}
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "stats") == 0)) {
cmd_pipeline_stats(tokens, n_tokens, out, out_size,
obj);
return;
}
if ((n_tokens >= 4) &&
(strcmp(tokens[2], "mirror") == 0) &&
(strcmp(tokens[3], "session") == 0)) {
cmd_pipeline_mirror_session(tokens, n_tokens, out, out_size, obj);
return;
}
}
if (strcmp(tokens[0], "thread") == 0) {
if ((n_tokens >= 5) &&
(strcmp(tokens[4], "enable") == 0)) {
cmd_thread_pipeline_enable(tokens, n_tokens,
out, out_size, obj);
return;
}
if ((n_tokens >= 5) &&
(strcmp(tokens[4], "disable") == 0)) {
cmd_thread_pipeline_disable(tokens, n_tokens,
out, out_size, obj);
return;
}
}
snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
}
int
cli_script_process(const char *file_name,
size_t msg_in_len_max,
size_t msg_out_len_max,
void *obj)
{
char *msg_in = NULL, *msg_out = NULL;
FILE *f = NULL;
if ((file_name == NULL) ||
(strlen(file_name) == 0) ||
(msg_in_len_max == 0) ||
(msg_out_len_max == 0))
return -EINVAL;
msg_in = malloc(msg_in_len_max + 1);
msg_out = malloc(msg_out_len_max + 1);
if ((msg_in == NULL) ||
(msg_out == NULL)) {
free(msg_out);
free(msg_in);
return -ENOMEM;
}
f = fopen(file_name, "r");
if (f == NULL) {
free(msg_out);
free(msg_in);
return -EIO;
}
for ( ; ; ) {
if (fgets(msg_in, msg_in_len_max + 1, f) == NULL)
break;
printf("%s", msg_in);
msg_out[0] = 0;
cli_process(msg_in,
msg_out,
msg_out_len_max,
obj);
if (strlen(msg_out))
printf("%s", msg_out);
}
fclose(f);
free(msg_out);
free(msg_in);
return 0;
}