1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2018 Intel Corporation 3 */ 4 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include <rte_common.h> 9 #include <rte_string_fns.h> 10 11 #include "rte_eth_softnic_internals.h" 12 13 int 14 softnic_pipeline_init(struct pmd_internals *p) 15 { 16 TAILQ_INIT(&p->pipeline_list); 17 18 return 0; 19 } 20 21 void 22 softnic_pipeline_free(struct pmd_internals *p) 23 { 24 for ( ; ; ) { 25 struct pipeline *pipeline; 26 27 pipeline = TAILQ_FIRST(&p->pipeline_list); 28 if (pipeline == NULL) 29 break; 30 31 TAILQ_REMOVE(&p->pipeline_list, pipeline, node); 32 rte_swx_ctl_pipeline_free(pipeline->ctl); 33 rte_swx_pipeline_free(pipeline->p); 34 free(pipeline); 35 } 36 } 37 38 void 39 softnic_pipeline_disable_all(struct pmd_internals *p) 40 { 41 struct pipeline *pipeline; 42 43 TAILQ_FOREACH(pipeline, &p->pipeline_list, node) 44 if (pipeline->enabled) 45 softnic_thread_pipeline_disable(p, 46 pipeline->thread_id, 47 pipeline); 48 } 49 50 uint32_t 51 softnic_pipeline_thread_count(struct pmd_internals *p, uint32_t thread_id) 52 { 53 struct pipeline *pipeline; 54 uint32_t count = 0; 55 56 TAILQ_FOREACH(pipeline, &p->pipeline_list, node) 57 if ((pipeline->enabled) && (pipeline->thread_id == thread_id)) 58 count++; 59 60 return count; 61 } 62 63 struct pipeline * 64 softnic_pipeline_find(struct pmd_internals *p, 65 const char *name) 66 { 67 struct pipeline *pipeline; 68 69 if (name == NULL) 70 return NULL; 71 72 TAILQ_FOREACH(pipeline, &p->pipeline_list, node) 73 if (strcmp(name, pipeline->name) == 0) 74 return pipeline; 75 76 return NULL; 77 } 78 79 #ifndef MAX_LINE_LENGTH 80 #define MAX_LINE_LENGTH 2048 81 #endif 82 83 /* The Soft NIC device internal resources such as mempools, rings or pipelines are globally visible, 84 * hence they need to have globally unique names. In order to apply the same configuration scripts 85 * unmodified to all the Soft NIC devices that instantiate the same program, the pipeline I/O 86 * configuration files are silently translated internally to prefix the name of the above resources 87 * with the Soft NIC device name, thus making the resource names globally unique. 88 */ 89 static int 90 iospec_translate(struct pmd_internals *softnic __rte_unused, 91 const char *file_in_name, 92 const char *file_out_name) 93 { 94 FILE *fi = NULL, *fo = NULL; 95 char *line = NULL; 96 int status = 0; 97 98 /* File open. */ 99 fi = fopen(file_in_name, "r"); 100 fo = fopen(file_out_name, "w"); 101 if (!fi || !fo) { 102 status = -EIO; 103 goto free; 104 } 105 106 /* Memory allocation. */ 107 line = malloc(MAX_LINE_LENGTH); 108 if (!line) { 109 status = -ENOMEM; 110 goto free; 111 } 112 113 /* Read from the input file and write to the output file. */ 114 for ( ; ; ) { 115 char *ptr = line; 116 uint32_t n_tokens; 117 int flag = 0; 118 119 /* Read next line. */ 120 if (!fgets(line, MAX_LINE_LENGTH, fi)) 121 break; 122 123 /* Parse the line into tokens. */ 124 for (n_tokens = 0; ; n_tokens++) { 125 char *token; 126 127 /* Read token. */ 128 token = strtok_r(ptr, " \f\n\r\t\v", &ptr); 129 if (!token) 130 break; 131 132 /* Handle comments. */ 133 if (!n_tokens && 134 ((token[0] == '#') || 135 (token[0] == ';') || 136 ((token[0] == '/') && (token[1] == '/')))) 137 break; 138 139 /* Process token. */ 140 if (flag) { 141 fprintf(fo, "%s_%s ", softnic->params.name, token); 142 flag = 0; 143 continue; 144 } 145 146 if (!strcmp(token, "mempool") || 147 !strcmp(token, "ring")) { 148 flag = 1; 149 fprintf(fo, "%s ", token); 150 continue; 151 } 152 153 /* Default action: write token. */ 154 fprintf(fo, "%s ", token); 155 } 156 157 /* Handle empty or comment lines. */ 158 if (!n_tokens) 159 continue; 160 161 /* Write newline. */ 162 fprintf(fo, "\n"); 163 } 164 165 free: 166 /* Memory free. */ 167 free(line); 168 169 /* File close. */ 170 if (fi) 171 fclose(fi); 172 if (fo) 173 fclose(fo); 174 return status; 175 } 176 177 struct pipeline * 178 softnic_pipeline_create(struct pmd_internals *softnic, 179 const char *name, 180 const char *lib_file_name, 181 const char *iospec_file_name, 182 int numa_node) 183 { 184 char global_name[NAME_MAX]; 185 FILE *iospec_file = NULL; 186 struct pipeline *pipeline = NULL; 187 struct rte_swx_pipeline *p = NULL; 188 struct rte_swx_ctl_pipeline *ctl = NULL; 189 int status = 0; 190 191 /* Check input params */ 192 if (!name || !name[0] || softnic_pipeline_find(softnic, name)) 193 goto error; 194 195 /* Resource create */ 196 snprintf(global_name, sizeof(global_name), "/tmp/%s_%s.io", softnic->params.name, name); 197 198 status = iospec_translate(softnic, iospec_file_name, global_name); 199 if (status) 200 goto error; 201 202 iospec_file = fopen(global_name, "r"); 203 if (!iospec_file) 204 goto error; 205 206 snprintf(global_name, sizeof(global_name), "%s_%s", softnic->params.name, name); 207 208 status = rte_swx_pipeline_build_from_lib(&p, 209 global_name, 210 lib_file_name, 211 iospec_file, 212 numa_node); 213 if (status) 214 goto error; 215 216 fclose(iospec_file); 217 iospec_file = NULL; 218 219 ctl = rte_swx_ctl_pipeline_create(p); 220 if (!ctl) 221 goto error; 222 223 /* Node allocation */ 224 pipeline = calloc(1, sizeof(struct pipeline)); 225 if (!pipeline) 226 goto error; 227 228 /* Node fill in */ 229 strlcpy(pipeline->name, name, sizeof(pipeline->name)); 230 pipeline->p = p; 231 pipeline->ctl = ctl; 232 233 /* Node add to list */ 234 TAILQ_INSERT_TAIL(&softnic->pipeline_list, pipeline, node); 235 236 return pipeline; 237 238 error: 239 free(pipeline); 240 rte_swx_ctl_pipeline_free(ctl); 241 rte_swx_pipeline_free(p); 242 if (iospec_file) 243 fclose(iospec_file); 244 return NULL; 245 } 246