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(¶ms, 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(¶ms, attr); 111 112 /* copy the device port id and direction for further processing */ 113 ULP_COMP_FLD_IDX_WR(¶ms, BNXT_ULP_CF_IDX_INCOMING_IF, 114 dev->data->port_id); 115 ULP_COMP_FLD_IDX_WR(¶ms, 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, ¶ms); 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, ¶ms); 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(¶ms); 130 if (ret != BNXT_TF_RC_SUCCESS) 131 goto parse_error; 132 133 ret = ulp_matcher_pattern_match(¶ms, &class_id); 134 if (ret != BNXT_TF_RC_SUCCESS) 135 goto parse_error; 136 137 ret = ulp_matcher_action_match(¶ms, &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 = ¶ms.hdr_bitmap; 143 mapper_cparms.hdr_field = params.hdr_field; 144 mapper_cparms.comp_fld = params.comp_fld; 145 mapper_cparms.act = ¶ms.act_bitmap; 146 mapper_cparms.act_prop = ¶ms.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(¶ms, 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(¶ms, attr); 198 199 /* Parse the rte flow pattern */ 200 ret = bnxt_ulp_rte_parser_hdr_parse(pattern, ¶ms); 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, ¶ms); 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(¶ms); 211 if (ret != BNXT_TF_RC_SUCCESS) 212 goto parse_error; 213 214 ret = ulp_matcher_pattern_match(¶ms, &class_id); 215 216 if (ret != BNXT_TF_RC_SUCCESS) 217 goto parse_error; 218 219 ret = ulp_matcher_action_match(¶ms, &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 }; 365