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