1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2018 Intel Corporation
3  */
4 
5 #include <stdint.h>
6 #include <stdlib.h>
7 #include <string.h>
8 
9 #include <rte_string_fns.h>
10 #include <rte_table_hash_func.h>
11 
12 #include "rte_eth_softnic_internals.h"
13 
14 /**
15  * Input port
16  */
17 int
softnic_port_in_action_profile_init(struct pmd_internals * p)18 softnic_port_in_action_profile_init(struct pmd_internals *p)
19 {
20 	TAILQ_INIT(&p->port_in_action_profile_list);
21 
22 	return 0;
23 }
24 
25 void
softnic_port_in_action_profile_free(struct pmd_internals * p)26 softnic_port_in_action_profile_free(struct pmd_internals *p)
27 {
28 	for ( ; ; ) {
29 		struct softnic_port_in_action_profile *profile;
30 
31 		profile = TAILQ_FIRST(&p->port_in_action_profile_list);
32 		if (profile == NULL)
33 			break;
34 
35 		TAILQ_REMOVE(&p->port_in_action_profile_list, profile, node);
36 		free(profile);
37 	}
38 }
39 
40 struct softnic_port_in_action_profile *
softnic_port_in_action_profile_find(struct pmd_internals * p,const char * name)41 softnic_port_in_action_profile_find(struct pmd_internals *p,
42 	const char *name)
43 {
44 	struct softnic_port_in_action_profile *profile;
45 
46 	if (name == NULL)
47 		return NULL;
48 
49 	TAILQ_FOREACH(profile, &p->port_in_action_profile_list, node)
50 		if (strcmp(profile->name, name) == 0)
51 			return profile;
52 
53 	return NULL;
54 }
55 
56 struct softnic_port_in_action_profile *
softnic_port_in_action_profile_create(struct pmd_internals * p,const char * name,struct softnic_port_in_action_profile_params * params)57 softnic_port_in_action_profile_create(struct pmd_internals *p,
58 	const char *name,
59 	struct softnic_port_in_action_profile_params *params)
60 {
61 	struct softnic_port_in_action_profile *profile;
62 	struct rte_port_in_action_profile *ap;
63 	int status;
64 
65 	/* Check input params */
66 	if (name == NULL ||
67 		softnic_port_in_action_profile_find(p, name) ||
68 		params == NULL)
69 		return NULL;
70 
71 	if ((params->action_mask & (1LLU << RTE_PORT_IN_ACTION_LB)) &&
72 		params->lb.f_hash == NULL) {
73 		switch (params->lb.key_size) {
74 		case  8:
75 			params->lb.f_hash = rte_table_hash_crc_key8;
76 			break;
77 
78 		case 16:
79 			params->lb.f_hash = rte_table_hash_crc_key16;
80 			break;
81 
82 		case 24:
83 			params->lb.f_hash = rte_table_hash_crc_key24;
84 			break;
85 
86 		case 32:
87 			params->lb.f_hash = rte_table_hash_crc_key32;
88 			break;
89 
90 		case 40:
91 			params->lb.f_hash = rte_table_hash_crc_key40;
92 			break;
93 
94 		case 48:
95 			params->lb.f_hash = rte_table_hash_crc_key48;
96 			break;
97 
98 		case 56:
99 			params->lb.f_hash = rte_table_hash_crc_key56;
100 			break;
101 
102 		case 64:
103 			params->lb.f_hash = rte_table_hash_crc_key64;
104 			break;
105 
106 		default:
107 			return NULL;
108 		}
109 
110 		params->lb.seed = 0;
111 	}
112 
113 	/* Resource */
114 	ap = rte_port_in_action_profile_create(0);
115 	if (ap == NULL)
116 		return NULL;
117 
118 	if (params->action_mask & (1LLU << RTE_PORT_IN_ACTION_FLTR)) {
119 		status = rte_port_in_action_profile_action_register(ap,
120 			RTE_PORT_IN_ACTION_FLTR,
121 			&params->fltr);
122 
123 		if (status) {
124 			rte_port_in_action_profile_free(ap);
125 			return NULL;
126 		}
127 	}
128 
129 	if (params->action_mask & (1LLU << RTE_PORT_IN_ACTION_LB)) {
130 		status = rte_port_in_action_profile_action_register(ap,
131 			RTE_PORT_IN_ACTION_LB,
132 			&params->lb);
133 
134 		if (status) {
135 			rte_port_in_action_profile_free(ap);
136 			return NULL;
137 		}
138 	}
139 
140 	status = rte_port_in_action_profile_freeze(ap);
141 	if (status) {
142 		rte_port_in_action_profile_free(ap);
143 		return NULL;
144 	}
145 
146 	/* Node allocation */
147 	profile = calloc(1, sizeof(struct softnic_port_in_action_profile));
148 	if (profile == NULL) {
149 		rte_port_in_action_profile_free(ap);
150 		return NULL;
151 	}
152 
153 	/* Node fill in */
154 	strlcpy(profile->name, name, sizeof(profile->name));
155 	memcpy(&profile->params, params, sizeof(*params));
156 	profile->ap = ap;
157 
158 	/* Node add to list */
159 	TAILQ_INSERT_TAIL(&p->port_in_action_profile_list, profile, node);
160 
161 	return profile;
162 }
163 
164 /**
165  * Table
166  */
167 int
softnic_table_action_profile_init(struct pmd_internals * p)168 softnic_table_action_profile_init(struct pmd_internals *p)
169 {
170 	TAILQ_INIT(&p->table_action_profile_list);
171 
172 	return 0;
173 }
174 
175 void
softnic_table_action_profile_free(struct pmd_internals * p)176 softnic_table_action_profile_free(struct pmd_internals *p)
177 {
178 	for ( ; ; ) {
179 		struct softnic_table_action_profile *profile;
180 
181 		profile = TAILQ_FIRST(&p->table_action_profile_list);
182 		if (profile == NULL)
183 			break;
184 
185 		TAILQ_REMOVE(&p->table_action_profile_list, profile, node);
186 		free(profile);
187 	}
188 }
189 
190 struct softnic_table_action_profile *
softnic_table_action_profile_find(struct pmd_internals * p,const char * name)191 softnic_table_action_profile_find(struct pmd_internals *p,
192 	const char *name)
193 {
194 	struct softnic_table_action_profile *profile;
195 
196 	if (name == NULL)
197 		return NULL;
198 
199 	TAILQ_FOREACH(profile, &p->table_action_profile_list, node)
200 		if (strcmp(profile->name, name) == 0)
201 			return profile;
202 
203 	return NULL;
204 }
205 
206 struct softnic_table_action_profile *
softnic_table_action_profile_create(struct pmd_internals * p,const char * name,struct softnic_table_action_profile_params * params)207 softnic_table_action_profile_create(struct pmd_internals *p,
208 	const char *name,
209 	struct softnic_table_action_profile_params *params)
210 {
211 	struct softnic_table_action_profile *profile;
212 	struct rte_table_action_profile *ap;
213 	int status;
214 
215 	/* Check input params */
216 	if (name == NULL ||
217 		softnic_table_action_profile_find(p, name) ||
218 		params == NULL ||
219 		((params->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) == 0))
220 		return NULL;
221 
222 	if ((params->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) &&
223 		params->lb.f_hash == NULL) {
224 		switch (params->lb.key_size) {
225 		case 8:
226 			params->lb.f_hash = rte_table_hash_crc_key8;
227 			break;
228 
229 		case 16:
230 			params->lb.f_hash = rte_table_hash_crc_key16;
231 			break;
232 
233 		case 24:
234 			params->lb.f_hash = rte_table_hash_crc_key24;
235 			break;
236 
237 		case 32:
238 			params->lb.f_hash = rte_table_hash_crc_key32;
239 			break;
240 
241 		case 40:
242 			params->lb.f_hash = rte_table_hash_crc_key40;
243 			break;
244 
245 		case 48:
246 			params->lb.f_hash = rte_table_hash_crc_key48;
247 			break;
248 
249 		case 56:
250 			params->lb.f_hash = rte_table_hash_crc_key56;
251 			break;
252 
253 		case 64:
254 			params->lb.f_hash = rte_table_hash_crc_key64;
255 			break;
256 
257 		default:
258 			return NULL;
259 		}
260 
261 		params->lb.seed = 0;
262 	}
263 
264 	/* Resource */
265 	ap = rte_table_action_profile_create(&params->common);
266 	if (ap == NULL)
267 		return NULL;
268 
269 	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
270 		status = rte_table_action_profile_action_register(ap,
271 			RTE_TABLE_ACTION_FWD,
272 			NULL);
273 
274 		if (status) {
275 			rte_table_action_profile_free(ap);
276 			return NULL;
277 		}
278 	}
279 
280 	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
281 		status = rte_table_action_profile_action_register(ap,
282 			RTE_TABLE_ACTION_LB,
283 			&params->lb);
284 
285 		if (status) {
286 			rte_table_action_profile_free(ap);
287 			return NULL;
288 		}
289 	}
290 
291 	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
292 		status = rte_table_action_profile_action_register(ap,
293 			RTE_TABLE_ACTION_MTR,
294 			&params->mtr);
295 
296 		if (status) {
297 			rte_table_action_profile_free(ap);
298 			return NULL;
299 		}
300 	}
301 
302 	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
303 		status = rte_table_action_profile_action_register(ap,
304 			RTE_TABLE_ACTION_TM,
305 			&params->tm);
306 
307 		if (status) {
308 			rte_table_action_profile_free(ap);
309 			return NULL;
310 		}
311 	}
312 
313 	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
314 		status = rte_table_action_profile_action_register(ap,
315 			RTE_TABLE_ACTION_ENCAP,
316 			&params->encap);
317 
318 		if (status) {
319 			rte_table_action_profile_free(ap);
320 			return NULL;
321 		}
322 	}
323 
324 	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
325 		status = rte_table_action_profile_action_register(ap,
326 			RTE_TABLE_ACTION_NAT,
327 			&params->nat);
328 
329 		if (status) {
330 			rte_table_action_profile_free(ap);
331 			return NULL;
332 		}
333 	}
334 
335 	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
336 		status = rte_table_action_profile_action_register(ap,
337 			RTE_TABLE_ACTION_TTL,
338 			&params->ttl);
339 
340 		if (status) {
341 			rte_table_action_profile_free(ap);
342 			return NULL;
343 		}
344 	}
345 
346 	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
347 		status = rte_table_action_profile_action_register(ap,
348 			RTE_TABLE_ACTION_STATS,
349 			&params->stats);
350 
351 		if (status) {
352 			rte_table_action_profile_free(ap);
353 			return NULL;
354 		}
355 	}
356 	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
357 		status = rte_table_action_profile_action_register(ap,
358 			RTE_TABLE_ACTION_TIME,
359 			NULL);
360 
361 		if (status) {
362 			rte_table_action_profile_free(ap);
363 			return NULL;
364 		}
365 	}
366 
367 	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
368 		status = rte_table_action_profile_action_register(ap,
369 			RTE_TABLE_ACTION_TAG,
370 			NULL);
371 
372 		if (status) {
373 			rte_table_action_profile_free(ap);
374 			return NULL;
375 		}
376 	}
377 
378 	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
379 		status = rte_table_action_profile_action_register(ap,
380 			RTE_TABLE_ACTION_DECAP,
381 			NULL);
382 
383 		if (status) {
384 			rte_table_action_profile_free(ap);
385 			return NULL;
386 		}
387 	}
388 
389 	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
390 		status = rte_table_action_profile_action_register(ap,
391 			RTE_TABLE_ACTION_SYM_CRYPTO,
392 			&params->sym_crypto);
393 
394 		if (status) {
395 			rte_table_action_profile_free(ap);
396 			return NULL;
397 		}
398 	}
399 
400 	status = rte_table_action_profile_freeze(ap);
401 	if (status) {
402 		rte_table_action_profile_free(ap);
403 		return NULL;
404 	}
405 
406 	/* Node allocation */
407 	profile = calloc(1, sizeof(struct softnic_table_action_profile));
408 	if (profile == NULL) {
409 		rte_table_action_profile_free(ap);
410 		return NULL;
411 	}
412 
413 	/* Node fill in */
414 	strlcpy(profile->name, name, sizeof(profile->name));
415 	memcpy(&profile->params, params, sizeof(*params));
416 	profile->ap = ap;
417 
418 	/* Node add to list */
419 	TAILQ_INSERT_TAIL(&p->table_action_profile_list, profile, node);
420 
421 	return profile;
422 }
423