X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=examples%2Fpipeline%2Fcli.c;h=1e2dd9d704245741dd25a13fdcc8998a9f8b44c1;hb=7f4d3d1242e3eb3faa4fdf851361101d63f51c23;hp=cacfb2823b7119f5e8a5f3c7f7dc800522d9e182;hpb=77a413017c2d22a2be0337c14be523e4675dabdd;p=dpdk.git diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c index cacfb2823b..1e2dd9d704 100644 --- a/examples/pipeline/cli.c +++ b/examples/pipeline/cli.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -54,7 +55,7 @@ parser_read_uint64(uint64_t *value, const char *p) if (!isdigit(*p)) return -EINVAL; - val = strtoul(p, &next, 10); + val = strtoul(p, &next, 0); if (p == next) return -EINVAL; @@ -493,6 +494,32 @@ cmd_ring(char **tokens, } } +static const char cmd_tap_help[] = +"tap \n"; + +static void +cmd_tap(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct tap *tap; + char *name; + + if (n_tokens < 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + name = tokens[1]; + + tap = tap_create(obj, name); + if (tap == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + static const char cmd_pipeline_create_help[] = "pipeline create \n"; @@ -530,7 +557,8 @@ static const char cmd_pipeline_port_in_help[] = "pipeline port in \n" " link rxq bsz \n" " ring bsz \n" -" | source \n"; +" | source \n" +" | tap mempool mtu bsz \n"; static void cmd_pipeline_port_in(char **tokens, @@ -678,6 +706,68 @@ cmd_pipeline_port_in(char **tokens, port_id, "source", ¶ms); + } else if (strcmp(tokens[t0], "tap") == 0) { + struct rte_swx_port_fd_reader_params params; + struct tap *tap; + struct mempool *mp; + + if (n_tokens < t0 + 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port in tap"); + return; + } + + tap = tap_find(obj, tokens[t0 + 1]); + if (!tap) { + snprintf(out, out_size, MSG_ARG_INVALID, + "tap_name"); + return; + } + params.fd = tap->fd; + + if (strcmp(tokens[t0 + 2], "mempool") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "mempool"); + return; + } + + mp = mempool_find(obj, tokens[t0 + 3]); + if (!mp) { + snprintf(out, out_size, MSG_ARG_INVALID, + "mempool_name"); + return; + } + params.mempool = mp->m; + + if (strcmp(tokens[t0 + 4], "mtu") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "mtu"); + return; + } + + if (parser_read_uint32(¶ms.mtu, tokens[t0 + 5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); + return; + } + + if (strcmp(tokens[t0 + 6], "bsz") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); + return; + } + + if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 7])) { + snprintf(out, out_size, MSG_ARG_INVALID, + "burst_size"); + return; + } + + t0 += 8; + + status = rte_swx_pipeline_port_in_config(p->p, + port_id, + "fd", + ¶ms); + } else { snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); return; @@ -698,7 +788,8 @@ static const char cmd_pipeline_port_out_help[] = "pipeline port out \n" " link txq bsz \n" " ring bsz \n" -" | sink | none\n"; +" | sink | none\n" +" | tap bsz \n"; static void cmd_pipeline_port_out(char **tokens, @@ -832,6 +923,41 @@ cmd_pipeline_port_out(char **tokens, port_id, "sink", ¶ms); + } else if (strcmp(tokens[t0], "tap") == 0) { + struct rte_swx_port_fd_writer_params params; + struct tap *tap; + + if (n_tokens < t0 + 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port out tap"); + return; + } + + tap = tap_find(obj, tokens[t0 + 1]); + if (!tap) { + snprintf(out, out_size, MSG_ARG_INVALID, + "tap_name"); + return; + } + params.fd = tap->fd; + + if (strcmp(tokens[t0 + 2], "bsz") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); + return; + } + + if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 3])) { + snprintf(out, out_size, MSG_ARG_INVALID, + "burst_size"); + return; + } + + t0 += 4; + + status = rte_swx_pipeline_port_out_config(p->p, + port_id, + "fd", + ¶ms); } else { snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); return; @@ -912,25 +1038,76 @@ table_entry_free(struct rte_swx_table_entry *entry) free(entry); } -static const char cmd_pipeline_table_update_help[] = -"pipeline table update " -" "; +#ifndef MAX_LINE_SIZE +#define MAX_LINE_SIZE 2048 +#endif + +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; + + /* Buffer allocation. */ + line = malloc(MAX_LINE_SIZE); + if (!line) + return -ENOMEM; + + /* File read. */ + for (line_id = 1; ; line_id++) { + struct rte_swx_table_entry *entry; + int is_blank_or_comment; + + if (fgets(line, MAX_LINE_SIZE, file) == NULL) + break; + + entry = rte_swx_ctl_pipeline_table_entry_read(p, + table_name, + line, + &is_blank_or_comment); + if (!entry) { + if (is_blank_or_comment) + continue; + + status = -EINVAL; + goto error; + } + + status = rte_swx_ctl_pipeline_table_entry_add(p, + 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 table add \n"; static void -cmd_pipeline_table_update(char **tokens, - uint32_t n_tokens, - char *out, - size_t out_size, - void *obj) +cmd_pipeline_table_add(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) { struct pipeline *p; - char *pipeline_name, *table_name, *line = NULL; - char *file_name_add, *file_name_delete, *file_name_default; - FILE *file_add = NULL, *file_delete = NULL, *file_default = NULL; - uint32_t line_id; + char *pipeline_name, *table_name, *file_name; + FILE *file = NULL; + uint32_t file_line_number = 0; int status; - if (n_tokens != 8) { + if (n_tokens != 6) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -942,265 +1119,235 @@ cmd_pipeline_table_update(char **tokens, return; } - if (strcmp(tokens[2], "table") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); - return; - } - table_name = tokens[3]; - if (strcmp(tokens[4], "update") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "update"); + file_name = tokens[5]; + file = fopen(file_name, "r"); + if (!file) { + snprintf(out, out_size, "Cannot open file %s.\n", file_name); return; } - file_name_add = tokens[5]; - file_name_delete = tokens[6]; - file_name_default = tokens[7]; + status = pipeline_table_entries_add(p->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); - /* File open. */ - if (strcmp(file_name_add, "none")) { - file_add = fopen(file_name_add, "r"); - if (!file_add) { - snprintf(out, out_size, "Cannot open file %s", - file_name_add); - goto error; - } - } + 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; + + /* Buffer allocation. */ + line = malloc(MAX_LINE_SIZE); + if (!line) + return -ENOMEM; + + /* File read. */ + for (line_id = 1; ; line_id++) { + struct rte_swx_table_entry *entry; + int is_blank_or_comment; + + if (fgets(line, MAX_LINE_SIZE, file) == NULL) + break; - if (strcmp(file_name_delete, "none")) { - file_delete = fopen(file_name_delete, "r"); - if (!file_delete) { - snprintf(out, out_size, "Cannot open file %s", - file_name_delete); + entry = rte_swx_ctl_pipeline_table_entry_read(p, + table_name, + line, + &is_blank_or_comment); + if (!entry) { + if (is_blank_or_comment) + continue; + + status = -EINVAL; goto error; } - } - if (strcmp(file_name_default, "none")) { - file_default = fopen(file_name_default, "r"); - if (!file_default) { - snprintf(out, out_size, "Cannot open file %s", - file_name_default); + status = rte_swx_ctl_pipeline_table_entry_delete(p, + table_name, + entry); + table_entry_free(entry); + if (status) goto error; - } } - if (!file_add && !file_delete && !file_default) { - snprintf(out, out_size, "Nothing to be done."); - return; - } +error: + *file_line_number = line_id; + free(line); + return status; +} - /* Buffer allocation. */ - line = malloc(2048); - if (!line) { - snprintf(out, out_size, MSG_OUT_OF_MEMORY); - goto error; - } +static const char cmd_pipeline_table_delete_help[] = +"pipeline table delete \n"; - /* Add. */ - if (file_add) - for (line_id = 1; ; line_id++) { - struct rte_swx_table_entry *entry; +static void +cmd_pipeline_table_delete(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct pipeline *p; + char *pipeline_name, *table_name, *file_name; + FILE *file = NULL; + uint32_t file_line_number = 0; + int status; - if (fgets(line, 2048, file_add) == NULL) - break; + if (n_tokens != 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } - entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl, - table_name, - line); - if (!entry) { - snprintf(out, out_size, MSG_FILE_ERR, - file_name_add, line_id); - goto error; - } + pipeline_name = tokens[1]; + p = pipeline_find(obj, pipeline_name); + if (!p || !p->ctl) { + snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); + return; + } - status = rte_swx_ctl_pipeline_table_entry_add(p->ctl, - table_name, - entry); - table_entry_free(entry); - if (status) { - snprintf(out, out_size, - "Invalid entry in file %s at line %u", - file_name_add, line_id); - goto error; - } - } + 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; + } - /* Delete. */ - if (file_delete) - for (line_id = 1; ; line_id++) { - struct rte_swx_table_entry *entry; + status = pipeline_table_entries_delete(p->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); - if (fgets(line, 2048, file_delete) == NULL) - break; + fclose(file); +} - entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl, - table_name, - line); - if (!entry) { - snprintf(out, out_size, MSG_FILE_ERR, - file_name_delete, line_id); - goto error; - } +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; - status = rte_swx_ctl_pipeline_table_entry_delete(p->ctl, - table_name, - entry); - table_entry_free(entry); - if (status) { - snprintf(out, out_size, - "Invalid entry in file %s at line %u", - file_name_delete, line_id); - goto error; - } - } + /* Buffer allocation. */ + line = malloc(MAX_LINE_SIZE); + if (!line) + return -ENOMEM; - /* Default. */ - if (file_default) - for (line_id = 1; ; line_id++) { - struct rte_swx_table_entry *entry; + /* File read. */ + for (line_id = 1; ; line_id++) { + struct rte_swx_table_entry *entry; + int is_blank_or_comment; - if (fgets(line, 2048, file_default) == NULL) - break; + if (fgets(line, MAX_LINE_SIZE, file) == NULL) + break; - entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl, - table_name, - line); - if (!entry) { - snprintf(out, out_size, MSG_FILE_ERR, - file_name_default, line_id); - goto error; - } + entry = rte_swx_ctl_pipeline_table_entry_read(p, + table_name, + line, + &is_blank_or_comment); + if (!entry) { + if (is_blank_or_comment) + continue; - status = rte_swx_ctl_pipeline_table_default_entry_add(p->ctl, - table_name, - entry); - table_entry_free(entry); - if (status) { - snprintf(out, out_size, - "Invalid entry in file %s at line %u", - file_name_default, line_id); - goto error; - } + status = -EINVAL; + goto error; } - status = rte_swx_ctl_pipeline_commit(p->ctl, 1); - if (status) { - snprintf(out, out_size, "Commit failed."); - goto error; + status = rte_swx_ctl_pipeline_table_default_entry_add(p, + table_name, + entry); + table_entry_free(entry); + if (status) + goto error; } - - rte_swx_ctl_pipeline_table_fprintf(stdout, p->ctl, table_name); - - free(line); - if (file_add) - fclose(file_add); - if (file_delete) - fclose(file_delete); - if (file_default) - fclose(file_default); - return; - error: - rte_swx_ctl_pipeline_abort(p->ctl); + *file_line_number = line_id; free(line); - if (file_add) - fclose(file_add); - if (file_delete) - fclose(file_delete); - if (file_default) - fclose(file_default); + return status; } -static const char cmd_pipeline_stats_help[] = -"pipeline stats\n"; +static const char cmd_pipeline_table_default_help[] = +"pipeline table default \n"; static void -cmd_pipeline_stats(char **tokens, - uint32_t n_tokens, - char *out, - size_t out_size, - void *obj) +cmd_pipeline_table_default(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) { - struct rte_swx_ctl_pipeline_info info; struct pipeline *p; - uint32_t i; + char *pipeline_name, *table_name, *file_name; + FILE *file = NULL; + uint32_t file_line_number = 0; int status; - if (n_tokens != 3) { + if (n_tokens != 6) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } - p = pipeline_find(obj, tokens[1]); + pipeline_name = tokens[1]; + p = pipeline_find(obj, pipeline_name); if (!p || !p->ctl) { 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; - } + table_name = tokens[3]; - status = rte_swx_ctl_pipeline_info_get(p->p, &info); - if (status) { - snprintf(out, out_size, "Pipeline info get error."); + file_name = tokens[5]; + file = fopen(file_name, "r"); + if (!file) { + snprintf(out, out_size, "Cannot open file %s.\n", file_name); return; } - snprintf(out, out_size, "Input ports:\n"); - out_size -= strlen(out); - out += strlen(out); - - for (i = 0; i < info.n_ports_in; i++) { - struct rte_swx_port_in_stats stats; - - rte_swx_ctl_pipeline_port_in_stats_read(p->p, i, &stats); - - snprintf(out, out_size, "\tPort %u:" - " packets %" PRIu64 - " bytes %" PRIu64 - " empty %" PRIu64 "\n", - i, stats.n_pkts, stats.n_bytes, stats.n_empty); - out_size -= strlen(out); - out += strlen(out); - } - - snprintf(out, out_size, "Output ports:\n"); - out_size -= strlen(out); - out += strlen(out); - - for (i = 0; i < info.n_ports_out; i++) { - struct rte_swx_port_out_stats stats; - - rte_swx_ctl_pipeline_port_out_stats_read(p->p, i, &stats); + status = pipeline_table_default_entry_add(p->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); - snprintf(out, out_size, "\tPort %u:" - " packets %" PRIu64 - " bytes %" PRIu64 "\n", - i, stats.n_pkts, stats.n_bytes); - out_size -= strlen(out); - out += strlen(out); - } + fclose(file); } -static const char cmd_thread_pipeline_enable_help[] = -"thread pipeline enable\n"; +static const char cmd_pipeline_table_show_help[] = +"pipeline table show\n"; static void -cmd_thread_pipeline_enable(char **tokens, +cmd_pipeline_table_show(char **tokens, uint32_t n_tokens, char *out, size_t out_size, void *obj) { - char *pipeline_name; struct pipeline *p; - uint32_t thread_id; + char *pipeline_name, *table_name; int status; if (n_tokens != 5) { @@ -1208,26 +1355,1196 @@ cmd_thread_pipeline_enable(char **tokens, 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]; + pipeline_name = tokens[1]; p = pipeline_find(obj, pipeline_name); if (!p || !p->ctl) { 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; + table_name = tokens[3]; + status = rte_swx_ctl_pipeline_table_fprintf(stdout, p->ctl, table_name); + if (status) + snprintf(out, out_size, MSG_ARG_INVALID, "table_name"); +} + +static const char cmd_pipeline_selector_group_add_help[] = +"pipeline selector group add\n"; + +static void +cmd_pipeline_selector_group_add(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct pipeline *p; + 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]; + p = pipeline_find(obj, pipeline_name); + if (!p || !p->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; + } + + status = rte_swx_ctl_pipeline_selector_group_add(p->ctl, + 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 selector group delete \n"; + +static void +cmd_pipeline_selector_group_delete(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct pipeline *p; + 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]; + p = pipeline_find(obj, pipeline_name); + if (!p || !p->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; + } + + status = rte_swx_ctl_pipeline_selector_group_delete(p->ctl, + 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; /* TRUE. */ + + return 0; /* FALSE. */ +} + +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; + + /* Check input arguments. */ + if (!string || !string[0]) + goto error; + + /* Memory allocation. */ + s0 = strdup(string); + if (!s0) + goto error; + + /* Parse the string into tokens. */ + 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; + + /* + * Group ID. + */ + if (parser_read_uint32(&group_id_val, tokens[1]) != 0) + goto error; + *group_id = group_id_val; + + /* + * Member ID. + */ + if (parser_read_uint32(&member_id_val, tokens[3]) != 0) + goto error; + *member_id = member_id_val; + + tokens += 4; + n_tokens -= 4; + + /* + * Weight. + */ + 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; + + /* Buffer allocation. */ + line = malloc(MAX_LINE_SIZE); + if (!line) + return -ENOMEM; + + /* File read. */ + 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; + } + + status = rte_swx_ctl_pipeline_selector_group_member_add(p, + 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 selector group member add "; + +static void +cmd_pipeline_selector_group_member_add(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct pipeline *p; + 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]; + p = pipeline_find(obj, pipeline_name); + if (!p || !p->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(p->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; + + /* Buffer allocation. */ + line = malloc(MAX_LINE_SIZE); + if (!line) + return -ENOMEM; + + /* File read. */ + 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; + } + + status = rte_swx_ctl_pipeline_selector_group_member_delete(p, + 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 selector group member delete "; + +static void +cmd_pipeline_selector_group_member_delete(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct pipeline *p; + 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]; + p = pipeline_find(obj, pipeline_name); + if (!p || !p->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(p->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 selector show\n"; + +static void +cmd_pipeline_selector_show(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct pipeline *p; + char *pipeline_name, *selector_name; + int status; + + if (n_tokens != 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + p = pipeline_find(obj, pipeline_name); + if (!p || !p->ctl) { + snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); + return; + } + + selector_name = tokens[3]; + status = rte_swx_ctl_pipeline_selector_fprintf(stdout, + p->ctl, selector_name); + if (status) + snprintf(out, out_size, MSG_ARG_INVALID, "selector_name"); +} + +static const char cmd_pipeline_commit_help[] = +"pipeline commit\n"; + +static void +cmd_pipeline_commit(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct pipeline *p; + char *pipeline_name; + int status; + + if (n_tokens != 3) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + p = pipeline_find(obj, pipeline_name); + if (!p || !p->ctl) { + snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); + return; + } + + status = rte_swx_ctl_pipeline_commit(p->ctl, 1); + 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 abort\n"; + +static void +cmd_pipeline_abort(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct pipeline *p; + char *pipeline_name; + + if (n_tokens != 3) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + p = pipeline_find(obj, pipeline_name); + if (!p || !p->ctl) { + snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); + return; + } + + rte_swx_ctl_pipeline_abort(p->ctl); +} + +static const char cmd_pipeline_regrd_help[] = +"pipeline regrd \n"; + +static void +cmd_pipeline_regrd(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct pipeline *p; + const char *name; + uint64_t value; + uint32_t idx; + int status; + + if (n_tokens != 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + p = pipeline_find(obj, tokens[1]); + if (!p || !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 (parser_read_uint32(&idx, tokens[4])) { + snprintf(out, out_size, MSG_ARG_INVALID, "index"); + return; + } + + status = rte_swx_ctl_pipeline_regarray_read(p->p, name, idx, &value); + if (status) { + snprintf(out, out_size, "Command failed.\n"); + return; + } + + snprintf(out, out_size, "0x%" PRIx64 "\n", value); +} + +static const char cmd_pipeline_regwr_help[] = +"pipeline regwr \n"; + +static void +cmd_pipeline_regwr(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct pipeline *p; + const char *name; + uint64_t value; + uint32_t idx; + int status; + + if (n_tokens != 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + p = pipeline_find(obj, tokens[1]); + if (!p || !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 (parser_read_uint32(&idx, tokens[4])) { + snprintf(out, out_size, MSG_ARG_INVALID, "index"); + return; + } + + if (parser_read_uint64(&value, tokens[5])) { + snprintf(out, out_size, MSG_ARG_INVALID, "value"); + return; + } + + status = rte_swx_ctl_pipeline_regarray_write(p->p, name, idx, value); + if (status) { + snprintf(out, out_size, "Command failed.\n"); + return; + } +} + +static const char cmd_pipeline_meter_profile_add_help[] = +"pipeline meter profile add " + "cir pir cbs pbs \n"; + +static void +cmd_pipeline_meter_profile_add(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct rte_meter_trtcm_params params; + struct pipeline *p; + const char *profile_name; + int status; + + if (n_tokens != 14) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + p = pipeline_find(obj, tokens[1]); + if (!p || !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; + } + + 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; + } + + status = rte_swx_ctl_meter_profile_add(p->p, profile_name, ¶ms); + if (status) { + snprintf(out, out_size, "Command failed.\n"); + return; + } +} + +static const char cmd_pipeline_meter_profile_delete_help[] = +"pipeline meter profile delete\n"; + +static void +cmd_pipeline_meter_profile_delete(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct pipeline *p; + const char *profile_name; + int status; + + if (n_tokens != 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + p = pipeline_find(obj, tokens[1]); + if (!p || !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; + } + + 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; + } + + status = rte_swx_ctl_meter_profile_delete(p->p, profile_name); + if (status) { + snprintf(out, out_size, "Command failed.\n"); + return; + } +} + +static const char cmd_pipeline_meter_reset_help[] = +"pipeline meter from to " + "reset\n"; + +static void +cmd_pipeline_meter_reset(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct pipeline *p; + const char *name; + uint32_t idx0 = 0, idx1 = 0; + + if (n_tokens != 9) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + p = pipeline_find(obj, tokens[1]); + if (!p || !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], "from")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from"); + return; + } + + if (parser_read_uint32(&idx0, tokens[5])) { + snprintf(out, out_size, MSG_ARG_INVALID, "index0"); + return; + } + + if (strcmp(tokens[6], "to")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to"); + return; + } + + if (parser_read_uint32(&idx1, tokens[7]) || (idx1 < idx0)) { + snprintf(out, out_size, MSG_ARG_INVALID, "index1"); + return; + } + + if (strcmp(tokens[8], "reset")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "reset"); + return; + } + + for ( ; idx0 <= idx1; idx0++) { + int status; + + status = rte_swx_ctl_meter_reset(p->p, name, idx0); + if (status) { + snprintf(out, out_size, "Command failed for index %u.\n", idx0); + return; + } + } +} + +static const char cmd_pipeline_meter_set_help[] = +"pipeline meter from to " + "set profile \n"; + +static void +cmd_pipeline_meter_set(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct pipeline *p; + const char *name, *profile_name; + uint32_t idx0 = 0, idx1 = 0; + + if (n_tokens != 11) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + p = pipeline_find(obj, tokens[1]); + if (!p || !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], "from")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from"); + return; + } + + if (parser_read_uint32(&idx0, tokens[5])) { + snprintf(out, out_size, MSG_ARG_INVALID, "index0"); + return; + } + + if (strcmp(tokens[6], "to")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to"); + return; + } + + if (parser_read_uint32(&idx1, tokens[7]) || (idx1 < idx0)) { + snprintf(out, out_size, MSG_ARG_INVALID, "index1"); + return; + } + + if (strcmp(tokens[8], "set")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "set"); + return; + } + + if (strcmp(tokens[9], "profile")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); + return; + } + + profile_name = tokens[10]; + + for ( ; idx0 <= idx1; idx0++) { + int status; + + status = rte_swx_ctl_meter_set(p->p, name, idx0, profile_name); + if (status) { + snprintf(out, out_size, "Command failed for index %u.\n", idx0); + return; + } + } +} + +static const char cmd_pipeline_meter_stats_help[] = +"pipeline meter from to " + "stats\n"; + +static void +cmd_pipeline_meter_stats(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct rte_swx_ctl_meter_stats stats; + struct pipeline *p; + const char *name; + uint32_t idx0 = 0, idx1 = 0; + + if (n_tokens != 9) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + p = pipeline_find(obj, tokens[1]); + if (!p || !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], "from")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from"); + return; + } + + if (parser_read_uint32(&idx0, tokens[5])) { + snprintf(out, out_size, MSG_ARG_INVALID, "index0"); + return; + } + + if (strcmp(tokens[6], "to")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to"); + return; + } + + if (parser_read_uint32(&idx1, tokens[7]) || (idx1 < idx0)) { + snprintf(out, out_size, MSG_ARG_INVALID, "index1"); + return; + } + + if (strcmp(tokens[8], "stats")) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); + return; + } + + /* Table header. */ + 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); + + /* Table rows. */ + for ( ; idx0 <= idx1; idx0++) { + int status; + + status = rte_swx_ctl_meter_stats_read(p->p, name, idx0, &stats); + if (status) { + snprintf(out, out_size, "Pipeline 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, + stats.n_pkts[RTE_COLOR_GREEN], + stats.n_pkts[RTE_COLOR_YELLOW], + stats.n_pkts[RTE_COLOR_RED], + stats.n_bytes[RTE_COLOR_GREEN], + stats.n_bytes[RTE_COLOR_YELLOW], + stats.n_bytes[RTE_COLOR_RED]); + out_size -= strlen(out); + out += strlen(out); + } +} + +static const char cmd_pipeline_stats_help[] = +"pipeline stats\n"; + +static void +cmd_pipeline_stats(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + struct rte_swx_ctl_pipeline_info info; + struct pipeline *p; + uint32_t i; + int status; + + if (n_tokens != 3) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + p = pipeline_find(obj, tokens[1]); + if (!p || !p->ctl) { + 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; + } + + status = rte_swx_ctl_pipeline_info_get(p->p, &info); + 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); + + for (i = 0; i < info.n_ports_in; i++) { + struct rte_swx_port_in_stats stats; + + rte_swx_ctl_pipeline_port_in_stats_read(p->p, i, &stats); + + snprintf(out, out_size, "\tPort %u:" + " packets %" PRIu64 + " bytes %" PRIu64 + " empty %" PRIu64 "\n", + i, stats.n_pkts, stats.n_bytes, stats.n_empty); + out_size -= strlen(out); + out += strlen(out); + } + + snprintf(out, out_size, "\nOutput ports:\n"); + out_size -= strlen(out); + out += strlen(out); + + for (i = 0; i < info.n_ports_out; i++) { + struct rte_swx_port_out_stats stats; + + rte_swx_ctl_pipeline_port_out_stats_read(p->p, i, &stats); + + snprintf(out, out_size, "\tPort %u:" + " packets %" PRIu64 + " bytes %" PRIu64 "\n", + i, stats.n_pkts, stats.n_bytes); + out_size -= strlen(out); + out += strlen(out); + } + + snprintf(out, out_size, "\nTables:\n"); + out_size -= strlen(out); + out += strlen(out); + + for (i = 0; i < info.n_tables; i++) { + struct rte_swx_ctl_table_info table_info; + uint64_t n_pkts_action[info.n_actions]; + struct rte_swx_table_stats stats = { + .n_pkts_hit = 0, + .n_pkts_miss = 0, + .n_pkts_action = n_pkts_action, + }; + uint32_t j; + + status = rte_swx_ctl_table_info_get(p->p, i, &table_info); + if (status) { + snprintf(out, out_size, "Table info get error."); + return; + } + + status = rte_swx_ctl_pipeline_table_stats_read(p->p, table_info.name, &stats); + 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", + table_info.name, + stats.n_pkts_hit, + stats.n_pkts_miss); + out_size -= strlen(out); + out += strlen(out); + + for (j = 0; j < info.n_actions; j++) { + struct rte_swx_ctl_action_info action_info; + + status = rte_swx_ctl_action_info_get(p->p, j, &action_info); + if (status) { + snprintf(out, out_size, "Action info get error."); + return; + } + + snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n", + action_info.name, + stats.n_pkts_action[j]); + out_size -= strlen(out); + out += strlen(out); + } + } +} + +static const char cmd_thread_pipeline_enable_help[] = +"thread pipeline enable\n"; + +static void +cmd_thread_pipeline_enable(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + void *obj) +{ + char *pipeline_name; + struct pipeline *p; + 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]; + p = pipeline_find(obj, pipeline_name); + if (!p || !p->ctl) { + 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; } status = thread_pipeline_enable(thread_id, obj, pipeline_name); @@ -1303,11 +2620,29 @@ cmd_help(char **tokens, "List of commands:\n" "\tmempool\n" "\tlink\n" + "\ttap\n" "\tpipeline create\n" "\tpipeline port in\n" "\tpipeline port out\n" "\tpipeline build\n" - "\tpipeline table update\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 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" "\tthread pipeline enable\n" "\tthread pipeline disable\n\n"); @@ -1329,6 +2664,11 @@ cmd_help(char **tokens, return; } + if (strcmp(tokens[0], "tap") == 0) { + snprintf(out, out_size, "\n%s\n", cmd_tap_help); + return; + } + if ((strcmp(tokens[0], "pipeline") == 0) && (n_tokens == 2) && (strcmp(tokens[1], "create") == 0)) { snprintf(out, out_size, "\n%s\n", cmd_pipeline_create_help); @@ -1359,9 +2699,152 @@ cmd_help(char **tokens, if ((strcmp(tokens[0], "pipeline") == 0) && (n_tokens == 3) && (strcmp(tokens[1], "table") == 0) && - (strcmp(tokens[2], "update") == 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 == 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_table_update_help); + 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; } @@ -1434,6 +2917,11 @@ cli_process(char *in, char *out, size_t out_size, void *obj) return; } + if (strcmp(tokens[0], "tap") == 0) { + cmd_tap(tokens, n_tokens, out, out_size, obj); + return; + } + if (strcmp(tokens[0], "pipeline") == 0) { if ((n_tokens >= 3) && (strcmp(tokens[2], "create") == 0)) { @@ -1465,13 +2953,147 @@ cli_process(char *in, char *out, size_t out_size, void *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 >= 3) && + (strcmp(tokens[2], "commit") == 0)) { + cmd_pipeline_commit(tokens, n_tokens, out, + out_size, obj); + return; + } + if ((n_tokens >= 3) && - (strcmp(tokens[2], "table") == 0)) { - cmd_pipeline_table_update(tokens, n_tokens, out, + (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") == 0) && + (strcmp(tokens[8], "reset") == 0)) { + cmd_pipeline_meter_reset(tokens, n_tokens, out, out_size, obj); + return; + } + + if ((n_tokens >= 9) && + (strcmp(tokens[2], "meter") == 0) && + (strcmp(tokens[8], "set") == 0)) { + cmd_pipeline_meter_set(tokens, n_tokens, out, out_size, obj); + return; + } + + if ((n_tokens >= 9) && + (strcmp(tokens[2], "meter") == 0) && + (strcmp(tokens[8], "stats") == 0)) { + 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,