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
softnic_pipeline_init(struct pmd_internals * p)14 softnic_pipeline_init(struct pmd_internals *p)
15 {
16 TAILQ_INIT(&p->pipeline_list);
17
18 return 0;
19 }
20
21 void
softnic_pipeline_free(struct pmd_internals * p)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
softnic_pipeline_disable_all(struct pmd_internals * p)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
softnic_pipeline_thread_count(struct pmd_internals * p,uint32_t thread_id)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 *
softnic_pipeline_find(struct pmd_internals * p,const char * name)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
iospec_translate(struct pmd_internals * softnic __rte_unused,const char * file_in_name,const char * file_out_name)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 *
softnic_pipeline_create(struct pmd_internals * softnic,const char * name,const char * lib_file_name,const char * iospec_file_name,int numa_node)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