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 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(¶ms, 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(¶ms, attr); 206 207 /* Parse the rte flow pattern */ 208 ret = bnxt_ulp_rte_parser_hdr_parse(pattern, ¶ms); 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, ¶ms); 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(¶ms); 219 if (ret != BNXT_TF_RC_SUCCESS) 220 goto parse_error; 221 222 ret = ulp_matcher_pattern_match(¶ms, &class_id); 223 224 if (ret != BNXT_TF_RC_SUCCESS) 225 goto parse_error; 226 227 ret = ulp_matcher_action_match(¶ms, &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 }; 380