net/softnic: fix memory leak as profile is freed
[dpdk.git] / drivers / net / softnic / rte_eth_softnic_action.c
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
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
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 *
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 *
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
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
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                 rte_table_action_profile_free(profile->ap);
187                 free(profile);
188         }
189 }
190
191 struct softnic_table_action_profile *
192 softnic_table_action_profile_find(struct pmd_internals *p,
193         const char *name)
194 {
195         struct softnic_table_action_profile *profile;
196
197         if (name == NULL)
198                 return NULL;
199
200         TAILQ_FOREACH(profile, &p->table_action_profile_list, node)
201                 if (strcmp(profile->name, name) == 0)
202                         return profile;
203
204         return NULL;
205 }
206
207 struct softnic_table_action_profile *
208 softnic_table_action_profile_create(struct pmd_internals *p,
209         const char *name,
210         struct softnic_table_action_profile_params *params)
211 {
212         struct softnic_table_action_profile *profile;
213         struct rte_table_action_profile *ap;
214         int status;
215
216         /* Check input params */
217         if (name == NULL ||
218                 softnic_table_action_profile_find(p, name) ||
219                 params == NULL ||
220                 ((params->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) == 0))
221                 return NULL;
222
223         if ((params->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) &&
224                 params->lb.f_hash == NULL) {
225                 switch (params->lb.key_size) {
226                 case 8:
227                         params->lb.f_hash = rte_table_hash_crc_key8;
228                         break;
229
230                 case 16:
231                         params->lb.f_hash = rte_table_hash_crc_key16;
232                         break;
233
234                 case 24:
235                         params->lb.f_hash = rte_table_hash_crc_key24;
236                         break;
237
238                 case 32:
239                         params->lb.f_hash = rte_table_hash_crc_key32;
240                         break;
241
242                 case 40:
243                         params->lb.f_hash = rte_table_hash_crc_key40;
244                         break;
245
246                 case 48:
247                         params->lb.f_hash = rte_table_hash_crc_key48;
248                         break;
249
250                 case 56:
251                         params->lb.f_hash = rte_table_hash_crc_key56;
252                         break;
253
254                 case 64:
255                         params->lb.f_hash = rte_table_hash_crc_key64;
256                         break;
257
258                 default:
259                         return NULL;
260                 }
261
262                 params->lb.seed = 0;
263         }
264
265         /* Resource */
266         ap = rte_table_action_profile_create(&params->common);
267         if (ap == NULL)
268                 return NULL;
269
270         if (params->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
271                 status = rte_table_action_profile_action_register(ap,
272                         RTE_TABLE_ACTION_FWD,
273                         NULL);
274
275                 if (status) {
276                         rte_table_action_profile_free(ap);
277                         return NULL;
278                 }
279         }
280
281         if (params->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
282                 status = rte_table_action_profile_action_register(ap,
283                         RTE_TABLE_ACTION_LB,
284                         &params->lb);
285
286                 if (status) {
287                         rte_table_action_profile_free(ap);
288                         return NULL;
289                 }
290         }
291
292         if (params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
293                 status = rte_table_action_profile_action_register(ap,
294                         RTE_TABLE_ACTION_MTR,
295                         &params->mtr);
296
297                 if (status) {
298                         rte_table_action_profile_free(ap);
299                         return NULL;
300                 }
301         }
302
303         if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
304                 status = rte_table_action_profile_action_register(ap,
305                         RTE_TABLE_ACTION_TM,
306                         &params->tm);
307
308                 if (status) {
309                         rte_table_action_profile_free(ap);
310                         return NULL;
311                 }
312         }
313
314         if (params->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
315                 status = rte_table_action_profile_action_register(ap,
316                         RTE_TABLE_ACTION_ENCAP,
317                         &params->encap);
318
319                 if (status) {
320                         rte_table_action_profile_free(ap);
321                         return NULL;
322                 }
323         }
324
325         if (params->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
326                 status = rte_table_action_profile_action_register(ap,
327                         RTE_TABLE_ACTION_NAT,
328                         &params->nat);
329
330                 if (status) {
331                         rte_table_action_profile_free(ap);
332                         return NULL;
333                 }
334         }
335
336         if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
337                 status = rte_table_action_profile_action_register(ap,
338                         RTE_TABLE_ACTION_TTL,
339                         &params->ttl);
340
341                 if (status) {
342                         rte_table_action_profile_free(ap);
343                         return NULL;
344                 }
345         }
346
347         if (params->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
348                 status = rte_table_action_profile_action_register(ap,
349                         RTE_TABLE_ACTION_STATS,
350                         &params->stats);
351
352                 if (status) {
353                         rte_table_action_profile_free(ap);
354                         return NULL;
355                 }
356         }
357         if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
358                 status = rte_table_action_profile_action_register(ap,
359                         RTE_TABLE_ACTION_TIME,
360                         NULL);
361
362                 if (status) {
363                         rte_table_action_profile_free(ap);
364                         return NULL;
365                 }
366         }
367
368         if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
369                 status = rte_table_action_profile_action_register(ap,
370                         RTE_TABLE_ACTION_TAG,
371                         NULL);
372
373                 if (status) {
374                         rte_table_action_profile_free(ap);
375                         return NULL;
376                 }
377         }
378
379         if (params->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
380                 status = rte_table_action_profile_action_register(ap,
381                         RTE_TABLE_ACTION_DECAP,
382                         NULL);
383
384                 if (status) {
385                         rte_table_action_profile_free(ap);
386                         return NULL;
387                 }
388         }
389
390         if (params->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
391                 status = rte_table_action_profile_action_register(ap,
392                         RTE_TABLE_ACTION_SYM_CRYPTO,
393                         &params->sym_crypto);
394
395                 if (status) {
396                         rte_table_action_profile_free(ap);
397                         return NULL;
398                 }
399         }
400
401         status = rte_table_action_profile_freeze(ap);
402         if (status) {
403                 rte_table_action_profile_free(ap);
404                 return NULL;
405         }
406
407         /* Node allocation */
408         profile = calloc(1, sizeof(struct softnic_table_action_profile));
409         if (profile == NULL) {
410                 rte_table_action_profile_free(ap);
411                 return NULL;
412         }
413
414         /* Node fill in */
415         strlcpy(profile->name, name, sizeof(profile->name));
416         memcpy(&profile->params, params, sizeof(*params));
417         profile->ap = ap;
418
419         /* Node add to list */
420         TAILQ_INSERT_TAIL(&p->table_action_profile_list, profile, node);
421
422         return profile;
423 }