15074e1d5SCristian Dumitrescu /* SPDX-License-Identifier: BSD-3-Clause 25074e1d5SCristian Dumitrescu * Copyright(c) 2020 Intel Corporation 35074e1d5SCristian Dumitrescu */ 45074e1d5SCristian Dumitrescu 55074e1d5SCristian Dumitrescu #include <stdio.h> 65074e1d5SCristian Dumitrescu #include <stdint.h> 75074e1d5SCristian Dumitrescu #include <stdlib.h> 85074e1d5SCristian Dumitrescu #include <string.h> 95074e1d5SCristian Dumitrescu 105074e1d5SCristian Dumitrescu #include <rte_common.h> 115074e1d5SCristian Dumitrescu #include <rte_ethdev.h> 125074e1d5SCristian Dumitrescu #include <rte_swx_port_ethdev.h> 135074e1d5SCristian Dumitrescu #include <rte_swx_port_source_sink.h> 145074e1d5SCristian Dumitrescu #include <rte_swx_pipeline.h> 155074e1d5SCristian Dumitrescu #include <rte_swx_ctl.h> 165074e1d5SCristian Dumitrescu 175074e1d5SCristian Dumitrescu #include "cli.h" 185074e1d5SCristian Dumitrescu 195074e1d5SCristian Dumitrescu #include "obj.h" 205074e1d5SCristian Dumitrescu #include "thread.h" 215074e1d5SCristian Dumitrescu 225074e1d5SCristian Dumitrescu #ifndef CMD_MAX_TOKENS 235074e1d5SCristian Dumitrescu #define CMD_MAX_TOKENS 256 245074e1d5SCristian Dumitrescu #endif 255074e1d5SCristian Dumitrescu 265074e1d5SCristian Dumitrescu #define MSG_OUT_OF_MEMORY "Not enough memory.\n" 275074e1d5SCristian Dumitrescu #define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n" 285074e1d5SCristian Dumitrescu #define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n" 295074e1d5SCristian Dumitrescu #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n" 305074e1d5SCristian Dumitrescu #define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n" 315074e1d5SCristian Dumitrescu #define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n" 325074e1d5SCristian Dumitrescu #define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n" 335074e1d5SCristian Dumitrescu #define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n" 345074e1d5SCristian Dumitrescu #define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n" 355074e1d5SCristian Dumitrescu #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n" 365074e1d5SCristian Dumitrescu #define MSG_CMD_FAIL "Command \"%s\" failed.\n" 375074e1d5SCristian Dumitrescu 385074e1d5SCristian Dumitrescu #define skip_white_spaces(pos) \ 395074e1d5SCristian Dumitrescu ({ \ 405074e1d5SCristian Dumitrescu __typeof__(pos) _p = (pos); \ 415074e1d5SCristian Dumitrescu for ( ; isspace(*_p); _p++) \ 425074e1d5SCristian Dumitrescu ; \ 435074e1d5SCristian Dumitrescu _p; \ 445074e1d5SCristian Dumitrescu }) 455074e1d5SCristian Dumitrescu 465074e1d5SCristian Dumitrescu static int 475074e1d5SCristian Dumitrescu parser_read_uint64(uint64_t *value, const char *p) 485074e1d5SCristian Dumitrescu { 495074e1d5SCristian Dumitrescu char *next; 505074e1d5SCristian Dumitrescu uint64_t val; 515074e1d5SCristian Dumitrescu 525074e1d5SCristian Dumitrescu p = skip_white_spaces(p); 535074e1d5SCristian Dumitrescu if (!isdigit(*p)) 545074e1d5SCristian Dumitrescu return -EINVAL; 555074e1d5SCristian Dumitrescu 565074e1d5SCristian Dumitrescu val = strtoul(p, &next, 10); 575074e1d5SCristian Dumitrescu if (p == next) 585074e1d5SCristian Dumitrescu return -EINVAL; 595074e1d5SCristian Dumitrescu 605074e1d5SCristian Dumitrescu p = next; 615074e1d5SCristian Dumitrescu switch (*p) { 625074e1d5SCristian Dumitrescu case 'T': 635074e1d5SCristian Dumitrescu val *= 1024ULL; 645074e1d5SCristian Dumitrescu /* fall through */ 655074e1d5SCristian Dumitrescu case 'G': 665074e1d5SCristian Dumitrescu val *= 1024ULL; 675074e1d5SCristian Dumitrescu /* fall through */ 685074e1d5SCristian Dumitrescu case 'M': 695074e1d5SCristian Dumitrescu val *= 1024ULL; 705074e1d5SCristian Dumitrescu /* fall through */ 715074e1d5SCristian Dumitrescu case 'k': 725074e1d5SCristian Dumitrescu case 'K': 735074e1d5SCristian Dumitrescu val *= 1024ULL; 745074e1d5SCristian Dumitrescu p++; 755074e1d5SCristian Dumitrescu break; 765074e1d5SCristian Dumitrescu } 775074e1d5SCristian Dumitrescu 785074e1d5SCristian Dumitrescu p = skip_white_spaces(p); 795074e1d5SCristian Dumitrescu if (*p != '\0') 805074e1d5SCristian Dumitrescu return -EINVAL; 815074e1d5SCristian Dumitrescu 825074e1d5SCristian Dumitrescu *value = val; 835074e1d5SCristian Dumitrescu return 0; 845074e1d5SCristian Dumitrescu } 855074e1d5SCristian Dumitrescu 865074e1d5SCristian Dumitrescu static int 875074e1d5SCristian Dumitrescu parser_read_uint32(uint32_t *value, const char *p) 885074e1d5SCristian Dumitrescu { 895074e1d5SCristian Dumitrescu uint64_t val = 0; 905074e1d5SCristian Dumitrescu int ret = parser_read_uint64(&val, p); 915074e1d5SCristian Dumitrescu 925074e1d5SCristian Dumitrescu if (ret < 0) 935074e1d5SCristian Dumitrescu return ret; 945074e1d5SCristian Dumitrescu 955074e1d5SCristian Dumitrescu if (val > UINT32_MAX) 965074e1d5SCristian Dumitrescu return -ERANGE; 975074e1d5SCristian Dumitrescu 985074e1d5SCristian Dumitrescu *value = val; 995074e1d5SCristian Dumitrescu return 0; 1005074e1d5SCristian Dumitrescu } 1015074e1d5SCristian Dumitrescu 1025074e1d5SCristian Dumitrescu static int 1035074e1d5SCristian Dumitrescu parser_read_uint16(uint16_t *value, const char *p) 1045074e1d5SCristian Dumitrescu { 1055074e1d5SCristian Dumitrescu uint64_t val = 0; 1065074e1d5SCristian Dumitrescu int ret = parser_read_uint64(&val, p); 1075074e1d5SCristian Dumitrescu 1085074e1d5SCristian Dumitrescu if (ret < 0) 1095074e1d5SCristian Dumitrescu return ret; 1105074e1d5SCristian Dumitrescu 1115074e1d5SCristian Dumitrescu if (val > UINT16_MAX) 1125074e1d5SCristian Dumitrescu return -ERANGE; 1135074e1d5SCristian Dumitrescu 1145074e1d5SCristian Dumitrescu *value = val; 1155074e1d5SCristian Dumitrescu return 0; 1165074e1d5SCristian Dumitrescu } 1175074e1d5SCristian Dumitrescu 1185074e1d5SCristian Dumitrescu #define PARSE_DELIMITER " \f\n\r\t\v" 1195074e1d5SCristian Dumitrescu 1205074e1d5SCristian Dumitrescu static int 1215074e1d5SCristian Dumitrescu parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens) 1225074e1d5SCristian Dumitrescu { 1235074e1d5SCristian Dumitrescu uint32_t i; 1245074e1d5SCristian Dumitrescu 1255074e1d5SCristian Dumitrescu if ((string == NULL) || 1265074e1d5SCristian Dumitrescu (tokens == NULL) || 1275074e1d5SCristian Dumitrescu (*n_tokens < 1)) 1285074e1d5SCristian Dumitrescu return -EINVAL; 1295074e1d5SCristian Dumitrescu 1305074e1d5SCristian Dumitrescu for (i = 0; i < *n_tokens; i++) { 1315074e1d5SCristian Dumitrescu tokens[i] = strtok_r(string, PARSE_DELIMITER, &string); 1325074e1d5SCristian Dumitrescu if (tokens[i] == NULL) 1335074e1d5SCristian Dumitrescu break; 1345074e1d5SCristian Dumitrescu } 1355074e1d5SCristian Dumitrescu 1365074e1d5SCristian Dumitrescu if ((i == *n_tokens) && strtok_r(string, PARSE_DELIMITER, &string)) 1375074e1d5SCristian Dumitrescu return -E2BIG; 1385074e1d5SCristian Dumitrescu 1395074e1d5SCristian Dumitrescu *n_tokens = i; 1405074e1d5SCristian Dumitrescu return 0; 1415074e1d5SCristian Dumitrescu } 1425074e1d5SCristian Dumitrescu 1435074e1d5SCristian Dumitrescu static int 1445074e1d5SCristian Dumitrescu is_comment(char *in) 1455074e1d5SCristian Dumitrescu { 1465074e1d5SCristian Dumitrescu if ((strlen(in) && index("!#%;", in[0])) || 1475074e1d5SCristian Dumitrescu (strncmp(in, "//", 2) == 0) || 1485074e1d5SCristian Dumitrescu (strncmp(in, "--", 2) == 0)) 1495074e1d5SCristian Dumitrescu return 1; 1505074e1d5SCristian Dumitrescu 1515074e1d5SCristian Dumitrescu return 0; 1525074e1d5SCristian Dumitrescu } 1535074e1d5SCristian Dumitrescu 1545074e1d5SCristian Dumitrescu static const char cmd_mempool_help[] = 1555074e1d5SCristian Dumitrescu "mempool <mempool_name>\n" 1565074e1d5SCristian Dumitrescu " buffer <buffer_size>\n" 1575074e1d5SCristian Dumitrescu " pool <pool_size>\n" 1585074e1d5SCristian Dumitrescu " cache <cache_size>\n" 1595074e1d5SCristian Dumitrescu " cpu <cpu_id>\n"; 1605074e1d5SCristian Dumitrescu 1615074e1d5SCristian Dumitrescu static void 1625074e1d5SCristian Dumitrescu cmd_mempool(char **tokens, 1635074e1d5SCristian Dumitrescu uint32_t n_tokens, 1645074e1d5SCristian Dumitrescu char *out, 1655074e1d5SCristian Dumitrescu size_t out_size, 1665074e1d5SCristian Dumitrescu void *obj) 1675074e1d5SCristian Dumitrescu { 1685074e1d5SCristian Dumitrescu struct mempool_params p; 1695074e1d5SCristian Dumitrescu char *name; 1705074e1d5SCristian Dumitrescu struct mempool *mempool; 1715074e1d5SCristian Dumitrescu 1725074e1d5SCristian Dumitrescu if (n_tokens != 10) { 1735074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1745074e1d5SCristian Dumitrescu return; 1755074e1d5SCristian Dumitrescu } 1765074e1d5SCristian Dumitrescu 1775074e1d5SCristian Dumitrescu name = tokens[1]; 1785074e1d5SCristian Dumitrescu 1795074e1d5SCristian Dumitrescu if (strcmp(tokens[2], "buffer") != 0) { 1805074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer"); 1815074e1d5SCristian Dumitrescu return; 1825074e1d5SCristian Dumitrescu } 1835074e1d5SCristian Dumitrescu 1845074e1d5SCristian Dumitrescu if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) { 1855074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size"); 1865074e1d5SCristian Dumitrescu return; 1875074e1d5SCristian Dumitrescu } 1885074e1d5SCristian Dumitrescu 1895074e1d5SCristian Dumitrescu if (strcmp(tokens[4], "pool") != 0) { 1905074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool"); 1915074e1d5SCristian Dumitrescu return; 1925074e1d5SCristian Dumitrescu } 1935074e1d5SCristian Dumitrescu 1945074e1d5SCristian Dumitrescu if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) { 1955074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "pool_size"); 1965074e1d5SCristian Dumitrescu return; 1975074e1d5SCristian Dumitrescu } 1985074e1d5SCristian Dumitrescu 1995074e1d5SCristian Dumitrescu if (strcmp(tokens[6], "cache") != 0) { 2005074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache"); 2015074e1d5SCristian Dumitrescu return; 2025074e1d5SCristian Dumitrescu } 2035074e1d5SCristian Dumitrescu 2045074e1d5SCristian Dumitrescu if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) { 2055074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "cache_size"); 2065074e1d5SCristian Dumitrescu return; 2075074e1d5SCristian Dumitrescu } 2085074e1d5SCristian Dumitrescu 2095074e1d5SCristian Dumitrescu if (strcmp(tokens[8], "cpu") != 0) { 2105074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); 2115074e1d5SCristian Dumitrescu return; 2125074e1d5SCristian Dumitrescu } 2135074e1d5SCristian Dumitrescu 2145074e1d5SCristian Dumitrescu if (parser_read_uint32(&p.cpu_id, tokens[9]) != 0) { 2155074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); 2165074e1d5SCristian Dumitrescu return; 2175074e1d5SCristian Dumitrescu } 2185074e1d5SCristian Dumitrescu 2195074e1d5SCristian Dumitrescu mempool = mempool_create(obj, name, &p); 2205074e1d5SCristian Dumitrescu if (mempool == NULL) { 2215074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2225074e1d5SCristian Dumitrescu return; 2235074e1d5SCristian Dumitrescu } 2245074e1d5SCristian Dumitrescu } 2255074e1d5SCristian Dumitrescu 2265074e1d5SCristian Dumitrescu static const char cmd_link_help[] = 2275074e1d5SCristian Dumitrescu "link <link_name>\n" 2285074e1d5SCristian Dumitrescu " dev <device_name> | port <port_id>\n" 2295074e1d5SCristian Dumitrescu " rxq <n_queues> <queue_size> <mempool_name>\n" 2305074e1d5SCristian Dumitrescu " txq <n_queues> <queue_size>\n" 2315074e1d5SCristian Dumitrescu " promiscuous on | off\n" 2325074e1d5SCristian Dumitrescu " [rss <qid_0> ... <qid_n>]\n"; 2335074e1d5SCristian Dumitrescu 2345074e1d5SCristian Dumitrescu static void 2355074e1d5SCristian Dumitrescu cmd_link(char **tokens, 2365074e1d5SCristian Dumitrescu uint32_t n_tokens, 2375074e1d5SCristian Dumitrescu char *out, 2385074e1d5SCristian Dumitrescu size_t out_size, 2395074e1d5SCristian Dumitrescu void *obj) 2405074e1d5SCristian Dumitrescu { 2415074e1d5SCristian Dumitrescu struct link_params p; 2425074e1d5SCristian Dumitrescu struct link_params_rss rss; 2435074e1d5SCristian Dumitrescu struct link *link; 2445074e1d5SCristian Dumitrescu char *name; 2455074e1d5SCristian Dumitrescu 2465074e1d5SCristian Dumitrescu memset(&p, 0, sizeof(p)); 2475074e1d5SCristian Dumitrescu 2485074e1d5SCristian Dumitrescu if ((n_tokens < 13) || (n_tokens > 14 + LINK_RXQ_RSS_MAX)) { 2495074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2505074e1d5SCristian Dumitrescu return; 2515074e1d5SCristian Dumitrescu } 2525074e1d5SCristian Dumitrescu name = tokens[1]; 2535074e1d5SCristian Dumitrescu 2545074e1d5SCristian Dumitrescu if (strcmp(tokens[2], "dev") == 0) 2555074e1d5SCristian Dumitrescu p.dev_name = tokens[3]; 2565074e1d5SCristian Dumitrescu else if (strcmp(tokens[2], "port") == 0) { 2575074e1d5SCristian Dumitrescu p.dev_name = NULL; 2585074e1d5SCristian Dumitrescu 2595074e1d5SCristian Dumitrescu if (parser_read_uint16(&p.port_id, tokens[3]) != 0) { 2605074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 2615074e1d5SCristian Dumitrescu return; 2625074e1d5SCristian Dumitrescu } 2635074e1d5SCristian Dumitrescu } else { 2645074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port"); 2655074e1d5SCristian Dumitrescu return; 2665074e1d5SCristian Dumitrescu } 2675074e1d5SCristian Dumitrescu 2685074e1d5SCristian Dumitrescu if (strcmp(tokens[4], "rxq") != 0) { 2695074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq"); 2705074e1d5SCristian Dumitrescu return; 2715074e1d5SCristian Dumitrescu } 2725074e1d5SCristian Dumitrescu 2735074e1d5SCristian Dumitrescu if (parser_read_uint32(&p.rx.n_queues, tokens[5]) != 0) { 2745074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "n_queues"); 2755074e1d5SCristian Dumitrescu return; 2765074e1d5SCristian Dumitrescu } 2775074e1d5SCristian Dumitrescu if (parser_read_uint32(&p.rx.queue_size, tokens[6]) != 0) { 2785074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "queue_size"); 2795074e1d5SCristian Dumitrescu return; 2805074e1d5SCristian Dumitrescu } 2815074e1d5SCristian Dumitrescu 2825074e1d5SCristian Dumitrescu p.rx.mempool_name = tokens[7]; 2835074e1d5SCristian Dumitrescu 2845074e1d5SCristian Dumitrescu if (strcmp(tokens[8], "txq") != 0) { 2855074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq"); 2865074e1d5SCristian Dumitrescu return; 2875074e1d5SCristian Dumitrescu } 2885074e1d5SCristian Dumitrescu 2895074e1d5SCristian Dumitrescu if (parser_read_uint32(&p.tx.n_queues, tokens[9]) != 0) { 2905074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "n_queues"); 2915074e1d5SCristian Dumitrescu return; 2925074e1d5SCristian Dumitrescu } 2935074e1d5SCristian Dumitrescu 2945074e1d5SCristian Dumitrescu if (parser_read_uint32(&p.tx.queue_size, tokens[10]) != 0) { 2955074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "queue_size"); 2965074e1d5SCristian Dumitrescu return; 2975074e1d5SCristian Dumitrescu } 2985074e1d5SCristian Dumitrescu 2995074e1d5SCristian Dumitrescu if (strcmp(tokens[11], "promiscuous") != 0) { 3005074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous"); 3015074e1d5SCristian Dumitrescu return; 3025074e1d5SCristian Dumitrescu } 3035074e1d5SCristian Dumitrescu 3045074e1d5SCristian Dumitrescu if (strcmp(tokens[12], "on") == 0) 3055074e1d5SCristian Dumitrescu p.promiscuous = 1; 3065074e1d5SCristian Dumitrescu else if (strcmp(tokens[12], "off") == 0) 3075074e1d5SCristian Dumitrescu p.promiscuous = 0; 3085074e1d5SCristian Dumitrescu else { 3095074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off"); 3105074e1d5SCristian Dumitrescu return; 3115074e1d5SCristian Dumitrescu } 3125074e1d5SCristian Dumitrescu 3135074e1d5SCristian Dumitrescu /* RSS */ 3145074e1d5SCristian Dumitrescu p.rx.rss = NULL; 3155074e1d5SCristian Dumitrescu if (n_tokens > 13) { 3165074e1d5SCristian Dumitrescu uint32_t queue_id, i; 3175074e1d5SCristian Dumitrescu 3185074e1d5SCristian Dumitrescu if (strcmp(tokens[13], "rss") != 0) { 3195074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss"); 3205074e1d5SCristian Dumitrescu return; 3215074e1d5SCristian Dumitrescu } 3225074e1d5SCristian Dumitrescu 3235074e1d5SCristian Dumitrescu p.rx.rss = &rss; 3245074e1d5SCristian Dumitrescu 3255074e1d5SCristian Dumitrescu rss.n_queues = 0; 3265074e1d5SCristian Dumitrescu for (i = 14; i < n_tokens; i++) { 3275074e1d5SCristian Dumitrescu if (parser_read_uint32(&queue_id, tokens[i]) != 0) { 3285074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, 3295074e1d5SCristian Dumitrescu "queue_id"); 3305074e1d5SCristian Dumitrescu return; 3315074e1d5SCristian Dumitrescu } 3325074e1d5SCristian Dumitrescu 3335074e1d5SCristian Dumitrescu rss.queue_id[rss.n_queues] = queue_id; 3345074e1d5SCristian Dumitrescu rss.n_queues++; 3355074e1d5SCristian Dumitrescu } 3365074e1d5SCristian Dumitrescu } 3375074e1d5SCristian Dumitrescu 3385074e1d5SCristian Dumitrescu link = link_create(obj, name, &p); 3395074e1d5SCristian Dumitrescu if (link == NULL) { 3405074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 3415074e1d5SCristian Dumitrescu return; 3425074e1d5SCristian Dumitrescu } 3435074e1d5SCristian Dumitrescu } 3445074e1d5SCristian Dumitrescu 3455074e1d5SCristian Dumitrescu /* Print the link stats and info */ 3465074e1d5SCristian Dumitrescu static void 3475074e1d5SCristian Dumitrescu print_link_info(struct link *link, char *out, size_t out_size) 3485074e1d5SCristian Dumitrescu { 3495074e1d5SCristian Dumitrescu struct rte_eth_stats stats; 3505074e1d5SCristian Dumitrescu struct rte_ether_addr mac_addr; 3515074e1d5SCristian Dumitrescu struct rte_eth_link eth_link; 3525074e1d5SCristian Dumitrescu uint16_t mtu; 3535074e1d5SCristian Dumitrescu int ret; 3545074e1d5SCristian Dumitrescu 3555074e1d5SCristian Dumitrescu memset(&stats, 0, sizeof(stats)); 3565074e1d5SCristian Dumitrescu rte_eth_stats_get(link->port_id, &stats); 3575074e1d5SCristian Dumitrescu 3585074e1d5SCristian Dumitrescu ret = rte_eth_macaddr_get(link->port_id, &mac_addr); 3595074e1d5SCristian Dumitrescu if (ret != 0) { 3605074e1d5SCristian Dumitrescu snprintf(out, out_size, "\n%s: MAC address get failed: %s", 3615074e1d5SCristian Dumitrescu link->name, rte_strerror(-ret)); 3625074e1d5SCristian Dumitrescu return; 3635074e1d5SCristian Dumitrescu } 3645074e1d5SCristian Dumitrescu 3655074e1d5SCristian Dumitrescu ret = rte_eth_link_get(link->port_id, ð_link); 3665074e1d5SCristian Dumitrescu if (ret < 0) { 3675074e1d5SCristian Dumitrescu snprintf(out, out_size, "\n%s: link get failed: %s", 3685074e1d5SCristian Dumitrescu link->name, rte_strerror(-ret)); 3695074e1d5SCristian Dumitrescu return; 3705074e1d5SCristian Dumitrescu } 3715074e1d5SCristian Dumitrescu 3725074e1d5SCristian Dumitrescu rte_eth_dev_get_mtu(link->port_id, &mtu); 3735074e1d5SCristian Dumitrescu 3745074e1d5SCristian Dumitrescu snprintf(out, out_size, 3755074e1d5SCristian Dumitrescu "\n" 3765074e1d5SCristian Dumitrescu "%s: flags=<%s> mtu %u\n" 3775074e1d5SCristian Dumitrescu "\tether %02X:%02X:%02X:%02X:%02X:%02X rxqueues %u txqueues %u\n" 3785074e1d5SCristian Dumitrescu "\tport# %u speed %s\n" 3795074e1d5SCristian Dumitrescu "\tRX packets %" PRIu64" bytes %" PRIu64"\n" 3805074e1d5SCristian Dumitrescu "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n" 3815074e1d5SCristian Dumitrescu "\tTX packets %" PRIu64" bytes %" PRIu64"\n" 3825074e1d5SCristian Dumitrescu "\tTX errors %" PRIu64"\n", 3835074e1d5SCristian Dumitrescu link->name, 3845074e1d5SCristian Dumitrescu eth_link.link_status == 0 ? "DOWN" : "UP", 3855074e1d5SCristian Dumitrescu mtu, 3865074e1d5SCristian Dumitrescu mac_addr.addr_bytes[0], mac_addr.addr_bytes[1], 3875074e1d5SCristian Dumitrescu mac_addr.addr_bytes[2], mac_addr.addr_bytes[3], 3885074e1d5SCristian Dumitrescu mac_addr.addr_bytes[4], mac_addr.addr_bytes[5], 3895074e1d5SCristian Dumitrescu link->n_rxq, 3905074e1d5SCristian Dumitrescu link->n_txq, 3915074e1d5SCristian Dumitrescu link->port_id, 3925074e1d5SCristian Dumitrescu rte_eth_link_speed_to_str(eth_link.link_speed), 3935074e1d5SCristian Dumitrescu stats.ipackets, 3945074e1d5SCristian Dumitrescu stats.ibytes, 3955074e1d5SCristian Dumitrescu stats.ierrors, 3965074e1d5SCristian Dumitrescu stats.imissed, 3975074e1d5SCristian Dumitrescu stats.rx_nombuf, 3985074e1d5SCristian Dumitrescu stats.opackets, 3995074e1d5SCristian Dumitrescu stats.obytes, 4005074e1d5SCristian Dumitrescu stats.oerrors); 4015074e1d5SCristian Dumitrescu } 4025074e1d5SCristian Dumitrescu 4035074e1d5SCristian Dumitrescu /* 4045074e1d5SCristian Dumitrescu * link show [<link_name>] 4055074e1d5SCristian Dumitrescu */ 4065074e1d5SCristian Dumitrescu static void 4075074e1d5SCristian Dumitrescu cmd_link_show(char **tokens, 4085074e1d5SCristian Dumitrescu uint32_t n_tokens, 4095074e1d5SCristian Dumitrescu char *out, 4105074e1d5SCristian Dumitrescu size_t out_size, 4115074e1d5SCristian Dumitrescu void *obj) 4125074e1d5SCristian Dumitrescu { 4135074e1d5SCristian Dumitrescu struct link *link; 4145074e1d5SCristian Dumitrescu char *link_name; 4155074e1d5SCristian Dumitrescu 4165074e1d5SCristian Dumitrescu if (n_tokens != 2 && n_tokens != 3) { 4175074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4185074e1d5SCristian Dumitrescu return; 4195074e1d5SCristian Dumitrescu } 4205074e1d5SCristian Dumitrescu 4215074e1d5SCristian Dumitrescu if (n_tokens == 2) { 4225074e1d5SCristian Dumitrescu link = link_next(obj, NULL); 4235074e1d5SCristian Dumitrescu 4245074e1d5SCristian Dumitrescu while (link != NULL) { 4255074e1d5SCristian Dumitrescu out_size = out_size - strlen(out); 4265074e1d5SCristian Dumitrescu out = &out[strlen(out)]; 4275074e1d5SCristian Dumitrescu 4285074e1d5SCristian Dumitrescu print_link_info(link, out, out_size); 4295074e1d5SCristian Dumitrescu link = link_next(obj, link); 4305074e1d5SCristian Dumitrescu } 4315074e1d5SCristian Dumitrescu } else { 4325074e1d5SCristian Dumitrescu out_size = out_size - strlen(out); 4335074e1d5SCristian Dumitrescu out = &out[strlen(out)]; 4345074e1d5SCristian Dumitrescu 4355074e1d5SCristian Dumitrescu link_name = tokens[2]; 4365074e1d5SCristian Dumitrescu link = link_find(obj, link_name); 4375074e1d5SCristian Dumitrescu 4385074e1d5SCristian Dumitrescu if (link == NULL) { 4395074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, 4405074e1d5SCristian Dumitrescu "Link does not exist"); 4415074e1d5SCristian Dumitrescu return; 4425074e1d5SCristian Dumitrescu } 4435074e1d5SCristian Dumitrescu print_link_info(link, out, out_size); 4445074e1d5SCristian Dumitrescu } 4455074e1d5SCristian Dumitrescu } 4465074e1d5SCristian Dumitrescu 4475074e1d5SCristian Dumitrescu static const char cmd_pipeline_create_help[] = 4485074e1d5SCristian Dumitrescu "pipeline <pipeline_name> create <numa_node>\n"; 4495074e1d5SCristian Dumitrescu 4505074e1d5SCristian Dumitrescu static void 4515074e1d5SCristian Dumitrescu cmd_pipeline_create(char **tokens, 4525074e1d5SCristian Dumitrescu uint32_t n_tokens, 4535074e1d5SCristian Dumitrescu char *out, 4545074e1d5SCristian Dumitrescu size_t out_size, 4555074e1d5SCristian Dumitrescu void *obj) 4565074e1d5SCristian Dumitrescu { 4575074e1d5SCristian Dumitrescu struct pipeline *p; 4585074e1d5SCristian Dumitrescu char *name; 4595074e1d5SCristian Dumitrescu uint32_t numa_node; 4605074e1d5SCristian Dumitrescu 4615074e1d5SCristian Dumitrescu if (n_tokens != 4) { 4625074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4635074e1d5SCristian Dumitrescu return; 4645074e1d5SCristian Dumitrescu } 4655074e1d5SCristian Dumitrescu 4665074e1d5SCristian Dumitrescu name = tokens[1]; 4675074e1d5SCristian Dumitrescu 4685074e1d5SCristian Dumitrescu if (parser_read_uint32(&numa_node, tokens[3]) != 0) { 4695074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "numa_node"); 4705074e1d5SCristian Dumitrescu return; 4715074e1d5SCristian Dumitrescu } 4725074e1d5SCristian Dumitrescu 4735074e1d5SCristian Dumitrescu p = pipeline_create(obj, name, (int)numa_node); 4745074e1d5SCristian Dumitrescu if (!p) { 4755074e1d5SCristian Dumitrescu snprintf(out, out_size, "pipeline create error."); 4765074e1d5SCristian Dumitrescu return; 4775074e1d5SCristian Dumitrescu } 4785074e1d5SCristian Dumitrescu } 4795074e1d5SCristian Dumitrescu 4805074e1d5SCristian Dumitrescu static const char cmd_pipeline_port_in_help[] = 4815074e1d5SCristian Dumitrescu "pipeline <pipeline_name> port in <port_id>\n" 4825074e1d5SCristian Dumitrescu " link <link_name> rxq <queue_id> bsz <burst_size>\n" 4837fef9ef1SYogesh Jangra " | source <mempool_name> <file_name>\n"; 4845074e1d5SCristian Dumitrescu 4855074e1d5SCristian Dumitrescu static void 4865074e1d5SCristian Dumitrescu cmd_pipeline_port_in(char **tokens, 4875074e1d5SCristian Dumitrescu uint32_t n_tokens, 4885074e1d5SCristian Dumitrescu char *out, 4895074e1d5SCristian Dumitrescu size_t out_size, 4905074e1d5SCristian Dumitrescu void *obj) 4915074e1d5SCristian Dumitrescu { 4925074e1d5SCristian Dumitrescu struct pipeline *p; 4935074e1d5SCristian Dumitrescu int status; 4945074e1d5SCristian Dumitrescu uint32_t port_id = 0, t0; 4955074e1d5SCristian Dumitrescu 4965074e1d5SCristian Dumitrescu if (n_tokens < 6) { 4975074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 4985074e1d5SCristian Dumitrescu return; 4995074e1d5SCristian Dumitrescu } 5005074e1d5SCristian Dumitrescu 5015074e1d5SCristian Dumitrescu p = pipeline_find(obj, tokens[1]); 5025074e1d5SCristian Dumitrescu if (!p || p->ctl) { 5035074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 5045074e1d5SCristian Dumitrescu return; 5055074e1d5SCristian Dumitrescu } 5065074e1d5SCristian Dumitrescu 5075074e1d5SCristian Dumitrescu if (strcmp(tokens[2], "port") != 0) { 5085074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 5095074e1d5SCristian Dumitrescu return; 5105074e1d5SCristian Dumitrescu } 5115074e1d5SCristian Dumitrescu 5125074e1d5SCristian Dumitrescu if (strcmp(tokens[3], "in") != 0) { 5135074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 5145074e1d5SCristian Dumitrescu return; 5155074e1d5SCristian Dumitrescu } 5165074e1d5SCristian Dumitrescu 5175074e1d5SCristian Dumitrescu if (parser_read_uint32(&port_id, tokens[4]) != 0) { 5185074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 5195074e1d5SCristian Dumitrescu return; 5205074e1d5SCristian Dumitrescu } 5215074e1d5SCristian Dumitrescu 5225074e1d5SCristian Dumitrescu t0 = 5; 5235074e1d5SCristian Dumitrescu 5245074e1d5SCristian Dumitrescu if (strcmp(tokens[t0], "link") == 0) { 5255074e1d5SCristian Dumitrescu struct rte_swx_port_ethdev_reader_params params; 5265074e1d5SCristian Dumitrescu struct link *link; 5275074e1d5SCristian Dumitrescu 5285074e1d5SCristian Dumitrescu if (n_tokens < t0 + 6) { 5295074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, 5305074e1d5SCristian Dumitrescu "pipeline port in link"); 5315074e1d5SCristian Dumitrescu return; 5325074e1d5SCristian Dumitrescu } 5335074e1d5SCristian Dumitrescu 5345074e1d5SCristian Dumitrescu link = link_find(obj, tokens[t0 + 1]); 5355074e1d5SCristian Dumitrescu if (!link) { 5365074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, 5375074e1d5SCristian Dumitrescu "link_name"); 5385074e1d5SCristian Dumitrescu return; 5395074e1d5SCristian Dumitrescu } 5405074e1d5SCristian Dumitrescu params.dev_name = link->dev_name; 5415074e1d5SCristian Dumitrescu 5425074e1d5SCristian Dumitrescu if (strcmp(tokens[t0 + 2], "rxq") != 0) { 5435074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq"); 5445074e1d5SCristian Dumitrescu return; 5455074e1d5SCristian Dumitrescu } 5465074e1d5SCristian Dumitrescu 5475074e1d5SCristian Dumitrescu if (parser_read_uint16(¶ms.queue_id, tokens[t0 + 3]) != 0) { 5485074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, 5495074e1d5SCristian Dumitrescu "queue_id"); 5505074e1d5SCristian Dumitrescu return; 5515074e1d5SCristian Dumitrescu } 5525074e1d5SCristian Dumitrescu 5535074e1d5SCristian Dumitrescu if (strcmp(tokens[t0 + 4], "bsz") != 0) { 5545074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); 5555074e1d5SCristian Dumitrescu return; 5565074e1d5SCristian Dumitrescu } 5575074e1d5SCristian Dumitrescu 5585074e1d5SCristian Dumitrescu if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 5])) { 5595074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, 5605074e1d5SCristian Dumitrescu "burst_size"); 5615074e1d5SCristian Dumitrescu return; 5625074e1d5SCristian Dumitrescu } 5635074e1d5SCristian Dumitrescu 5645074e1d5SCristian Dumitrescu t0 += 6; 5655074e1d5SCristian Dumitrescu 5665074e1d5SCristian Dumitrescu status = rte_swx_pipeline_port_in_config(p->p, 5675074e1d5SCristian Dumitrescu port_id, 5685074e1d5SCristian Dumitrescu "ethdev", 5695074e1d5SCristian Dumitrescu ¶ms); 5705074e1d5SCristian Dumitrescu } else if (strcmp(tokens[t0], "source") == 0) { 5715074e1d5SCristian Dumitrescu struct rte_swx_port_source_params params; 5725074e1d5SCristian Dumitrescu struct mempool *mp; 5735074e1d5SCristian Dumitrescu 5745074e1d5SCristian Dumitrescu if (n_tokens < t0 + 3) { 5755074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, 5765074e1d5SCristian Dumitrescu "pipeline port in source"); 5775074e1d5SCristian Dumitrescu return; 5785074e1d5SCristian Dumitrescu } 5795074e1d5SCristian Dumitrescu 5805074e1d5SCristian Dumitrescu mp = mempool_find(obj, tokens[t0 + 1]); 5815074e1d5SCristian Dumitrescu if (!mp) { 5825074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, 5835074e1d5SCristian Dumitrescu "mempool_name"); 5845074e1d5SCristian Dumitrescu return; 5855074e1d5SCristian Dumitrescu } 5865074e1d5SCristian Dumitrescu params.pool = mp->m; 5875074e1d5SCristian Dumitrescu 5885074e1d5SCristian Dumitrescu params.file_name = tokens[t0 + 2]; 5895074e1d5SCristian Dumitrescu 5905074e1d5SCristian Dumitrescu t0 += 3; 5915074e1d5SCristian Dumitrescu 5925074e1d5SCristian Dumitrescu status = rte_swx_pipeline_port_in_config(p->p, 5935074e1d5SCristian Dumitrescu port_id, 5945074e1d5SCristian Dumitrescu "source", 5955074e1d5SCristian Dumitrescu ¶ms); 5965074e1d5SCristian Dumitrescu } else { 5975074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 5985074e1d5SCristian Dumitrescu return; 5995074e1d5SCristian Dumitrescu } 6005074e1d5SCristian Dumitrescu 6015074e1d5SCristian Dumitrescu if (status) { 6025074e1d5SCristian Dumitrescu snprintf(out, out_size, "port in error."); 6035074e1d5SCristian Dumitrescu return; 6045074e1d5SCristian Dumitrescu } 6055074e1d5SCristian Dumitrescu 6065074e1d5SCristian Dumitrescu if (n_tokens != t0) { 6075074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 6085074e1d5SCristian Dumitrescu return; 6095074e1d5SCristian Dumitrescu } 6105074e1d5SCristian Dumitrescu } 6115074e1d5SCristian Dumitrescu 6125074e1d5SCristian Dumitrescu static const char cmd_pipeline_port_out_help[] = 6135074e1d5SCristian Dumitrescu "pipeline <pipeline_name> port out <port_id>\n" 6145074e1d5SCristian Dumitrescu " link <link_name> txq <txq_id> bsz <burst_size>\n" 6155074e1d5SCristian Dumitrescu " | sink <file_name> | none\n"; 6165074e1d5SCristian Dumitrescu 6175074e1d5SCristian Dumitrescu static void 6185074e1d5SCristian Dumitrescu cmd_pipeline_port_out(char **tokens, 6195074e1d5SCristian Dumitrescu uint32_t n_tokens, 6205074e1d5SCristian Dumitrescu char *out, 6215074e1d5SCristian Dumitrescu size_t out_size, 6225074e1d5SCristian Dumitrescu void *obj) 6235074e1d5SCristian Dumitrescu { 6245074e1d5SCristian Dumitrescu struct pipeline *p; 6255074e1d5SCristian Dumitrescu int status; 6265074e1d5SCristian Dumitrescu uint32_t port_id = 0, t0; 6275074e1d5SCristian Dumitrescu 6285074e1d5SCristian Dumitrescu if (n_tokens < 6) { 6295074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 6305074e1d5SCristian Dumitrescu return; 6315074e1d5SCristian Dumitrescu } 6325074e1d5SCristian Dumitrescu 6335074e1d5SCristian Dumitrescu p = pipeline_find(obj, tokens[1]); 6345074e1d5SCristian Dumitrescu if (!p || p->ctl) { 6355074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 6365074e1d5SCristian Dumitrescu return; 6375074e1d5SCristian Dumitrescu } 6385074e1d5SCristian Dumitrescu 6395074e1d5SCristian Dumitrescu if (strcmp(tokens[2], "port") != 0) { 6405074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 6415074e1d5SCristian Dumitrescu return; 6425074e1d5SCristian Dumitrescu } 6435074e1d5SCristian Dumitrescu 6445074e1d5SCristian Dumitrescu if (strcmp(tokens[3], "out") != 0) { 6455074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out"); 6465074e1d5SCristian Dumitrescu return; 6475074e1d5SCristian Dumitrescu } 6485074e1d5SCristian Dumitrescu 6495074e1d5SCristian Dumitrescu if (parser_read_uint32(&port_id, tokens[4]) != 0) { 6505074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 6515074e1d5SCristian Dumitrescu return; 6525074e1d5SCristian Dumitrescu } 6535074e1d5SCristian Dumitrescu 6545074e1d5SCristian Dumitrescu t0 = 5; 6555074e1d5SCristian Dumitrescu 6565074e1d5SCristian Dumitrescu if (strcmp(tokens[t0], "link") == 0) { 6575074e1d5SCristian Dumitrescu struct rte_swx_port_ethdev_writer_params params; 6585074e1d5SCristian Dumitrescu struct link *link; 6595074e1d5SCristian Dumitrescu 6605074e1d5SCristian Dumitrescu if (n_tokens < t0 + 6) { 6615074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, 6625074e1d5SCristian Dumitrescu "pipeline port out link"); 6635074e1d5SCristian Dumitrescu return; 6645074e1d5SCristian Dumitrescu } 6655074e1d5SCristian Dumitrescu 6665074e1d5SCristian Dumitrescu link = link_find(obj, tokens[t0 + 1]); 6675074e1d5SCristian Dumitrescu if (!link) { 6685074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, 6695074e1d5SCristian Dumitrescu "link_name"); 6705074e1d5SCristian Dumitrescu return; 6715074e1d5SCristian Dumitrescu } 6725074e1d5SCristian Dumitrescu params.dev_name = link->dev_name; 6735074e1d5SCristian Dumitrescu 6745074e1d5SCristian Dumitrescu if (strcmp(tokens[t0 + 2], "txq") != 0) { 6755074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq"); 6765074e1d5SCristian Dumitrescu return; 6775074e1d5SCristian Dumitrescu } 6785074e1d5SCristian Dumitrescu 6795074e1d5SCristian Dumitrescu if (parser_read_uint16(¶ms.queue_id, tokens[t0 + 3]) != 0) { 6805074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, 6815074e1d5SCristian Dumitrescu "queue_id"); 6825074e1d5SCristian Dumitrescu return; 6835074e1d5SCristian Dumitrescu } 6845074e1d5SCristian Dumitrescu 6855074e1d5SCristian Dumitrescu if (strcmp(tokens[t0 + 4], "bsz") != 0) { 6865074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); 6875074e1d5SCristian Dumitrescu return; 6885074e1d5SCristian Dumitrescu } 6895074e1d5SCristian Dumitrescu 6905074e1d5SCristian Dumitrescu if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 5])) { 6915074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, 6925074e1d5SCristian Dumitrescu "burst_size"); 6935074e1d5SCristian Dumitrescu return; 6945074e1d5SCristian Dumitrescu } 6955074e1d5SCristian Dumitrescu 6965074e1d5SCristian Dumitrescu t0 += 6; 6975074e1d5SCristian Dumitrescu 6985074e1d5SCristian Dumitrescu status = rte_swx_pipeline_port_out_config(p->p, 6995074e1d5SCristian Dumitrescu port_id, 7005074e1d5SCristian Dumitrescu "ethdev", 7015074e1d5SCristian Dumitrescu ¶ms); 7025074e1d5SCristian Dumitrescu } else if (strcmp(tokens[t0], "sink") == 0) { 7035074e1d5SCristian Dumitrescu struct rte_swx_port_sink_params params; 7045074e1d5SCristian Dumitrescu 7055074e1d5SCristian Dumitrescu params.file_name = strcmp(tokens[t0 + 1], "none") ? 7065074e1d5SCristian Dumitrescu tokens[t0 + 1] : NULL; 7075074e1d5SCristian Dumitrescu 7085074e1d5SCristian Dumitrescu t0 += 2; 7095074e1d5SCristian Dumitrescu 7105074e1d5SCristian Dumitrescu status = rte_swx_pipeline_port_out_config(p->p, 7115074e1d5SCristian Dumitrescu port_id, 7125074e1d5SCristian Dumitrescu "sink", 7135074e1d5SCristian Dumitrescu ¶ms); 7145074e1d5SCristian Dumitrescu } else { 7155074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 7165074e1d5SCristian Dumitrescu return; 7175074e1d5SCristian Dumitrescu } 7185074e1d5SCristian Dumitrescu 7195074e1d5SCristian Dumitrescu if (status) { 7205074e1d5SCristian Dumitrescu snprintf(out, out_size, "port out error."); 7215074e1d5SCristian Dumitrescu return; 7225074e1d5SCristian Dumitrescu } 7235074e1d5SCristian Dumitrescu 7245074e1d5SCristian Dumitrescu if (n_tokens != t0) { 7255074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 7265074e1d5SCristian Dumitrescu return; 7275074e1d5SCristian Dumitrescu } 7285074e1d5SCristian Dumitrescu } 7295074e1d5SCristian Dumitrescu 7305074e1d5SCristian Dumitrescu static const char cmd_pipeline_build_help[] = 7315074e1d5SCristian Dumitrescu "pipeline <pipeline_name> build <spec_file>\n"; 7325074e1d5SCristian Dumitrescu 7335074e1d5SCristian Dumitrescu static void 7345074e1d5SCristian Dumitrescu cmd_pipeline_build(char **tokens, 7355074e1d5SCristian Dumitrescu uint32_t n_tokens, 7365074e1d5SCristian Dumitrescu char *out, 7375074e1d5SCristian Dumitrescu size_t out_size, 7385074e1d5SCristian Dumitrescu void *obj) 7395074e1d5SCristian Dumitrescu { 7405074e1d5SCristian Dumitrescu struct pipeline *p = NULL; 7415074e1d5SCristian Dumitrescu FILE *spec = NULL; 7425074e1d5SCristian Dumitrescu uint32_t err_line; 7435074e1d5SCristian Dumitrescu const char *err_msg; 7445074e1d5SCristian Dumitrescu int status; 7455074e1d5SCristian Dumitrescu 7465074e1d5SCristian Dumitrescu if (n_tokens != 4) { 7475074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 7485074e1d5SCristian Dumitrescu return; 7495074e1d5SCristian Dumitrescu } 7505074e1d5SCristian Dumitrescu 7515074e1d5SCristian Dumitrescu p = pipeline_find(obj, tokens[1]); 7525074e1d5SCristian Dumitrescu if (!p || p->ctl) { 7535074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 7545074e1d5SCristian Dumitrescu return; 7555074e1d5SCristian Dumitrescu } 7565074e1d5SCristian Dumitrescu 7575074e1d5SCristian Dumitrescu spec = fopen(tokens[3], "r"); 7585074e1d5SCristian Dumitrescu if (!spec) { 7595074e1d5SCristian Dumitrescu snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]); 7605074e1d5SCristian Dumitrescu return; 7615074e1d5SCristian Dumitrescu } 7625074e1d5SCristian Dumitrescu 7635074e1d5SCristian Dumitrescu status = rte_swx_pipeline_build_from_spec(p->p, 7645074e1d5SCristian Dumitrescu spec, 7655074e1d5SCristian Dumitrescu &err_line, 7665074e1d5SCristian Dumitrescu &err_msg); 7675074e1d5SCristian Dumitrescu fclose(spec); 7685074e1d5SCristian Dumitrescu if (status) { 7695074e1d5SCristian Dumitrescu snprintf(out, out_size, "Error %d at line %u: %s\n.", 7705074e1d5SCristian Dumitrescu status, err_line, err_msg); 7715074e1d5SCristian Dumitrescu return; 7725074e1d5SCristian Dumitrescu } 7735074e1d5SCristian Dumitrescu 7745074e1d5SCristian Dumitrescu p->ctl = rte_swx_ctl_pipeline_create(p->p); 7755074e1d5SCristian Dumitrescu if (!p->ctl) { 7765074e1d5SCristian Dumitrescu snprintf(out, out_size, "Pipeline control create failed."); 7775074e1d5SCristian Dumitrescu rte_swx_pipeline_free(p->p); 7785074e1d5SCristian Dumitrescu return; 7795074e1d5SCristian Dumitrescu } 7805074e1d5SCristian Dumitrescu } 7815074e1d5SCristian Dumitrescu 782275ebefeSCristian Dumitrescu static void 783275ebefeSCristian Dumitrescu table_entry_free(struct rte_swx_table_entry *entry) 784275ebefeSCristian Dumitrescu { 785275ebefeSCristian Dumitrescu if (!entry) 786275ebefeSCristian Dumitrescu return; 787275ebefeSCristian Dumitrescu 788275ebefeSCristian Dumitrescu free(entry->key); 789275ebefeSCristian Dumitrescu free(entry->key_mask); 790275ebefeSCristian Dumitrescu free(entry->action_data); 791275ebefeSCristian Dumitrescu free(entry); 792275ebefeSCristian Dumitrescu } 793275ebefeSCristian Dumitrescu 7945074e1d5SCristian Dumitrescu static const char cmd_pipeline_table_update_help[] = 7955074e1d5SCristian Dumitrescu "pipeline <pipeline_name> table <table_name> update <file_name_add> " 7965074e1d5SCristian Dumitrescu "<file_name_delete> <file_name_default>"; 7975074e1d5SCristian Dumitrescu 7985074e1d5SCristian Dumitrescu static void 7995074e1d5SCristian Dumitrescu cmd_pipeline_table_update(char **tokens, 8005074e1d5SCristian Dumitrescu uint32_t n_tokens, 8015074e1d5SCristian Dumitrescu char *out, 8025074e1d5SCristian Dumitrescu size_t out_size, 8035074e1d5SCristian Dumitrescu void *obj) 8045074e1d5SCristian Dumitrescu { 8055074e1d5SCristian Dumitrescu struct pipeline *p; 8065074e1d5SCristian Dumitrescu char *pipeline_name, *table_name, *line = NULL; 8075074e1d5SCristian Dumitrescu char *file_name_add, *file_name_delete, *file_name_default; 8085074e1d5SCristian Dumitrescu FILE *file_add = NULL, *file_delete = NULL, *file_default = NULL; 8095074e1d5SCristian Dumitrescu uint32_t line_id; 8105074e1d5SCristian Dumitrescu int status; 8115074e1d5SCristian Dumitrescu 8125074e1d5SCristian Dumitrescu if (n_tokens != 8) { 8135074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 8145074e1d5SCristian Dumitrescu return; 8155074e1d5SCristian Dumitrescu } 8165074e1d5SCristian Dumitrescu 8175074e1d5SCristian Dumitrescu pipeline_name = tokens[1]; 8185074e1d5SCristian Dumitrescu p = pipeline_find(obj, pipeline_name); 8195074e1d5SCristian Dumitrescu if (!p || !p->ctl) { 8205074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 8215074e1d5SCristian Dumitrescu return; 8225074e1d5SCristian Dumitrescu } 8235074e1d5SCristian Dumitrescu 8245074e1d5SCristian Dumitrescu if (strcmp(tokens[2], "table") != 0) { 8255074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 8265074e1d5SCristian Dumitrescu return; 8275074e1d5SCristian Dumitrescu } 8285074e1d5SCristian Dumitrescu 8295074e1d5SCristian Dumitrescu table_name = tokens[3]; 8305074e1d5SCristian Dumitrescu 8315074e1d5SCristian Dumitrescu if (strcmp(tokens[4], "update") != 0) { 8325074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "update"); 8335074e1d5SCristian Dumitrescu return; 8345074e1d5SCristian Dumitrescu } 8355074e1d5SCristian Dumitrescu 8365074e1d5SCristian Dumitrescu file_name_add = tokens[5]; 8375074e1d5SCristian Dumitrescu file_name_delete = tokens[6]; 8385074e1d5SCristian Dumitrescu file_name_default = tokens[7]; 8395074e1d5SCristian Dumitrescu 8405074e1d5SCristian Dumitrescu /* File open. */ 8415074e1d5SCristian Dumitrescu if (strcmp(file_name_add, "none")) { 8425074e1d5SCristian Dumitrescu file_add = fopen(file_name_add, "r"); 8435074e1d5SCristian Dumitrescu if (!file_add) { 8445074e1d5SCristian Dumitrescu snprintf(out, out_size, "Cannot open file %s", 8455074e1d5SCristian Dumitrescu file_name_add); 8465074e1d5SCristian Dumitrescu goto error; 8475074e1d5SCristian Dumitrescu } 8485074e1d5SCristian Dumitrescu } 8495074e1d5SCristian Dumitrescu 8505074e1d5SCristian Dumitrescu if (strcmp(file_name_delete, "none")) { 85164eaee23SCristian Dumitrescu file_delete = fopen(file_name_delete, "r"); 85264eaee23SCristian Dumitrescu if (!file_delete) { 8535074e1d5SCristian Dumitrescu snprintf(out, out_size, "Cannot open file %s", 8545074e1d5SCristian Dumitrescu file_name_delete); 8555074e1d5SCristian Dumitrescu goto error; 8565074e1d5SCristian Dumitrescu } 8575074e1d5SCristian Dumitrescu } 8585074e1d5SCristian Dumitrescu 8595074e1d5SCristian Dumitrescu if (strcmp(file_name_default, "none")) { 86064eaee23SCristian Dumitrescu file_default = fopen(file_name_default, "r"); 86164eaee23SCristian Dumitrescu if (!file_default) { 8625074e1d5SCristian Dumitrescu snprintf(out, out_size, "Cannot open file %s", 8635074e1d5SCristian Dumitrescu file_name_default); 8645074e1d5SCristian Dumitrescu goto error; 8655074e1d5SCristian Dumitrescu } 8665074e1d5SCristian Dumitrescu } 8675074e1d5SCristian Dumitrescu 8685074e1d5SCristian Dumitrescu if (!file_add && !file_delete && !file_default) { 8695074e1d5SCristian Dumitrescu snprintf(out, out_size, "Nothing to be done."); 8705074e1d5SCristian Dumitrescu return; 8715074e1d5SCristian Dumitrescu } 8725074e1d5SCristian Dumitrescu 8735074e1d5SCristian Dumitrescu /* Buffer allocation. */ 8745074e1d5SCristian Dumitrescu line = malloc(2048); 8755074e1d5SCristian Dumitrescu if (!line) { 8765074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_OUT_OF_MEMORY); 8775074e1d5SCristian Dumitrescu goto error; 8785074e1d5SCristian Dumitrescu } 8795074e1d5SCristian Dumitrescu 8805074e1d5SCristian Dumitrescu /* Add. */ 88103665a48SCristian Dumitrescu if (file_add) 8825074e1d5SCristian Dumitrescu for (line_id = 1; ; line_id++) { 8835074e1d5SCristian Dumitrescu struct rte_swx_table_entry *entry; 8845074e1d5SCristian Dumitrescu 8855074e1d5SCristian Dumitrescu if (fgets(line, 2048, file_add) == NULL) 8865074e1d5SCristian Dumitrescu break; 8875074e1d5SCristian Dumitrescu 8885074e1d5SCristian Dumitrescu entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl, 8895074e1d5SCristian Dumitrescu table_name, 8905074e1d5SCristian Dumitrescu line); 8915074e1d5SCristian Dumitrescu if (!entry) { 8925074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_FILE_ERR, 8935074e1d5SCristian Dumitrescu file_name_add, line_id); 8945074e1d5SCristian Dumitrescu goto error; 8955074e1d5SCristian Dumitrescu } 8965074e1d5SCristian Dumitrescu 8975074e1d5SCristian Dumitrescu status = rte_swx_ctl_pipeline_table_entry_add(p->ctl, 8985074e1d5SCristian Dumitrescu table_name, 8995074e1d5SCristian Dumitrescu entry); 900275ebefeSCristian Dumitrescu table_entry_free(entry); 9015074e1d5SCristian Dumitrescu if (status) { 9025074e1d5SCristian Dumitrescu snprintf(out, out_size, 9035074e1d5SCristian Dumitrescu "Invalid entry in file %s at line %u", 9045074e1d5SCristian Dumitrescu file_name_add, line_id); 9055074e1d5SCristian Dumitrescu goto error; 9065074e1d5SCristian Dumitrescu } 9075074e1d5SCristian Dumitrescu } 9085074e1d5SCristian Dumitrescu 9095074e1d5SCristian Dumitrescu 9105074e1d5SCristian Dumitrescu /* Delete. */ 91103665a48SCristian Dumitrescu if (file_delete) 9125074e1d5SCristian Dumitrescu for (line_id = 1; ; line_id++) { 9135074e1d5SCristian Dumitrescu struct rte_swx_table_entry *entry; 9145074e1d5SCristian Dumitrescu 9155074e1d5SCristian Dumitrescu if (fgets(line, 2048, file_delete) == NULL) 9165074e1d5SCristian Dumitrescu break; 9175074e1d5SCristian Dumitrescu 9185074e1d5SCristian Dumitrescu entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl, 9195074e1d5SCristian Dumitrescu table_name, 9205074e1d5SCristian Dumitrescu line); 9215074e1d5SCristian Dumitrescu if (!entry) { 9225074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_FILE_ERR, 9235074e1d5SCristian Dumitrescu file_name_delete, line_id); 9245074e1d5SCristian Dumitrescu goto error; 9255074e1d5SCristian Dumitrescu } 9265074e1d5SCristian Dumitrescu 9275074e1d5SCristian Dumitrescu status = rte_swx_ctl_pipeline_table_entry_delete(p->ctl, 9285074e1d5SCristian Dumitrescu table_name, 9295074e1d5SCristian Dumitrescu entry); 930275ebefeSCristian Dumitrescu table_entry_free(entry); 9315074e1d5SCristian Dumitrescu if (status) { 9325074e1d5SCristian Dumitrescu snprintf(out, out_size, 9335074e1d5SCristian Dumitrescu "Invalid entry in file %s at line %u", 9345074e1d5SCristian Dumitrescu file_name_delete, line_id); 9355074e1d5SCristian Dumitrescu goto error; 9365074e1d5SCristian Dumitrescu } 9375074e1d5SCristian Dumitrescu } 9385074e1d5SCristian Dumitrescu 9395074e1d5SCristian Dumitrescu /* Default. */ 94003665a48SCristian Dumitrescu if (file_default) 9415074e1d5SCristian Dumitrescu for (line_id = 1; ; line_id++) { 9425074e1d5SCristian Dumitrescu struct rte_swx_table_entry *entry; 9435074e1d5SCristian Dumitrescu 9445074e1d5SCristian Dumitrescu if (fgets(line, 2048, file_default) == NULL) 9455074e1d5SCristian Dumitrescu break; 9465074e1d5SCristian Dumitrescu 9475074e1d5SCristian Dumitrescu entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl, 9485074e1d5SCristian Dumitrescu table_name, 9495074e1d5SCristian Dumitrescu line); 9505074e1d5SCristian Dumitrescu if (!entry) { 9515074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_FILE_ERR, 9525074e1d5SCristian Dumitrescu file_name_default, line_id); 9535074e1d5SCristian Dumitrescu goto error; 9545074e1d5SCristian Dumitrescu } 9555074e1d5SCristian Dumitrescu 9565074e1d5SCristian Dumitrescu status = rte_swx_ctl_pipeline_table_default_entry_add(p->ctl, 9575074e1d5SCristian Dumitrescu table_name, 9585074e1d5SCristian Dumitrescu entry); 959275ebefeSCristian Dumitrescu table_entry_free(entry); 9605074e1d5SCristian Dumitrescu if (status) { 9615074e1d5SCristian Dumitrescu snprintf(out, out_size, 9625074e1d5SCristian Dumitrescu "Invalid entry in file %s at line %u", 9635074e1d5SCristian Dumitrescu file_name_default, line_id); 9645074e1d5SCristian Dumitrescu goto error; 9655074e1d5SCristian Dumitrescu } 9665074e1d5SCristian Dumitrescu } 9675074e1d5SCristian Dumitrescu 9685074e1d5SCristian Dumitrescu status = rte_swx_ctl_pipeline_commit(p->ctl, 1); 9695074e1d5SCristian Dumitrescu if (status) { 9705074e1d5SCristian Dumitrescu snprintf(out, out_size, "Commit failed."); 9715074e1d5SCristian Dumitrescu goto error; 9725074e1d5SCristian Dumitrescu } 9735074e1d5SCristian Dumitrescu 9745074e1d5SCristian Dumitrescu 9755074e1d5SCristian Dumitrescu rte_swx_ctl_pipeline_table_fprintf(stdout, p->ctl, table_name); 9765074e1d5SCristian Dumitrescu 97703665a48SCristian Dumitrescu free(line); 97803665a48SCristian Dumitrescu if (file_add) 97903665a48SCristian Dumitrescu fclose(file_add); 98003665a48SCristian Dumitrescu if (file_delete) 98103665a48SCristian Dumitrescu fclose(file_delete); 98203665a48SCristian Dumitrescu if (file_default) 98303665a48SCristian Dumitrescu fclose(file_default); 9845074e1d5SCristian Dumitrescu return; 9855074e1d5SCristian Dumitrescu 9865074e1d5SCristian Dumitrescu error: 9875074e1d5SCristian Dumitrescu rte_swx_ctl_pipeline_abort(p->ctl); 9885074e1d5SCristian Dumitrescu free(line); 9895074e1d5SCristian Dumitrescu if (file_add) 9905074e1d5SCristian Dumitrescu fclose(file_add); 9915074e1d5SCristian Dumitrescu if (file_delete) 9925074e1d5SCristian Dumitrescu fclose(file_delete); 9935074e1d5SCristian Dumitrescu if (file_default) 9945074e1d5SCristian Dumitrescu fclose(file_default); 9955074e1d5SCristian Dumitrescu } 9965074e1d5SCristian Dumitrescu 9975074e1d5SCristian Dumitrescu static const char cmd_pipeline_stats_help[] = 9985074e1d5SCristian Dumitrescu "pipeline <pipeline_name> stats\n"; 9995074e1d5SCristian Dumitrescu 10005074e1d5SCristian Dumitrescu static void 10015074e1d5SCristian Dumitrescu cmd_pipeline_stats(char **tokens, 10025074e1d5SCristian Dumitrescu uint32_t n_tokens, 10035074e1d5SCristian Dumitrescu char *out, 10045074e1d5SCristian Dumitrescu size_t out_size, 10055074e1d5SCristian Dumitrescu void *obj) 10065074e1d5SCristian Dumitrescu { 10075074e1d5SCristian Dumitrescu struct rte_swx_ctl_pipeline_info info; 10085074e1d5SCristian Dumitrescu struct pipeline *p; 10095074e1d5SCristian Dumitrescu uint32_t i; 10105074e1d5SCristian Dumitrescu int status; 10115074e1d5SCristian Dumitrescu 10125074e1d5SCristian Dumitrescu if (n_tokens != 3) { 10135074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 10145074e1d5SCristian Dumitrescu return; 10155074e1d5SCristian Dumitrescu } 10165074e1d5SCristian Dumitrescu 10175074e1d5SCristian Dumitrescu p = pipeline_find(obj, tokens[1]); 10185074e1d5SCristian Dumitrescu if (!p || !p->ctl) { 10195074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 10205074e1d5SCristian Dumitrescu return; 10215074e1d5SCristian Dumitrescu } 10225074e1d5SCristian Dumitrescu 10235074e1d5SCristian Dumitrescu if (strcmp(tokens[2], "stats")) { 10245074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 10255074e1d5SCristian Dumitrescu return; 10265074e1d5SCristian Dumitrescu } 10275074e1d5SCristian Dumitrescu 10285074e1d5SCristian Dumitrescu status = rte_swx_ctl_pipeline_info_get(p->p, &info); 10295074e1d5SCristian Dumitrescu if (status) { 10305074e1d5SCristian Dumitrescu snprintf(out, out_size, "Pipeline info get error."); 10315074e1d5SCristian Dumitrescu return; 10325074e1d5SCristian Dumitrescu } 10335074e1d5SCristian Dumitrescu 10345074e1d5SCristian Dumitrescu snprintf(out, out_size, "Input ports:\n"); 10355074e1d5SCristian Dumitrescu out_size -= strlen(out); 10365074e1d5SCristian Dumitrescu out += strlen(out); 10375074e1d5SCristian Dumitrescu 10385074e1d5SCristian Dumitrescu for (i = 0; i < info.n_ports_in; i++) { 10395074e1d5SCristian Dumitrescu struct rte_swx_port_in_stats stats; 10405074e1d5SCristian Dumitrescu 10415074e1d5SCristian Dumitrescu rte_swx_ctl_pipeline_port_in_stats_read(p->p, i, &stats); 10425074e1d5SCristian Dumitrescu 10435074e1d5SCristian Dumitrescu snprintf(out, out_size, "\tPort %u:" 10445074e1d5SCristian Dumitrescu " packets %" PRIu64 10455074e1d5SCristian Dumitrescu " bytes %" PRIu64 10465074e1d5SCristian Dumitrescu " empty %" PRIu64 "\n", 10475074e1d5SCristian Dumitrescu i, stats.n_pkts, stats.n_bytes, stats.n_empty); 10485074e1d5SCristian Dumitrescu out_size -= strlen(out); 10495074e1d5SCristian Dumitrescu out += strlen(out); 10505074e1d5SCristian Dumitrescu } 10515074e1d5SCristian Dumitrescu 10525074e1d5SCristian Dumitrescu snprintf(out, out_size, "Output ports:\n"); 10535074e1d5SCristian Dumitrescu out_size -= strlen(out); 10545074e1d5SCristian Dumitrescu out += strlen(out); 10555074e1d5SCristian Dumitrescu 10565074e1d5SCristian Dumitrescu for (i = 0; i < info.n_ports_out; i++) { 10575074e1d5SCristian Dumitrescu struct rte_swx_port_out_stats stats; 10585074e1d5SCristian Dumitrescu 10595074e1d5SCristian Dumitrescu rte_swx_ctl_pipeline_port_out_stats_read(p->p, i, &stats); 10605074e1d5SCristian Dumitrescu 10615074e1d5SCristian Dumitrescu snprintf(out, out_size, "\tPort %u:" 10625074e1d5SCristian Dumitrescu " packets %" PRIu64 10635074e1d5SCristian Dumitrescu " bytes %" PRIu64 "\n", 10645074e1d5SCristian Dumitrescu i, stats.n_pkts, stats.n_bytes); 10655074e1d5SCristian Dumitrescu out_size -= strlen(out); 10665074e1d5SCristian Dumitrescu out += strlen(out); 10675074e1d5SCristian Dumitrescu } 10685074e1d5SCristian Dumitrescu } 10695074e1d5SCristian Dumitrescu 10705074e1d5SCristian Dumitrescu static const char cmd_thread_pipeline_enable_help[] = 10715074e1d5SCristian Dumitrescu "thread <thread_id> pipeline <pipeline_name> enable\n"; 10725074e1d5SCristian Dumitrescu 10735074e1d5SCristian Dumitrescu static void 10745074e1d5SCristian Dumitrescu cmd_thread_pipeline_enable(char **tokens, 10755074e1d5SCristian Dumitrescu uint32_t n_tokens, 10765074e1d5SCristian Dumitrescu char *out, 10775074e1d5SCristian Dumitrescu size_t out_size, 10785074e1d5SCristian Dumitrescu void *obj) 10795074e1d5SCristian Dumitrescu { 10805074e1d5SCristian Dumitrescu char *pipeline_name; 10815074e1d5SCristian Dumitrescu struct pipeline *p; 10825074e1d5SCristian Dumitrescu uint32_t thread_id; 10835074e1d5SCristian Dumitrescu int status; 10845074e1d5SCristian Dumitrescu 10855074e1d5SCristian Dumitrescu if (n_tokens != 5) { 10865074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 10875074e1d5SCristian Dumitrescu return; 10885074e1d5SCristian Dumitrescu } 10895074e1d5SCristian Dumitrescu 10905074e1d5SCristian Dumitrescu if (parser_read_uint32(&thread_id, tokens[1]) != 0) { 10915074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 10925074e1d5SCristian Dumitrescu return; 10935074e1d5SCristian Dumitrescu } 10945074e1d5SCristian Dumitrescu 10955074e1d5SCristian Dumitrescu if (strcmp(tokens[2], "pipeline") != 0) { 10965074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 10975074e1d5SCristian Dumitrescu return; 10985074e1d5SCristian Dumitrescu } 10995074e1d5SCristian Dumitrescu 11005074e1d5SCristian Dumitrescu pipeline_name = tokens[3]; 11015074e1d5SCristian Dumitrescu p = pipeline_find(obj, pipeline_name); 11025074e1d5SCristian Dumitrescu if (!p || !p->ctl) { 11035074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 11045074e1d5SCristian Dumitrescu return; 11055074e1d5SCristian Dumitrescu } 11065074e1d5SCristian Dumitrescu 11075074e1d5SCristian Dumitrescu if (strcmp(tokens[4], "enable") != 0) { 11085074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); 11095074e1d5SCristian Dumitrescu return; 11105074e1d5SCristian Dumitrescu } 11115074e1d5SCristian Dumitrescu 11125074e1d5SCristian Dumitrescu status = thread_pipeline_enable(thread_id, obj, pipeline_name); 11135074e1d5SCristian Dumitrescu if (status) { 11145074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable"); 11155074e1d5SCristian Dumitrescu return; 11165074e1d5SCristian Dumitrescu } 11175074e1d5SCristian Dumitrescu } 11185074e1d5SCristian Dumitrescu 11195074e1d5SCristian Dumitrescu static const char cmd_thread_pipeline_disable_help[] = 11205074e1d5SCristian Dumitrescu "thread <thread_id> pipeline <pipeline_name> disable\n"; 11215074e1d5SCristian Dumitrescu 11225074e1d5SCristian Dumitrescu static void 11235074e1d5SCristian Dumitrescu cmd_thread_pipeline_disable(char **tokens, 11245074e1d5SCristian Dumitrescu uint32_t n_tokens, 11255074e1d5SCristian Dumitrescu char *out, 11265074e1d5SCristian Dumitrescu size_t out_size, 11275074e1d5SCristian Dumitrescu void *obj) 11285074e1d5SCristian Dumitrescu { 11295074e1d5SCristian Dumitrescu struct pipeline *p; 11305074e1d5SCristian Dumitrescu char *pipeline_name; 11315074e1d5SCristian Dumitrescu uint32_t thread_id; 11325074e1d5SCristian Dumitrescu int status; 11335074e1d5SCristian Dumitrescu 11345074e1d5SCristian Dumitrescu if (n_tokens != 5) { 11355074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 11365074e1d5SCristian Dumitrescu return; 11375074e1d5SCristian Dumitrescu } 11385074e1d5SCristian Dumitrescu 11395074e1d5SCristian Dumitrescu if (parser_read_uint32(&thread_id, tokens[1]) != 0) { 11405074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 11415074e1d5SCristian Dumitrescu return; 11425074e1d5SCristian Dumitrescu } 11435074e1d5SCristian Dumitrescu 11445074e1d5SCristian Dumitrescu if (strcmp(tokens[2], "pipeline") != 0) { 11455074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 11465074e1d5SCristian Dumitrescu return; 11475074e1d5SCristian Dumitrescu } 11485074e1d5SCristian Dumitrescu 11495074e1d5SCristian Dumitrescu pipeline_name = tokens[3]; 11505074e1d5SCristian Dumitrescu p = pipeline_find(obj, pipeline_name); 11515074e1d5SCristian Dumitrescu if (!p || !p->ctl) { 11525074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 11535074e1d5SCristian Dumitrescu return; 11545074e1d5SCristian Dumitrescu } 11555074e1d5SCristian Dumitrescu 11565074e1d5SCristian Dumitrescu if (strcmp(tokens[4], "disable") != 0) { 11575074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); 11585074e1d5SCristian Dumitrescu return; 11595074e1d5SCristian Dumitrescu } 11605074e1d5SCristian Dumitrescu 11615074e1d5SCristian Dumitrescu status = thread_pipeline_disable(thread_id, obj, pipeline_name); 11625074e1d5SCristian Dumitrescu if (status) { 11635074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_CMD_FAIL, 11645074e1d5SCristian Dumitrescu "thread pipeline disable"); 11655074e1d5SCristian Dumitrescu return; 11665074e1d5SCristian Dumitrescu } 11675074e1d5SCristian Dumitrescu } 11685074e1d5SCristian Dumitrescu 11695074e1d5SCristian Dumitrescu static void 11705074e1d5SCristian Dumitrescu cmd_help(char **tokens, 11715074e1d5SCristian Dumitrescu uint32_t n_tokens, 11725074e1d5SCristian Dumitrescu char *out, 11735074e1d5SCristian Dumitrescu size_t out_size, 11745074e1d5SCristian Dumitrescu void *arg __rte_unused) 11755074e1d5SCristian Dumitrescu { 11765074e1d5SCristian Dumitrescu tokens++; 11775074e1d5SCristian Dumitrescu n_tokens--; 11785074e1d5SCristian Dumitrescu 11795074e1d5SCristian Dumitrescu if (n_tokens == 0) { 11805074e1d5SCristian Dumitrescu snprintf(out, out_size, 11817fef9ef1SYogesh Jangra "Type 'help <command>' for command details.\n\n" 11827fef9ef1SYogesh Jangra "List of commands:\n" 11837fef9ef1SYogesh Jangra "\tmempool\n" 11847fef9ef1SYogesh Jangra "\tlink\n" 11857fef9ef1SYogesh Jangra "\tpipeline create\n" 11867fef9ef1SYogesh Jangra "\tpipeline port in\n" 11877fef9ef1SYogesh Jangra "\tpipeline port out\n" 11887fef9ef1SYogesh Jangra "\tpipeline build\n" 11897fef9ef1SYogesh Jangra "\tpipeline table update\n" 11907fef9ef1SYogesh Jangra "\tpipeline stats\n" 11917fef9ef1SYogesh Jangra "\tthread pipeline enable\n" 11927fef9ef1SYogesh Jangra "\tthread pipeline disable\n\n"); 11935074e1d5SCristian Dumitrescu return; 11945074e1d5SCristian Dumitrescu } 11955074e1d5SCristian Dumitrescu 11965074e1d5SCristian Dumitrescu if (strcmp(tokens[0], "mempool") == 0) { 11975074e1d5SCristian Dumitrescu snprintf(out, out_size, "\n%s\n", cmd_mempool_help); 11985074e1d5SCristian Dumitrescu return; 11995074e1d5SCristian Dumitrescu } 12005074e1d5SCristian Dumitrescu 12015074e1d5SCristian Dumitrescu if (strcmp(tokens[0], "link") == 0) { 12025074e1d5SCristian Dumitrescu snprintf(out, out_size, "\n%s\n", cmd_link_help); 12035074e1d5SCristian Dumitrescu return; 12045074e1d5SCristian Dumitrescu } 12055074e1d5SCristian Dumitrescu 12065074e1d5SCristian Dumitrescu if ((strcmp(tokens[0], "pipeline") == 0) && 12077fef9ef1SYogesh Jangra (n_tokens == 2) && (strcmp(tokens[1], "create") == 0)) { 12085074e1d5SCristian Dumitrescu snprintf(out, out_size, "\n%s\n", cmd_pipeline_create_help); 12095074e1d5SCristian Dumitrescu return; 12105074e1d5SCristian Dumitrescu } 12115074e1d5SCristian Dumitrescu 12125074e1d5SCristian Dumitrescu if ((strcmp(tokens[0], "pipeline") == 0) && 12137fef9ef1SYogesh Jangra (n_tokens == 3) && (strcmp(tokens[1], "port") == 0)) { 12147fef9ef1SYogesh Jangra if (strcmp(tokens[2], "in") == 0) { 12155074e1d5SCristian Dumitrescu snprintf(out, out_size, "\n%s\n", 12165074e1d5SCristian Dumitrescu cmd_pipeline_port_in_help); 12175074e1d5SCristian Dumitrescu return; 12185074e1d5SCristian Dumitrescu } 12195074e1d5SCristian Dumitrescu 12207fef9ef1SYogesh Jangra if (strcmp(tokens[2], "out") == 0) { 12215074e1d5SCristian Dumitrescu snprintf(out, out_size, "\n%s\n", 12225074e1d5SCristian Dumitrescu cmd_pipeline_port_out_help); 12235074e1d5SCristian Dumitrescu return; 12245074e1d5SCristian Dumitrescu } 12255074e1d5SCristian Dumitrescu } 12265074e1d5SCristian Dumitrescu 12275074e1d5SCristian Dumitrescu if ((strcmp(tokens[0], "pipeline") == 0) && 12287fef9ef1SYogesh Jangra (n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) { 12295074e1d5SCristian Dumitrescu snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help); 12305074e1d5SCristian Dumitrescu return; 12315074e1d5SCristian Dumitrescu } 12325074e1d5SCristian Dumitrescu 12335074e1d5SCristian Dumitrescu if ((strcmp(tokens[0], "pipeline") == 0) && 12347fef9ef1SYogesh Jangra (n_tokens == 3) && 12357fef9ef1SYogesh Jangra (strcmp(tokens[1], "table") == 0) && 12367fef9ef1SYogesh Jangra (strcmp(tokens[2], "update") == 0)) { 12375074e1d5SCristian Dumitrescu snprintf(out, out_size, "\n%s\n", 12385074e1d5SCristian Dumitrescu cmd_pipeline_table_update_help); 12395074e1d5SCristian Dumitrescu return; 12405074e1d5SCristian Dumitrescu } 12415074e1d5SCristian Dumitrescu 12425074e1d5SCristian Dumitrescu if ((strcmp(tokens[0], "pipeline") == 0) && 12437fef9ef1SYogesh Jangra (n_tokens == 2) && (strcmp(tokens[1], "stats") == 0)) { 12445074e1d5SCristian Dumitrescu snprintf(out, out_size, "\n%s\n", cmd_pipeline_stats_help); 12455074e1d5SCristian Dumitrescu return; 12465074e1d5SCristian Dumitrescu } 12475074e1d5SCristian Dumitrescu 12485074e1d5SCristian Dumitrescu if ((n_tokens == 3) && 12495074e1d5SCristian Dumitrescu (strcmp(tokens[0], "thread") == 0) && 12505074e1d5SCristian Dumitrescu (strcmp(tokens[1], "pipeline") == 0)) { 12515074e1d5SCristian Dumitrescu if (strcmp(tokens[2], "enable") == 0) { 12525074e1d5SCristian Dumitrescu snprintf(out, out_size, "\n%s\n", 12535074e1d5SCristian Dumitrescu cmd_thread_pipeline_enable_help); 12545074e1d5SCristian Dumitrescu return; 12555074e1d5SCristian Dumitrescu } 12565074e1d5SCristian Dumitrescu 12575074e1d5SCristian Dumitrescu if (strcmp(tokens[2], "disable") == 0) { 12585074e1d5SCristian Dumitrescu snprintf(out, out_size, "\n%s\n", 12595074e1d5SCristian Dumitrescu cmd_thread_pipeline_disable_help); 12605074e1d5SCristian Dumitrescu return; 12615074e1d5SCristian Dumitrescu } 12625074e1d5SCristian Dumitrescu } 12635074e1d5SCristian Dumitrescu 12645074e1d5SCristian Dumitrescu snprintf(out, out_size, "Invalid command\n"); 12655074e1d5SCristian Dumitrescu } 12665074e1d5SCristian Dumitrescu 12675074e1d5SCristian Dumitrescu void 12685074e1d5SCristian Dumitrescu cli_process(char *in, char *out, size_t out_size, void *obj) 12695074e1d5SCristian Dumitrescu { 12705074e1d5SCristian Dumitrescu char *tokens[CMD_MAX_TOKENS]; 12715074e1d5SCristian Dumitrescu uint32_t n_tokens = RTE_DIM(tokens); 12725074e1d5SCristian Dumitrescu int status; 12735074e1d5SCristian Dumitrescu 12745074e1d5SCristian Dumitrescu if (is_comment(in)) 12755074e1d5SCristian Dumitrescu return; 12765074e1d5SCristian Dumitrescu 12775074e1d5SCristian Dumitrescu status = parse_tokenize_string(in, tokens, &n_tokens); 12785074e1d5SCristian Dumitrescu if (status) { 12795074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_ARG_TOO_MANY, ""); 12805074e1d5SCristian Dumitrescu return; 12815074e1d5SCristian Dumitrescu } 12825074e1d5SCristian Dumitrescu 12835074e1d5SCristian Dumitrescu if (n_tokens == 0) 12845074e1d5SCristian Dumitrescu return; 12855074e1d5SCristian Dumitrescu 12865074e1d5SCristian Dumitrescu if (strcmp(tokens[0], "help") == 0) { 12875074e1d5SCristian Dumitrescu cmd_help(tokens, n_tokens, out, out_size, obj); 12885074e1d5SCristian Dumitrescu return; 12895074e1d5SCristian Dumitrescu } 12905074e1d5SCristian Dumitrescu 12915074e1d5SCristian Dumitrescu if (strcmp(tokens[0], "mempool") == 0) { 12925074e1d5SCristian Dumitrescu cmd_mempool(tokens, n_tokens, out, out_size, obj); 12935074e1d5SCristian Dumitrescu return; 12945074e1d5SCristian Dumitrescu } 12955074e1d5SCristian Dumitrescu 12965074e1d5SCristian Dumitrescu if (strcmp(tokens[0], "link") == 0) { 1297*821848f5SCristian Dumitrescu if ((n_tokens >= 2) && (strcmp(tokens[1], "show") == 0)) { 12985074e1d5SCristian Dumitrescu cmd_link_show(tokens, n_tokens, out, out_size, obj); 12995074e1d5SCristian Dumitrescu return; 13005074e1d5SCristian Dumitrescu } 13015074e1d5SCristian Dumitrescu 13025074e1d5SCristian Dumitrescu cmd_link(tokens, n_tokens, out, out_size, obj); 13035074e1d5SCristian Dumitrescu return; 13045074e1d5SCristian Dumitrescu } 13055074e1d5SCristian Dumitrescu 13065074e1d5SCristian Dumitrescu if (strcmp(tokens[0], "pipeline") == 0) { 13075074e1d5SCristian Dumitrescu if ((n_tokens >= 3) && 13085074e1d5SCristian Dumitrescu (strcmp(tokens[2], "create") == 0)) { 13095074e1d5SCristian Dumitrescu cmd_pipeline_create(tokens, n_tokens, out, out_size, 13105074e1d5SCristian Dumitrescu obj); 13115074e1d5SCristian Dumitrescu return; 13125074e1d5SCristian Dumitrescu } 13135074e1d5SCristian Dumitrescu 13145074e1d5SCristian Dumitrescu if ((n_tokens >= 4) && 13155074e1d5SCristian Dumitrescu (strcmp(tokens[2], "port") == 0) && 13165074e1d5SCristian Dumitrescu (strcmp(tokens[3], "in") == 0)) { 13175074e1d5SCristian Dumitrescu cmd_pipeline_port_in(tokens, n_tokens, out, out_size, 13185074e1d5SCristian Dumitrescu obj); 13195074e1d5SCristian Dumitrescu return; 13205074e1d5SCristian Dumitrescu } 13215074e1d5SCristian Dumitrescu 13225074e1d5SCristian Dumitrescu if ((n_tokens >= 4) && 13235074e1d5SCristian Dumitrescu (strcmp(tokens[2], "port") == 0) && 13245074e1d5SCristian Dumitrescu (strcmp(tokens[3], "out") == 0)) { 13255074e1d5SCristian Dumitrescu cmd_pipeline_port_out(tokens, n_tokens, out, out_size, 13265074e1d5SCristian Dumitrescu obj); 13275074e1d5SCristian Dumitrescu return; 13285074e1d5SCristian Dumitrescu } 13295074e1d5SCristian Dumitrescu 13305074e1d5SCristian Dumitrescu if ((n_tokens >= 3) && 13315074e1d5SCristian Dumitrescu (strcmp(tokens[2], "build") == 0)) { 13325074e1d5SCristian Dumitrescu cmd_pipeline_build(tokens, n_tokens, out, out_size, 13335074e1d5SCristian Dumitrescu obj); 13345074e1d5SCristian Dumitrescu return; 13355074e1d5SCristian Dumitrescu } 13365074e1d5SCristian Dumitrescu 13375074e1d5SCristian Dumitrescu if ((n_tokens >= 3) && 13385074e1d5SCristian Dumitrescu (strcmp(tokens[2], "table") == 0)) { 13395074e1d5SCristian Dumitrescu cmd_pipeline_table_update(tokens, n_tokens, out, 13405074e1d5SCristian Dumitrescu out_size, obj); 13415074e1d5SCristian Dumitrescu return; 13425074e1d5SCristian Dumitrescu } 13435074e1d5SCristian Dumitrescu 13445074e1d5SCristian Dumitrescu if ((n_tokens >= 3) && 13455074e1d5SCristian Dumitrescu (strcmp(tokens[2], "stats") == 0)) { 13465074e1d5SCristian Dumitrescu cmd_pipeline_stats(tokens, n_tokens, out, out_size, 13475074e1d5SCristian Dumitrescu obj); 13485074e1d5SCristian Dumitrescu return; 13495074e1d5SCristian Dumitrescu } 13505074e1d5SCristian Dumitrescu } 13515074e1d5SCristian Dumitrescu 13525074e1d5SCristian Dumitrescu if (strcmp(tokens[0], "thread") == 0) { 13535074e1d5SCristian Dumitrescu if ((n_tokens >= 5) && 13545074e1d5SCristian Dumitrescu (strcmp(tokens[4], "enable") == 0)) { 13555074e1d5SCristian Dumitrescu cmd_thread_pipeline_enable(tokens, n_tokens, 13565074e1d5SCristian Dumitrescu out, out_size, obj); 13575074e1d5SCristian Dumitrescu return; 13585074e1d5SCristian Dumitrescu } 13595074e1d5SCristian Dumitrescu 13605074e1d5SCristian Dumitrescu if ((n_tokens >= 5) && 13615074e1d5SCristian Dumitrescu (strcmp(tokens[4], "disable") == 0)) { 13625074e1d5SCristian Dumitrescu cmd_thread_pipeline_disable(tokens, n_tokens, 13635074e1d5SCristian Dumitrescu out, out_size, obj); 13645074e1d5SCristian Dumitrescu return; 13655074e1d5SCristian Dumitrescu } 13665074e1d5SCristian Dumitrescu } 13675074e1d5SCristian Dumitrescu 13685074e1d5SCristian Dumitrescu snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); 13695074e1d5SCristian Dumitrescu } 13705074e1d5SCristian Dumitrescu 13715074e1d5SCristian Dumitrescu int 13725074e1d5SCristian Dumitrescu cli_script_process(const char *file_name, 13735074e1d5SCristian Dumitrescu size_t msg_in_len_max, 13745074e1d5SCristian Dumitrescu size_t msg_out_len_max, 13755074e1d5SCristian Dumitrescu void *obj) 13765074e1d5SCristian Dumitrescu { 13775074e1d5SCristian Dumitrescu char *msg_in = NULL, *msg_out = NULL; 13785074e1d5SCristian Dumitrescu FILE *f = NULL; 13795074e1d5SCristian Dumitrescu 13805074e1d5SCristian Dumitrescu /* Check input arguments */ 13815074e1d5SCristian Dumitrescu if ((file_name == NULL) || 13825074e1d5SCristian Dumitrescu (strlen(file_name) == 0) || 13835074e1d5SCristian Dumitrescu (msg_in_len_max == 0) || 13845074e1d5SCristian Dumitrescu (msg_out_len_max == 0)) 13855074e1d5SCristian Dumitrescu return -EINVAL; 13865074e1d5SCristian Dumitrescu 13875074e1d5SCristian Dumitrescu msg_in = malloc(msg_in_len_max + 1); 13885074e1d5SCristian Dumitrescu msg_out = malloc(msg_out_len_max + 1); 13895074e1d5SCristian Dumitrescu if ((msg_in == NULL) || 13905074e1d5SCristian Dumitrescu (msg_out == NULL)) { 13915074e1d5SCristian Dumitrescu free(msg_out); 13925074e1d5SCristian Dumitrescu free(msg_in); 13935074e1d5SCristian Dumitrescu return -ENOMEM; 13945074e1d5SCristian Dumitrescu } 13955074e1d5SCristian Dumitrescu 13965074e1d5SCristian Dumitrescu /* Open input file */ 13975074e1d5SCristian Dumitrescu f = fopen(file_name, "r"); 13985074e1d5SCristian Dumitrescu if (f == NULL) { 13995074e1d5SCristian Dumitrescu free(msg_out); 14005074e1d5SCristian Dumitrescu free(msg_in); 14015074e1d5SCristian Dumitrescu return -EIO; 14025074e1d5SCristian Dumitrescu } 14035074e1d5SCristian Dumitrescu 14045074e1d5SCristian Dumitrescu /* Read file */ 14055074e1d5SCristian Dumitrescu for ( ; ; ) { 14065074e1d5SCristian Dumitrescu if (fgets(msg_in, msg_in_len_max + 1, f) == NULL) 14075074e1d5SCristian Dumitrescu break; 14085074e1d5SCristian Dumitrescu 14095074e1d5SCristian Dumitrescu printf("%s", msg_in); 14105074e1d5SCristian Dumitrescu msg_out[0] = 0; 14115074e1d5SCristian Dumitrescu 14125074e1d5SCristian Dumitrescu cli_process(msg_in, 14135074e1d5SCristian Dumitrescu msg_out, 14145074e1d5SCristian Dumitrescu msg_out_len_max, 14155074e1d5SCristian Dumitrescu obj); 14165074e1d5SCristian Dumitrescu 14175074e1d5SCristian Dumitrescu if (strlen(msg_out)) 14185074e1d5SCristian Dumitrescu printf("%s", msg_out); 14195074e1d5SCristian Dumitrescu } 14205074e1d5SCristian Dumitrescu 14215074e1d5SCristian Dumitrescu /* Close file */ 14225074e1d5SCristian Dumitrescu fclose(f); 14235074e1d5SCristian Dumitrescu free(msg_out); 14245074e1d5SCristian Dumitrescu free(msg_in); 14255074e1d5SCristian Dumitrescu return 0; 14265074e1d5SCristian Dumitrescu } 1427