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