From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id C3F6FA0C41; Wed, 17 Nov 2021 12:45:03 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 73085426E5; Wed, 17 Nov 2021 12:44:46 +0100 (CET) Received: from shelob.oktetlabs.ru (shelob.oktetlabs.ru [91.220.146.113]) by mails.dpdk.org (Postfix) with ESMTP id 46E4E4068C for ; Wed, 17 Nov 2021 12:44:41 +0100 (CET) Received: from bree.oktetlabs.ru (bree.oktetlabs.ru [192.168.34.5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by shelob.oktetlabs.ru (Postfix) with ESMTPS id F02A57F57C; Wed, 17 Nov 2021 14:44:40 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 shelob.oktetlabs.ru F02A57F57C Authentication-Results: shelob.oktetlabs.ru/F02A57F57C; dkim=none; dkim-atps=neutral From: Ivan Malov To: dev@dpdk.org Cc: Andrew Rybchenko , Andy Moreton Subject: [PATCH 4/4] net/sfc: support MAC address edits in transfer flows Date: Wed, 17 Nov 2021 14:44:38 +0300 Message-Id: <20211117114438.8347-5-ivan.malov@oktetlabs.ru> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211117114438.8347-1-ivan.malov@oktetlabs.ru> References: <20211117114438.8347-1-ivan.malov@oktetlabs.ru> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org These edits affect the outermost header in the current processing state of the packet, which might have been decapsulated by prior action DECAP. Signed-off-by: Ivan Malov Reviewed-by: Andrew Rybchenko Reviewed-by: Andy Moreton --- doc/guides/nics/features/sfc.ini | 2 + doc/guides/nics/sfc_efx.rst | 4 + drivers/net/sfc/sfc_mae.c | 292 ++++++++++++++++++++++++++++++- drivers/net/sfc/sfc_mae.h | 15 ++ 4 files changed, 310 insertions(+), 3 deletions(-) diff --git a/doc/guides/nics/features/sfc.ini b/doc/guides/nics/features/sfc.ini index 1ce2dc46ba..2e798b5ef5 100644 --- a/doc/guides/nics/features/sfc.ini +++ b/doc/guides/nics/features/sfc.ini @@ -79,6 +79,8 @@ port_representor = Y represented_port = Y queue = Y rss = Y +set_mac_dst = Y +set_mac_src = Y vf = Y vxlan_decap = Y vxlan_encap = Y diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index 00b95a4f58..39c6e23d5b 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -234,6 +234,10 @@ Supported actions (***transfer*** rules): - OF_VLAN_SET_PCP +- SET_MAC_DST + +- SET_MAC_SRC + - OF_DEC_NW_TTL - DEC_TTL diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c index b7a148afae..b34c9afd5b 100644 --- a/drivers/net/sfc/sfc_mae.c +++ b/drivers/net/sfc/sfc_mae.c @@ -290,6 +290,7 @@ sfc_mae_attach(struct sfc_adapter *sa) } TAILQ_INIT(&mae->outer_rules); + TAILQ_INIT(&mae->mac_addrs); TAILQ_INIT(&mae->encap_headers); TAILQ_INIT(&mae->action_sets); @@ -506,6 +507,189 @@ sfc_mae_outer_rule_disable(struct sfc_adapter *sa, --(fw_rsrc->refcnt); } +static struct sfc_mae_mac_addr * +sfc_mae_mac_addr_attach(struct sfc_adapter *sa, + const uint8_t addr_bytes[EFX_MAC_ADDR_LEN]) +{ + struct sfc_mae_mac_addr *mac_addr; + struct sfc_mae *mae = &sa->mae; + + SFC_ASSERT(sfc_adapter_is_locked(sa)); + + TAILQ_FOREACH(mac_addr, &mae->mac_addrs, entries) { + if (memcmp(mac_addr->addr_bytes, addr_bytes, + EFX_MAC_ADDR_LEN) == 0) { + sfc_dbg(sa, "attaching to mac_addr=%p", mac_addr); + ++(mac_addr->refcnt); + return mac_addr; + } + } + + return NULL; +} + +static int +sfc_mae_mac_addr_add(struct sfc_adapter *sa, + const uint8_t addr_bytes[EFX_MAC_ADDR_LEN], + struct sfc_mae_mac_addr **mac_addrp) +{ + struct sfc_mae_mac_addr *mac_addr; + struct sfc_mae *mae = &sa->mae; + + SFC_ASSERT(sfc_adapter_is_locked(sa)); + + mac_addr = rte_zmalloc("sfc_mae_mac_addr", sizeof(*mac_addr), 0); + if (mac_addr == NULL) + return ENOMEM; + + rte_memcpy(mac_addr->addr_bytes, addr_bytes, EFX_MAC_ADDR_LEN); + + mac_addr->refcnt = 1; + mac_addr->fw_rsrc.mac_id.id = EFX_MAE_RSRC_ID_INVALID; + + TAILQ_INSERT_TAIL(&mae->mac_addrs, mac_addr, entries); + + *mac_addrp = mac_addr; + + sfc_dbg(sa, "added mac_addr=%p", mac_addr); + + return 0; +} + +static void +sfc_mae_mac_addr_del(struct sfc_adapter *sa, struct sfc_mae_mac_addr *mac_addr) +{ + struct sfc_mae *mae = &sa->mae; + + if (mac_addr == NULL) + return; + + SFC_ASSERT(sfc_adapter_is_locked(sa)); + SFC_ASSERT(mac_addr->refcnt != 0); + + --(mac_addr->refcnt); + + if (mac_addr->refcnt != 0) + return; + + if (mac_addr->fw_rsrc.mac_id.id != EFX_MAE_RSRC_ID_INVALID || + mac_addr->fw_rsrc.refcnt != 0) { + sfc_err(sa, "deleting mac_addr=%p abandons its FW resource: MAC_ID=0x%08x, refcnt=%u", + mac_addr, mac_addr->fw_rsrc.mac_id.id, + mac_addr->fw_rsrc.refcnt); + } + + TAILQ_REMOVE(&mae->mac_addrs, mac_addr, entries); + rte_free(mac_addr); + + sfc_dbg(sa, "deleted mac_addr=%p", mac_addr); +} + +enum sfc_mae_mac_addr_type { + SFC_MAE_MAC_ADDR_DST, + SFC_MAE_MAC_ADDR_SRC +}; + +static int +sfc_mae_mac_addr_enable(struct sfc_adapter *sa, + struct sfc_mae_mac_addr *mac_addr, + enum sfc_mae_mac_addr_type type, + efx_mae_actions_t *aset_spec) +{ + struct sfc_mae_fw_rsrc *fw_rsrc; + int rc = 0; + + if (mac_addr == NULL) + return 0; + + SFC_ASSERT(sfc_adapter_is_locked(sa)); + + fw_rsrc = &mac_addr->fw_rsrc; + + if (fw_rsrc->refcnt == 0) { + SFC_ASSERT(fw_rsrc->mac_id.id == EFX_MAE_RSRC_ID_INVALID); + + rc = efx_mae_mac_addr_alloc(sa->nic, mac_addr->addr_bytes, + &fw_rsrc->mac_id); + if (rc != 0) { + sfc_err(sa, "failed to enable mac_addr=%p: %s", + mac_addr, strerror(rc)); + return rc; + } + } + + switch (type) { + case SFC_MAE_MAC_ADDR_DST: + rc = efx_mae_action_set_fill_in_dst_mac_id(aset_spec, + &fw_rsrc->mac_id); + break; + case SFC_MAE_MAC_ADDR_SRC: + rc = efx_mae_action_set_fill_in_src_mac_id(aset_spec, + &fw_rsrc->mac_id); + break; + default: + rc = EINVAL; + break; + } + + if (rc != 0) { + if (fw_rsrc->refcnt == 0) { + (void)efx_mae_mac_addr_free(sa->nic, &fw_rsrc->mac_id); + fw_rsrc->mac_id.id = EFX_MAE_RSRC_ID_INVALID; + } + + sfc_err(sa, "cannot fill in MAC address entry ID: %s", + strerror(rc)); + + return rc; + } + + if (fw_rsrc->refcnt == 0) { + sfc_dbg(sa, "enabled mac_addr=%p: MAC_ID=0x%08x", + mac_addr, fw_rsrc->mac_id.id); + } + + ++(fw_rsrc->refcnt); + + return 0; +} + +static void +sfc_mae_mac_addr_disable(struct sfc_adapter *sa, + struct sfc_mae_mac_addr *mac_addr) +{ + struct sfc_mae_fw_rsrc *fw_rsrc; + int rc; + + if (mac_addr == NULL) + return; + + SFC_ASSERT(sfc_adapter_is_locked(sa)); + + fw_rsrc = &mac_addr->fw_rsrc; + + if (fw_rsrc->mac_id.id == EFX_MAE_RSRC_ID_INVALID || + fw_rsrc->refcnt == 0) { + sfc_err(sa, "failed to disable mac_addr=%p: already disabled; MAC_ID=0x%08x, refcnt=%u", + mac_addr, fw_rsrc->mac_id.id, fw_rsrc->refcnt); + return; + } + + if (fw_rsrc->refcnt == 1) { + rc = efx_mae_mac_addr_free(sa->nic, &fw_rsrc->mac_id); + if (rc == 0) { + sfc_dbg(sa, "disabled mac_addr=%p with MAC_ID=0x%08x", + mac_addr, fw_rsrc->mac_id.id); + } else { + sfc_err(sa, "failed to disable mac_addr=%p with MAC_ID=0x%08x: %s", + mac_addr, fw_rsrc->mac_id.id, strerror(rc)); + } + fw_rsrc->mac_id.id = EFX_MAE_RSRC_ID_INVALID; + } + + --(fw_rsrc->refcnt); +} + static struct sfc_mae_encap_header * sfc_mae_encap_header_attach(struct sfc_adapter *sa, const struct sfc_mae_bounce_eh *bounce_eh) @@ -757,6 +941,8 @@ struct sfc_mae_aset_ctx { struct sfc_mae_encap_header *encap_header; struct sfc_flow_tunnel *counter_ft; unsigned int n_counters; + struct sfc_mae_mac_addr *dst_mac; + struct sfc_mae_mac_addr *src_mac; efx_mae_actions_t *spec; }; @@ -779,6 +965,8 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa, TAILQ_FOREACH(action_set, &mae->action_sets, entries) { if (action_set->encap_header == ctx->encap_header && + action_set->dst_mac_addr == ctx->dst_mac && + action_set->src_mac_addr == ctx->src_mac && efx_mae_action_set_specs_equal(action_set->spec, ctx->spec)) { sfc_dbg(sa, "attaching to action_set=%p", action_set); @@ -849,6 +1037,8 @@ sfc_mae_action_set_add(struct sfc_adapter *sa, action_set->refcnt = 1; action_set->spec = ctx->spec; action_set->encap_header = ctx->encap_header; + action_set->dst_mac_addr = ctx->dst_mac; + action_set->src_mac_addr = ctx->src_mac; action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID; @@ -884,6 +1074,8 @@ sfc_mae_action_set_del(struct sfc_adapter *sa, efx_mae_action_set_spec_fini(sa->nic, action_set->spec); sfc_mae_encap_header_del(sa, action_set->encap_header); + sfc_mae_mac_addr_del(sa, action_set->dst_mac_addr); + sfc_mae_mac_addr_del(sa, action_set->src_mac_addr); if (action_set->n_counters > 0) { SFC_ASSERT(action_set->n_counters == 1); SFC_ASSERT(action_set->counters[0].mae_id.id == @@ -901,6 +1093,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa, struct sfc_mae_action_set *action_set) { struct sfc_mae_encap_header *encap_header = action_set->encap_header; + struct sfc_mae_mac_addr *dst_mac_addr = action_set->dst_mac_addr; + struct sfc_mae_mac_addr *src_mac_addr = action_set->src_mac_addr; struct sfc_mae_counter_id *counters = action_set->counters; struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc; int rc; @@ -911,10 +1105,27 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa, SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID); SFC_ASSERT(action_set->spec != NULL); + rc = sfc_mae_mac_addr_enable(sa, dst_mac_addr, + SFC_MAE_MAC_ADDR_DST, + action_set->spec); + if (rc != 0) + return rc; + + rc = sfc_mae_mac_addr_enable(sa, src_mac_addr, + SFC_MAE_MAC_ADDR_SRC, + action_set->spec); + if (rc != 0) { + sfc_mae_mac_addr_disable(sa, dst_mac_addr); + return rc; + } + rc = sfc_mae_encap_header_enable(sa, encap_header, action_set->spec); - if (rc != 0) + if (rc != 0) { + sfc_mae_mac_addr_disable(sa, src_mac_addr); + sfc_mae_mac_addr_disable(sa, dst_mac_addr); return rc; + } rc = sfc_mae_counters_enable(sa, counters, action_set->n_counters, @@ -924,6 +1135,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa, action_set->n_counters, rte_strerror(rc)); sfc_mae_encap_header_disable(sa, encap_header); + sfc_mae_mac_addr_disable(sa, src_mac_addr); + sfc_mae_mac_addr_disable(sa, dst_mac_addr); return rc; } @@ -936,6 +1149,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa, (void)sfc_mae_counters_disable(sa, counters, action_set->n_counters); sfc_mae_encap_header_disable(sa, encap_header); + sfc_mae_mac_addr_disable(sa, src_mac_addr); + sfc_mae_mac_addr_disable(sa, dst_mac_addr); return rc; } @@ -983,6 +1198,8 @@ sfc_mae_action_set_disable(struct sfc_adapter *sa, } sfc_mae_encap_header_disable(sa, action_set->encap_header); + sfc_mae_mac_addr_disable(sa, action_set->src_mac_addr); + sfc_mae_mac_addr_disable(sa, action_set->dst_mac_addr); } --(fw_rsrc->refcnt); @@ -2895,6 +3112,54 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa, return rc; } +static int +sfc_mae_rule_parse_action_set_mac(struct sfc_adapter *sa, + enum sfc_mae_mac_addr_type type, + const struct rte_flow_action_set_mac *conf, + struct sfc_mae_aset_ctx *ctx, + struct rte_flow_error *error) +{ + struct sfc_mae_mac_addr **mac_addrp; + int rc; + + if (conf == NULL) { + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, + "the MAC address entry definition is NULL"); + } + + switch (type) { + case SFC_MAE_MAC_ADDR_DST: + rc = efx_mae_action_set_populate_set_dst_mac(ctx->spec); + mac_addrp = &ctx->dst_mac; + break; + case SFC_MAE_MAC_ADDR_SRC: + rc = efx_mae_action_set_populate_set_src_mac(ctx->spec); + mac_addrp = &ctx->src_mac; + break; + default: + rc = EINVAL; + break; + } + + if (rc != 0) + goto error; + + *mac_addrp = sfc_mae_mac_addr_attach(sa, conf->mac_addr); + if (*mac_addrp != NULL) + return 0; + + rc = sfc_mae_mac_addr_add(sa, conf->mac_addr, mac_addrp); + if (rc != 0) + goto error; + + return 0; + +error: + return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION, + NULL, "failed to request set MAC action"); +} + /* * An action supported by MAE may correspond to a bundle of RTE flow actions, * in example, VLAN_PUSH = OF_PUSH_VLAN + OF_VLAN_SET_VID + OF_VLAN_SET_PCP. @@ -3549,6 +3814,8 @@ sfc_mae_rule_parse_action_represented_port(struct sfc_adapter *sa, static const char * const action_names[] = { [RTE_FLOW_ACTION_TYPE_VXLAN_DECAP] = "VXLAN_DECAP", [RTE_FLOW_ACTION_TYPE_OF_POP_VLAN] = "OF_POP_VLAN", + [RTE_FLOW_ACTION_TYPE_SET_MAC_DST] = "SET_MAC_DST", + [RTE_FLOW_ACTION_TYPE_SET_MAC_SRC] = "SET_MAC_SRC", [RTE_FLOW_ACTION_TYPE_OF_DEC_NW_TTL] = "OF_DEC_NW_TTL", [RTE_FLOW_ACTION_TYPE_DEC_TTL] = "DEC_TTL", [RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] = "OF_PUSH_VLAN", @@ -3573,11 +3840,12 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa, const struct rte_flow_action *action, const struct sfc_flow_spec_mae *spec_mae, struct sfc_mae_actions_bundle *bundle, - efx_mae_actions_t *spec, + struct sfc_mae_aset_ctx *ctx, struct rte_flow_error *error) { const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule; const uint64_t rx_metadata = sa->negotiated_rx_metadata; + efx_mae_actions_t *spec = ctx->spec; bool custom_error = B_FALSE; int rc = 0; @@ -3596,6 +3864,22 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa, bundle->actions_mask); rc = efx_mae_action_set_populate_vlan_pop(spec); break; + case RTE_FLOW_ACTION_TYPE_SET_MAC_DST: + SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_MAC_DST, + bundle->actions_mask); + rc = sfc_mae_rule_parse_action_set_mac(sa, SFC_MAE_MAC_ADDR_DST, + action->conf, ctx, + error); + custom_error = B_TRUE; + break; + case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC: + SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_MAC_SRC, + bundle->actions_mask); + rc = sfc_mae_rule_parse_action_set_mac(sa, SFC_MAE_MAC_ADDR_SRC, + action->conf, ctx, + error); + custom_error = B_TRUE; + break; case RTE_FLOW_ACTION_TYPE_OF_DEC_NW_TTL: case RTE_FLOW_ACTION_TYPE_DEC_TTL: SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_DEC_NW_TTL, @@ -3813,7 +4097,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa, goto fail_rule_parse_action; rc = sfc_mae_rule_parse_action(sa, action, spec_mae, - &bundle, ctx.spec, error); + &bundle, &ctx, error); if (rc != 0) goto fail_rule_parse_action; } @@ -3880,6 +4164,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa, fail_process_encap_header: fail_rule_parse_action: + sfc_mae_mac_addr_del(sa, ctx.src_mac); + sfc_mae_mac_addr_del(sa, ctx.dst_mac); efx_mae_action_set_spec_fini(sa->nic, ctx.spec); fail_enforce_ft_count: diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h index 2750fbb9b1..3431aaa734 100644 --- a/drivers/net/sfc/sfc_mae.h +++ b/drivers/net/sfc/sfc_mae.h @@ -29,6 +29,7 @@ struct sfc_mae_fw_rsrc { union { efx_mae_aset_id_t aset_id; efx_mae_rule_id_t rule_id; + efx_mae_mac_id_t mac_id; efx_mae_eh_id_t eh_id; }; }; @@ -44,6 +45,16 @@ struct sfc_mae_outer_rule { TAILQ_HEAD(sfc_mae_outer_rules, sfc_mae_outer_rule); +/** MAC address registry entry */ +struct sfc_mae_mac_addr { + TAILQ_ENTRY(sfc_mae_mac_addr) entries; + unsigned int refcnt; + uint8_t addr_bytes[EFX_MAC_ADDR_LEN]; + struct sfc_mae_fw_rsrc fw_rsrc; +}; + +TAILQ_HEAD(sfc_mae_mac_addrs, sfc_mae_mac_addr); + /** Encap. header registry entry */ struct sfc_mae_encap_header { TAILQ_ENTRY(sfc_mae_encap_header) entries; @@ -79,6 +90,8 @@ struct sfc_mae_action_set { uint32_t n_counters; efx_mae_actions_t *spec; struct sfc_mae_encap_header *encap_header; + struct sfc_mae_mac_addr *dst_mac_addr; + struct sfc_mae_mac_addr *src_mac_addr; struct sfc_mae_fw_rsrc fw_rsrc; }; @@ -211,6 +224,8 @@ struct sfc_mae { struct sfc_mae_outer_rules outer_rules; /** Encap. header registry */ struct sfc_mae_encap_headers encap_headers; + /** MAC address registry */ + struct sfc_mae_mac_addrs mac_addrs; /** Action set registry */ struct sfc_mae_action_sets action_sets; /** Encap. header bounce buffer */ -- 2.30.2