1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2018 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <stdint.h> 7 #include <stdlib.h> 8 #include <string.h> 9 10 #include <rte_common.h> 11 #include <rte_cycles.h> 12 #include <rte_string_fns.h> 13 14 #include "rte_eth_softnic_internals.h" 15 #include "parser.h" 16 17 #ifndef CMD_MAX_TOKENS 18 #define CMD_MAX_TOKENS 256 19 #endif 20 21 #define MSG_OUT_OF_MEMORY "Not enough memory.\n" 22 #define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n" 23 #define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n" 24 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n" 25 #define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n" 26 #define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n" 27 #define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n" 28 #define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n" 29 #define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n" 30 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n" 31 #define MSG_CMD_FAIL "Command \"%s\" failed.\n" 32 33 static int 34 is_comment(char *in) 35 { 36 if ((strlen(in) && index("!#%;", in[0])) || 37 (strncmp(in, "//", 2) == 0) || 38 (strncmp(in, "--", 2) == 0)) 39 return 1; 40 41 return 0; 42 } 43 44 /** 45 * mempool <mempool_name> 46 * buffer <buffer_size> 47 * pool <pool_size> 48 * cache <cache_size> 49 */ 50 static void 51 cmd_mempool(struct pmd_internals *softnic, 52 char **tokens, 53 uint32_t n_tokens, 54 char *out, 55 size_t out_size) 56 { 57 struct softnic_mempool_params p; 58 char *name; 59 struct softnic_mempool *mempool; 60 61 if (n_tokens != 8) { 62 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 63 return; 64 } 65 66 name = tokens[1]; 67 68 if (strcmp(tokens[2], "buffer") != 0) { 69 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer"); 70 return; 71 } 72 73 if (softnic_parser_read_uint32(&p.buffer_size, tokens[3]) != 0) { 74 snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size"); 75 return; 76 } 77 78 if (strcmp(tokens[4], "pool") != 0) { 79 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool"); 80 return; 81 } 82 83 if (softnic_parser_read_uint32(&p.pool_size, tokens[5]) != 0) { 84 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size"); 85 return; 86 } 87 88 if (strcmp(tokens[6], "cache") != 0) { 89 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache"); 90 return; 91 } 92 93 if (softnic_parser_read_uint32(&p.cache_size, tokens[7]) != 0) { 94 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size"); 95 return; 96 } 97 98 mempool = softnic_mempool_create(softnic, name, &p); 99 if (mempool == NULL) { 100 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 101 return; 102 } 103 } 104 105 /** 106 * swq <swq_name> 107 * size <size> 108 */ 109 static void 110 cmd_swq(struct pmd_internals *softnic, 111 char **tokens, 112 uint32_t n_tokens, 113 char *out, 114 size_t out_size) 115 { 116 struct softnic_swq_params p; 117 char *name; 118 struct softnic_swq *swq; 119 120 if (n_tokens != 4) { 121 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 122 return; 123 } 124 125 name = tokens[1]; 126 127 if (strcmp(tokens[2], "size") != 0) { 128 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 129 return; 130 } 131 132 if (softnic_parser_read_uint32(&p.size, tokens[3]) != 0) { 133 snprintf(out, out_size, MSG_ARG_INVALID, "size"); 134 return; 135 } 136 137 swq = softnic_swq_create(softnic, name, &p); 138 if (swq == NULL) { 139 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 140 return; 141 } 142 } 143 144 /** 145 * thread <thread_id> pipeline <pipeline_name> enable 146 */ 147 static void 148 cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic, 149 char **tokens, 150 uint32_t n_tokens, 151 char *out, 152 size_t out_size) 153 { 154 char *pipeline_name; 155 struct pipeline *p; 156 uint32_t thread_id; 157 int status; 158 159 if (n_tokens != 5) { 160 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 161 return; 162 } 163 164 if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) { 165 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 166 return; 167 } 168 169 if (strcmp(tokens[2], "pipeline") != 0) { 170 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 171 return; 172 } 173 174 pipeline_name = tokens[3]; 175 p = softnic_pipeline_find(softnic, pipeline_name); 176 if (!p) { 177 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 178 return; 179 } 180 181 if (strcmp(tokens[4], "enable") != 0) { 182 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); 183 return; 184 } 185 186 status = softnic_thread_pipeline_enable(softnic, thread_id, p); 187 if (status) { 188 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable"); 189 return; 190 } 191 } 192 193 /** 194 * thread <thread_id> pipeline <pipeline_name> disable 195 */ 196 static void 197 cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic, 198 char **tokens, 199 uint32_t n_tokens, 200 char *out, 201 size_t out_size) 202 { 203 char *pipeline_name; 204 struct pipeline *p; 205 uint32_t thread_id; 206 int status; 207 208 if (n_tokens != 5) { 209 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 210 return; 211 } 212 213 if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) { 214 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 215 return; 216 } 217 218 if (strcmp(tokens[2], "pipeline") != 0) { 219 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 220 return; 221 } 222 223 pipeline_name = tokens[3]; 224 p = softnic_pipeline_find(softnic, pipeline_name); 225 if (!p) { 226 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name"); 227 return; 228 } 229 230 if (strcmp(tokens[4], "disable") != 0) { 231 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); 232 return; 233 } 234 235 status = softnic_thread_pipeline_disable(softnic, thread_id, p); 236 if (status) { 237 snprintf(out, out_size, MSG_CMD_FAIL, 238 "thread pipeline disable"); 239 return; 240 } 241 } 242 243 void 244 softnic_cli_process(char *in, char *out, size_t out_size, void *arg) 245 { 246 char *tokens[CMD_MAX_TOKENS]; 247 uint32_t n_tokens = RTE_DIM(tokens); 248 struct pmd_internals *softnic = arg; 249 int status; 250 251 if (is_comment(in)) 252 return; 253 254 status = softnic_parse_tokenize_string(in, tokens, &n_tokens); 255 if (status) { 256 snprintf(out, out_size, MSG_ARG_TOO_MANY, ""); 257 return; 258 } 259 260 if (n_tokens == 0) 261 return; 262 263 if (strcmp(tokens[0], "mempool") == 0) { 264 cmd_mempool(softnic, tokens, n_tokens, out, out_size); 265 return; 266 } 267 268 if (strcmp(tokens[0], "swq") == 0) { 269 cmd_swq(softnic, tokens, n_tokens, out, out_size); 270 return; 271 } 272 273 if (strcmp(tokens[0], "thread") == 0) { 274 if (n_tokens >= 5 && 275 (strcmp(tokens[4], "enable") == 0)) { 276 cmd_softnic_thread_pipeline_enable(softnic, tokens, n_tokens, 277 out, out_size); 278 return; 279 } 280 281 if (n_tokens >= 5 && 282 (strcmp(tokens[4], "disable") == 0)) { 283 cmd_softnic_thread_pipeline_disable(softnic, tokens, n_tokens, 284 out, out_size); 285 return; 286 } 287 } 288 289 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); 290 } 291 292 int 293 softnic_cli_script_process(struct pmd_internals *softnic, 294 const char *file_name, 295 size_t msg_in_len_max, 296 size_t msg_out_len_max) 297 { 298 char *msg_in = NULL, *msg_out = NULL; 299 FILE *f = NULL; 300 301 /* Check input arguments */ 302 if (file_name == NULL || 303 (strlen(file_name) == 0) || 304 msg_in_len_max == 0 || 305 msg_out_len_max == 0) 306 return -EINVAL; 307 308 msg_in = malloc(msg_in_len_max + 1); 309 msg_out = malloc(msg_out_len_max + 1); 310 if (msg_in == NULL || 311 msg_out == NULL) { 312 free(msg_out); 313 free(msg_in); 314 return -ENOMEM; 315 } 316 317 /* Open input file */ 318 f = fopen(file_name, "r"); 319 if (f == NULL) { 320 free(msg_out); 321 free(msg_in); 322 return -EIO; 323 } 324 325 /* Read file */ 326 for ( ; ; ) { 327 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL) 328 break; 329 330 printf("%s", msg_in); 331 msg_out[0] = 0; 332 333 softnic_cli_process(msg_in, 334 msg_out, 335 msg_out_len_max, 336 softnic); 337 338 if (strlen(msg_out)) 339 printf("%s", msg_out); 340 } 341 342 /* Close file */ 343 fclose(f); 344 free(msg_out); 345 free(msg_in); 346 return 0; 347 } 348