net/bnxt: combine default and regular flows
[dpdk.git] / drivers / net / bnxt / tf_ulp / bnxt_ulp_flow.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2020 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 <rte_malloc.h>
15
16 static int32_t
17 bnxt_ulp_flow_validate_args(const struct rte_flow_attr *attr,
18                             const struct rte_flow_item pattern[],
19                             const struct rte_flow_action actions[],
20                             struct rte_flow_error *error)
21 {
22         /* Perform the validation of the arguments for null */
23         if (!error)
24                 return BNXT_TF_RC_ERROR;
25
26         if (!pattern) {
27                 rte_flow_error_set(error,
28                                    EINVAL,
29                                    RTE_FLOW_ERROR_TYPE_ITEM_NUM,
30                                    NULL,
31                                    "NULL pattern.");
32                 return BNXT_TF_RC_ERROR;
33         }
34
35         if (!actions) {
36                 rte_flow_error_set(error,
37                                    EINVAL,
38                                    RTE_FLOW_ERROR_TYPE_ACTION_NUM,
39                                    NULL,
40                                    "NULL action.");
41                 return BNXT_TF_RC_ERROR;
42         }
43
44         if (!attr) {
45                 rte_flow_error_set(error,
46                                    EINVAL,
47                                    RTE_FLOW_ERROR_TYPE_ATTR,
48                                    NULL,
49                                    "NULL attribute.");
50                 return BNXT_TF_RC_ERROR;
51         }
52
53         if (attr->egress && attr->ingress) {
54                 rte_flow_error_set(error,
55                                    EINVAL,
56                                    RTE_FLOW_ERROR_TYPE_ATTR,
57                                    attr,
58                                    "EGRESS AND INGRESS UNSUPPORTED");
59                 return BNXT_TF_RC_ERROR;
60         }
61         return BNXT_TF_RC_SUCCESS;
62 }
63
64 static inline void
65 bnxt_ulp_set_dir_attributes(struct ulp_rte_parser_params *params,
66                             const struct rte_flow_attr *attr)
67 {
68         /* Set the flow attributes */
69         if (attr->egress)
70                 params->dir_attr |= BNXT_ULP_FLOW_ATTR_EGRESS;
71         if (attr->ingress)
72                 params->dir_attr |= BNXT_ULP_FLOW_ATTR_INGRESS;
73         if (attr->transfer)
74                 params->dir_attr |= BNXT_ULP_FLOW_ATTR_TRANSFER;
75 }
76
77 /* Function to create the rte flow. */
78 static struct rte_flow *
79 bnxt_ulp_flow_create(struct rte_eth_dev *dev,
80                      const struct rte_flow_attr *attr,
81                      const struct rte_flow_item pattern[],
82                      const struct rte_flow_action actions[],
83                      struct rte_flow_error *error)
84 {
85         struct bnxt_ulp_mapper_create_parms mapper_cparms = { 0 };
86         struct ulp_rte_parser_params params;
87         struct bnxt_ulp_context *ulp_ctx;
88         uint32_t class_id, act_tmpl;
89         struct rte_flow *flow_id;
90         uint32_t fid;
91         int ret = BNXT_TF_RC_ERROR;
92
93         if (bnxt_ulp_flow_validate_args(attr,
94                                         pattern, actions,
95                                         error) == BNXT_TF_RC_ERROR) {
96                 BNXT_TF_DBG(ERR, "Invalid arguments being passed\n");
97                 goto parse_error;
98         }
99
100         ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);
101         if (!ulp_ctx) {
102                 BNXT_TF_DBG(ERR, "ULP context is not initialized\n");
103                 goto parse_error;
104         }
105
106         /* Initialize the parser params */
107         memset(&params, 0, sizeof(struct ulp_rte_parser_params));
108         params.ulp_ctx = ulp_ctx;
109
110         /* Set the flow attributes */
111         bnxt_ulp_set_dir_attributes(&params, attr);
112
113         /* copy the device port id and direction for further processing */
114         ULP_COMP_FLD_IDX_WR(&params, BNXT_ULP_CF_IDX_INCOMING_IF,
115                             dev->data->port_id);
116         ULP_COMP_FLD_IDX_WR(&params, BNXT_ULP_CF_IDX_SVIF_FLAG,
117                             BNXT_ULP_INVALID_SVIF_VAL);
118
119         /* Parse the rte flow pattern */
120         ret = bnxt_ulp_rte_parser_hdr_parse(pattern, &params);
121         if (ret != BNXT_TF_RC_SUCCESS)
122                 goto parse_error;
123
124         /* Parse the rte flow action */
125         ret = bnxt_ulp_rte_parser_act_parse(actions, &params);
126         if (ret != BNXT_TF_RC_SUCCESS)
127                 goto parse_error;
128
129         /* Perform the rte flow post process */
130         ret = bnxt_ulp_rte_parser_post_process(&params);
131         if (ret != BNXT_TF_RC_SUCCESS)
132                 goto parse_error;
133
134         ret = ulp_matcher_pattern_match(&params, &class_id);
135         if (ret != BNXT_TF_RC_SUCCESS)
136                 goto parse_error;
137
138         ret = ulp_matcher_action_match(&params, &act_tmpl);
139         if (ret != BNXT_TF_RC_SUCCESS)
140                 goto parse_error;
141
142         mapper_cparms.app_priority = attr->priority;
143         mapper_cparms.hdr_bitmap = &params.hdr_bitmap;
144         mapper_cparms.hdr_field = params.hdr_field;
145         mapper_cparms.comp_fld = params.comp_fld;
146         mapper_cparms.act = &params.act_bitmap;
147         mapper_cparms.act_prop = &params.act_prop;
148         mapper_cparms.class_tid = class_id;
149         mapper_cparms.act_tid = act_tmpl;
150         mapper_cparms.flow_type = BNXT_ULP_FDB_TYPE_REGULAR;
151
152         /* Get the function id */
153         if (ulp_port_db_port_func_id_get(ulp_ctx,
154                                          dev->data->port_id,
155                                          &mapper_cparms.func_id)) {
156                 BNXT_TF_DBG(ERR, "conversion of port to func id failed\n");
157                 goto parse_error;
158         }
159         mapper_cparms.dir_attr = params.dir_attr;
160
161         /* Call the ulp mapper to create the flow in the hardware. */
162         ret = ulp_mapper_flow_create(ulp_ctx, &mapper_cparms, &fid);
163         if (!ret) {
164                 flow_id = (struct rte_flow *)((uintptr_t)fid);
165                 return flow_id;
166         }
167
168 parse_error:
169         rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
170                            "Failed to create flow.");
171         return NULL;
172 }
173
174 /* Function to validate the rte flow. */
175 static int
176 bnxt_ulp_flow_validate(struct rte_eth_dev *dev,
177                        const struct rte_flow_attr *attr,
178                        const struct rte_flow_item pattern[],
179                        const struct rte_flow_action actions[],
180                        struct rte_flow_error *error)
181 {
182         struct ulp_rte_parser_params            params;
183         uint32_t class_id, act_tmpl;
184         int ret = BNXT_TF_RC_ERROR;
185         struct bnxt_ulp_context *ulp_ctx;
186
187         if (bnxt_ulp_flow_validate_args(attr,
188                                         pattern, actions,
189                                         error) == BNXT_TF_RC_ERROR) {
190                 BNXT_TF_DBG(ERR, "Invalid arguments being passed\n");
191                 goto parse_error;
192         }
193
194         ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);
195         if (!ulp_ctx) {
196                 BNXT_TF_DBG(ERR, "ULP context is not initialized\n");
197                 goto parse_error;
198         }
199
200         /* Initialize the parser params */
201         memset(&params, 0, sizeof(struct ulp_rte_parser_params));
202         params.ulp_ctx = ulp_ctx;
203
204         /* Set the flow attributes */
205         bnxt_ulp_set_dir_attributes(&params, attr);
206
207         /* Parse the rte flow pattern */
208         ret = bnxt_ulp_rte_parser_hdr_parse(pattern, &params);
209         if (ret != BNXT_TF_RC_SUCCESS)
210                 goto parse_error;
211
212         /* Parse the rte flow action */
213         ret = bnxt_ulp_rte_parser_act_parse(actions, &params);
214         if (ret != BNXT_TF_RC_SUCCESS)
215                 goto parse_error;
216
217         /* Perform the rte flow post process */
218         ret = bnxt_ulp_rte_parser_post_process(&params);
219         if (ret != BNXT_TF_RC_SUCCESS)
220                 goto parse_error;
221
222         ret = ulp_matcher_pattern_match(&params, &class_id);
223
224         if (ret != BNXT_TF_RC_SUCCESS)
225                 goto parse_error;
226
227         ret = ulp_matcher_action_match(&params, &act_tmpl);
228         if (ret != BNXT_TF_RC_SUCCESS)
229                 goto parse_error;
230
231         /* all good return success */
232         return ret;
233
234 parse_error:
235         rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
236                            "Failed to validate flow.");
237         return -EINVAL;
238 }
239
240 /* Function to destroy the rte flow. */
241 int
242 bnxt_ulp_flow_destroy(struct rte_eth_dev *dev,
243                       struct rte_flow *flow,
244                       struct rte_flow_error *error)
245 {
246         int ret = 0;
247         struct bnxt_ulp_context *ulp_ctx;
248         uint32_t flow_id;
249         uint16_t func_id;
250
251         ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);
252         if (!ulp_ctx) {
253                 BNXT_TF_DBG(ERR, "ULP context is not initialized\n");
254                 if (error)
255                         rte_flow_error_set(error, EINVAL,
256                                            RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
257                                            "Failed to destroy flow.");
258                 return -EINVAL;
259         }
260
261         flow_id = (uint32_t)(uintptr_t)flow;
262
263         if (ulp_port_db_port_func_id_get(ulp_ctx,
264                                          dev->data->port_id,
265                                          &func_id)) {
266                 BNXT_TF_DBG(ERR, "conversion of port to func id failed\n");
267                 if (error)
268                         rte_flow_error_set(error, EINVAL,
269                                            RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
270                                            "Failed to destroy flow.");
271                 return -EINVAL;
272         }
273
274         if (ulp_flow_db_validate_flow_func(ulp_ctx, flow_id, func_id) ==
275             false) {
276                 BNXT_TF_DBG(ERR, "Incorrect device params\n");
277                 if (error)
278                         rte_flow_error_set(error, EINVAL,
279                                            RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
280                                            "Failed to destroy flow.");
281                 return -EINVAL;
282         }
283
284         ret = ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
285                                       flow_id);
286         if (ret) {
287                 BNXT_TF_DBG(ERR, "Failed to destroy flow.\n");
288                 if (error)
289                         rte_flow_error_set(error, -ret,
290                                            RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
291                                            "Failed to destroy flow.");
292         }
293
294         return ret;
295 }
296
297 /* Function to destroy the rte flows. */
298 static int32_t
299 bnxt_ulp_flow_flush(struct rte_eth_dev *eth_dev,
300                     struct rte_flow_error *error)
301 {
302         struct bnxt_ulp_context *ulp_ctx;
303         int32_t ret = 0;
304         uint16_t func_id;
305
306         ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev);
307         if (!ulp_ctx) {
308                 return ret;
309         }
310
311         /* Free the resources for the last device */
312         if (ulp_ctx_deinit_allowed(ulp_ctx)) {
313                 ret = ulp_flow_db_session_flow_flush(ulp_ctx);
314         } else if (bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx)) {
315                 ret = ulp_port_db_port_func_id_get(ulp_ctx,
316                                                    eth_dev->data->port_id,
317                                                    &func_id);
318                 if (!ret)
319                         ret = ulp_flow_db_function_flow_flush(ulp_ctx, func_id);
320                 else
321                         BNXT_TF_DBG(ERR, "convert port to func id failed\n");
322         }
323         if (ret)
324                 rte_flow_error_set(error, ret,
325                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
326                                    "Failed to flush flow.");
327         return ret;
328 }
329
330 /* Function to query the rte flows. */
331 static int32_t
332 bnxt_ulp_flow_query(struct rte_eth_dev *eth_dev,
333                     struct rte_flow *flow,
334                     const struct rte_flow_action *action,
335                     void *data,
336                     struct rte_flow_error *error)
337 {
338         int rc = 0;
339         struct bnxt_ulp_context *ulp_ctx;
340         struct rte_flow_query_count *count;
341         uint32_t flow_id;
342
343         ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev);
344         if (!ulp_ctx) {
345                 BNXT_TF_DBG(ERR, "ULP context is not initialized\n");
346                 rte_flow_error_set(error, EINVAL,
347                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
348                                    "Failed to query flow.");
349                 return -EINVAL;
350         }
351
352         flow_id = (uint32_t)(uintptr_t)flow;
353
354         switch (action->type) {
355         case RTE_FLOW_ACTION_TYPE_COUNT:
356                 count = data;
357                 rc = ulp_fc_mgr_query_count_get(ulp_ctx, flow_id, count);
358                 if (rc) {
359                         rte_flow_error_set(error, EINVAL,
360                                            RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
361                                            "Failed to query flow.");
362                 }
363                 break;
364         default:
365                 rte_flow_error_set(error, -rc, RTE_FLOW_ERROR_TYPE_ACTION_NUM,
366                                    NULL, "Unsupported action item");
367         }
368
369         return rc;
370 }
371
372 const struct rte_flow_ops bnxt_ulp_rte_flow_ops = {
373         .validate = bnxt_ulp_flow_validate,
374         .create = bnxt_ulp_flow_create,
375         .destroy = bnxt_ulp_flow_destroy,
376         .flush = bnxt_ulp_flow_flush,
377         .query = bnxt_ulp_flow_query,
378         .isolate = NULL
379 };