Add pattern parsing stub, define and implement flow cleanup method.
The latter is needed to free any dynamic structures allocated
during flow parsing.
Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
struct sfc_flow_ops_by_spec {
sfc_flow_parse_cb_t *parse;
+ sfc_flow_cleanup_cb_t *cleanup;
sfc_flow_insert_cb_t *insert;
sfc_flow_remove_cb_t *remove;
};
static sfc_flow_parse_cb_t sfc_flow_parse_rte_to_filter;
+static sfc_flow_parse_cb_t sfc_flow_parse_rte_to_mae;
static sfc_flow_insert_cb_t sfc_flow_filter_insert;
static sfc_flow_remove_cb_t sfc_flow_filter_remove;
static const struct sfc_flow_ops_by_spec sfc_flow_ops_filter = {
.parse = sfc_flow_parse_rte_to_filter,
+ .cleanup = NULL,
.insert = sfc_flow_filter_insert,
.remove = sfc_flow_filter_remove,
};
+static const struct sfc_flow_ops_by_spec sfc_flow_ops_mae = {
+ .parse = sfc_flow_parse_rte_to_mae,
+ .cleanup = sfc_mae_flow_cleanup,
+ .insert = NULL,
+ .remove = NULL,
+};
+
static const struct sfc_flow_ops_by_spec *
sfc_flow_get_ops_by_spec(struct rte_flow *flow)
{
case SFC_FLOW_SPEC_FILTER:
ops = &sfc_flow_ops_filter;
break;
+ case SFC_FLOW_SPEC_MAE:
+ ops = &sfc_flow_ops_mae;
+ break;
default:
SFC_ASSERT(false);
break;
}
spec->type = SFC_FLOW_SPEC_MAE;
spec_mae->priority = attr->priority;
+ spec_mae->match_spec = NULL;
}
return 0;
return rc;
}
+static int
+sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
+ const struct rte_flow_item pattern[],
+ __rte_unused const struct rte_flow_action actions[],
+ struct rte_flow *flow,
+ struct rte_flow_error *error)
+{
+ struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+ struct sfc_flow_spec *spec = &flow->spec;
+ struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+ int rc;
+
+ rc = sfc_mae_rule_parse_pattern(sa, pattern, spec_mae, error);
+ if (rc != 0)
+ return rc;
+
+ return 0;
+}
+
static int
sfc_flow_parse(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
}
static void
-sfc_flow_free(__rte_unused struct sfc_adapter *sa, struct rte_flow *flow)
+sfc_flow_free(struct sfc_adapter *sa, struct rte_flow *flow)
{
+ const struct sfc_flow_ops_by_spec *ops;
+
+ ops = sfc_flow_get_ops_by_spec(flow);
+ if (ops != NULL && ops->cleanup != NULL)
+ ops->cleanup(sa, flow);
+
rte_free(flow);
}
struct sfc_flow_spec_mae {
/* Desired priority level */
unsigned int priority;
+ /* EFX match specification */
+ efx_mae_match_spec_t *match_spec;
};
/* Flow specification */
/* Flow parse context types */
enum sfc_flow_parse_ctx_type {
SFC_FLOW_PARSE_CTX_FILTER = 0,
+ SFC_FLOW_PARSE_CTX_MAE,
SFC_FLOW_PARSE_CTX_NTYPES
};
union {
/* Context pointer valid for filter-based (VNIC) flows */
efx_filter_spec_t *filter;
+ /* Context pointer valid for MAE-based flows */
+ struct sfc_mae_parse_ctx *mae;
};
};
struct rte_flow *flow,
struct rte_flow_error *error);
+typedef void (sfc_flow_cleanup_cb_t)(struct sfc_adapter *sa,
+ struct rte_flow *flow);
+
typedef int (sfc_flow_insert_cb_t)(struct sfc_adapter *sa,
struct rte_flow *flow);
sfc_log_init(sa, "done");
}
+
+void
+sfc_mae_flow_cleanup(struct sfc_adapter *sa,
+ struct rte_flow *flow)
+{
+ struct sfc_flow_spec *spec;
+ struct sfc_flow_spec_mae *spec_mae;
+
+ if (flow == NULL)
+ return;
+
+ spec = &flow->spec;
+
+ if (spec == NULL)
+ return;
+
+ spec_mae = &spec->mae;
+
+ if (spec_mae->match_spec != NULL)
+ efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
+}
+
+static const struct sfc_flow_item sfc_flow_items[] = {
+};
+
+int
+sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
+ const struct rte_flow_item pattern[],
+ struct sfc_flow_spec_mae *spec,
+ struct rte_flow_error *error)
+{
+ struct sfc_mae_parse_ctx ctx_mae;
+ struct sfc_flow_parse_ctx ctx;
+ int rc;
+
+ memset(&ctx_mae, 0, sizeof(ctx_mae));
+
+ rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
+ spec->priority,
+ &ctx_mae.match_spec_action);
+ if (rc != 0) {
+ rc = rte_flow_error_set(error, rc,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Failed to initialise action rule match specification");
+ goto fail_init_match_spec_action;
+ }
+
+ ctx.type = SFC_FLOW_PARSE_CTX_MAE;
+ ctx.mae = &ctx_mae;
+
+ rc = sfc_flow_parse_pattern(sfc_flow_items, RTE_DIM(sfc_flow_items),
+ pattern, &ctx, error);
+ if (rc != 0)
+ goto fail_parse_pattern;
+
+ spec->match_spec = ctx_mae.match_spec_action;
+
+ return 0;
+
+fail_parse_pattern:
+ efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);
+
+fail_init_match_spec_action:
+ return rc;
+}
};
struct sfc_adapter;
+struct sfc_flow_spec;
+
+struct sfc_mae_parse_ctx {
+ efx_mae_match_spec_t *match_spec_action;
+};
int sfc_mae_attach(struct sfc_adapter *sa);
void sfc_mae_detach(struct sfc_adapter *sa);
+sfc_flow_cleanup_cb_t sfc_mae_flow_cleanup;
+int sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
+ const struct rte_flow_item pattern[],
+ struct sfc_flow_spec_mae *spec,
+ struct rte_flow_error *error);
#ifdef __cplusplus
}