Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2023 Intel Corporation
3 : : */
4 : :
5 : : #include <arpa/inet.h>
6 : :
7 : : #include "cpfl_flow_parser.h"
8 : :
9 : : static enum rte_flow_item_type
10 : 0 : cpfl_get_item_type_by_str(const char *type)
11 : : {
12 [ # # ]: 0 : if (strcmp(type, "eth") == 0)
13 : : return RTE_FLOW_ITEM_TYPE_ETH;
14 [ # # ]: 0 : else if (strcmp(type, "ipv4") == 0)
15 : : return RTE_FLOW_ITEM_TYPE_IPV4;
16 [ # # ]: 0 : else if (strcmp(type, "tcp") == 0)
17 : : return RTE_FLOW_ITEM_TYPE_TCP;
18 [ # # ]: 0 : else if (strcmp(type, "udp") == 0)
19 : : return RTE_FLOW_ITEM_TYPE_UDP;
20 [ # # ]: 0 : else if (strcmp(type, "vxlan") == 0)
21 : : return RTE_FLOW_ITEM_TYPE_VXLAN;
22 [ # # ]: 0 : else if (strcmp(type, "icmp") == 0)
23 : : return RTE_FLOW_ITEM_TYPE_ICMP;
24 [ # # ]: 0 : else if (strcmp(type, "vlan") == 0)
25 : : return RTE_FLOW_ITEM_TYPE_VLAN;
26 : :
27 : 0 : PMD_DRV_LOG(ERR, "Not support this type: %s.", type);
28 : 0 : return RTE_FLOW_ITEM_TYPE_VOID;
29 : : }
30 : :
31 : : static enum rte_flow_action_type
32 : 0 : cpfl_get_action_type_by_str(const char *type)
33 : : {
34 [ # # ]: 0 : if (strcmp(type, "vxlan_encap") == 0)
35 : : return RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP;
36 [ # # ]: 0 : else if (strcmp(type, "vxlan_decap") == 0)
37 : : return RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
38 [ # # ]: 0 : else if (strcmp(type, "prog") == 0)
39 : : return RTE_FLOW_ACTION_TYPE_PROG;
40 : :
41 : 0 : PMD_DRV_LOG(ERR, "Not support this type: %s.", type);
42 : 0 : return RTE_FLOW_ACTION_TYPE_VOID;
43 : : }
44 : :
45 : : static const char *
46 : 0 : cpfl_json_t_to_string(json_t *object, const char *name)
47 : : {
48 : : json_t *subobject;
49 : :
50 [ # # ]: 0 : if (!object) {
51 : 0 : PMD_DRV_LOG(ERR, "object doesn't exist.");
52 : 0 : return NULL;
53 : : }
54 : 0 : subobject = json_object_get(object, name);
55 [ # # ]: 0 : if (!subobject) {
56 : 0 : PMD_DRV_LOG(ERR, "%s doesn't exist.", name);
57 : 0 : return NULL;
58 : : }
59 : :
60 : 0 : return json_string_value(subobject);
61 : : }
62 : :
63 : : static int
64 : 0 : cpfl_json_t_to_int(json_t *object, const char *name, int *value)
65 : : {
66 : : json_t *subobject;
67 : :
68 [ # # ]: 0 : if (!object) {
69 : 0 : PMD_DRV_LOG(ERR, "object doesn't exist.");
70 : 0 : return -EINVAL;
71 : : }
72 : 0 : subobject = json_object_get(object, name);
73 [ # # ]: 0 : if (!subobject) {
74 : 0 : PMD_DRV_LOG(ERR, "%s doesn't exist.", name);
75 : 0 : return -EINVAL;
76 : : }
77 [ # # ]: 0 : if (!json_is_integer(subobject)) {
78 : 0 : PMD_DRV_LOG(ERR, "%s is not an integer.", name);
79 : 0 : return -EINVAL;
80 : : }
81 : 0 : *value = (int)json_integer_value(subobject);
82 : :
83 : 0 : return 0;
84 : : }
85 : :
86 : : static int
87 : 0 : cpfl_json_t_to_uint16(json_t *object, const char *name, uint16_t *value)
88 : : {
89 : : json_t *subobject;
90 : :
91 [ # # ]: 0 : if (!object) {
92 : 0 : PMD_DRV_LOG(ERR, "object doesn't exist.");
93 : 0 : return -EINVAL;
94 : : }
95 : 0 : subobject = json_object_get(object, name);
96 [ # # ]: 0 : if (!subobject) {
97 : 0 : PMD_DRV_LOG(ERR, "%s doesn't exist.", name);
98 : 0 : return -EINVAL;
99 : : }
100 [ # # ]: 0 : if (!json_is_integer(subobject)) {
101 : 0 : PMD_DRV_LOG(ERR, "%s is not an integer.", name);
102 : 0 : return -EINVAL;
103 : : }
104 : 0 : *value = (uint16_t)json_integer_value(subobject);
105 : :
106 : 0 : return 0;
107 : : }
108 : :
109 : : static int
110 : 0 : cpfl_json_t_to_uint32(json_t *object, const char *name, uint32_t *value)
111 : : {
112 : : json_t *subobject;
113 : :
114 [ # # ]: 0 : if (!object) {
115 : 0 : PMD_DRV_LOG(ERR, "object doesn't exist.");
116 : 0 : return -EINVAL;
117 : : }
118 : 0 : subobject = json_object_get(object, name);
119 [ # # ]: 0 : if (!subobject) {
120 : 0 : PMD_DRV_LOG(ERR, "%s doesn't exist.", name);
121 : 0 : return -EINVAL;
122 : : }
123 [ # # ]: 0 : if (!json_is_integer(subobject)) {
124 : 0 : PMD_DRV_LOG(ERR, "%s is not an integer.", name);
125 : 0 : return -EINVAL;
126 : : }
127 : 0 : *value = (uint32_t)json_integer_value(subobject);
128 : :
129 : 0 : return 0;
130 : : }
131 : :
132 : : static int
133 : 0 : cpfl_flow_js_pattern_key_attr(json_t *ob_pr_key_attrs, struct cpfl_flow_js_pr *js_pr)
134 : : {
135 : : int i, len;
136 : : struct cpfl_flow_js_pr_key_attr *attr;
137 : :
138 : 0 : len = json_array_size(ob_pr_key_attrs);
139 : 0 : js_pr->key.attributes = rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr_key_attr), 0);
140 [ # # ]: 0 : if (!js_pr->key.attributes) {
141 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory.");
142 : 0 : return -ENOMEM;
143 : : }
144 : 0 : js_pr->key.attr_size = len;
145 : : attr = js_pr->key.attributes;
146 [ # # ]: 0 : for (i = 0; i < len; i++) {
147 : : json_t *object;
148 : : const char *name;
149 : 0 : uint16_t value = 0;
150 : : int ret;
151 : :
152 : 0 : object = json_array_get(ob_pr_key_attrs, i);
153 : 0 : name = cpfl_json_t_to_string(object, "Name");
154 [ # # ]: 0 : if (!name) {
155 : 0 : PMD_DRV_LOG(ERR, "Can not parse string 'Name'.");
156 : 0 : goto err;
157 : : }
158 : 0 : ret = cpfl_json_t_to_uint16(object, "Value", &value);
159 [ # # ]: 0 : if (ret < 0) {
160 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'value'.");
161 : 0 : goto err;
162 : : }
163 [ # # ]: 0 : if (strcmp(name, "ingress") == 0) {
164 : 0 : attr->ingress = value;
165 [ # # ]: 0 : } else if (strcmp(name, "egress") == 0) {
166 : 0 : attr->egress = value;
167 : : } else {
168 : : /* TODO: more... */
169 : 0 : PMD_DRV_LOG(ERR, "Not support attr name: %s.", name);
170 : 0 : goto err;
171 : : }
172 : : }
173 : :
174 : : return 0;
175 : : err:
176 : 0 : rte_free(js_pr->key.attributes);
177 : 0 : return -EINVAL;
178 : : }
179 : :
180 : : static int
181 : 0 : cpfl_flow_js_pattern_key_proto_field(json_t *ob_fields,
182 : : struct cpfl_flow_js_pr_key_proto *js_field)
183 : : {
184 : : int len, i;
185 : :
186 [ # # ]: 0 : if (!ob_fields)
187 : : return 0;
188 : 0 : len = json_array_size(ob_fields);
189 [ # # ]: 0 : if (len == 0)
190 : : return 0;
191 : 0 : js_field->fields_size = len;
192 : 0 : js_field->fields =
193 : 0 : rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr_key_proto_field) * len, 0);
194 [ # # ]: 0 : if (!js_field->fields) {
195 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory.");
196 : 0 : return -ENOMEM;
197 : : }
198 [ # # ]: 0 : for (i = 0; i < len; i++) {
199 : : json_t *object;
200 : : const char *name, *mask;
201 : 0 : uint32_t mask_32b = 0;
202 : : int ret;
203 : :
204 : 0 : object = json_array_get(ob_fields, i);
205 : 0 : name = cpfl_json_t_to_string(object, "name");
206 [ # # ]: 0 : if (!name) {
207 : 0 : PMD_DRV_LOG(ERR, "Can not parse string 'name'.");
208 : 0 : goto err;
209 : : }
210 [ # # ]: 0 : if (strlen(name) > CPFL_JS_STR_SIZE - 1) {
211 : 0 : PMD_DRV_LOG(ERR, "The 'name' is too long.");
212 : 0 : goto err;
213 : : }
214 [ # # ]: 0 : strncpy(js_field->fields[i].name, name, CPFL_JS_STR_SIZE - 1);
215 : :
216 [ # # ]: 0 : if (js_field->type == RTE_FLOW_ITEM_TYPE_ETH ||
217 : : js_field->type == RTE_FLOW_ITEM_TYPE_IPV4) {
218 : : /* Added a check for parsing mask value of the next_proto_id field. */
219 [ # # ]: 0 : if (strcmp(name, "next_proto_id") == 0) {
220 : 0 : ret = cpfl_json_t_to_uint32(object, "mask", &mask_32b);
221 [ # # ]: 0 : if (ret < 0) {
222 : 0 : PMD_DRV_LOG(ERR, "Cannot parse uint32 'mask'.");
223 : 0 : goto err;
224 : : }
225 : 0 : js_field->fields[i].mask_32b = mask_32b;
226 : : } else {
227 : 0 : mask = cpfl_json_t_to_string(object, "mask");
228 [ # # ]: 0 : if (!mask) {
229 : 0 : PMD_DRV_LOG(ERR, "Can not parse string 'mask'.");
230 : 0 : goto err;
231 : : }
232 [ # # ]: 0 : if (rte_strscpy(js_field->fields[i].mask,
233 : : mask, CPFL_JS_STR_SIZE) < 0) {
234 : 0 : PMD_DRV_LOG(ERR, "The 'mask' is too long.");
235 : 0 : goto err;
236 : : }
237 : : }
238 : :
239 : : } else {
240 : 0 : ret = cpfl_json_t_to_uint32(object, "mask", &mask_32b);
241 [ # # ]: 0 : if (ret < 0) {
242 : 0 : PMD_DRV_LOG(ERR, "Can not parse uint32 'mask'.");
243 : 0 : goto err;
244 : : }
245 : 0 : js_field->fields[i].mask_32b = mask_32b;
246 : : }
247 : : }
248 : :
249 : : return 0;
250 : :
251 : : err:
252 : 0 : rte_free(js_field->fields);
253 : 0 : return -EINVAL;
254 : : }
255 : :
256 : : static int
257 : 0 : cpfl_flow_js_pattern_key_proto(json_t *ob_pr_key_protos, struct cpfl_flow_js_pr *js_pr)
258 : : {
259 : : int len, i, ret;
260 : :
261 : 0 : len = json_array_size(ob_pr_key_protos);
262 [ # # ]: 0 : if (len == 0)
263 : : return 0;
264 : 0 : js_pr->key.proto_size = len;
265 : 0 : js_pr->key.protocols = rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr_key_proto) * len, 0);
266 [ # # ]: 0 : if (!js_pr->key.protocols) {
267 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory.");
268 : 0 : return -ENOMEM;
269 : : }
270 : :
271 [ # # ]: 0 : for (i = 0; i < len; i++) {
272 : : json_t *object, *ob_fields;
273 : : const char *type;
274 : : enum rte_flow_item_type item_type;
275 : :
276 : 0 : object = json_array_get(ob_pr_key_protos, i);
277 : : /* pr->key->proto->type */
278 : 0 : type = cpfl_json_t_to_string(object, "type");
279 [ # # ]: 0 : if (!type) {
280 : 0 : PMD_DRV_LOG(ERR, "Can not parse string 'type'.");
281 : 0 : goto err;
282 : : }
283 : 0 : item_type = cpfl_get_item_type_by_str(type);
284 [ # # ]: 0 : if (item_type == RTE_FLOW_ITEM_TYPE_VOID)
285 : 0 : goto err;
286 : 0 : js_pr->key.protocols[i].type = item_type;
287 : : /* pr->key->proto->fields */
288 : 0 : ob_fields = json_object_get(object, "fields");
289 : 0 : ret = cpfl_flow_js_pattern_key_proto_field(ob_fields,
290 : 0 : &js_pr->key.protocols[i]);
291 [ # # ]: 0 : if (ret < 0)
292 : 0 : goto err;
293 : : }
294 : :
295 : : return 0;
296 : :
297 : 0 : err:
298 : 0 : rte_free(js_pr->key.protocols);
299 : 0 : return -EINVAL;
300 : : }
301 : :
302 : : static int
303 : 0 : cpfl_flow_js_pattern_act_fv_proto(json_t *ob_value, struct cpfl_flow_js_fv *js_fv)
304 : : {
305 : 0 : uint16_t layer = 0, offset = 0, mask = 0;
306 : : const char *header;
307 : : enum rte_flow_item_type type;
308 : : int ret;
309 : :
310 : 0 : ret = cpfl_json_t_to_uint16(ob_value, "layer", &layer);
311 [ # # ]: 0 : if (ret < 0) {
312 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'value'.");
313 : 0 : return -EINVAL;
314 : : }
315 : :
316 : 0 : header = cpfl_json_t_to_string(ob_value, "header");
317 [ # # ]: 0 : if (!header) {
318 : 0 : PMD_DRV_LOG(ERR, "Can not parse string 'header'.");
319 : 0 : return -EINVAL;
320 : : }
321 : 0 : ret = cpfl_json_t_to_uint16(ob_value, "offset", &offset);
322 [ # # ]: 0 : if (ret < 0) {
323 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'offset'.");
324 : 0 : return -EINVAL;
325 : : }
326 : 0 : ret = cpfl_json_t_to_uint16(ob_value, "mask", &mask);
327 [ # # ]: 0 : if (ret < 0) {
328 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'mask'.");
329 : 0 : return -EINVAL;
330 : : }
331 : 0 : type = cpfl_get_item_type_by_str(header);
332 [ # # ]: 0 : if (type == RTE_FLOW_ITEM_TYPE_VOID)
333 : : return -EINVAL;
334 : 0 : js_fv->proto.layer = layer;
335 : 0 : js_fv->proto.offset = offset;
336 : 0 : js_fv->proto.mask = mask;
337 : 0 : js_fv->proto.header = type;
338 : :
339 : 0 : return 0;
340 : : }
341 : :
342 : : static int
343 : 0 : cpfl_flow_js_pattern_act_fv_metadata(json_t *ob_value, struct cpfl_flow_js_fv *js_fv)
344 : : {
345 : : int ret;
346 : :
347 : 0 : ret = cpfl_json_t_to_uint16(ob_value, "type", &js_fv->meta.type);
348 [ # # ]: 0 : if (ret < 0) {
349 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'size'.");
350 : 0 : return ret;
351 : : }
352 : 0 : ret = cpfl_json_t_to_uint16(ob_value, "offset", &js_fv->meta.offset);
353 [ # # ]: 0 : if (ret < 0) {
354 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'size'.");
355 : 0 : return ret;
356 : : }
357 : 0 : ret = cpfl_json_t_to_uint16(ob_value, "mask", &js_fv->meta.mask);
358 [ # # ]: 0 : if (ret < 0) {
359 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'size'.");
360 : 0 : return ret;
361 : : }
362 : :
363 : : return 0;
364 : : }
365 : :
366 : : static int
367 : 0 : cpfl_flow_js_pattern_act_fv(json_t *ob_fvs, struct cpfl_flow_js_pr_action *js_act)
368 : : {
369 : : int len, i;
370 : :
371 : 0 : len = json_array_size(ob_fvs);
372 [ # # ]: 0 : if (len == 0)
373 : : return 0;
374 : 0 : js_act->sem.fv = rte_malloc(NULL, sizeof(struct cpfl_flow_js_fv) * len, 0);
375 [ # # ]: 0 : if (!js_act->sem.fv) {
376 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory.");
377 : 0 : return -ENOMEM;
378 : : }
379 : 0 : js_act->sem.fv_size = len;
380 [ # # ]: 0 : for (i = 0; i < len; i++) {
381 : : struct cpfl_flow_js_fv *js_fv;
382 : : json_t *object, *ob_value;
383 : 0 : uint16_t offset = 0;
384 : : const char *type;
385 : : int ret;
386 : :
387 : 0 : js_fv = &js_act->sem.fv[i];
388 : 0 : object = json_array_get(ob_fvs, i);
389 : 0 : ret = cpfl_json_t_to_uint16(object, "offset", &offset);
390 [ # # ]: 0 : if (ret < 0) {
391 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'offset'.");
392 : 0 : goto err;
393 : : }
394 : 0 : js_fv->offset = offset;
395 : :
396 : 0 : type = cpfl_json_t_to_string(object, "type");
397 [ # # ]: 0 : if (!type) {
398 : 0 : PMD_DRV_LOG(ERR, "Can not parse string 'type'.");
399 : 0 : goto err;
400 : : }
401 : 0 : ob_value = json_object_get(object, "value");
402 [ # # ]: 0 : if (strcmp(type, "immediate") == 0) {
403 : 0 : js_fv->type = CPFL_FV_TYPE_IMMEDIATE;
404 : 0 : js_fv->immediate = json_integer_value(ob_value);
405 [ # # ]: 0 : } else if (strcmp(type, "metadata") == 0) {
406 : 0 : js_fv->type = CPFL_FV_TYPE_METADATA;
407 : 0 : cpfl_flow_js_pattern_act_fv_metadata(ob_value, js_fv);
408 [ # # ]: 0 : } else if (strcmp(type, "protocol") == 0) {
409 : 0 : js_fv->type = CPFL_FV_TYPE_PROTOCOL;
410 : 0 : cpfl_flow_js_pattern_act_fv_proto(ob_value, js_fv);
411 : : } else {
412 : 0 : PMD_DRV_LOG(ERR, "Not support this type: %s.", type);
413 : 0 : goto err;
414 : : }
415 : : }
416 : :
417 : : return 0;
418 : :
419 : : err:
420 : 0 : rte_free(js_act->sem.fv);
421 : 0 : return -EINVAL;
422 : : }
423 : :
424 : : static int
425 : 0 : cpfl_flow_js_pattern_per_act(json_t *ob_per_act, struct cpfl_flow_js_pr_action *js_act)
426 : : {
427 : : const char *type;
428 : : int ret;
429 : :
430 : : /* pr->actions->type */
431 : 0 : type = cpfl_json_t_to_string(ob_per_act, "type");
432 [ # # ]: 0 : if (!type) {
433 : 0 : PMD_DRV_LOG(ERR, "Can not parse string 'type'.");
434 : 0 : return -EINVAL;
435 : : }
436 : : /* pr->actions->data */
437 [ # # ]: 0 : if (strcmp(type, "sem") == 0) {
438 : : json_t *ob_fvs, *ob_sem;
439 : :
440 : 0 : js_act->type = CPFL_JS_PR_ACTION_TYPE_SEM;
441 : 0 : ob_sem = json_object_get(ob_per_act, "data");
442 : 0 : ret = cpfl_json_t_to_uint16(ob_sem, "profile", &js_act->sem.prof);
443 [ # # ]: 0 : if (ret < 0) {
444 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'profile'.");
445 : 0 : return -EINVAL;
446 : : }
447 : 0 : ret = cpfl_json_t_to_uint16(ob_sem, "subprofile", &js_act->sem.subprof);
448 [ # # ]: 0 : if (ret < 0) {
449 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'subprofile'.");
450 : 0 : return -EINVAL;
451 : : }
452 : 0 : ret = cpfl_json_t_to_uint16(ob_sem, "keysize", &js_act->sem.keysize);
453 [ # # ]: 0 : if (ret < 0) {
454 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'keysize'.");
455 : 0 : return -EINVAL;
456 : : }
457 : 0 : ob_fvs = json_object_get(ob_sem, "fieldvectors");
458 : 0 : ret = cpfl_flow_js_pattern_act_fv(ob_fvs, js_act);
459 : : if (ret < 0)
460 : : return ret;
461 : : } else {
462 : 0 : PMD_DRV_LOG(ERR, "Not support this type: %s.", type);
463 : 0 : return -EINVAL;
464 : : }
465 : :
466 : : return 0;
467 : : }
468 : :
469 : : static int
470 : 0 : cpfl_flow_js_pattern_act(json_t *ob_pr_acts, struct cpfl_flow_js_pr *js_pr)
471 : : {
472 : : int i, len, ret;
473 : :
474 : 0 : len = json_array_size(ob_pr_acts);
475 [ # # ]: 0 : if (len == 0)
476 : : return 0;
477 : 0 : js_pr->actions = rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr_action) * len, 0);
478 [ # # ]: 0 : if (!js_pr->actions) {
479 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory.");
480 : 0 : return -ENOMEM;
481 : : }
482 : 0 : js_pr->actions_size = len;
483 [ # # ]: 0 : for (i = 0; i < len; i++) {
484 : : struct cpfl_flow_js_pr_action *js_act;
485 : : json_t *object;
486 : :
487 : 0 : object = json_array_get(ob_pr_acts, i);
488 : 0 : js_act = &js_pr->actions[i];
489 : 0 : ret = cpfl_flow_js_pattern_per_act(object, js_act);
490 [ # # ]: 0 : if (ret < 0) {
491 : 0 : rte_free(js_pr->actions);
492 : 0 : PMD_DRV_LOG(ERR, "Can not parse pattern action.");
493 : 0 : return -EINVAL;
494 : : }
495 : : }
496 : :
497 : : return 0;
498 : : }
499 : :
500 : : /**
501 : : * The patterns object array defines a set of rules directing the PMD to match sequences of
502 : : * rte_flow protocol headers and translate them into profile/field vectors for each pipeline
503 : : * stage. This object is mandatory.
504 : : */
505 : : static int
506 : 0 : cpfl_flow_js_pattern_rule(json_t *ob_root, struct cpfl_flow_js_parser *parser)
507 : : {
508 : : json_t *ob_prs;
509 : : int i, len;
510 : :
511 : : /* Pattern Rules */
512 : 0 : ob_prs = json_object_get(ob_root, "patterns");
513 [ # # ]: 0 : if (!ob_prs) {
514 : 0 : PMD_DRV_LOG(ERR, "The patterns is mandatory.");
515 : 0 : return -EINVAL;
516 : : }
517 : :
518 : 0 : len = json_array_size(ob_prs);
519 [ # # ]: 0 : if (len == 0)
520 : : return 0;
521 : 0 : parser->patterns = rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr) * len, 0);
522 [ # # ]: 0 : if (!parser->patterns) {
523 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory.");
524 : 0 : return -ENOMEM;
525 : : }
526 : 0 : parser->pr_size = len;
527 [ # # ]: 0 : for (i = 0; i < len; i++) {
528 : : json_t *object;
529 : : json_t *ob_pr_actions;
530 : : json_t *ob_pr_key;
531 : : json_t *ob_pr_key_protos;
532 : : json_t *ob_pr_key_attrs;
533 : : int ret;
534 : :
535 : 0 : object = json_array_get(ob_prs, i);
536 : : /* pr->key */
537 : 0 : ob_pr_key = json_object_get(object, "key");
538 : : /* pr->key->protocols */
539 : 0 : ob_pr_key_protos = json_object_get(ob_pr_key, "protocols");
540 : 0 : ret = cpfl_flow_js_pattern_key_proto(ob_pr_key_protos, &parser->patterns[i]);
541 [ # # ]: 0 : if (ret < 0) {
542 : 0 : PMD_DRV_LOG(ERR, "Can not parse key->protocols.");
543 : 0 : goto err;
544 : : }
545 : : /* pr->key->attributes */
546 : 0 : ob_pr_key_attrs = json_object_get(ob_pr_key, "attributes");
547 : 0 : ret = cpfl_flow_js_pattern_key_attr(ob_pr_key_attrs, &parser->patterns[i]);
548 [ # # ]: 0 : if (ret < 0) {
549 : 0 : PMD_DRV_LOG(ERR, "Can not parse key->attributes.");
550 : 0 : goto err;
551 : : }
552 : : /* pr->actions */
553 : 0 : ob_pr_actions = json_object_get(object, "actions");
554 : 0 : ret = cpfl_flow_js_pattern_act(ob_pr_actions, &parser->patterns[i]);
555 [ # # ]: 0 : if (ret < 0) {
556 : 0 : PMD_DRV_LOG(ERR, "Can not parse pattern action.");
557 : 0 : goto err;
558 : : }
559 : : }
560 : :
561 : : return 0;
562 : :
563 : 0 : err:
564 : 0 : rte_free(parser->patterns);
565 : 0 : return -EINVAL;
566 : : }
567 : :
568 : : static int
569 : 0 : cpfl_flow_js_mr_key(json_t *ob_mr_keys, struct cpfl_flow_js_mr_key *js_mr_key)
570 : : {
571 : : int len, i;
572 : :
573 : 0 : len = json_array_size(ob_mr_keys);
574 [ # # ]: 0 : if (len == 0)
575 : : return 0;
576 : 0 : js_mr_key->actions = rte_malloc(NULL, sizeof(struct cpfl_flow_js_mr_key_action) * len, 0);
577 [ # # ]: 0 : if (!js_mr_key->actions) {
578 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory.");
579 : 0 : return -ENOMEM;
580 : : }
581 : 0 : js_mr_key->actions_size = len;
582 [ # # ]: 0 : for (i = 0; i < len; i++) {
583 : : json_t *object, *ob_data;
584 : : const char *type;
585 : : enum rte_flow_action_type act_type;
586 : :
587 : 0 : object = json_array_get(ob_mr_keys, i);
588 : : /* mr->key->actions->type */
589 : 0 : type = cpfl_json_t_to_string(object, "type");
590 [ # # ]: 0 : if (!type) {
591 : 0 : PMD_DRV_LOG(ERR, "Can not parse string 'type'.");
592 : 0 : goto err;
593 : : }
594 : 0 : act_type = cpfl_get_action_type_by_str(type);
595 [ # # ]: 0 : if (act_type == RTE_FLOW_ACTION_TYPE_VOID)
596 : 0 : goto err;
597 : 0 : js_mr_key->actions[i].type = act_type;
598 : : /* mr->key->actions->data */
599 : 0 : ob_data = json_object_get(object, "data");
600 [ # # ]: 0 : if (js_mr_key->actions[i].type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) {
601 : : json_t *ob_protos;
602 : : int proto_size, j;
603 : : struct cpfl_flow_js_mr_key_action_vxlan_encap *encap;
604 : :
605 : 0 : ob_protos = json_object_get(ob_data, "protocols");
606 : 0 : encap = &js_mr_key->actions[i].encap;
607 [ # # ]: 0 : if (!ob_protos) {
608 : 0 : encap->proto_size = 0;
609 : 0 : continue;
610 : : }
611 : 0 : proto_size = json_array_size(ob_protos);
612 : 0 : encap->proto_size = proto_size;
613 [ # # ]: 0 : for (j = 0; j < proto_size; j++) {
614 : : const char *s;
615 : : json_t *subobject;
616 : : enum rte_flow_item_type proto_type;
617 : :
618 : 0 : subobject = json_array_get(ob_protos, j);
619 : 0 : s = json_string_value(subobject);
620 : 0 : proto_type = cpfl_get_item_type_by_str(s);
621 [ # # ]: 0 : if (proto_type == RTE_FLOW_ITEM_TYPE_VOID) {
622 : 0 : PMD_DRV_LOG(ERR, "parse VXLAN_ENCAP failed.");
623 : 0 : goto err;
624 : : }
625 : 0 : encap->protocols[j] = proto_type;
626 : : }
627 [ # # ]: 0 : } else if (js_mr_key->actions[i].type == RTE_FLOW_ACTION_TYPE_PROG) {
628 : : int ret;
629 : : uint32_t param_size, j;
630 : 0 : uint16_t value = 0;
631 : : json_t *ob_param, *subobject;
632 : : const char *name;
633 : :
634 : 0 : ret = cpfl_json_t_to_uint32(object, "id", &js_mr_key->actions[i].prog.id);
635 [ # # ]: 0 : if (ret < 0) {
636 : 0 : PMD_DRV_LOG(ERR, "Can not parse uint32 'id'.");
637 : 0 : goto err;
638 : : }
639 [ # # ]: 0 : if (json_object_get(object, "name")) {
640 : 0 : js_mr_key->actions[i].prog.has_name = TRUE;
641 : 0 : name = cpfl_json_t_to_string(object, "name");
642 [ # # ]: 0 : if (!name) {
643 : 0 : PMD_DRV_LOG(ERR, "Can not parse string 'name'.");
644 : 0 : goto err;
645 : : }
646 [ # # ]: 0 : if (strlen(name) > CPFL_JS_STR_SIZE - 1) {
647 : 0 : PMD_DRV_LOG(ERR, "The 'name' is too long.");
648 : 0 : goto err;
649 : : }
650 : 0 : strncpy(js_mr_key->actions[i].prog.name, name,
651 : : CPFL_JS_STR_SIZE - 1);
652 : : }
653 : :
654 : 0 : ob_param = json_object_get(object, "parameters");
655 : 0 : param_size = json_array_size(ob_param);
656 : 0 : js_mr_key->actions[i].prog.param_size = param_size;
657 [ # # ]: 0 : for (j = 0; j < param_size; j++) {
658 : 0 : subobject = json_array_get(ob_param, j);
659 : 0 : ret = cpfl_json_t_to_uint16(subobject, "index", &value);
660 [ # # ]: 0 : if (ret < 0) {
661 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'index'.");
662 : 0 : goto err;
663 : : }
664 : 0 : js_mr_key->actions[i].prog.params[j].index = value;
665 [ # # ]: 0 : if (json_object_get(subobject, "name")) {
666 : 0 : js_mr_key->actions[i].prog.params[j].has_name = TRUE;
667 : 0 : name = cpfl_json_t_to_string(subobject, "name");
668 [ # # ]: 0 : if (!name) {
669 : 0 : PMD_DRV_LOG(ERR, "Can not parse string 'name'.");
670 : 0 : goto err;
671 : : }
672 [ # # ]: 0 : if (strlen(name) > CPFL_JS_STR_SIZE - 1) {
673 : 0 : PMD_DRV_LOG(ERR, "The 'name' is too long.");
674 : 0 : goto err;
675 : : }
676 : 0 : strncpy(js_mr_key->actions[i].prog.params[j].name, name,
677 : : CPFL_JS_STR_SIZE - 1);
678 : : }
679 : 0 : ret = cpfl_json_t_to_uint16(subobject, "size", &value);
680 [ # # ]: 0 : if (ret < 0) {
681 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'size'.");
682 : 0 : goto err;
683 : : }
684 : 0 : js_mr_key->actions[i].prog.params[j].size = value;
685 : : }
686 : :
687 [ # # ]: 0 : } else if (js_mr_key->actions[i].type != RTE_FLOW_ACTION_TYPE_VXLAN_DECAP) {
688 : 0 : PMD_DRV_LOG(ERR, "not support this type: %d.", js_mr_key->actions[i].type);
689 : 0 : goto err;
690 : : }
691 : : }
692 : :
693 : : return 0;
694 : :
695 : 0 : err:
696 : 0 : rte_free(js_mr_key->actions);
697 : 0 : return -EINVAL;
698 : : }
699 : :
700 : : static int
701 : 0 : cpfl_flow_js_mr_layout(json_t *ob_layouts, struct cpfl_flow_js_mr_action_mod *js_mod)
702 : : {
703 : : int len, i;
704 : :
705 : 0 : len = json_array_size(ob_layouts);
706 : 0 : js_mod->layout_size = len;
707 [ # # ]: 0 : if (len == 0)
708 : : return 0;
709 : :
710 [ # # ]: 0 : for (i = 0; i < len; i++) {
711 : : json_t *object;
712 : 0 : int index = 0, size = 0, offset = 0;
713 : : int ret;
714 : : const char *hint;
715 : :
716 : 0 : object = json_array_get(ob_layouts, i);
717 : 0 : ret = cpfl_json_t_to_int(object, "index", &index);
718 [ # # ]: 0 : if (ret < 0) {
719 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'index'.");
720 : 0 : goto err;
721 : : }
722 : 0 : js_mod->layout[i].index = index;
723 : 0 : ret = cpfl_json_t_to_int(object, "size", &size);
724 [ # # ]: 0 : if (ret < 0) {
725 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'size'.");
726 : 0 : goto err;
727 : : }
728 : 0 : js_mod->layout[i].size = size;
729 : 0 : ret = cpfl_json_t_to_int(object, "offset", &offset);
730 [ # # ]: 0 : if (ret < 0) {
731 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'offset'.");
732 : 0 : goto err;
733 : : }
734 : 0 : js_mod->layout[i].offset = offset;
735 : 0 : hint = cpfl_json_t_to_string(object, "hint");
736 [ # # ]: 0 : if (!hint) {
737 : 0 : PMD_DRV_LOG(ERR, "Can not parse string 'hint'.");
738 : 0 : goto err;
739 : : }
740 [ # # ]: 0 : if (strlen(hint) > CPFL_JS_STR_SIZE - 1) {
741 : 0 : PMD_DRV_LOG(ERR, "The 'hint' is too long.");
742 : 0 : goto err;
743 : : }
744 : 0 : strncpy(js_mod->layout[i].hint, hint, CPFL_JS_STR_SIZE - 1);
745 : : }
746 : :
747 : : return 0;
748 : :
749 : : err:
750 : 0 : return -EINVAL;
751 : : }
752 : :
753 : : static int
754 : 0 : cpfl_flow_js_mr_content(json_t *ob_content, struct cpfl_flow_js_mr_action_mod *js_mod)
755 : : {
756 : : int ret, len, i;
757 : : json_t *ob_field;
758 : :
759 [ # # ]: 0 : if (!ob_content)
760 : : return 0;
761 : :
762 : 0 : js_mod->is_content = TRUE;
763 : 0 : ret = cpfl_json_t_to_uint16(ob_content, "size", &js_mod->content.size);
764 [ # # ]: 0 : if (ret < 0) {
765 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'size'.");
766 : 0 : return -EINVAL;
767 : : }
768 : :
769 : 0 : ob_field = json_object_get(ob_content, "fields");
770 : 0 : len = json_array_size(ob_field);
771 : 0 : js_mod->content.field_size = len;
772 [ # # ]: 0 : if (len == 0)
773 : : return 0;
774 : :
775 [ # # ]: 0 : for (i = 0; i < len; i++) {
776 : : json_t *object;
777 : 0 : uint16_t start = 0, width = 0, index = 0;
778 : : const char *type;
779 : :
780 : 0 : object = json_array_get(ob_field, i);
781 : 0 : type = cpfl_json_t_to_string(object, "type");
782 [ # # ]: 0 : if (!type) {
783 : 0 : PMD_DRV_LOG(ERR, "Can not parse string 'type'.");
784 : 0 : goto err;
785 : : }
786 [ # # ]: 0 : if (strlen(type) > CPFL_JS_STR_SIZE - 1) {
787 : 0 : PMD_DRV_LOG(ERR, "The 'type' is too long.");
788 : 0 : goto err;
789 : : }
790 : 0 : strncpy(js_mod->content.fields[i].type, type, CPFL_JS_STR_SIZE - 1);
791 : 0 : ret = cpfl_json_t_to_uint16(object, "start", &start);
792 [ # # ]: 0 : if (ret < 0) {
793 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'start'.");
794 : 0 : goto err;
795 : : }
796 : 0 : js_mod->content.fields[i].start = start;
797 : 0 : ret = cpfl_json_t_to_uint16(object, "width", &width);
798 [ # # ]: 0 : if (ret < 0) {
799 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'width'.");
800 : 0 : goto err;
801 : : }
802 : 0 : js_mod->content.fields[i].width = width;
803 [ # # ]: 0 : if (strcmp(type, "parameter") == 0) {
804 : 0 : ret = cpfl_json_t_to_uint16(object, "index", &index);
805 [ # # ]: 0 : if (ret < 0) {
806 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'index'.");
807 : 0 : goto err;
808 : : }
809 : 0 : js_mod->content.fields[i].index = index;
810 [ # # ]: 0 : } else if (strcmp(type, "constant") == 0) {
811 : : json_t *ob_value, *subobj;
812 : : int value_len, j;
813 : :
814 : 0 : ob_value = json_object_get(object, "value");
815 : 0 : value_len = json_array_size(ob_value);
816 [ # # ]: 0 : for (j = 0; j < value_len; j++) {
817 : 0 : subobj = json_array_get(ob_value, j);
818 : 0 : js_mod->content.fields[i].value[j] =
819 : 0 : (uint8_t)json_integer_value(subobj);
820 : : }
821 : : }
822 : : }
823 : :
824 : : return 0;
825 : :
826 : : err:
827 : 0 : return -EINVAL;
828 : : }
829 : :
830 : : static int
831 : 0 : cpfl_flow_js_mr_action(json_t *ob_mr_act, struct cpfl_flow_js_mr_action *js_mr_act)
832 : : {
833 : : json_t *ob_data;
834 : : const char *type;
835 : :
836 : : /* mr->action->type */
837 : 0 : type = cpfl_json_t_to_string(ob_mr_act, "type");
838 [ # # ]: 0 : if (!type) {
839 : 0 : PMD_DRV_LOG(ERR, "Can not parse string 'type'.");
840 : 0 : return -EINVAL;
841 : : }
842 : : /* mr->action->data */
843 : 0 : ob_data = json_object_get(ob_mr_act, "data");
844 [ # # ]: 0 : if (strcmp(type, "mod") == 0) {
845 : : json_t *ob_layouts, *ob_content;
846 : 0 : uint16_t profile = 0;
847 : : int ret;
848 : :
849 : 0 : js_mr_act->type = CPFL_JS_MR_ACTION_TYPE_MOD;
850 : 0 : ret = cpfl_json_t_to_uint16(ob_data, "profile", &profile);
851 [ # # ]: 0 : if (ret < 0) {
852 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'profile'.");
853 : 0 : return -EINVAL;
854 : : }
855 : 0 : js_mr_act->mod.prof = profile;
856 : 0 : ob_layouts = json_object_get(ob_data, "layout");
857 : 0 : ret = cpfl_flow_js_mr_layout(ob_layouts, &js_mr_act->mod);
858 [ # # ]: 0 : if (ret < 0) {
859 : 0 : PMD_DRV_LOG(ERR, "Can not parse layout.");
860 : 0 : return ret;
861 : : }
862 : 0 : ob_content = json_object_get(ob_data, "content");
863 : 0 : ret = cpfl_flow_js_mr_content(ob_content, &js_mr_act->mod);
864 [ # # ]: 0 : if (ret < 0) {
865 : 0 : PMD_DRV_LOG(ERR, "Can not parse 'content'.");
866 : 0 : return ret;
867 : : }
868 : : } else {
869 : 0 : PMD_DRV_LOG(ERR, "not support this type: %s.", type);
870 : 0 : return -EINVAL;
871 : : }
872 : :
873 : 0 : return 0;
874 : : }
875 : :
876 : : /**
877 : : * The modifications object array defines a set of rules for the PMD to match rte_flow
878 : : * modification actions and translate them into the Modification profile. This object
879 : : * is optional.
880 : : */
881 : : static int
882 : 0 : cpfl_flow_js_mod_rule(json_t *ob_root, struct cpfl_flow_js_parser *parser)
883 : : {
884 : : json_t *ob_mrs;
885 : : int i, len;
886 : :
887 : 0 : ob_mrs = json_object_get(ob_root, "modifications");
888 [ # # ]: 0 : if (!ob_mrs) {
889 : 0 : PMD_DRV_LOG(INFO, "The modifications is optional.");
890 : 0 : return 0;
891 : : }
892 : 0 : len = json_array_size(ob_mrs);
893 [ # # ]: 0 : if (len == 0)
894 : : return 0;
895 : 0 : parser->mr_size = len;
896 : 0 : parser->modifications = rte_malloc(NULL, sizeof(struct cpfl_flow_js_mr) * len, 0);
897 [ # # ]: 0 : if (!parser->modifications) {
898 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory.");
899 : 0 : return -ENOMEM;
900 : : }
901 [ # # ]: 0 : for (i = 0; i < len; i++) {
902 : : int ret;
903 : : json_t *object, *ob_mr_key, *ob_mr_action, *ob_mr_key_action;
904 : :
905 : 0 : object = json_array_get(ob_mrs, i);
906 : : /* mr->key */
907 : 0 : ob_mr_key = json_object_get(object, "key");
908 : : /* mr->key->actions */
909 : 0 : ob_mr_key_action = json_object_get(ob_mr_key, "actions");
910 : 0 : ret = cpfl_flow_js_mr_key(ob_mr_key_action, &parser->modifications[i].key);
911 [ # # ]: 0 : if (ret < 0) {
912 : 0 : PMD_DRV_LOG(ERR, "parse mr_key failed.");
913 : 0 : goto err;
914 : : }
915 : : /* mr->action */
916 : 0 : ob_mr_action = json_object_get(object, "action");
917 : 0 : ret = cpfl_flow_js_mr_action(ob_mr_action, &parser->modifications[i].action);
918 [ # # ]: 0 : if (ret < 0) {
919 : 0 : PMD_DRV_LOG(ERR, "parse mr_action failed.");
920 : 0 : goto err;
921 : : }
922 : : }
923 : :
924 : : return 0;
925 : :
926 : 0 : err:
927 : 0 : rte_free(parser->modifications);
928 : 0 : return -EINVAL;
929 : : }
930 : :
931 : : static int
932 : 0 : cpfl_parser_init(json_t *ob_root, struct cpfl_flow_js_parser *parser)
933 : : {
934 : : int ret = 0;
935 : :
936 : 0 : ret = cpfl_flow_js_pattern_rule(ob_root, parser);
937 [ # # ]: 0 : if (ret < 0) {
938 : 0 : PMD_DRV_LOG(ERR, "parse pattern_rule failed.");
939 : 0 : return ret;
940 : : }
941 : 0 : ret = cpfl_flow_js_mod_rule(ob_root, parser);
942 [ # # ]: 0 : if (ret < 0) {
943 : 0 : PMD_DRV_LOG(ERR, "parse mod_rule failed.");
944 : 0 : return ret;
945 : : }
946 : :
947 : : return 0;
948 : : }
949 : :
950 : : int
951 : 0 : cpfl_parser_create(struct cpfl_flow_js_parser **flow_parser, const char *filename)
952 : : {
953 : : struct cpfl_flow_js_parser *parser;
954 : : json_error_t json_error;
955 : : json_t *root;
956 : : int ret;
957 : :
958 : 0 : parser = rte_zmalloc("flow_parser", sizeof(struct cpfl_flow_js_parser), 0);
959 [ # # ]: 0 : if (!parser) {
960 : 0 : PMD_DRV_LOG(ERR, "Not enough memory to create flow parser.");
961 : 0 : return -ENOMEM;
962 : : }
963 : 0 : root = json_load_file(filename, 0, &json_error);
964 [ # # ]: 0 : if (!root) {
965 : 0 : PMD_DRV_LOG(ERR, "Bad JSON file \"%s\": %s", filename, json_error.text);
966 : 0 : goto free_parser;
967 : : }
968 : 0 : ret = cpfl_parser_init(root, parser);
969 [ # # ]: 0 : if (ret < 0) {
970 : 0 : PMD_DRV_LOG(ERR, "parser init failed.");
971 : 0 : goto free_parser;
972 : : }
973 : 0 : *flow_parser = parser;
974 : 0 : json_decref(root);
975 : :
976 : 0 : return 0;
977 : 0 : free_parser:
978 : 0 : rte_free(parser);
979 : 0 : return -EINVAL;
980 : : }
981 : :
982 : : static void
983 : : cpfl_parser_free_pr_action(struct cpfl_flow_js_pr_action *pr_act)
984 : : {
985 : 0 : if (pr_act->type == CPFL_JS_PR_ACTION_TYPE_SEM)
986 : 0 : rte_free(pr_act->sem.fv);
987 : : }
988 : :
989 : : int
990 : 0 : cpfl_parser_destroy(struct cpfl_flow_js_parser *parser)
991 : : {
992 : : int i, j;
993 : :
994 [ # # ]: 0 : if (!parser)
995 : : return 0;
996 : :
997 [ # # ]: 0 : for (i = 0; i < parser->pr_size; i++) {
998 : 0 : struct cpfl_flow_js_pr *pattern = &parser->patterns[i];
999 : :
1000 [ # # ]: 0 : for (j = 0; j < pattern->key.proto_size; j++)
1001 : 0 : rte_free(pattern->key.protocols[j].fields);
1002 : 0 : rte_free(pattern->key.protocols);
1003 : 0 : rte_free(pattern->key.attributes);
1004 : :
1005 [ # # ]: 0 : for (j = 0; j < pattern->actions_size; j++) {
1006 : : struct cpfl_flow_js_pr_action *pr_act;
1007 : :
1008 [ # # ]: 0 : pr_act = &pattern->actions[j];
1009 : : cpfl_parser_free_pr_action(pr_act);
1010 : : }
1011 : 0 : rte_free(pattern->actions);
1012 : : }
1013 : 0 : rte_free(parser->patterns);
1014 [ # # ]: 0 : for (i = 0; i < parser->mr_size; i++) {
1015 : 0 : struct cpfl_flow_js_mr *mr = &parser->modifications[i];
1016 : :
1017 : 0 : rte_free(mr->key.actions);
1018 : : }
1019 : 0 : rte_free(parser->modifications);
1020 : 0 : rte_free(parser);
1021 : :
1022 : 0 : return 0;
1023 : : }
1024 : :
1025 : : static int
1026 : : cpfl_get_items_length(const struct rte_flow_item *items)
1027 : 0 : {
1028 : : int length = 0;
1029 : : const struct rte_flow_item *item = items;
1030 : :
1031 [ # # # # : 0 : while ((item + length++)->type != RTE_FLOW_ITEM_TYPE_END)
# # # # ]
1032 : 0 : continue;
1033 : : return length;
1034 : : }
1035 : :
1036 : : static int
1037 : : cpfl_get_actions_length(const struct rte_flow_action *actions)
1038 : 0 : {
1039 : : int length = 0;
1040 : : const struct rte_flow_action *action = actions;
1041 : :
1042 [ # # ]: 0 : while ((action + length++)->type != RTE_FLOW_ACTION_TYPE_END)
1043 : 0 : continue;
1044 : : return length;
1045 : : }
1046 : :
1047 : : static int
1048 : 0 : cpfl_parse_fv_protocol(struct cpfl_flow_js_fv *js_fv, const struct rte_flow_item *items,
1049 : : uint16_t offset, uint8_t *fv)
1050 : : {
1051 : : uint16_t v_layer, v_offset, v_mask;
1052 : : enum rte_flow_item_type v_header;
1053 : : int j, layer, length;
1054 : : uint16_t temp_fv;
1055 : :
1056 : : length = cpfl_get_items_length(items);
1057 : 0 : v_layer = js_fv->proto.layer;
1058 : 0 : v_header = js_fv->proto.header;
1059 : 0 : v_offset = js_fv->proto.offset;
1060 : 0 : v_mask = js_fv->proto.mask;
1061 : : layer = 0;
1062 [ # # ]: 0 : for (j = 0; j < length - 1; j++) {
1063 [ # # ]: 0 : if (items[j].type == v_header) {
1064 [ # # ]: 0 : if (layer == v_layer) {
1065 : : /* copy out 16 bits from offset */
1066 : : const uint8_t *pointer;
1067 : :
1068 : 0 : pointer = &(((const uint8_t *)(items[j].spec))[v_offset]);
1069 : 0 : temp_fv = ntohs((*((const uint16_t *)pointer)) & v_mask);
1070 : 0 : fv[2 * offset] = (uint8_t)(temp_fv >> 8);
1071 : 0 : fv[2 * offset + 1] = (uint8_t)(temp_fv & 0x00ff);
1072 : 0 : break;
1073 : : }
1074 : 0 : layer++;
1075 : : }
1076 : : }
1077 : :
1078 : 0 : return 0;
1079 : : }
1080 : :
1081 : : static int
1082 : 0 : cpfl_parse_fieldvectors(struct cpfl_itf *itf, struct cpfl_flow_js_fv *js_fvs, int size,
1083 : : uint8_t *fv, const struct rte_flow_item *items)
1084 : : {
1085 : : int i, ret;
1086 : :
1087 [ # # ]: 0 : for (i = 0; i < size; i++) {
1088 : : uint16_t offset, temp_fv, value_int;
1089 : : enum cpfl_flow_js_fv_type type;
1090 : : struct cpfl_flow_js_fv *js_fv;
1091 : :
1092 : 0 : js_fv = &js_fvs[i];
1093 : 0 : offset = js_fv->offset;
1094 : 0 : type = js_fv->type;
1095 [ # # ]: 0 : if (type == CPFL_FV_TYPE_IMMEDIATE) {
1096 : 0 : value_int = js_fv->immediate;
1097 : 0 : temp_fv = (value_int << 8) & 0xff00;
1098 : 0 : fv[2 * offset] = (uint8_t)(temp_fv >> 8);
1099 : 0 : fv[2 * offset + 1] = (uint8_t)(temp_fv & 0x00ff);
1100 [ # # ]: 0 : } else if (type == CPFL_FV_TYPE_METADATA) {
1101 : : uint16_t type, v_offset, mask;
1102 : :
1103 : 0 : type = js_fv->meta.type;
1104 : 0 : v_offset = js_fv->meta.offset;
1105 : 0 : mask = js_fv->meta.mask;
1106 : 0 : temp_fv = cpfl_metadata_read16(&itf->adapter->meta, type, v_offset) & mask;
1107 : 0 : fv[2 * offset] = (uint8_t)(temp_fv & 0x00ff);
1108 : 0 : fv[2 * offset + 1] = (uint8_t)(temp_fv >> 8);
1109 [ # # ]: 0 : } else if (type == CPFL_FV_TYPE_PROTOCOL) {
1110 : 0 : ret = cpfl_parse_fv_protocol(js_fv, items, offset, fv);
1111 [ # # ]: 0 : if (ret)
1112 : 0 : return ret;
1113 : : } else {
1114 : 0 : PMD_DRV_LOG(DEBUG, "not support this type: %d.", type);
1115 : 0 : return -EINVAL;
1116 : : }
1117 : : }
1118 : :
1119 : : return 0;
1120 : : }
1121 : :
1122 : : static int
1123 : 0 : cpfl_parse_pr_actions(struct cpfl_itf *itf,
1124 : : struct cpfl_flow_js_pr_action *actions,
1125 : : int size,
1126 : : const struct rte_flow_item *items,
1127 : : const struct rte_flow_attr *attr,
1128 : : struct cpfl_flow_pr_action *pr_action)
1129 : : {
1130 : : int i, ret;
1131 : :
1132 [ # # ]: 0 : for (i = 0; i < size; i++) {
1133 : : struct cpfl_flow_js_pr_action *pr_act;
1134 : : enum cpfl_flow_pr_action_type type;
1135 : :
1136 : 0 : pr_act = &actions[i];
1137 : : /* pr->actions->type */
1138 : 0 : type = pr_act->type;
1139 : : /* pr->actions->data */
1140 [ # # # # ]: 0 : if (attr->group == 1 && type == CPFL_JS_PR_ACTION_TYPE_SEM) {
1141 : : struct cpfl_flow_js_pr_action_sem *sem = &pr_act->sem;
1142 : :
1143 : 0 : pr_action->type = CPFL_JS_PR_ACTION_TYPE_SEM;
1144 : 0 : pr_action->sem.prof = sem->prof;
1145 : 0 : pr_action->sem.subprof = sem->subprof;
1146 : 0 : pr_action->sem.keysize = sem->keysize;
1147 : 0 : memset(pr_action->sem.cpfl_flow_pr_fv, 0,
1148 : : sizeof(pr_action->sem.cpfl_flow_pr_fv));
1149 : 0 : ret = cpfl_parse_fieldvectors(itf, sem->fv, sem->fv_size,
1150 : : pr_action->sem.cpfl_flow_pr_fv, items);
1151 : 0 : return ret;
1152 [ # # ]: 0 : } else if (attr->group > 4 || attr->group == 0) {
1153 : : return -EPERM;
1154 : : }
1155 : : }
1156 : :
1157 : : return 0;
1158 : : }
1159 : :
1160 : : static int
1161 : 0 : cpfl_check_eth_mask(const char *mask, struct rte_ether_addr addr)
1162 : : {
1163 : : int i, ret;
1164 : : struct rte_ether_addr mask_bytes;
1165 : :
1166 : 0 : ret = rte_ether_unformat_addr(mask, &mask_bytes);
1167 [ # # ]: 0 : if (ret < 0) {
1168 : 0 : PMD_DRV_LOG(ERR, "translate mac address from string to rte_ether_addr failed.");
1169 : 0 : return -EINVAL;
1170 : : }
1171 : : /* validate eth mask addr if match */
1172 [ # # ]: 0 : for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
1173 [ # # ]: 0 : if (mask_bytes.addr_bytes[i] != addr.addr_bytes[i])
1174 : : return -EINVAL;
1175 : : }
1176 : :
1177 : : return 0;
1178 : : }
1179 : :
1180 : : static int
1181 : : cpfl_check_ipv4_mask(const char *mask, rte_be32_t addr)
1182 : : {
1183 : : uint32_t out_addr;
1184 : :
1185 : : /* 0: success; -EINVAL: invalid; -ENOTSUP: fail */
1186 : 0 : int ret = inet_pton(AF_INET, mask, &out_addr);
1187 : :
1188 [ # # # # ]: 0 : if (ret < 0)
1189 : : return -EINVAL;
1190 : : /* validate ipv4 mask addr if match */
1191 [ # # # # ]: 0 : if (out_addr != addr)
1192 : : return -EINVAL;
1193 : :
1194 : : return 0;
1195 : : }
1196 : :
1197 : : static int
1198 : 0 : cpfl_check_eth(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_eth *eth_mask)
1199 : : {
1200 : : int field_size, j;
1201 : : int flag_dst_addr, flag_src_addr, flag_ether_type;
1202 : : struct cpfl_flow_js_pr_key_proto_field *field;
1203 : :
1204 [ # # ]: 0 : if (!proto)
1205 : : return 0;
1206 : 0 : field_size = proto->fields_size;
1207 [ # # ]: 0 : if (field_size != 0 && !eth_mask)
1208 : : return -EINVAL;
1209 : :
1210 [ # # ]: 0 : if (field_size == 0 && eth_mask)
1211 : : return -EINVAL;
1212 : :
1213 [ # # ]: 0 : if (field_size == 0 && !eth_mask)
1214 : : return 0;
1215 : :
1216 : : flag_dst_addr = false;
1217 : : flag_src_addr = false;
1218 : : flag_ether_type = false;
1219 [ # # ]: 0 : for (j = 0; j < field_size; j++) {
1220 : : const char *name, *s_mask;
1221 : :
1222 : 0 : field = &proto->fields[j];
1223 : : /* match: rte_flow_item_eth.dst, more see Field Mapping
1224 : : */
1225 : 0 : name = field->name;
1226 : : /* match: rte_flow_item->mask */
1227 [ # # ]: 0 : if (strcmp(name, "src_addr") == 0) {
1228 : 0 : s_mask = field->mask;
1229 [ # # ]: 0 : if (cpfl_check_eth_mask(s_mask, eth_mask->src) < 0)
1230 : : return -EINVAL;
1231 : : flag_src_addr = true;
1232 [ # # ]: 0 : } else if (strcmp(name, "dst_addr") == 0) {
1233 : 0 : s_mask = field->mask;
1234 [ # # ]: 0 : if (cpfl_check_eth_mask(s_mask, eth_mask->dst) < 0)
1235 : : return -EINVAL;
1236 : : flag_dst_addr = true;
1237 [ # # ]: 0 : } else if (strcmp(name, "ether_type") == 0) {
1238 : 0 : uint16_t mask = (uint16_t)field->mask_32b;
1239 : :
1240 [ # # ]: 0 : if (mask != eth_mask->type)
1241 : : return -EINVAL;
1242 : : flag_ether_type = true;
1243 : : } else {
1244 : : /* TODO: more type... */
1245 : 0 : PMD_DRV_LOG(ERR, "not support this name.");
1246 : 0 : return -EINVAL;
1247 : : }
1248 : : }
1249 [ # # ]: 0 : if (!flag_src_addr) {
1250 [ # # ]: 0 : if (strcmp((const char *)eth_mask->src.addr_bytes, "\x00\x00\x00\x00\x00\x00") != 0)
1251 : : return -EINVAL;
1252 : : }
1253 [ # # ]: 0 : if (!flag_dst_addr) {
1254 [ # # ]: 0 : if (strcmp((const char *)eth_mask->dst.addr_bytes, "\x00\x00\x00\x00\x00\x00") != 0)
1255 : : return -EINVAL;
1256 : : }
1257 [ # # ]: 0 : if (!flag_ether_type) {
1258 [ # # ]: 0 : if (eth_mask->hdr.ether_type != (rte_be16_t)0)
1259 : 0 : return -EINVAL;
1260 : : }
1261 : :
1262 : : return 0;
1263 : : }
1264 : :
1265 : : static int
1266 : 0 : cpfl_check_ipv4(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_ipv4 *ipv4_mask)
1267 : : {
1268 : : int field_size, j;
1269 : : int flag_next_proto_id, flag_src_addr, flag_dst_addr;
1270 : : struct cpfl_flow_js_pr_key_proto_field *field;
1271 : :
1272 [ # # ]: 0 : if (!proto)
1273 : : return 0;
1274 : :
1275 : 0 : field_size = proto->fields_size;
1276 [ # # ]: 0 : if (field_size != 0 && !ipv4_mask)
1277 : : return -EINVAL;
1278 : :
1279 [ # # ]: 0 : if (field_size == 0 && ipv4_mask)
1280 : : return -EINVAL;
1281 : :
1282 [ # # ]: 0 : if (field_size == 0 && !ipv4_mask)
1283 : : return 0;
1284 : :
1285 : : flag_dst_addr = false;
1286 : : flag_src_addr = false;
1287 : : flag_next_proto_id = false;
1288 [ # # ]: 0 : for (j = 0; j < field_size; j++) {
1289 : : const char *name;
1290 : :
1291 : 0 : field = &proto->fields[j];
1292 : 0 : name = field->name;
1293 [ # # ]: 0 : if (strcmp(name, "src_addr") == 0) {
1294 : : const char *mask;
1295 : :
1296 : 0 : mask = field->mask;
1297 : 0 : if (cpfl_check_ipv4_mask(mask, ipv4_mask->hdr.src_addr) < 0)
1298 : 0 : return -EINVAL;
1299 : : flag_src_addr = true;
1300 [ # # ]: 0 : } else if (strcmp(name, "dst_addr") == 0) {
1301 : : const char *mask;
1302 : :
1303 : 0 : mask = field->mask;
1304 : 0 : if (cpfl_check_ipv4_mask(mask, ipv4_mask->hdr.dst_addr) < 0)
1305 : 0 : return -EINVAL;
1306 : : flag_dst_addr = true;
1307 [ # # ]: 0 : } else if (strcmp(name, "next_proto_id") == 0) {
1308 : : uint8_t mask;
1309 : :
1310 : 0 : mask = (uint8_t)field->mask_32b;
1311 [ # # ]: 0 : if (mask != ipv4_mask->hdr.next_proto_id)
1312 : : return -EINVAL;
1313 : : flag_next_proto_id = true;
1314 : : } else {
1315 : 0 : PMD_DRV_LOG(ERR, "not support this name.");
1316 : 0 : return -EINVAL;
1317 : : }
1318 : : }
1319 [ # # ]: 0 : if (!flag_src_addr) {
1320 [ # # ]: 0 : if (ipv4_mask->hdr.src_addr != (rte_be32_t)0)
1321 : : return -EINVAL;
1322 : : }
1323 [ # # ]: 0 : if (!flag_dst_addr) {
1324 [ # # ]: 0 : if (ipv4_mask->hdr.dst_addr != (rte_be32_t)0)
1325 : : return -EINVAL;
1326 : : }
1327 [ # # ]: 0 : if (!flag_next_proto_id) {
1328 [ # # ]: 0 : if (ipv4_mask->hdr.next_proto_id != (uint8_t)0)
1329 : 0 : return -EINVAL;
1330 : : }
1331 : :
1332 : : return 0;
1333 : : }
1334 : :
1335 : : static int
1336 : 0 : cpfl_check_tcp(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_tcp *tcp_mask)
1337 : : {
1338 : : int field_size, j;
1339 : : int flag_src_port, flag_dst_port;
1340 : : struct cpfl_flow_js_pr_key_proto_field *field;
1341 : :
1342 [ # # ]: 0 : if (!proto)
1343 : : return 0;
1344 : :
1345 : 0 : field_size = proto->fields_size;
1346 [ # # ]: 0 : if (field_size != 0 && !tcp_mask)
1347 : : return -EINVAL;
1348 : :
1349 [ # # ]: 0 : if (field_size == 0 && tcp_mask)
1350 : : return -EINVAL;
1351 : :
1352 [ # # ]: 0 : if (field_size == 0 && !tcp_mask)
1353 : : return 0;
1354 : :
1355 : : flag_src_port = false;
1356 : : flag_dst_port = false;
1357 [ # # ]: 0 : for (j = 0; j < field_size; j++) {
1358 : : const char *name;
1359 : : uint16_t mask;
1360 : :
1361 : 0 : field = &proto->fields[j];
1362 : 0 : name = field->name;
1363 : 0 : mask = (uint16_t)field->mask_32b;
1364 [ # # ]: 0 : if (strcmp(name, "src_port") == 0) {
1365 [ # # ]: 0 : if (tcp_mask->hdr.src_port != mask)
1366 : : return -EINVAL;
1367 : : flag_src_port = true;
1368 [ # # ]: 0 : } else if (strcmp(name, "dst_port") == 0) {
1369 [ # # ]: 0 : if (tcp_mask->hdr.dst_port != mask)
1370 : : return -EINVAL;
1371 : : flag_dst_port = true;
1372 : : } else {
1373 : 0 : PMD_DRV_LOG(ERR, "not support this name.");
1374 : 0 : return -EINVAL;
1375 : : }
1376 : : }
1377 [ # # ]: 0 : if (!flag_src_port) {
1378 [ # # ]: 0 : if (tcp_mask->hdr.src_port != (rte_be16_t)0)
1379 : : return -EINVAL;
1380 : : }
1381 [ # # ]: 0 : if (!flag_dst_port) {
1382 [ # # ]: 0 : if (tcp_mask->hdr.dst_port != (rte_be16_t)0)
1383 : 0 : return -EINVAL;
1384 : : }
1385 : :
1386 : : return 0;
1387 : : }
1388 : :
1389 : : static int
1390 : 0 : cpfl_check_udp(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_udp *udp_mask)
1391 : : {
1392 : : int field_size, j;
1393 : : bool flag_src_port, flag_dst_port;
1394 : : struct cpfl_flow_js_pr_key_proto_field *field;
1395 : :
1396 [ # # ]: 0 : if (!proto)
1397 : : return 0;
1398 : 0 : field_size = proto->fields_size;
1399 [ # # ]: 0 : if (field_size != 0 && !udp_mask)
1400 : : return -EINVAL;
1401 [ # # ]: 0 : if (field_size == 0 && udp_mask)
1402 : : return -EINVAL;
1403 [ # # ]: 0 : if (field_size == 0 && !udp_mask)
1404 : : return 0;
1405 : : flag_src_port = false;
1406 : : flag_dst_port = false;
1407 [ # # ]: 0 : for (j = 0; j < field_size; j++) {
1408 : : const char *name;
1409 : : uint16_t mask;
1410 : :
1411 : 0 : field = &proto->fields[j];
1412 : : /* match: rte_flow_item_eth.dst */
1413 : 0 : name = field->name; /* match: rte_flow_item->mask */
1414 : 0 : mask = (uint16_t)field->mask_32b;
1415 [ # # ]: 0 : if (strcmp(name, "src_port") == 0) {
1416 [ # # ]: 0 : if (udp_mask->hdr.src_port != mask)
1417 : : return -EINVAL;
1418 : : flag_src_port = true;
1419 [ # # ]: 0 : } else if (strcmp(name, "dst_port") == 0) {
1420 [ # # ]: 0 : if (udp_mask->hdr.dst_port != mask)
1421 : : return -EINVAL;
1422 : : flag_dst_port = true;
1423 : : } else {
1424 : 0 : PMD_DRV_LOG(ERR, "not support this name: %s.", name);
1425 : 0 : return -EINVAL;
1426 : : }
1427 : : }
1428 [ # # ]: 0 : if (!flag_src_port) {
1429 [ # # ]: 0 : if (udp_mask->hdr.src_port != (rte_be16_t)0)
1430 : : return -EINVAL;
1431 : : }
1432 [ # # ]: 0 : if (!flag_dst_port) {
1433 [ # # ]: 0 : if (udp_mask->hdr.dst_port != (rte_be16_t)0)
1434 : 0 : return -EINVAL;
1435 : : }
1436 : :
1437 : : return 0;
1438 : : }
1439 : :
1440 : : static int
1441 : 0 : cpfl_check_vxlan(struct cpfl_flow_js_pr_key_proto *proto,
1442 : : const struct rte_flow_item_vxlan *vxlan_mask)
1443 : : {
1444 : : int field_size, j;
1445 : : struct cpfl_flow_js_pr_key_proto_field *field;
1446 : :
1447 [ # # ]: 0 : if (!proto)
1448 : : return 0;
1449 : 0 : field_size = proto->fields_size;
1450 [ # # ]: 0 : if (field_size != 0 && !vxlan_mask)
1451 : : return -EINVAL;
1452 [ # # ]: 0 : if (field_size == 0 && vxlan_mask)
1453 : : return -EINVAL;
1454 [ # # ]: 0 : if (field_size == 0 && !vxlan_mask)
1455 : : return 0;
1456 [ # # ]: 0 : for (j = 0; j < field_size; j++) {
1457 : : const char *name;
1458 : : int64_t mask;
1459 : :
1460 : 0 : field = &proto->fields[j];
1461 : 0 : name = field->name;
1462 : : /* match: rte_flow_item->mask */
1463 : 0 : mask = (int64_t)field->mask_32b;
1464 [ # # ]: 0 : if (strcmp(name, "vx_vni") == 0) {
1465 [ # # ]: 0 : if ((int64_t)RTE_BE32(vxlan_mask->hdr.vx_vni) != mask)
1466 : : return -EINVAL;
1467 : : } else {
1468 : 0 : PMD_DRV_LOG(ERR, "not support this name.");
1469 : 0 : return -EINVAL;
1470 : : }
1471 : : }
1472 : :
1473 : : return 0;
1474 : : }
1475 : :
1476 : : static int
1477 : : cpfl_check_icmp(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_icmp *icmp_mask)
1478 : : {
1479 : : int field_size;
1480 : :
1481 : : if (!proto)
1482 : : return 0;
1483 : 0 : field_size = proto->fields_size;
1484 : 0 : if ((field_size != 0 && !icmp_mask) || (field_size == 0 && icmp_mask))
1485 : : return -EINVAL;
1486 : :
1487 : : return 0;
1488 : : }
1489 : :
1490 : : static int
1491 : 0 : cpfl_check_pattern_key_proto(struct cpfl_flow_js_pr_key_proto *protocols,
1492 : : int proto_size,
1493 : : const struct rte_flow_item *items)
1494 : : {
1495 : : int i, length;
1496 : : int j = 0;
1497 : :
1498 : : length = cpfl_get_items_length(items);
1499 [ # # ]: 0 : if (proto_size > length - 1)
1500 : : return -EINVAL;
1501 [ # # ]: 0 : for (i = 0; i < proto_size; i++) {
1502 : : struct cpfl_flow_js_pr_key_proto *key_proto;
1503 : : enum rte_flow_item_type type;
1504 : :
1505 : 0 : key_proto = &protocols[i];
1506 : : /* pr->key->proto->type */
1507 : 0 : type = key_proto->type;
1508 : : /* pr->key->proto->fields */
1509 [ # # # # : 0 : switch (type) {
# # # ]
1510 : 0 : case RTE_FLOW_ITEM_TYPE_ETH:
1511 [ # # ]: 0 : if (items[j++].type == RTE_FLOW_ITEM_TYPE_ETH) {
1512 : : const struct rte_flow_item_eth *eth_mask;
1513 : : int ret;
1514 : :
1515 : 0 : eth_mask = (const struct rte_flow_item_eth *)items[i].mask;
1516 : 0 : ret = cpfl_check_eth(key_proto, eth_mask);
1517 [ # # ]: 0 : if (ret < 0)
1518 : 0 : return ret;
1519 : : } else {
1520 : : return -EINVAL;
1521 : : }
1522 : : break;
1523 : 0 : case RTE_FLOW_ITEM_TYPE_IPV4:
1524 [ # # ]: 0 : if (items[j++].type == RTE_FLOW_ITEM_TYPE_IPV4) {
1525 : : const struct rte_flow_item_ipv4 *ipv4_mask;
1526 : : int ret;
1527 : :
1528 : 0 : ipv4_mask = (const struct rte_flow_item_ipv4 *)items[i].mask;
1529 : 0 : ret = cpfl_check_ipv4(key_proto, ipv4_mask);
1530 [ # # ]: 0 : if (ret < 0)
1531 : 0 : return ret;
1532 : : } else {
1533 : : return -EINVAL;
1534 : : }
1535 : : break;
1536 : 0 : case RTE_FLOW_ITEM_TYPE_TCP:
1537 [ # # ]: 0 : if (items[j++].type == RTE_FLOW_ITEM_TYPE_TCP) {
1538 : : const struct rte_flow_item_tcp *tcp_mask;
1539 : : int ret;
1540 : :
1541 : 0 : tcp_mask = (const struct rte_flow_item_tcp *)items[i].mask;
1542 : 0 : ret = cpfl_check_tcp(key_proto, tcp_mask);
1543 [ # # ]: 0 : if (ret < 0)
1544 : 0 : return ret;
1545 : : } else {
1546 : : return -EINVAL;
1547 : : }
1548 : : break;
1549 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
1550 [ # # ]: 0 : if (items[j++].type == RTE_FLOW_ITEM_TYPE_UDP) {
1551 : : const struct rte_flow_item_udp *udp_mask;
1552 : : int ret;
1553 : :
1554 : 0 : udp_mask = (const struct rte_flow_item_udp *)items[i].mask;
1555 : 0 : ret = cpfl_check_udp(key_proto, udp_mask);
1556 [ # # ]: 0 : if (ret < 0)
1557 : 0 : return ret;
1558 : : } else {
1559 : : return -EINVAL;
1560 : : }
1561 : : break;
1562 : 0 : case RTE_FLOW_ITEM_TYPE_VXLAN:
1563 [ # # ]: 0 : if (items[j++].type == RTE_FLOW_ITEM_TYPE_VXLAN) {
1564 : : const struct rte_flow_item_vxlan *vxlan_mask;
1565 : : int ret;
1566 : :
1567 : 0 : vxlan_mask = (const struct rte_flow_item_vxlan *)items[i].mask;
1568 : 0 : ret = cpfl_check_vxlan(key_proto, vxlan_mask);
1569 [ # # ]: 0 : if (ret < 0)
1570 : 0 : return ret;
1571 : : } else {
1572 : : return -EINVAL;
1573 : : }
1574 : : break;
1575 : 0 : case RTE_FLOW_ITEM_TYPE_ICMP:
1576 [ # # ]: 0 : if (items[j++].type == RTE_FLOW_ITEM_TYPE_ICMP) {
1577 : : const struct rte_flow_item_icmp *icmp_mask;
1578 : : int ret;
1579 : :
1580 [ # # ]: 0 : icmp_mask = (const struct rte_flow_item_icmp *)items[i].mask;
1581 : : ret = cpfl_check_icmp(key_proto, icmp_mask);
1582 : : if (ret < 0)
1583 : : return ret;
1584 : : } else {
1585 : : return -EINVAL;
1586 : : }
1587 : : break;
1588 : 0 : default:
1589 : 0 : PMD_DRV_LOG(ERR, "Not support this type: %d.", type);
1590 : 0 : return -EPERM;
1591 : : }
1592 : : }
1593 [ # # ]: 0 : if (items[j].type != RTE_FLOW_ITEM_TYPE_END)
1594 : 0 : return -EINVAL;
1595 : :
1596 : : return 0;
1597 : : }
1598 : :
1599 : : static int
1600 : 0 : cpfl_check_pattern_key_attr(struct cpfl_flow_js_pr_key_attr *key_attr,
1601 : : const struct rte_flow_attr *attr)
1602 : : {
1603 [ # # ]: 0 : if (key_attr->ingress != attr->ingress) {
1604 : 0 : PMD_DRV_LOG(DEBUG, "ingress not match.");
1605 : 0 : return -EINVAL;
1606 : : }
1607 [ # # ]: 0 : if (key_attr->egress != attr->egress) {
1608 : 0 : PMD_DRV_LOG(DEBUG, "egress not match.");
1609 : 0 : return -EINVAL;
1610 : : }
1611 : :
1612 : : return 0;
1613 : : }
1614 : :
1615 : : static int
1616 : 0 : cpfl_check_pattern_key(struct cpfl_flow_js_pr *pattern,
1617 : : const struct rte_flow_item *items,
1618 : : const struct rte_flow_attr *attr)
1619 : : {
1620 : : int ret;
1621 : :
1622 : : /* pr->key */
1623 : : /* pr->key->protocols */
1624 : 0 : ret = cpfl_check_pattern_key_proto(pattern->key.protocols,
1625 : 0 : pattern->key.proto_size, items);
1626 [ # # ]: 0 : if (ret < 0)
1627 : : return -EINVAL;
1628 : : /* pr->key->attributes */
1629 : 0 : ret = cpfl_check_pattern_key_attr(pattern->key.attributes, attr);
1630 [ # # ]: 0 : if (ret < 0)
1631 : 0 : return -EINVAL;
1632 : :
1633 : : return 0;
1634 : : }
1635 : :
1636 : : /* output: struct cpfl_flow_pr_action* pr_action */
1637 : : int
1638 : 0 : cpfl_flow_parse_items(struct cpfl_itf *itf,
1639 : : struct cpfl_flow_js_parser *parser,
1640 : : const struct rte_flow_item *items,
1641 : : const struct rte_flow_attr *attr,
1642 : : struct cpfl_flow_pr_action *pr_action)
1643 : : {
1644 : : int i, size;
1645 : : struct cpfl_flow_js_pr *pattern;
1646 : :
1647 : 0 : size = parser->pr_size;
1648 [ # # ]: 0 : for (i = 0; i < size; i++) {
1649 : : int ret;
1650 : :
1651 : 0 : pattern = &parser->patterns[i];
1652 : 0 : ret = cpfl_check_pattern_key(pattern, items, attr);
1653 [ # # ]: 0 : if (ret < 0)
1654 : : continue;
1655 : : /* pr->actions */
1656 : 0 : ret = cpfl_parse_pr_actions(itf, pattern->actions, pattern->actions_size,
1657 : : items, attr, pr_action);
1658 : 0 : return ret;
1659 : : }
1660 : :
1661 : : return -EINVAL;
1662 : : }
1663 : :
1664 : : /* modifications rules */
1665 : : static int
1666 : 0 : cpfl_check_actions_vxlan_encap(struct cpfl_flow_mr_key_action_vxlan_encap *encap,
1667 : : const struct rte_flow_action *action)
1668 : : {
1669 : : const struct rte_flow_action_vxlan_encap *action_vxlan_encap;
1670 : : struct rte_flow_item *definition;
1671 : : int def_length, i, proto_size;
1672 : :
1673 : 0 : action_vxlan_encap = (const struct rte_flow_action_vxlan_encap *)action->conf;
1674 : 0 : definition = action_vxlan_encap->definition;
1675 : : def_length = cpfl_get_items_length(definition);
1676 : 0 : proto_size = encap->proto_size;
1677 [ # # ]: 0 : if (proto_size != def_length - 1) {
1678 : 0 : PMD_DRV_LOG(DEBUG, "protocols not match.");
1679 : 0 : return -EINVAL;
1680 : : }
1681 [ # # ]: 0 : for (i = 0; i < proto_size; i++) {
1682 : : enum rte_flow_item_type proto;
1683 : :
1684 : 0 : proto = encap->protocols[i];
1685 [ # # ]: 0 : if (proto == RTE_FLOW_ITEM_TYPE_VLAN) {
1686 [ # # ]: 0 : if (definition[i].type != RTE_FLOW_ITEM_TYPE_VOID) {
1687 : 0 : PMD_DRV_LOG(DEBUG, "protocols not match.");
1688 : 0 : return -EINVAL;
1689 : : }
1690 [ # # ]: 0 : } else if (proto != definition[i].type) {
1691 : 0 : PMD_DRV_LOG(DEBUG, "protocols not match.");
1692 : 0 : return -EINVAL;
1693 : : }
1694 : : }
1695 : :
1696 : : return 0;
1697 : : }
1698 : :
1699 : : static int
1700 : 0 : cpfl_parse_check_prog_action(struct cpfl_flow_js_mr_key_action *key_act,
1701 : : struct cpfl_flow_mr_key_action_prog *mr_key_prog,
1702 : : const struct rte_flow_action_prog *prog)
1703 : : {
1704 : : uint32_t k;
1705 : : bool check_name;
1706 : :
1707 : 0 : check_name = key_act->prog.has_name ? strcmp(prog->name, key_act->prog.name) == 0
1708 [ # # ]: 0 : : (uint32_t)atol(prog->name) == key_act->prog.id;
1709 [ # # ]: 0 : if (!check_name) {
1710 : 0 : PMD_DRV_LOG(ERR, "Not support this prog type: %s.", prog->name);
1711 : 0 : return -EINVAL;
1712 : : }
1713 [ # # ]: 0 : if (key_act->prog.param_size != prog->args_num)
1714 : : return -EINVAL;
1715 [ # # ]: 0 : for (k = 0; k < key_act->prog.param_size; k++) {
1716 : 0 : const struct rte_flow_action_prog_argument *arg = &prog->args[k];
1717 : : struct cpfl_flow_js_prog_parameter *param = &key_act->prog.params[k];
1718 : :
1719 : 0 : check_name = param->has_name ? strcmp(arg->name, param->name) == 0
1720 [ # # ]: 0 : : atoi(arg->name) == param->index;
1721 [ # # # # ]: 0 : if (!check_name || arg->size != param->size)
1722 : : return -EINVAL;
1723 [ # # ]: 0 : if (param->has_name) {
1724 : 0 : mr_key_prog->has_name = TRUE;
1725 : 0 : strncpy(mr_key_prog->name[param->index], param->name,
1726 : : CPFL_JS_STR_SIZE - 1);
1727 : : }
1728 : : }
1729 : :
1730 : : return 0;
1731 : : }
1732 : :
1733 : : /* check and parse */
1734 : : static int
1735 : 0 : cpfl_parse_mr_key_action(struct cpfl_flow_js_mr_key_action *key_acts, int size,
1736 : : const struct rte_flow_action *actions,
1737 : : struct cpfl_flow_mr_key_action *mr_key_action)
1738 : : {
1739 : : int actions_length, i;
1740 : : int j = 0;
1741 : : int ret;
1742 : :
1743 : : actions_length = cpfl_get_actions_length(actions);
1744 [ # # ]: 0 : if (size > actions_length - 1)
1745 : : return -EINVAL;
1746 [ # # ]: 0 : for (i = 0; i < size; i++) {
1747 : : enum rte_flow_action_type type;
1748 : : struct cpfl_flow_js_mr_key_action *key_act;
1749 : :
1750 : 0 : key_act = &key_acts[i];
1751 : : /* mr->key->actions->type */
1752 : 0 : type = key_act->type;
1753 : : /* mr->key->actions->data */
1754 [ # # ]: 0 : if (type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) {
1755 : : int proto_size, k;
1756 : : struct cpfl_flow_mr_key_action_vxlan_encap *encap;
1757 : :
1758 [ # # ]: 0 : while (j < actions_length &&
1759 [ # # ]: 0 : actions[j].type != RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) {
1760 : 0 : j++;
1761 : : }
1762 [ # # ]: 0 : if (j >= actions_length)
1763 : : return -EINVAL;
1764 : 0 : mr_key_action->mods[i].type = RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP;
1765 : 0 : mr_key_action->mods[i].encap.action = &actions[j];
1766 : 0 : encap = &mr_key_action->mods[i].encap;
1767 : :
1768 : 0 : proto_size = key_act->encap.proto_size;
1769 : 0 : encap->proto_size = proto_size;
1770 [ # # ]: 0 : for (k = 0; k < proto_size; k++) {
1771 : : enum rte_flow_item_type proto;
1772 : :
1773 : 0 : proto = key_act->encap.protocols[k];
1774 : 0 : encap->protocols[k] = proto;
1775 : : }
1776 : 0 : ret = cpfl_check_actions_vxlan_encap(encap, &actions[j]);
1777 [ # # ]: 0 : if (ret < 0)
1778 : : return -EINVAL;
1779 : 0 : j++;
1780 [ # # ]: 0 : } else if (type == RTE_FLOW_ACTION_TYPE_VXLAN_DECAP) {
1781 [ # # ]: 0 : while (j < actions_length &&
1782 [ # # ]: 0 : actions[j].type != RTE_FLOW_ACTION_TYPE_VXLAN_DECAP) {
1783 : 0 : j++;
1784 : : }
1785 [ # # ]: 0 : if (j >= actions_length)
1786 : : return -EINVAL;
1787 : 0 : mr_key_action->mods[i].type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
1788 : 0 : j++;
1789 [ # # ]: 0 : } else if (type == RTE_FLOW_ACTION_TYPE_PROG) {
1790 : : const struct rte_flow_action_prog *prog;
1791 : :
1792 [ # # ]: 0 : while (j < actions_length &&
1793 [ # # ]: 0 : actions[j].type != RTE_FLOW_ACTION_TYPE_PROG) {
1794 : 0 : j++;
1795 : : }
1796 [ # # ]: 0 : if (j >= actions_length)
1797 : : return -EINVAL;
1798 : 0 : prog = actions[j].conf;
1799 : 0 : mr_key_action->prog.prog = prog;
1800 : 0 : ret = cpfl_parse_check_prog_action(key_act, &mr_key_action->prog, prog);
1801 [ # # ]: 0 : if (ret < 0)
1802 : : return -EINVAL;
1803 : : } else {
1804 : 0 : PMD_DRV_LOG(ERR, "Not support this type: %d.", type);
1805 : 0 : return -EPERM;
1806 : : }
1807 : : }
1808 : :
1809 : : return 0;
1810 : : }
1811 : :
1812 : : /* output: uint8_t *buffer, uint16_t *byte_len */
1813 : : static int
1814 : 0 : cpfl_parse_layout(struct cpfl_flow_js_mr_layout *layouts, int layout_size,
1815 : : struct cpfl_flow_mr_key_mod *mods,
1816 : : uint8_t *buffer, uint16_t *byte_len)
1817 : : {
1818 : : int i;
1819 : : int start = 0;
1820 : :
1821 [ # # ]: 0 : for (i = 0; i < layout_size; i++) {
1822 : : int index, size, offset;
1823 : : const char *hint;
1824 : : const uint8_t *addr = NULL;
1825 : : struct cpfl_flow_mr_key_mod *temp;
1826 : : struct cpfl_flow_js_mr_layout *layout;
1827 : :
1828 : 0 : layout = &layouts[i];
1829 : : /* index links to the element of the actions array. */
1830 : 0 : index = layout->index;
1831 : 0 : size = layout->size;
1832 : 0 : offset = layout->offset;
1833 [ # # ]: 0 : if (index == -1) {
1834 : : hint = "dummpy";
1835 : 0 : start += size;
1836 : 0 : continue;
1837 : : }
1838 : 0 : hint = layout->hint;
1839 : 0 : temp = mods + index;
1840 [ # # ]: 0 : if (temp->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) {
1841 : : const struct rte_flow_action_vxlan_encap *action_vxlan_encap;
1842 : : struct rte_flow_item *definition;
1843 : : int def_length, k;
1844 : :
1845 : 0 : action_vxlan_encap =
1846 : 0 : (const struct rte_flow_action_vxlan_encap *)temp->encap.action->conf;
1847 : 0 : definition = action_vxlan_encap->definition;
1848 : : def_length = cpfl_get_items_length(definition);
1849 [ # # ]: 0 : for (k = 0; k < def_length - 1; k++) {
1850 [ # # ]: 0 : if ((strcmp(hint, "eth") == 0 &&
1851 [ # # ]: 0 : definition[k].type == RTE_FLOW_ITEM_TYPE_ETH) ||
1852 [ # # ]: 0 : (strcmp(hint, "ipv4") == 0 &&
1853 [ # # ]: 0 : definition[k].type == RTE_FLOW_ITEM_TYPE_IPV4) ||
1854 [ # # ]: 0 : (strcmp(hint, "udp") == 0 &&
1855 [ # # ]: 0 : definition[k].type == RTE_FLOW_ITEM_TYPE_UDP) ||
1856 [ # # ]: 0 : (strcmp(hint, "tcp") == 0 &&
1857 [ # # ]: 0 : definition[k].type == RTE_FLOW_ITEM_TYPE_TCP) ||
1858 [ # # ]: 0 : (strcmp(hint, "vxlan") == 0 &&
1859 [ # # ]: 0 : definition[k].type == RTE_FLOW_ITEM_TYPE_VXLAN)) {
1860 : 0 : addr = (const uint8_t *)(definition[k].spec);
1861 [ # # ]: 0 : if (start > 255) {
1862 : 0 : *byte_len = 0;
1863 : 0 : PMD_DRV_LOG(ERR, "byte length is too long: %s",
1864 : : hint);
1865 : 0 : return -EINVAL;
1866 : : }
1867 : 0 : memcpy(buffer + start, addr + offset, size);
1868 : : break;
1869 : : } /* TODO: more hint... */
1870 : : }
1871 [ # # ]: 0 : if (k == def_length - 1) {
1872 : 0 : *byte_len = 0;
1873 : 0 : PMD_DRV_LOG(ERR, "can not find corresponding hint: %s", hint);
1874 : 0 : return -EINVAL;
1875 : : }
1876 : : } else {
1877 : 0 : *byte_len = 0;
1878 : 0 : PMD_DRV_LOG(ERR, "Not support this type: %d.", temp->type);
1879 : 0 : return -EINVAL;
1880 : : } /* else TODO: more type... */
1881 : 0 : start += size;
1882 : : }
1883 : 0 : *byte_len = start;
1884 : :
1885 : 0 : return 0;
1886 : : }
1887 : :
1888 : : static int
1889 : 0 : cpfl_parse_content(struct cpfl_flow_js_mr_content *content,
1890 : : struct cpfl_flow_mr_key_action_prog *prog, uint8_t *buffer)
1891 : : {
1892 : : int i, j;
1893 : :
1894 [ # # ]: 0 : for (i = 0; i < content->field_size; i++) {
1895 : : uint16_t start, width, shift_bit;
1896 : :
1897 : 0 : start = content->fields[i].start / 8;
1898 : 0 : width = (content->fields[i].width + 7) / 8;
1899 : 0 : shift_bit = (8 - content->fields[i].start % 8 - content->fields[i].width % 8) % 8;
1900 : :
1901 [ # # ]: 0 : for (j = 0; j < width; j++) {
1902 : : uint8_t old_value = 0;
1903 : :
1904 [ # # ]: 0 : if (strcmp(content->fields[i].type, "parameter") == 0) {
1905 : : uint32_t k;
1906 : 0 : uint16_t index = content->fields[i].index;
1907 : 0 : const struct rte_flow_action_prog *act_prog = prog->prog;
1908 : :
1909 [ # # ]: 0 : for (k = 0; k < act_prog->args_num; k++) {
1910 : 0 : const char *name = act_prog->args[k].name;
1911 : :
1912 [ # # ]: 0 : if ((prog->has_name &&
1913 [ # # # # ]: 0 : strcmp(prog->name[index], name) == 0) ||
1914 [ # # ]: 0 : (!prog->has_name && atoi(name) == index)) {
1915 : 0 : old_value = act_prog->args[k].value[j];
1916 : 0 : break;
1917 : : }
1918 : : }
1919 [ # # ]: 0 : if (k == act_prog->args_num)
1920 : : return -EINVAL;
1921 [ # # ]: 0 : } else if (strcmp(content->fields[i].type, "constant") == 0) {
1922 : 0 : old_value = content->fields[i].value[j];
1923 : : } else {
1924 : : return -EINVAL;
1925 : : }
1926 : 0 : memset(buffer + start + j, buffer[start + j] | old_value << shift_bit, 1);
1927 : : }
1928 : : }
1929 : :
1930 : : return 0;
1931 : : }
1932 : :
1933 : : static int
1934 : 0 : cpfl_parse_mr_action(struct cpfl_flow_js_mr_action *action,
1935 : : struct cpfl_flow_mr_key_action *mr_key_action,
1936 : : struct cpfl_flow_mr_action *mr_action)
1937 : : {
1938 : : enum cpfl_flow_mr_action_type type;
1939 : :
1940 : : /* mr->action->type */
1941 : 0 : type = action->type;
1942 : : /* mr->action->data */
1943 [ # # ]: 0 : if (action->mod.is_content) {
1944 : 0 : struct cpfl_flow_js_mr_content *content = &action->mod.content;
1945 : :
1946 : 0 : mr_action->type = CPFL_JS_MR_ACTION_TYPE_MOD;
1947 : : mr_action->mod.byte_len = 0;
1948 : 0 : mr_action->mod.prof = action->mod.prof;
1949 : 0 : mr_action->mod.byte_len = content->size;
1950 : 0 : memset(mr_action->mod.data, 0, sizeof(mr_action->mod.data));
1951 : :
1952 : 0 : return cpfl_parse_content(content, &mr_key_action->prog, mr_action->mod.data);
1953 : : }
1954 : :
1955 [ # # ]: 0 : if (type == CPFL_JS_MR_ACTION_TYPE_MOD) {
1956 : : struct cpfl_flow_js_mr_layout *layout;
1957 : :
1958 : 0 : mr_action->type = CPFL_JS_MR_ACTION_TYPE_MOD;
1959 : 0 : mr_action->mod.byte_len = 0;
1960 : 0 : mr_action->mod.prof = action->mod.prof;
1961 : 0 : layout = action->mod.layout;
1962 : : if (!layout)
1963 : : return 0;
1964 : 0 : memset(mr_action->mod.data, 0, sizeof(mr_action->mod.data));
1965 : :
1966 : 0 : return cpfl_parse_layout(layout, action->mod.layout_size, mr_key_action->mods,
1967 : : mr_action->mod.data, &mr_action->mod.byte_len);
1968 : : }
1969 : 0 : PMD_DRV_LOG(ERR, "Not support this type: %d.", type);
1970 : :
1971 : 0 : return -EINVAL;
1972 : : }
1973 : :
1974 : : static int
1975 : : cpfl_check_mod_key(struct cpfl_flow_js_mr *mr, const struct rte_flow_action *actions,
1976 : : struct cpfl_flow_mr_key_action *mr_key_action)
1977 : : {
1978 : : int key_action_size;
1979 : :
1980 : : /* mr->key->actions */
1981 : 0 : key_action_size = mr->key.actions_size;
1982 : 0 : return cpfl_parse_mr_key_action(mr->key.actions, key_action_size, actions, mr_key_action);
1983 : : }
1984 : :
1985 : : /* output: struct cpfl_flow_mr_action *mr_action */
1986 : : static int
1987 : 0 : cpfl_parse_mod_rules(struct cpfl_flow_js_parser *parser, const struct rte_flow_action *actions,
1988 : : struct cpfl_flow_mr_action *mr_action)
1989 : : {
1990 : : int i;
1991 : 0 : struct cpfl_flow_mr_key_action mr_key_action = {0};
1992 : :
1993 [ # # ]: 0 : for (i = 0; i < parser->mr_size; i++) {
1994 : : int ret;
1995 : : struct cpfl_flow_js_mr *mr;
1996 : :
1997 : 0 : mr = &parser->modifications[i];
1998 [ # # ]: 0 : if (!mr)
1999 : : return -EINVAL;
2000 : : ret = cpfl_check_mod_key(mr, actions, &mr_key_action);
2001 [ # # ]: 0 : if (ret < 0)
2002 : : continue;
2003 : : /* mr->action */
2004 : 0 : return cpfl_parse_mr_action(&mr->action, &mr_key_action, mr_action);
2005 : : }
2006 : :
2007 : : return -EINVAL;
2008 : : }
2009 : :
2010 : : int
2011 : 0 : cpfl_flow_parse_actions(struct cpfl_flow_js_parser *parser, const struct rte_flow_action *actions,
2012 : : struct cpfl_flow_mr_action *mr_action)
2013 : : {
2014 : : /* modifications rules */
2015 [ # # ]: 0 : if (!parser->modifications) {
2016 : 0 : PMD_DRV_LOG(INFO, "The modifications is optional.");
2017 : 0 : return 0;
2018 : : }
2019 : :
2020 : 0 : return cpfl_parse_mod_rules(parser, actions, mr_action);
2021 : : }
2022 : :
2023 : : bool
2024 [ # # ]: 0 : cpfl_metadata_write_port_id(struct cpfl_itf *itf)
2025 : : {
2026 : : uint16_t dev_id;
2027 : : const int type = 0;
2028 : : const int offset = 5;
2029 : :
2030 : : dev_id = cpfl_get_port_id(itf);
2031 [ # # ]: 0 : if (dev_id == CPFL_INVALID_HW_ID) {
2032 : 0 : PMD_DRV_LOG(ERR, "fail to get hw ID");
2033 : 0 : return false;
2034 : : }
2035 : 0 : cpfl_metadata_write16(&itf->adapter->meta, type, offset, dev_id << 3);
2036 : :
2037 : 0 : return true;
2038 : : }
2039 : :
2040 : : bool
2041 : 0 : cpfl_metadata_write_targetvsi(struct cpfl_itf *itf)
2042 : : {
2043 : : uint16_t dev_id;
2044 : : const int type = 6;
2045 : : const int offset = 2;
2046 : :
2047 : 0 : dev_id = cpfl_get_vsi_id(itf);
2048 [ # # ]: 0 : if (dev_id == CPFL_INVALID_HW_ID) {
2049 : 0 : PMD_DRV_LOG(ERR, "fail to get hw ID");
2050 : 0 : return false;
2051 : : }
2052 : 0 : cpfl_metadata_write16(&itf->adapter->meta, type, offset, dev_id << 1);
2053 : :
2054 : 0 : return true;
2055 : : }
2056 : :
2057 : : bool
2058 : 0 : cpfl_metadata_write_sourcevsi(struct cpfl_itf *itf)
2059 : : {
2060 : : uint16_t dev_id;
2061 : : const int type = 6;
2062 : : const int offset = 0;
2063 : :
2064 : 0 : dev_id = cpfl_get_vsi_id(itf);
2065 [ # # ]: 0 : if (dev_id == CPFL_INVALID_HW_ID) {
2066 : 0 : PMD_DRV_LOG(ERR, "fail to get hw ID");
2067 : 0 : return false;
2068 : : }
2069 : 0 : cpfl_metadata_write16(&itf->adapter->meta, type, offset, dev_id);
2070 : :
2071 : 0 : return true;
2072 : : }
2073 : :
2074 : 0 : bool cpfl_metadata_write_vsi(struct cpfl_itf *itf)
2075 : : {
2076 : : uint16_t dev_id;
2077 : : const int type = 0;
2078 : : const int offset = 24;
2079 : :
2080 : 0 : dev_id = cpfl_get_vsi_id(itf);
2081 [ # # ]: 0 : if (dev_id == CPFL_INVALID_HW_ID) {
2082 : 0 : PMD_DRV_LOG(ERR, "fail to get hw ID");
2083 : 0 : return false;
2084 : : }
2085 : 0 : cpfl_metadata_write16(&itf->adapter->meta, type, offset, dev_id);
2086 : :
2087 : 0 : return true;
2088 : : }
|