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(¶ms, 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(¶ms, attr); 112 113 /* copy the device port id and direction for further processing */ 114 ULP_COMP_FLD_IDX_WR(¶ms, BNXT_ULP_CF_IDX_INCOMING_IF, 115 dev->data->port_id); 116 ULP_COMP_FLD_IDX_WR(¶ms, 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, ¶ms); 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, ¶ms); 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(¶ms); 131 if (ret != BNXT_TF_RC_SUCCESS) 132 goto parse_error; 133 134 ret = ulp_matcher_pattern_match(¶ms, &class_id); 135 if (ret != BNXT_TF_RC_SUCCESS) 136 goto parse_error; 137 138 ret = ulp_matcher_action_match(¶ms, &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 = ¶ms.hdr_bitmap; 144 mapper_cparms.hdr_field = params.hdr_field; 145 mapper_cparms.comp_fld = params.comp_fld; 146 mapper_cparms.act = ¶ms.act_bitmap; 147 mapper_cparms.act_prop = ¶ms.act_prop; 148 mapper_cparms.class_tid = class_id; 149 mapper_cparms.act_tid = act_tmpl; 150 151 /* Get the function id */ 152 if (ulp_port_db_port_func_id_get(ulp_ctx, 153 dev->data->port_id, 154 &mapper_cparms.func_id)) { 155 BNXT_TF_DBG(ERR, "conversion of port to func id failed\n"); 156 goto parse_error; 157 } 158 mapper_cparms.dir_attr = params.dir_attr; 159 160 /* Call the ulp mapper to create the flow in the hardware. */ 161 ret = ulp_mapper_flow_create(ulp_ctx, &mapper_cparms, &fid); 162 if (!ret) { 163 flow_id = (struct rte_flow *)((uintptr_t)fid); 164 return flow_id; 165 } 166 167 parse_error: 168 rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 169 "Failed to create flow."); 170 return NULL; 171 } 172 173 /* Function to validate the rte flow. */ 174 static int 175 bnxt_ulp_flow_validate(struct rte_eth_dev *dev, 176 const struct rte_flow_attr *attr, 177 const struct rte_flow_item pattern[], 178 const struct rte_flow_action actions[], 179 struct rte_flow_error *error) 180 { 181 struct ulp_rte_parser_params params; 182 uint32_t class_id, act_tmpl; 183 int ret = BNXT_TF_RC_ERROR; 184 struct bnxt_ulp_context *ulp_ctx; 185 186 if (bnxt_ulp_flow_validate_args(attr, 187 pattern, actions, 188 error) == BNXT_TF_RC_ERROR) { 189 BNXT_TF_DBG(ERR, "Invalid arguments being passed\n"); 190 goto parse_error; 191 } 192 193 ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev); 194 if (!ulp_ctx) { 195 BNXT_TF_DBG(ERR, "ULP context is not initialized\n"); 196 goto parse_error; 197 } 198 199 /* Initialize the parser params */ 200 memset(¶ms, 0, sizeof(struct ulp_rte_parser_params)); 201 params.ulp_ctx = ulp_ctx; 202 203 /* Set the flow attributes */ 204 bnxt_ulp_set_dir_attributes(¶ms, attr); 205 206 /* Parse the rte flow pattern */ 207 ret = bnxt_ulp_rte_parser_hdr_parse(pattern, ¶ms); 208 if (ret != BNXT_TF_RC_SUCCESS) 209 goto parse_error; 210 211 /* Parse the rte flow action */ 212 ret = bnxt_ulp_rte_parser_act_parse(actions, ¶ms); 213 if (ret != BNXT_TF_RC_SUCCESS) 214 goto parse_error; 215 216 /* Perform the rte flow post process */ 217 ret = bnxt_ulp_rte_parser_post_process(¶ms); 218 if (ret != BNXT_TF_RC_SUCCESS) 219 goto parse_error; 220 221 ret = ulp_matcher_pattern_match(¶ms, &class_id); 222 223 if (ret != BNXT_TF_RC_SUCCESS) 224 goto parse_error; 225 226 ret = ulp_matcher_action_match(¶ms, &act_tmpl); 227 if (ret != BNXT_TF_RC_SUCCESS) 228 goto parse_error; 229 230 /* all good return success */ 231 return ret; 232 233 parse_error: 234 rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 235 "Failed to validate flow."); 236 return -EINVAL; 237 } 238 239 /* Function to destroy the rte flow. */ 240 int 241 bnxt_ulp_flow_destroy(struct rte_eth_dev *dev, 242 struct rte_flow *flow, 243 struct rte_flow_error *error) 244 { 245 int ret = 0; 246 struct bnxt_ulp_context *ulp_ctx; 247 uint32_t flow_id; 248 uint16_t func_id; 249 250 ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev); 251 if (!ulp_ctx) { 252 BNXT_TF_DBG(ERR, "ULP context is not initialized\n"); 253 if (error) 254 rte_flow_error_set(error, EINVAL, 255 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 256 "Failed to destroy flow."); 257 return -EINVAL; 258 } 259 260 flow_id = (uint32_t)(uintptr_t)flow; 261 262 if (ulp_port_db_port_func_id_get(ulp_ctx, 263 dev->data->port_id, 264 &func_id)) { 265 BNXT_TF_DBG(ERR, "conversion of port to func id failed\n"); 266 if (error) 267 rte_flow_error_set(error, EINVAL, 268 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 269 "Failed to destroy flow."); 270 return -EINVAL; 271 } 272 273 if (ulp_flow_db_validate_flow_func(ulp_ctx, flow_id, func_id) == 274 false) { 275 BNXT_TF_DBG(ERR, "Incorrect device params\n"); 276 if (error) 277 rte_flow_error_set(error, EINVAL, 278 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 279 "Failed to destroy flow."); 280 return -EINVAL; 281 } 282 283 ret = ulp_mapper_flow_destroy(ulp_ctx, flow_id, 284 BNXT_ULP_REGULAR_FLOW_TABLE); 285 if (ret) { 286 BNXT_TF_DBG(ERR, "Failed to destroy flow.\n"); 287 if (error) 288 rte_flow_error_set(error, -ret, 289 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 290 "Failed to destroy flow."); 291 } 292 293 return ret; 294 } 295 296 /* Function to destroy the rte flows. */ 297 static int32_t 298 bnxt_ulp_flow_flush(struct rte_eth_dev *eth_dev, 299 struct rte_flow_error *error) 300 { 301 struct bnxt_ulp_context *ulp_ctx; 302 int32_t ret = 0; 303 uint16_t func_id; 304 305 ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev); 306 if (!ulp_ctx) { 307 return ret; 308 } 309 310 /* Free the resources for the last device */ 311 if (ulp_ctx_deinit_allowed(ulp_ctx)) { 312 ret = ulp_flow_db_session_flow_flush(ulp_ctx); 313 } else if (bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx)) { 314 ret = ulp_port_db_port_func_id_get(ulp_ctx, 315 eth_dev->data->port_id, 316 &func_id); 317 if (!ret) 318 ret = ulp_flow_db_function_flow_flush(ulp_ctx, func_id); 319 else 320 BNXT_TF_DBG(ERR, "convert port to func id failed\n"); 321 } 322 if (ret) 323 rte_flow_error_set(error, ret, 324 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 325 "Failed to flush flow."); 326 return ret; 327 } 328 329 /* Function to query the rte flows. */ 330 static int32_t 331 bnxt_ulp_flow_query(struct rte_eth_dev *eth_dev, 332 struct rte_flow *flow, 333 const struct rte_flow_action *action, 334 void *data, 335 struct rte_flow_error *error) 336 { 337 int rc = 0; 338 struct bnxt_ulp_context *ulp_ctx; 339 struct rte_flow_query_count *count; 340 uint32_t flow_id; 341 342 ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev); 343 if (!ulp_ctx) { 344 BNXT_TF_DBG(ERR, "ULP context is not initialized\n"); 345 rte_flow_error_set(error, EINVAL, 346 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 347 "Failed to query flow."); 348 return -EINVAL; 349 } 350 351 flow_id = (uint32_t)(uintptr_t)flow; 352 353 switch (action->type) { 354 case RTE_FLOW_ACTION_TYPE_COUNT: 355 count = data; 356 rc = ulp_fc_mgr_query_count_get(ulp_ctx, flow_id, count); 357 if (rc) { 358 rte_flow_error_set(error, EINVAL, 359 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 360 "Failed to query flow."); 361 } 362 break; 363 default: 364 rte_flow_error_set(error, -rc, RTE_FLOW_ERROR_TYPE_ACTION_NUM, 365 NULL, "Unsupported action item"); 366 } 367 368 return rc; 369 } 370 371 const struct rte_flow_ops bnxt_ulp_rte_flow_ops = { 372 .validate = bnxt_ulp_flow_validate, 373 .create = bnxt_ulp_flow_create, 374 .destroy = bnxt_ulp_flow_destroy, 375 .flush = bnxt_ulp_flow_flush, 376 .query = bnxt_ulp_flow_query, 377 .isolate = NULL 378 }; 379