]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
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 <rte_malloc.h> | |
13 | ||
14 | static int32_t | |
15 | bnxt_ulp_flow_validate_args(const struct rte_flow_attr *attr, | |
16 | const struct rte_flow_item pattern[], | |
17 | const struct rte_flow_action actions[], | |
18 | struct rte_flow_error *error) | |
19 | { | |
20 | /* Perform the validation of the arguments for null */ | |
21 | if (!error) | |
22 | return BNXT_TF_RC_ERROR; | |
23 | ||
24 | if (!pattern) { | |
25 | rte_flow_error_set(error, | |
26 | EINVAL, | |
27 | RTE_FLOW_ERROR_TYPE_ITEM_NUM, | |
28 | NULL, | |
29 | "NULL pattern."); | |
30 | return BNXT_TF_RC_ERROR; | |
31 | } | |
32 | ||
33 | if (!actions) { | |
34 | rte_flow_error_set(error, | |
35 | EINVAL, | |
36 | RTE_FLOW_ERROR_TYPE_ACTION_NUM, | |
37 | NULL, | |
38 | "NULL action."); | |
39 | return BNXT_TF_RC_ERROR; | |
40 | } | |
41 | ||
42 | if (!attr) { | |
43 | rte_flow_error_set(error, | |
44 | EINVAL, | |
45 | RTE_FLOW_ERROR_TYPE_ATTR, | |
46 | NULL, | |
47 | "NULL attribute."); | |
48 | return BNXT_TF_RC_ERROR; | |
49 | } | |
50 | ||
51 | if (attr->egress && attr->ingress) { | |
52 | rte_flow_error_set(error, | |
53 | EINVAL, | |
54 | RTE_FLOW_ERROR_TYPE_ATTR, | |
55 | attr, | |
56 | "EGRESS AND INGRESS UNSUPPORTED"); | |
57 | return BNXT_TF_RC_ERROR; | |
58 | } | |
59 | return BNXT_TF_RC_SUCCESS; | |
60 | } | |
61 | ||
62 | /* Function to create the rte flow. */ | |
63 | static struct rte_flow * | |
64 | bnxt_ulp_flow_create(struct rte_eth_dev *dev, | |
65 | const struct rte_flow_attr *attr, | |
66 | const struct rte_flow_item pattern[], | |
67 | const struct rte_flow_action actions[], | |
68 | struct rte_flow_error *error) | |
69 | { | |
70 | struct bnxt_ulp_mapper_create_parms mapper_cparms = { 0 }; | |
71 | struct ulp_rte_parser_params params; | |
72 | struct bnxt_ulp_context *ulp_ctx; | |
73 | uint32_t class_id, act_tmpl; | |
74 | struct rte_flow *flow_id; | |
75 | uint32_t fid; | |
76 | int ret; | |
77 | ||
78 | if (bnxt_ulp_flow_validate_args(attr, | |
79 | pattern, actions, | |
80 | error) == BNXT_TF_RC_ERROR) { | |
81 | BNXT_TF_DBG(ERR, "Invalid arguments being passed\n"); | |
82 | return NULL; | |
83 | } | |
84 | ||
85 | ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev); | |
86 | if (!ulp_ctx) { | |
87 | BNXT_TF_DBG(ERR, "ULP context is not initialized\n"); | |
88 | return NULL; | |
89 | } | |
90 | ||
91 | /* Initialize the parser params */ | |
92 | memset(¶ms, 0, sizeof(struct ulp_rte_parser_params)); | |
93 | params.ulp_ctx = ulp_ctx; | |
94 | ||
95 | if (attr->egress) | |
96 | params.dir = ULP_DIR_EGRESS; | |
97 | ||
98 | /* copy the device port id and direction for further processing */ | |
99 | ULP_UTIL_CHF_IDX_WR(¶ms, BNXT_ULP_CHF_IDX_INCOMING_IF, | |
100 | dev->data->port_id); | |
101 | ULP_UTIL_CHF_IDX_WR(¶ms, BNXT_ULP_CHF_IDX_DIRECTION, params.dir); | |
102 | ||
103 | /* Parse the rte flow pattern */ | |
104 | ret = bnxt_ulp_rte_parser_hdr_parse(pattern, ¶ms); | |
105 | if (ret != BNXT_TF_RC_SUCCESS) | |
106 | goto parse_error; | |
107 | ||
108 | /* Parse the rte flow action */ | |
109 | ret = bnxt_ulp_rte_parser_act_parse(actions, ¶ms); | |
110 | if (ret != BNXT_TF_RC_SUCCESS) | |
111 | goto parse_error; | |
112 | ||
113 | ret = ulp_matcher_pattern_match(¶ms, &class_id); | |
114 | if (ret != BNXT_TF_RC_SUCCESS) | |
115 | goto parse_error; | |
116 | ||
117 | ret = ulp_matcher_action_match(¶ms, &act_tmpl); | |
118 | if (ret != BNXT_TF_RC_SUCCESS) | |
119 | goto parse_error; | |
120 | ||
121 | mapper_cparms.app_priority = attr->priority; | |
122 | mapper_cparms.hdr_bitmap = ¶ms.hdr_bitmap; | |
123 | mapper_cparms.hdr_field = params.hdr_field; | |
124 | mapper_cparms.act = ¶ms.act_bitmap; | |
125 | mapper_cparms.act_prop = ¶ms.act_prop; | |
126 | mapper_cparms.class_tid = class_id; | |
127 | mapper_cparms.act_tid = act_tmpl; | |
128 | mapper_cparms.func_id = bnxt_get_fw_func_id(dev->data->port_id); | |
129 | mapper_cparms.dir = params.dir; | |
130 | ||
131 | /* Call the ulp mapper to create the flow in the hardware. */ | |
132 | ret = ulp_mapper_flow_create(ulp_ctx, &mapper_cparms, &fid); | |
133 | if (!ret) { | |
134 | flow_id = (struct rte_flow *)((uintptr_t)fid); | |
135 | return flow_id; | |
136 | } | |
137 | ||
138 | parse_error: | |
139 | rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, | |
140 | "Failed to create flow."); | |
141 | return NULL; | |
142 | } | |
143 | ||
144 | /* Function to validate the rte flow. */ | |
145 | static int | |
146 | bnxt_ulp_flow_validate(struct rte_eth_dev *dev, | |
147 | const struct rte_flow_attr *attr, | |
148 | const struct rte_flow_item pattern[], | |
149 | const struct rte_flow_action actions[], | |
150 | struct rte_flow_error *error) | |
151 | { | |
152 | struct ulp_rte_parser_params params; | |
153 | uint32_t class_id, act_tmpl; | |
154 | int ret; | |
155 | struct bnxt_ulp_context *ulp_ctx; | |
156 | ||
157 | if (bnxt_ulp_flow_validate_args(attr, | |
158 | pattern, actions, | |
159 | error) == BNXT_TF_RC_ERROR) { | |
160 | BNXT_TF_DBG(ERR, "Invalid arguments being passed\n"); | |
161 | return -EINVAL; | |
162 | } | |
163 | ||
164 | ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev); | |
165 | if (!ulp_ctx) { | |
166 | BNXT_TF_DBG(ERR, "ULP context is not initialized\n"); | |
167 | return -EINVAL; | |
168 | } | |
169 | ||
170 | /* Initialize the parser params */ | |
171 | memset(¶ms, 0, sizeof(struct ulp_rte_parser_params)); | |
172 | params.ulp_ctx = ulp_ctx; | |
173 | ||
174 | if (attr->egress) | |
175 | params.dir = ULP_DIR_EGRESS; | |
176 | ||
177 | /* Parse the rte flow pattern */ | |
178 | ret = bnxt_ulp_rte_parser_hdr_parse(pattern, ¶ms); | |
179 | if (ret != BNXT_TF_RC_SUCCESS) | |
180 | goto parse_error; | |
181 | ||
182 | /* Parse the rte flow action */ | |
183 | ret = bnxt_ulp_rte_parser_act_parse(actions, ¶ms); | |
184 | if (ret != BNXT_TF_RC_SUCCESS) | |
185 | goto parse_error; | |
186 | ||
187 | ret = ulp_matcher_pattern_match(¶ms, &class_id); | |
188 | ||
189 | if (ret != BNXT_TF_RC_SUCCESS) | |
190 | goto parse_error; | |
191 | ||
192 | ret = ulp_matcher_action_match(¶ms, &act_tmpl); | |
193 | if (ret != BNXT_TF_RC_SUCCESS) | |
194 | goto parse_error; | |
195 | ||
196 | /* all good return success */ | |
197 | return ret; | |
198 | ||
199 | parse_error: | |
200 | rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, | |
201 | "Failed to validate flow."); | |
202 | return -EINVAL; | |
203 | } | |
204 | ||
205 | /* Function to destroy the rte flow. */ | |
206 | static int | |
207 | bnxt_ulp_flow_destroy(struct rte_eth_dev *dev, | |
208 | struct rte_flow *flow, | |
209 | struct rte_flow_error *error) | |
210 | { | |
211 | int ret = 0; | |
212 | struct bnxt_ulp_context *ulp_ctx; | |
213 | uint32_t flow_id; | |
214 | uint16_t func_id; | |
215 | ||
216 | ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev); | |
217 | if (!ulp_ctx) { | |
218 | BNXT_TF_DBG(ERR, "ULP context is not initialized\n"); | |
219 | rte_flow_error_set(error, EINVAL, | |
220 | RTE_FLOW_ERROR_TYPE_HANDLE, NULL, | |
221 | "Failed to destroy flow."); | |
222 | return -EINVAL; | |
223 | } | |
224 | ||
225 | flow_id = (uint32_t)(uintptr_t)flow; | |
226 | func_id = bnxt_get_fw_func_id(dev->data->port_id); | |
227 | ||
228 | if (ulp_flow_db_validate_flow_func(ulp_ctx, flow_id, func_id) == | |
229 | false) { | |
230 | BNXT_TF_DBG(ERR, "Incorrect device params\n"); | |
231 | rte_flow_error_set(error, EINVAL, | |
232 | RTE_FLOW_ERROR_TYPE_HANDLE, NULL, | |
233 | "Failed to destroy flow."); | |
234 | return -EINVAL; | |
235 | } | |
236 | ||
237 | ret = ulp_mapper_flow_destroy(ulp_ctx, flow_id); | |
238 | if (ret) | |
239 | rte_flow_error_set(error, -ret, | |
240 | RTE_FLOW_ERROR_TYPE_HANDLE, NULL, | |
241 | "Failed to destroy flow."); | |
242 | ||
243 | return ret; | |
244 | } | |
245 | ||
246 | /* Function to destroy the rte flows. */ | |
247 | static int32_t | |
248 | bnxt_ulp_flow_flush(struct rte_eth_dev *eth_dev, | |
249 | struct rte_flow_error *error) | |
250 | { | |
251 | struct bnxt_ulp_context *ulp_ctx; | |
252 | int32_t ret = 0; | |
253 | struct bnxt *bp; | |
254 | uint16_t func_id; | |
255 | ||
256 | ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev); | |
257 | if (!ulp_ctx) { | |
258 | BNXT_TF_DBG(ERR, "ULP context is not initialized\n"); | |
259 | rte_flow_error_set(error, EINVAL, | |
260 | RTE_FLOW_ERROR_TYPE_HANDLE, NULL, | |
261 | "Failed to flush flow."); | |
262 | return -EINVAL; | |
263 | } | |
264 | bp = eth_dev->data->dev_private; | |
265 | ||
266 | /* Free the resources for the last device */ | |
267 | if (ulp_ctx_deinit_allowed(bp)) { | |
268 | ret = ulp_flow_db_session_flow_flush(ulp_ctx); | |
269 | } else if (bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx)) { | |
270 | func_id = bnxt_get_fw_func_id(eth_dev->data->port_id); | |
271 | ret = ulp_flow_db_function_flow_flush(ulp_ctx, func_id); | |
272 | } | |
273 | if (ret) | |
274 | rte_flow_error_set(error, ret, | |
275 | RTE_FLOW_ERROR_TYPE_HANDLE, NULL, | |
276 | "Failed to flush flow."); | |
277 | return ret; | |
278 | } | |
279 | ||
280 | const struct rte_flow_ops bnxt_ulp_rte_flow_ops = { | |
281 | .validate = bnxt_ulp_flow_validate, | |
282 | .create = bnxt_ulp_flow_create, | |
283 | .destroy = bnxt_ulp_flow_destroy, | |
284 | .flush = bnxt_ulp_flow_flush, | |
285 | .query = NULL, | |
286 | .isolate = NULL | |
287 | }; |