From 041f22ec349461a278831c1c6faee758a4002529 Mon Sep 17 00:00:00 2001 From: Ivan Malov Date: Tue, 20 Oct 2020 10:13:04 +0100 Subject: [PATCH] net/sfc: implement flow insert/remove in MAE backend Exercise action set allocation / release and action rule insertion / removal in order to let flow API callers actually get created flows functioning. Signed-off-by: Ivan Malov Signed-off-by: Andrew Rybchenko Reviewed-by: Andy Moreton --- drivers/net/sfc/sfc_flow.c | 5 +- drivers/net/sfc/sfc_flow.h | 2 + drivers/net/sfc/sfc_mae.c | 108 +++++++++++++++++++++++++++++++++++++ drivers/net/sfc/sfc_mae.h | 12 +++++ 4 files changed, 125 insertions(+), 2 deletions(-) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index f4d53bf770..3af95ac8ee 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -50,8 +50,8 @@ static const struct sfc_flow_ops_by_spec sfc_flow_ops_mae = { .parse = sfc_flow_parse_rte_to_mae, .verify = sfc_mae_flow_verify, .cleanup = sfc_mae_flow_cleanup, - .insert = NULL, - .remove = NULL, + .insert = sfc_mae_flow_insert, + .remove = sfc_mae_flow_remove, }; static const struct sfc_flow_ops_by_spec * @@ -1202,6 +1202,7 @@ sfc_flow_parse_attr(struct sfc_adapter *sa, spec_mae->priority = attr->priority; spec_mae->match_spec = NULL; spec_mae->action_set = NULL; + spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID; } return 0; diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h index 7d15f47e60..d3bdbd5f75 100644 --- a/drivers/net/sfc/sfc_flow.h +++ b/drivers/net/sfc/sfc_flow.h @@ -67,6 +67,8 @@ struct sfc_flow_spec_mae { efx_mae_match_spec_t *match_spec; /* Action set registry entry */ struct sfc_mae_action_set *action_set; + /* Firmware-allocated rule ID */ + efx_mae_rule_id_t rule_id; }; /* Flow specification */ diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c index 057eef537b..ea15ccaedb 100644 --- a/drivers/net/sfc/sfc_mae.c +++ b/drivers/net/sfc/sfc_mae.c @@ -113,6 +113,8 @@ sfc_mae_action_set_add(struct sfc_adapter *sa, action_set->refcnt = 1; action_set->spec = spec; + action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID; + TAILQ_INSERT_TAIL(&mae->action_sets, action_set, entries); *action_setp = action_set; @@ -134,11 +136,62 @@ sfc_mae_action_set_del(struct sfc_adapter *sa, if (action_set->refcnt != 0) return; + SFC_ASSERT(action_set->fw_rsrc.aset_id.id == EFX_MAE_RSRC_ID_INVALID); + SFC_ASSERT(action_set->fw_rsrc.refcnt == 0); + efx_mae_action_set_spec_fini(sa->nic, action_set->spec); TAILQ_REMOVE(&mae->action_sets, action_set, entries); rte_free(action_set); } +static int +sfc_mae_action_set_enable(struct sfc_adapter *sa, + struct sfc_mae_action_set *action_set) +{ + struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc; + int rc; + + SFC_ASSERT(sfc_adapter_is_locked(sa)); + + if (fw_rsrc->refcnt == 0) { + SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID); + SFC_ASSERT(action_set->spec != NULL); + + rc = efx_mae_action_set_alloc(sa->nic, action_set->spec, + &fw_rsrc->aset_id); + if (rc != 0) + return rc; + } + + ++(fw_rsrc->refcnt); + + return 0; +} + +static int +sfc_mae_action_set_disable(struct sfc_adapter *sa, + struct sfc_mae_action_set *action_set) +{ + struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc; + int rc; + + SFC_ASSERT(sfc_adapter_is_locked(sa)); + SFC_ASSERT(fw_rsrc->aset_id.id != EFX_MAE_RSRC_ID_INVALID); + SFC_ASSERT(fw_rsrc->refcnt != 0); + + if (fw_rsrc->refcnt == 1) { + rc = efx_mae_action_set_free(sa->nic, &fw_rsrc->aset_id); + if (rc != 0) + return rc; + + fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID; + } + + --(fw_rsrc->refcnt); + + return 0; +} + void sfc_mae_flow_cleanup(struct sfc_adapter *sa, struct rte_flow *flow) @@ -156,6 +209,8 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa, spec_mae = &spec->mae; + SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID); + if (spec_mae->action_set != NULL) sfc_mae_action_set_del(sa, spec_mae->action_set); @@ -563,3 +618,56 @@ sfc_mae_flow_verify(struct sfc_adapter *sa, return sfc_mae_action_rule_class_verify(sa, spec_mae); } + +int +sfc_mae_flow_insert(struct sfc_adapter *sa, + struct rte_flow *flow) +{ + struct sfc_flow_spec *spec = &flow->spec; + struct sfc_flow_spec_mae *spec_mae = &spec->mae; + struct sfc_mae_action_set *action_set = spec_mae->action_set; + struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc; + int rc; + + SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID); + SFC_ASSERT(action_set != NULL); + + rc = sfc_mae_action_set_enable(sa, action_set); + if (rc != 0) + goto fail_action_set_enable; + + rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec, + NULL, &fw_rsrc->aset_id, + &spec_mae->rule_id); + if (rc != 0) + goto fail_action_rule_insert; + + return 0; + +fail_action_rule_insert: + (void)sfc_mae_action_set_disable(sa, action_set); + +fail_action_set_enable: + return rc; +} + +int +sfc_mae_flow_remove(struct sfc_adapter *sa, + struct rte_flow *flow) +{ + struct sfc_flow_spec *spec = &flow->spec; + struct sfc_flow_spec_mae *spec_mae = &spec->mae; + struct sfc_mae_action_set *action_set = spec_mae->action_set; + int rc; + + SFC_ASSERT(spec_mae->rule_id.id != EFX_MAE_RSRC_ID_INVALID); + SFC_ASSERT(action_set != NULL); + + rc = efx_mae_action_rule_remove(sa->nic, &spec_mae->rule_id); + if (rc != 0) + return rc; + + spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID; + + return sfc_mae_action_set_disable(sa, action_set); +} diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h index 1ef582e82b..d9f0ee3cbc 100644 --- a/drivers/net/sfc/sfc_mae.h +++ b/drivers/net/sfc/sfc_mae.h @@ -18,11 +18,21 @@ extern "C" { #endif +/** FW-allocatable resource context */ +struct sfc_mae_fw_rsrc { + unsigned int refcnt; + RTE_STD_C11 + union { + efx_mae_aset_id_t aset_id; + }; +}; + /** Action set registry entry */ struct sfc_mae_action_set { TAILQ_ENTRY(sfc_mae_action_set) entries; unsigned int refcnt; efx_mae_actions_t *spec; + struct sfc_mae_fw_rsrc fw_rsrc; }; TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set); @@ -63,6 +73,8 @@ int sfc_mae_rule_parse_actions(struct sfc_adapter *sa, struct sfc_mae_action_set **action_setp, struct rte_flow_error *error); sfc_flow_verify_cb_t sfc_mae_flow_verify; +sfc_flow_insert_cb_t sfc_mae_flow_insert; +sfc_flow_remove_cb_t sfc_mae_flow_remove; #ifdef __cplusplus } -- 2.20.1