xref: /dpdk/drivers/net/softnic/rte_eth_softnic_pipeline.c (revision fa0a52a70866bb479835fba68252bc2633dc5898)
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