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_COMP_FLD_IDX_WR(¶ms, BNXT_ULP_CF_IDX_INCOMING_IF, 100 dev->data->port_id); 101 ULP_COMP_FLD_IDX_WR(¶ms, BNXT_ULP_CF_IDX_DIRECTION, params.dir); 102 ULP_COMP_FLD_IDX_WR(¶ms, BNXT_ULP_CF_IDX_SVIF_FLAG, 103 BNXT_ULP_INVALID_SVIF_VAL); 104 105 /* Parse the rte flow pattern */ 106 ret = bnxt_ulp_rte_parser_hdr_parse(pattern, ¶ms); 107 if (ret != BNXT_TF_RC_SUCCESS) 108 goto parse_error; 109 110 /* Parse the rte flow action */ 111 ret = bnxt_ulp_rte_parser_act_parse(actions, ¶ms); 112 if (ret != BNXT_TF_RC_SUCCESS) 113 goto parse_error; 114 115 ret = ulp_matcher_pattern_match(¶ms, &class_id); 116 if (ret != BNXT_TF_RC_SUCCESS) 117 goto parse_error; 118 119 ret = ulp_matcher_action_match(¶ms, &act_tmpl); 120 if (ret != BNXT_TF_RC_SUCCESS) 121 goto parse_error; 122 123 mapper_cparms.app_priority = attr->priority; 124 mapper_cparms.hdr_bitmap = ¶ms.hdr_bitmap; 125 mapper_cparms.hdr_field = params.hdr_field; 126 mapper_cparms.comp_fld = params.comp_fld; 127 mapper_cparms.act = ¶ms.act_bitmap; 128 mapper_cparms.act_prop = ¶ms.act_prop; 129 mapper_cparms.class_tid = class_id; 130 mapper_cparms.act_tid = act_tmpl; 131 mapper_cparms.func_id = bnxt_get_fw_func_id(dev->data->port_id); 132 mapper_cparms.dir = params.dir; 133 134 /* Call the ulp mapper to create the flow in the hardware. */ 135 ret = ulp_mapper_flow_create(ulp_ctx, &mapper_cparms, &fid); 136 if (!ret) { 137 flow_id = (struct rte_flow *)((uintptr_t)fid); 138 return flow_id; 139 } 140 141 parse_error: 142 rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 143 "Failed to create flow."); 144 return NULL; 145 } 146 147 /* Function to validate the rte flow. */ 148 static int 149 bnxt_ulp_flow_validate(struct rte_eth_dev *dev, 150 const struct rte_flow_attr *attr, 151 const struct rte_flow_item pattern[], 152 const struct rte_flow_action actions[], 153 struct rte_flow_error *error) 154 { 155 struct ulp_rte_parser_params params; 156 uint32_t class_id, act_tmpl; 157 int ret; 158 struct bnxt_ulp_context *ulp_ctx; 159 160 if (bnxt_ulp_flow_validate_args(attr, 161 pattern, actions, 162 error) == BNXT_TF_RC_ERROR) { 163 BNXT_TF_DBG(ERR, "Invalid arguments being passed\n"); 164 return -EINVAL; 165 } 166 167 ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev); 168 if (!ulp_ctx) { 169 BNXT_TF_DBG(ERR, "ULP context is not initialized\n"); 170 return -EINVAL; 171 } 172 173 /* Initialize the parser params */ 174 memset(¶ms, 0, sizeof(struct ulp_rte_parser_params)); 175 params.ulp_ctx = ulp_ctx; 176 177 if (attr->egress) 178 params.dir = ULP_DIR_EGRESS; 179 180 /* Parse the rte flow pattern */ 181 ret = bnxt_ulp_rte_parser_hdr_parse(pattern, ¶ms); 182 if (ret != BNXT_TF_RC_SUCCESS) 183 goto parse_error; 184 185 /* Parse the rte flow action */ 186 ret = bnxt_ulp_rte_parser_act_parse(actions, ¶ms); 187 if (ret != BNXT_TF_RC_SUCCESS) 188 goto parse_error; 189 190 ret = ulp_matcher_pattern_match(¶ms, &class_id); 191 192 if (ret != BNXT_TF_RC_SUCCESS) 193 goto parse_error; 194 195 ret = ulp_matcher_action_match(¶ms, &act_tmpl); 196 if (ret != BNXT_TF_RC_SUCCESS) 197 goto parse_error; 198 199 /* all good return success */ 200 return ret; 201 202 parse_error: 203 rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 204 "Failed to validate flow."); 205 return -EINVAL; 206 } 207 208 /* Function to destroy the rte flow. */ 209 static int 210 bnxt_ulp_flow_destroy(struct rte_eth_dev *dev, 211 struct rte_flow *flow, 212 struct rte_flow_error *error) 213 { 214 int ret = 0; 215 struct bnxt_ulp_context *ulp_ctx; 216 uint32_t flow_id; 217 uint16_t func_id; 218 219 ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev); 220 if (!ulp_ctx) { 221 BNXT_TF_DBG(ERR, "ULP context is not initialized\n"); 222 rte_flow_error_set(error, EINVAL, 223 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 224 "Failed to destroy flow."); 225 return -EINVAL; 226 } 227 228 flow_id = (uint32_t)(uintptr_t)flow; 229 func_id = bnxt_get_fw_func_id(dev->data->port_id); 230 231 if (ulp_flow_db_validate_flow_func(ulp_ctx, flow_id, func_id) == 232 false) { 233 BNXT_TF_DBG(ERR, "Incorrect device params\n"); 234 rte_flow_error_set(error, EINVAL, 235 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 236 "Failed to destroy flow."); 237 return -EINVAL; 238 } 239 240 ret = ulp_mapper_flow_destroy(ulp_ctx, flow_id); 241 if (ret) 242 rte_flow_error_set(error, -ret, 243 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 244 "Failed to destroy flow."); 245 246 return ret; 247 } 248 249 /* Function to destroy the rte flows. */ 250 static int32_t 251 bnxt_ulp_flow_flush(struct rte_eth_dev *eth_dev, 252 struct rte_flow_error *error) 253 { 254 struct bnxt_ulp_context *ulp_ctx; 255 int32_t ret = 0; 256 struct bnxt *bp; 257 uint16_t func_id; 258 259 ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev); 260 if (!ulp_ctx) { 261 BNXT_TF_DBG(ERR, "ULP context is not initialized\n"); 262 rte_flow_error_set(error, EINVAL, 263 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 264 "Failed to flush flow."); 265 return -EINVAL; 266 } 267 bp = eth_dev->data->dev_private; 268 269 /* Free the resources for the last device */ 270 if (ulp_ctx_deinit_allowed(bp)) { 271 ret = ulp_flow_db_session_flow_flush(ulp_ctx); 272 } else if (bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx)) { 273 func_id = bnxt_get_fw_func_id(eth_dev->data->port_id); 274 ret = ulp_flow_db_function_flow_flush(ulp_ctx, func_id); 275 } 276 if (ret) 277 rte_flow_error_set(error, ret, 278 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 279 "Failed to flush flow."); 280 return ret; 281 } 282 283 const struct rte_flow_ops bnxt_ulp_rte_flow_ops = { 284 .validate = bnxt_ulp_flow_validate, 285 .create = bnxt_ulp_flow_create, 286 .destroy = bnxt_ulp_flow_destroy, 287 .flush = bnxt_ulp_flow_flush, 288 .query = NULL, 289 .isolate = NULL 290 }; 291