net/ice: save rule on switch filter creation
[dpdk.git] / drivers / net / bnxt / tf_ulp / bnxt_ulp_flow.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2021 Broadcom
3  * All rights reserved.
4  */
5
6 #include "bnxt.h"
7 #include "bnxt_tf_common.h"
8 #include "ulp_rte_parser.h"
9 #include "ulp_matcher.h"
10 #include "ulp_flow_db.h"
11 #include "ulp_mapper.h"
12 #include "ulp_fc_mgr.h"
13 #include "ulp_port_db.h"
14 #include "ulp_ha_mgr.h"
15 #include "ulp_tun.h"
16 #include <rte_malloc.h>
17
18 static int32_t
19 bnxt_ulp_flow_validate_args(const struct rte_flow_attr *attr,
20                             const struct rte_flow_item pattern[],
21                             const struct rte_flow_action actions[],
22                             struct rte_flow_error *error)
23 {
24         /* Perform the validation of the arguments for null */
25         if (!error)
26                 return BNXT_TF_RC_ERROR;
27
28         if (!pattern) {
29                 rte_flow_error_set(error,
30                                    EINVAL,
31                                    RTE_FLOW_ERROR_TYPE_ITEM_NUM,
32                                    NULL,
33                                    "NULL pattern.");
34                 return BNXT_TF_RC_ERROR;
35         }
36
37         if (!actions) {
38                 rte_flow_error_set(error,
39                                    EINVAL,
40                                    RTE_FLOW_ERROR_TYPE_ACTION_NUM,
41                                    NULL,
42                                    "NULL action.");
43                 return BNXT_TF_RC_ERROR;
44         }
45
46         if (!attr) {
47                 rte_flow_error_set(error,
48                                    EINVAL,
49                                    RTE_FLOW_ERROR_TYPE_ATTR,
50                                    NULL,
51                                    "NULL attribute.");
52                 return BNXT_TF_RC_ERROR;
53         }
54
55         if (attr->egress && attr->ingress) {
56                 rte_flow_error_set(error,
57                                    EINVAL,
58                                    RTE_FLOW_ERROR_TYPE_ATTR,
59                                    attr,
60                                    "EGRESS AND INGRESS UNSUPPORTED");
61                 return BNXT_TF_RC_ERROR;
62         }
63         return BNXT_TF_RC_SUCCESS;
64 }
65
66 static inline void
67 bnxt_ulp_set_dir_attributes(struct ulp_rte_parser_params *params,
68                             const struct rte_flow_attr *attr)
69 {
70         /* Set the flow attributes */
71         if (attr->egress)
72                 params->dir_attr |= BNXT_ULP_FLOW_ATTR_EGRESS;
73         if (attr->ingress)
74                 params->dir_attr |= BNXT_ULP_FLOW_ATTR_INGRESS;
75 #if RTE_VERSION_NUM(17, 11, 10, 16) < RTE_VERSION
76         if (attr->transfer)
77                 params->dir_attr |= BNXT_ULP_FLOW_ATTR_TRANSFER;
78 #endif
79 }
80
81 void
82 bnxt_ulp_init_mapper_params(struct bnxt_ulp_mapper_create_parms *mapper_cparms,
83                             struct ulp_rte_parser_params *params,
84                             enum bnxt_ulp_fdb_type flow_type)
85 {
86         uint32_t ulp_flags = 0;
87
88         memset(mapper_cparms, 0, sizeof(*mapper_cparms));
89         mapper_cparms->flow_type = flow_type;
90         mapper_cparms->app_priority = params->priority;
91         mapper_cparms->dir_attr = params->dir_attr;
92         mapper_cparms->class_tid = params->class_id;
93         mapper_cparms->act_tid = params->act_tmpl;
94         mapper_cparms->func_id = params->func_id;
95         mapper_cparms->hdr_bitmap = &params->hdr_bitmap;
96         mapper_cparms->enc_hdr_bitmap = &params->enc_hdr_bitmap;
97         mapper_cparms->hdr_field = params->hdr_field;
98         mapper_cparms->enc_field = params->enc_field;
99         mapper_cparms->comp_fld = params->comp_fld;
100         mapper_cparms->act = &params->act_bitmap;
101         mapper_cparms->act_prop = &params->act_prop;
102         mapper_cparms->flow_id = params->fid;
103         mapper_cparms->parent_flow = params->parent_flow;
104         mapper_cparms->child_flow = params->child_flow;
105         mapper_cparms->fld_bitmap = &params->fld_bitmap;
106         mapper_cparms->flow_pattern_id = params->flow_pattern_id;
107         mapper_cparms->act_pattern_id = params->act_pattern_id;
108         mapper_cparms->app_id = params->app_id;
109         mapper_cparms->port_id = params->port_id;
110         mapper_cparms->tun_idx = params->tun_idx;
111
112         /* update the signature fields into the computed field list */
113         ULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_HDR_SIG_ID,
114                             params->hdr_sig_id);
115         ULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_FLOW_SIG_ID,
116                             params->flow_sig_id);
117
118         /* update the WC Priority flag */
119         if (!bnxt_ulp_cntxt_ptr2_ulp_flags_get(params->ulp_ctx, &ulp_flags) &&
120             ULP_HIGH_AVAIL_IS_ENABLED(ulp_flags)) {
121                 enum ulp_ha_mgr_region region = ULP_HA_REGION_LOW;
122                 int32_t rc;
123
124                 rc = ulp_ha_mgr_region_get(params->ulp_ctx, &region);
125                 if (rc)
126                         BNXT_TF_DBG(ERR, "Unable to get WC region\n");
127                 if (region == ULP_HA_REGION_HI)
128                         ULP_COMP_FLD_IDX_WR(params,
129                                             BNXT_ULP_CF_IDX_WC_IS_HA_HIGH_REG,
130                                             1);
131         }
132 }
133
134 /* Function to create the rte flow. */
135 static struct rte_flow *
136 bnxt_ulp_flow_create(struct rte_eth_dev *dev,
137                      const struct rte_flow_attr *attr,
138                      const struct rte_flow_item pattern[],
139                      const struct rte_flow_action actions[],
140                      struct rte_flow_error *error)
141 {
142         struct bnxt_ulp_mapper_create_parms mapper_cparms = { 0 };
143         struct ulp_rte_parser_params params;
144         struct bnxt_ulp_context *ulp_ctx;
145         int rc, ret = BNXT_TF_RC_ERROR;
146         struct rte_flow *flow_id;
147         uint16_t func_id;
148         uint32_t fid;
149
150         if (bnxt_ulp_flow_validate_args(attr,
151                                         pattern, actions,
152                                         error) == BNXT_TF_RC_ERROR) {
153                 BNXT_TF_DBG(ERR, "Invalid arguments being passed\n");
154                 goto flow_error;
155         }
156
157         ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);
158         if (!ulp_ctx) {
159                 BNXT_TF_DBG(ERR, "ULP context is not initialized\n");
160                 goto flow_error;
161         }
162
163         /* Initialize the parser params */
164         memset(&params, 0, sizeof(struct ulp_rte_parser_params));
165         params.ulp_ctx = ulp_ctx;
166
167         if (bnxt_ulp_cntxt_app_id_get(params.ulp_ctx, &params.app_id)) {
168                 BNXT_TF_DBG(ERR, "failed to get the app id\n");
169                 goto flow_error;
170         }
171
172         /* Set the flow attributes */
173         bnxt_ulp_set_dir_attributes(&params, attr);
174
175         /* copy the device port id and direction for further processing */
176         ULP_COMP_FLD_IDX_WR(&params, BNXT_ULP_CF_IDX_INCOMING_IF,
177                             dev->data->port_id);
178         ULP_COMP_FLD_IDX_WR(&params, BNXT_ULP_CF_IDX_DEV_PORT_ID,
179                             dev->data->port_id);
180         ULP_COMP_FLD_IDX_WR(&params, BNXT_ULP_CF_IDX_SVIF_FLAG,
181                             BNXT_ULP_INVALID_SVIF_VAL);
182
183         /* Get the function id */
184         if (ulp_port_db_port_func_id_get(ulp_ctx,
185                                          dev->data->port_id,
186                                          &func_id)) {
187                 BNXT_TF_DBG(ERR, "conversion of port to func id failed\n");
188                 goto flow_error;
189         }
190
191         /* Protect flow creation */
192         if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
193                 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
194                 goto flow_error;
195         }
196
197         /* Allocate a Flow ID for attaching all resources for the flow to.
198          * Once allocated, all errors have to walk the list of resources and
199          * free each of them.
200          */
201         rc = ulp_flow_db_fid_alloc(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
202                                    func_id, &fid);
203         if (rc) {
204                 BNXT_TF_DBG(ERR, "Unable to allocate flow table entry\n");
205                 goto release_lock;
206         }
207
208         /* Parse the rte flow pattern */
209         ret = bnxt_ulp_rte_parser_hdr_parse(pattern, &params);
210         if (ret != BNXT_TF_RC_SUCCESS)
211                 goto free_fid;
212
213         /* Parse the rte flow action */
214         ret = bnxt_ulp_rte_parser_act_parse(actions, &params);
215         if (ret != BNXT_TF_RC_SUCCESS)
216                 goto free_fid;
217
218         params.fid = fid;
219         params.func_id = func_id;
220         params.priority = attr->priority;
221         params.port_id = dev->data->port_id;
222
223         /* Perform the rte flow post process */
224         bnxt_ulp_rte_parser_post_process(&params);
225
226         /* do the tunnel offload process if any */
227         ret = ulp_tunnel_offload_process(&params);
228         if (ret == BNXT_TF_RC_ERROR)
229                 goto free_fid;
230
231         ret = ulp_matcher_pattern_match(&params, &params.class_id);
232         if (ret != BNXT_TF_RC_SUCCESS)
233                 goto free_fid;
234
235         ret = ulp_matcher_action_match(&params, &params.act_tmpl);
236         if (ret != BNXT_TF_RC_SUCCESS)
237                 goto free_fid;
238
239         bnxt_ulp_init_mapper_params(&mapper_cparms, &params,
240                                     BNXT_ULP_FDB_TYPE_REGULAR);
241         /* Call the ulp mapper to create the flow in the hardware. */
242         ret = ulp_mapper_flow_create(ulp_ctx, &mapper_cparms);
243         if (ret)
244                 goto free_fid;
245
246         bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
247
248         flow_id = (struct rte_flow *)((uintptr_t)fid);
249         return flow_id;
250
251 free_fid:
252         ulp_flow_db_fid_free(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR, fid);
253 release_lock:
254         bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
255 flow_error:
256         rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
257                            "Failed to create flow.");
258         return NULL;
259 }
260
261 /* Function to validate the rte flow. */
262 static int
263 bnxt_ulp_flow_validate(struct rte_eth_dev *dev,
264                        const struct rte_flow_attr *attr,
265                        const struct rte_flow_item pattern[],
266                        const struct rte_flow_action actions[],
267                        struct rte_flow_error *error)
268 {
269         struct ulp_rte_parser_params params;
270         struct bnxt_ulp_context *ulp_ctx;
271         uint32_t class_id, act_tmpl;
272         int ret = BNXT_TF_RC_ERROR;
273
274         if (bnxt_ulp_flow_validate_args(attr,
275                                         pattern, actions,
276                                         error) == BNXT_TF_RC_ERROR) {
277                 BNXT_TF_DBG(ERR, "Invalid arguments being passed\n");
278                 goto parse_error;
279         }
280
281         ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);
282         if (!ulp_ctx) {
283                 BNXT_TF_DBG(ERR, "ULP context is not initialized\n");
284                 goto parse_error;
285         }
286
287         /* Initialize the parser params */
288         memset(&params, 0, sizeof(struct ulp_rte_parser_params));
289         params.ulp_ctx = ulp_ctx;
290
291         if (bnxt_ulp_cntxt_app_id_get(params.ulp_ctx, &params.app_id)) {
292                 BNXT_TF_DBG(ERR, "failed to get the app id\n");
293                 goto parse_error;
294         }
295
296         /* Set the flow attributes */
297         bnxt_ulp_set_dir_attributes(&params, attr);
298
299         /* Parse the rte flow pattern */
300         ret = bnxt_ulp_rte_parser_hdr_parse(pattern, &params);
301         if (ret != BNXT_TF_RC_SUCCESS)
302                 goto parse_error;
303
304         /* Parse the rte flow action */
305         ret = bnxt_ulp_rte_parser_act_parse(actions, &params);
306         if (ret != BNXT_TF_RC_SUCCESS)
307                 goto parse_error;
308
309         /* Perform the rte flow post process */
310         bnxt_ulp_rte_parser_post_process(&params);
311
312         /* do the tunnel offload process if any */
313         ret = ulp_tunnel_offload_process(&params);
314         if (ret == BNXT_TF_RC_ERROR)
315                 goto parse_error;
316
317         ret = ulp_matcher_pattern_match(&params, &class_id);
318
319         if (ret != BNXT_TF_RC_SUCCESS)
320                 goto parse_error;
321
322         ret = ulp_matcher_action_match(&params, &act_tmpl);
323         if (ret != BNXT_TF_RC_SUCCESS)
324                 goto parse_error;
325
326         /* all good return success */
327         return ret;
328
329 parse_error:
330         rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
331                            "Failed to validate flow.");
332         return -EINVAL;
333 }
334
335 /* Function to destroy the rte flow. */
336 int
337 bnxt_ulp_flow_destroy(struct rte_eth_dev *dev,
338                       struct rte_flow *flow,
339                       struct rte_flow_error *error)
340 {
341         struct bnxt_ulp_context *ulp_ctx;
342         uint32_t flow_id;
343         uint16_t func_id;
344         int ret;
345
346         ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);
347         if (!ulp_ctx) {
348                 BNXT_TF_DBG(ERR, "ULP context is not initialized\n");
349                 if (error)
350                         rte_flow_error_set(error, EINVAL,
351                                            RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
352                                            "Failed to destroy flow.");
353                 return -EINVAL;
354         }
355
356         flow_id = (uint32_t)(uintptr_t)flow;
357
358         if (ulp_port_db_port_func_id_get(ulp_ctx,
359                                          dev->data->port_id,
360                                          &func_id)) {
361                 BNXT_TF_DBG(ERR, "conversion of port to func id failed\n");
362                 if (error)
363                         rte_flow_error_set(error, EINVAL,
364                                            RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
365                                            "Failed to destroy flow.");
366                 return -EINVAL;
367         }
368
369         if (ulp_flow_db_validate_flow_func(ulp_ctx, flow_id, func_id) ==
370             false) {
371                 BNXT_TF_DBG(ERR, "Incorrect device params\n");
372                 if (error)
373                         rte_flow_error_set(error, EINVAL,
374                                            RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
375                                            "Failed to destroy flow.");
376                 return -EINVAL;
377         }
378
379         if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
380                 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
381                 return -EINVAL;
382         }
383         ret = ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
384                                       flow_id);
385         if (ret) {
386                 BNXT_TF_DBG(ERR, "Failed to destroy flow.\n");
387                 if (error)
388                         rte_flow_error_set(error, -ret,
389                                            RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
390                                            "Failed to destroy flow.");
391         }
392         bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
393
394         return ret;
395 }
396
397 /* Function to destroy the rte flows. */
398 static int32_t
399 bnxt_ulp_flow_flush(struct rte_eth_dev *eth_dev,
400                     struct rte_flow_error *error)
401 {
402         struct bnxt_ulp_context *ulp_ctx;
403         int32_t ret = 0;
404         uint16_t func_id;
405
406         ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev);
407         if (!ulp_ctx) {
408                 return ret;
409         }
410
411         /* Free the resources for the last device */
412         if (ulp_ctx_deinit_allowed(ulp_ctx)) {
413                 ret = ulp_flow_db_session_flow_flush(ulp_ctx);
414         } else if (bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx)) {
415                 ret = ulp_port_db_port_func_id_get(ulp_ctx,
416                                                    eth_dev->data->port_id,
417                                                    &func_id);
418                 if (!ret)
419                         ret = ulp_flow_db_function_flow_flush(ulp_ctx, func_id);
420                 else
421                         BNXT_TF_DBG(ERR, "convert port to func id failed\n");
422         }
423         if (ret)
424                 rte_flow_error_set(error, ret,
425                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
426                                    "Failed to flush flow.");
427         return ret;
428 }
429
430 /* Function to query the rte flows. */
431 static int32_t
432 bnxt_ulp_flow_query(struct rte_eth_dev *eth_dev,
433                     struct rte_flow *flow,
434                     const struct rte_flow_action *action,
435                     void *data,
436                     struct rte_flow_error *error)
437 {
438         int rc = 0;
439         struct bnxt_ulp_context *ulp_ctx;
440         struct rte_flow_query_count *count;
441         uint32_t flow_id;
442
443         ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev);
444         if (!ulp_ctx) {
445                 BNXT_TF_DBG(ERR, "ULP context is not initialized\n");
446                 rte_flow_error_set(error, EINVAL,
447                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
448                                    "Failed to query flow.");
449                 return -EINVAL;
450         }
451
452         flow_id = (uint32_t)(uintptr_t)flow;
453
454         switch (action->type) {
455         case RTE_FLOW_ACTION_TYPE_COUNT:
456                 count = data;
457                 rc = ulp_fc_mgr_query_count_get(ulp_ctx, flow_id, count);
458                 if (rc) {
459                         rte_flow_error_set(error, EINVAL,
460                                            RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
461                                            "Failed to query flow.");
462                 }
463                 break;
464         default:
465                 rte_flow_error_set(error, -rc, RTE_FLOW_ERROR_TYPE_ACTION_NUM,
466                                    NULL, "Unsupported action item");
467         }
468
469         return rc;
470 }
471
472 /* Tunnel offload Apis */
473 #define BNXT_ULP_TUNNEL_OFFLOAD_NUM_ITEMS       1
474
475 static int
476 bnxt_ulp_tunnel_decap_set(struct rte_eth_dev *eth_dev,
477                           struct rte_flow_tunnel *tunnel,
478                           struct rte_flow_action **pmd_actions,
479                           uint32_t *num_of_actions,
480                           struct rte_flow_error *error)
481 {
482         struct bnxt_ulp_context *ulp_ctx;
483         struct bnxt_flow_app_tun_ent *tun_entry;
484         int32_t rc = 0;
485
486         ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev);
487         if (ulp_ctx == NULL) {
488                 BNXT_TF_DBG(ERR, "ULP context is not initialized\n");
489                 rte_flow_error_set(error, EINVAL,
490                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
491                                    "ULP context uninitialized");
492                 return -EINVAL;
493         }
494
495         if (tunnel == NULL) {
496                 BNXT_TF_DBG(ERR, "No tunnel specified\n");
497                 rte_flow_error_set(error, EINVAL,
498                                    RTE_FLOW_ERROR_TYPE_ATTR, NULL,
499                                    "no tunnel specified");
500                 return -EINVAL;
501         }
502
503         if (tunnel->type != RTE_FLOW_ITEM_TYPE_VXLAN) {
504                 BNXT_TF_DBG(ERR, "Tunnel type unsupported\n");
505                 rte_flow_error_set(error, EINVAL,
506                                    RTE_FLOW_ERROR_TYPE_ATTR, NULL,
507                                    "tunnel type unsupported");
508                 return -EINVAL;
509         }
510
511         rc = ulp_app_tun_search_entry(ulp_ctx, tunnel, &tun_entry);
512         if (rc < 0) {
513                 rte_flow_error_set(error, EINVAL,
514                                    RTE_FLOW_ERROR_TYPE_ATTR, NULL,
515                                    "tunnel decap set failed");
516                 return -EINVAL;
517         }
518
519         rc = ulp_app_tun_entry_set_decap_action(tun_entry);
520         if (rc < 0) {
521                 rte_flow_error_set(error, EINVAL,
522                                    RTE_FLOW_ERROR_TYPE_ATTR, NULL,
523                                    "tunnel decap set failed");
524                 return -EINVAL;
525         }
526
527         *pmd_actions = &tun_entry->action;
528         *num_of_actions = BNXT_ULP_TUNNEL_OFFLOAD_NUM_ITEMS;
529         return 0;
530 }
531
532 static int
533 bnxt_ulp_tunnel_match(struct rte_eth_dev *eth_dev,
534                       struct rte_flow_tunnel *tunnel,
535                       struct rte_flow_item **pmd_items,
536                       uint32_t *num_of_items,
537                       struct rte_flow_error *error)
538 {
539         struct bnxt_ulp_context *ulp_ctx;
540         struct bnxt_flow_app_tun_ent *tun_entry;
541         int32_t rc = 0;
542
543         ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev);
544         if (ulp_ctx == NULL) {
545                 BNXT_TF_DBG(ERR, "ULP context is not initialized\n");
546                 rte_flow_error_set(error, EINVAL,
547                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
548                                    "ULP context uninitialized");
549                 return -EINVAL;
550         }
551
552         if (tunnel == NULL) {
553                 BNXT_TF_DBG(ERR, "No tunnel specified\n");
554                 rte_flow_error_set(error, EINVAL,
555                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
556                                    "no tunnel specified");
557                 return -EINVAL;
558         }
559
560         if (tunnel->type != RTE_FLOW_ITEM_TYPE_VXLAN) {
561                 BNXT_TF_DBG(ERR, "Tunnel type unsupported\n");
562                 rte_flow_error_set(error, EINVAL,
563                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
564                                    "tunnel type unsupported");
565                 return -EINVAL;
566         }
567
568         rc = ulp_app_tun_search_entry(ulp_ctx, tunnel, &tun_entry);
569         if (rc < 0) {
570                 rte_flow_error_set(error, EINVAL,
571                                    RTE_FLOW_ERROR_TYPE_ATTR, NULL,
572                                    "tunnel match set failed");
573                 return -EINVAL;
574         }
575
576         rc = ulp_app_tun_entry_set_decap_item(tun_entry);
577         if (rc < 0) {
578                 rte_flow_error_set(error, EINVAL,
579                                    RTE_FLOW_ERROR_TYPE_ATTR, NULL,
580                                    "tunnel match set failed");
581                 return -EINVAL;
582         }
583
584         *pmd_items = &tun_entry->item;
585         *num_of_items = BNXT_ULP_TUNNEL_OFFLOAD_NUM_ITEMS;
586         return 0;
587 }
588
589 static int
590 bnxt_ulp_tunnel_decap_release(struct rte_eth_dev *eth_dev,
591                               struct rte_flow_action *pmd_actions,
592                               uint32_t num_actions,
593                               struct rte_flow_error *error)
594 {
595         struct bnxt_ulp_context *ulp_ctx;
596         struct bnxt_flow_app_tun_ent *tun_entry;
597         const struct rte_flow_action *action_item = pmd_actions;
598
599         ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev);
600         if (ulp_ctx == NULL) {
601                 BNXT_TF_DBG(ERR, "ULP context is not initialized\n");
602                 rte_flow_error_set(error, EINVAL,
603                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
604                                    "ULP context uninitialized");
605                 return -EINVAL;
606         }
607         if (num_actions != BNXT_ULP_TUNNEL_OFFLOAD_NUM_ITEMS) {
608                 BNXT_TF_DBG(ERR, "num actions is invalid\n");
609                 rte_flow_error_set(error, EINVAL,
610                                    RTE_FLOW_ERROR_TYPE_ATTR, NULL,
611                                    "num actions is invalid");
612                 return -EINVAL;
613         }
614         while (action_item && action_item->type != RTE_FLOW_ACTION_TYPE_END) {
615                 if (action_item->type == (typeof(tun_entry->action.type))
616                     BNXT_RTE_FLOW_ACTION_TYPE_VXLAN_DECAP) {
617                         tun_entry = ulp_app_tun_match_entry(ulp_ctx,
618                                                             action_item->conf);
619                         ulp_app_tun_entry_delete(tun_entry);
620                 }
621                 action_item++;
622         }
623         return 0;
624 }
625
626 static int
627 bnxt_ulp_tunnel_item_release(struct rte_eth_dev *eth_dev,
628                              struct rte_flow_item *pmd_items,
629                              uint32_t num_items,
630                              struct rte_flow_error *error)
631 {
632         struct bnxt_ulp_context *ulp_ctx;
633         struct bnxt_flow_app_tun_ent *tun_entry;
634
635         ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev);
636         if (ulp_ctx == NULL) {
637                 BNXT_TF_DBG(ERR, "ULP context is not initialized\n");
638                 rte_flow_error_set(error, EINVAL,
639                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
640                                    "ULP context uninitialized");
641                 return -EINVAL;
642         }
643         if (num_items != BNXT_ULP_TUNNEL_OFFLOAD_NUM_ITEMS) {
644                 BNXT_TF_DBG(ERR, "num items is invalid\n");
645                 rte_flow_error_set(error, EINVAL,
646                                    RTE_FLOW_ERROR_TYPE_ATTR, NULL,
647                                    "num items is invalid");
648                 return -EINVAL;
649         }
650
651         tun_entry = ulp_app_tun_match_entry(ulp_ctx, pmd_items->spec);
652         ulp_app_tun_entry_delete(tun_entry);
653         return 0;
654 }
655
656 const struct rte_flow_ops bnxt_ulp_rte_flow_ops = {
657         .validate = bnxt_ulp_flow_validate,
658         .create = bnxt_ulp_flow_create,
659         .destroy = bnxt_ulp_flow_destroy,
660         .flush = bnxt_ulp_flow_flush,
661         .query = bnxt_ulp_flow_query,
662         .isolate = NULL,
663         /* Tunnel offload callbacks */
664         .tunnel_decap_set = bnxt_ulp_tunnel_decap_set,
665         .tunnel_match = bnxt_ulp_tunnel_match,
666         .tunnel_action_decap_release = bnxt_ulp_tunnel_decap_release,
667         .tunnel_item_release = bnxt_ulp_tunnel_item_release,
668         .get_restore_info = NULL
669 };