From patchwork Mon Apr 15 14:56:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Simon Horman X-Patchwork-Id: 1085684 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=netronome.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=netronome-com.20150623.gappssmtp.com header.i=@netronome-com.20150623.gappssmtp.com header.b="FOFhZkmB"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44jWmR1KZBz9s55 for ; Tue, 16 Apr 2019 00:56:39 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727862AbfDOO4f (ORCPT ); Mon, 15 Apr 2019 10:56:35 -0400 Received: from mail-ed1-f66.google.com ([209.85.208.66]:33664 "EHLO mail-ed1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727857AbfDOO4e (ORCPT ); Mon, 15 Apr 2019 10:56:34 -0400 Received: by mail-ed1-f66.google.com with SMTP id d55so14183087ede.0 for ; Mon, 15 Apr 2019 07:56:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netronome-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=lb4HlCsRlRHgCUisDpg3KTO8ElPyycRWA4LdLgblTxQ=; b=FOFhZkmBq9FmON6gC5zDPST2VU/XH8oFv4Da9SqdUYvj4ImJLJ28ILZ9AxlDO7Q6ye E4Gar5/AOcZGlKG3RwdLwZO/W/Vj+Pg/VVEu64AvYdPerRJGC5nheS6niqWPzXuOMV1D m7dF+nGNMy6qf630kF88H6lbokPbx3eD46JSGSsWi5z+GPYqlgqTiI2WTeyBVp2pwEV2 W68P4Em6lxcSbzNh3DbeH0PwK7wn9TgtAaAP4u+JV5l+P7vcxp+aYgN0lRTjSfCBXtGU Jev/VScQEIcve4F5/DyPaOmexVt8iJWvgY3TL/Kz/1gV8Ff81Nx0o/vHbJHEl0wKq1wX k2yw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lb4HlCsRlRHgCUisDpg3KTO8ElPyycRWA4LdLgblTxQ=; b=OOlx4lccGwF5gmZz7L2z7y+QbUM418PeSQCn4GLB1SRb+Nh8eHXtscAkjjFDWNFbBV T+mlTBkMPiU14S5w7DMWybh6c6DlrpdJ7Lb6NuLrt7JGOgfOyCDy0c/mzntL0rUMZtjN wTE/DIgyTbUfns7jpXtiC57h6NadKDLM9fDoOjoeI1sNuZzR8KM7uaTGBKFHDAIgXfMG rQ/5meefWiSZg+QxhIa8C7BBxE78AKmyjPEGS7+8wB032kWmMi6vGte9JtWmP1jMlP7Q V6lFLwUU6eYjmISqjedcqgqVo8AdJb8peXU+wmQb5gyqbVO/ileJxshP4sgAk9NRteeM QDZA== X-Gm-Message-State: APjAAAWCittWlCUu88zO4PZX9KLzpYURizKjT1BrsJJSKW06wgnmfsxm Gwfg33uEW/cQilaQv8WCQT78SA== X-Google-Smtp-Source: APXvYqw7yIXWF5VrZsaiHWhOiF9clLtLV/7lJXddjhNVZGOxozdvwmjsQ0175YBi1bGKw7hEeNHuhw== X-Received: by 2002:a50:9ea5:: with SMTP id a34mr35477345edf.191.1555340191057; Mon, 15 Apr 2019 07:56:31 -0700 (PDT) Received: from reginn.horms.nl ([2001:982:756:703:d63d:7eff:fe99:ac9d]) by smtp.gmail.com with ESMTPSA id c38sm2540023ede.61.2019.04.15.07.56.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 15 Apr 2019 07:56:30 -0700 (PDT) From: Simon Horman To: David Miller , Jakub Kicinski Cc: netdev@vger.kernel.org, oss-drivers@netronome.com, John Hurley , Simon Horman Subject: [PATCH net-next 11/11] nfp: flower: offload merge flows Date: Mon, 15 Apr 2019 16:56:03 +0200 Message-Id: <20190415145603.32491-12-simon.horman@netronome.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190415145603.32491-1-simon.horman@netronome.com> References: <20190415145603.32491-1-simon.horman@netronome.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: John Hurley A merge flow is formed from 2 sub flows. The match fields of the merge are the same as the first sub flow that has formed it, with the actions being a combination of the first and second sub flow. Therefore, a merge flow should replace sub flow 1 when offloaded. Offload valid merge flows by using a new 'flow mod' message type to replace an existing offloaded rule. Track the deletion of sub flows that are linked to a merge flow and revert offloaded merge rules if required. Signed-off-by: John Hurley Signed-off-by: Simon Horman --- drivers/net/ethernet/netronome/nfp/flower/cmsg.h | 1 + drivers/net/ethernet/netronome/nfp/flower/main.h | 3 + .../net/ethernet/netronome/nfp/flower/metadata.c | 16 +-- .../net/ethernet/netronome/nfp/flower/offload.c | 119 +++++++++++++++++++-- 4 files changed, 126 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h index 9288595032cc..a10c29ade5c2 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h @@ -402,6 +402,7 @@ struct nfp_flower_cmsg_hdr { /* Types defined for port related control messages */ enum nfp_flower_cmsg_type_port { NFP_FLOWER_CMSG_TYPE_FLOW_ADD = 0, + NFP_FLOWER_CMSG_TYPE_FLOW_MOD = 1, NFP_FLOWER_CMSG_TYPE_FLOW_DEL = 2, NFP_FLOWER_CMSG_TYPE_LAG_CONFIG = 4, NFP_FLOWER_CMSG_TYPE_PORT_REIFY = 6, diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index 896f538d6997..675f43f06526 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -253,6 +253,7 @@ struct nfp_fl_payload { char *mask_data; char *action_data; struct list_head linked_flows; + bool in_hw; }; struct nfp_fl_payload_link { @@ -329,6 +330,8 @@ int nfp_compile_flow_metadata(struct nfp_app *app, struct tc_cls_flower_offload *flow, struct nfp_fl_payload *nfp_flow, struct net_device *netdev); +void __nfp_modify_flow_metadata(struct nfp_flower_priv *priv, + struct nfp_fl_payload *nfp_flow); int nfp_modify_flow_metadata(struct nfp_app *app, struct nfp_fl_payload *nfp_flow); diff --git a/drivers/net/ethernet/netronome/nfp/flower/metadata.c b/drivers/net/ethernet/netronome/nfp/flower/metadata.c index d68307e5bf16..3d326efdc814 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/metadata.c +++ b/drivers/net/ethernet/netronome/nfp/flower/metadata.c @@ -276,9 +276,6 @@ nfp_check_mask_remove(struct nfp_app *app, char *mask_data, u32 mask_len, if (!mask_entry) return false; - if (meta_flags) - *meta_flags &= ~NFP_FL_META_FLAG_MANAGE_MASK; - *mask_id = mask_entry->mask_id; mask_entry->ref_cnt--; if (!mask_entry->ref_cnt) { @@ -367,6 +364,14 @@ int nfp_compile_flow_metadata(struct nfp_app *app, return err; } +void __nfp_modify_flow_metadata(struct nfp_flower_priv *priv, + struct nfp_fl_payload *nfp_flow) +{ + nfp_flow->meta.flags &= ~NFP_FL_META_FLAG_MANAGE_MASK; + nfp_flow->meta.flow_version = cpu_to_be64(priv->flower_version); + priv->flower_version++; +} + int nfp_modify_flow_metadata(struct nfp_app *app, struct nfp_fl_payload *nfp_flow) { @@ -375,13 +380,12 @@ int nfp_modify_flow_metadata(struct nfp_app *app, u8 new_mask_id = 0; u32 temp_ctx_id; + __nfp_modify_flow_metadata(priv, nfp_flow); + nfp_check_mask_remove(app, nfp_flow->mask_data, nfp_flow->meta.mask_len, &nfp_flow->meta.flags, &new_mask_id); - nfp_flow->meta.flow_version = cpu_to_be64(priv->flower_version); - priv->flower_version++; - /* Update flow payload with mask ids. */ nfp_flow->unmasked_data[NFP_FL_MASK_ID_LOCATION] = new_mask_id; diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index 1249b89ba660..df81d86ee16b 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -348,7 +348,7 @@ nfp_flower_calculate_key_layers(struct nfp_app *app, break; case cpu_to_be16(ETH_P_IPV6): - key_layer |= NFP_FLOWER_LAYER_IPV6; + key_layer |= NFP_FLOWER_LAYER_IPV6; key_size += sizeof(struct nfp_flower_ipv6); break; @@ -399,6 +399,7 @@ nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer) flow_pay->nfp_tun_ipv4_addr = 0; flow_pay->meta.flags = 0; INIT_LIST_HEAD(&flow_pay->linked_flows); + flow_pay->in_hw = false; return flow_pay; @@ -769,6 +770,8 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app, struct nfp_fl_payload *sub_flow1, struct nfp_fl_payload *sub_flow2) { + struct tc_cls_flower_offload merge_tc_off; + struct nfp_flower_priv *priv = app->priv; struct nfp_fl_payload *merge_flow; struct nfp_fl_key_ls merge_key_ls; int err; @@ -810,8 +813,34 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app, if (err) goto err_unlink_sub_flow1; - err = -EOPNOTSUPP; + merge_tc_off.cookie = merge_flow->tc_flower_cookie; + err = nfp_compile_flow_metadata(app, &merge_tc_off, merge_flow, + merge_flow->ingress_dev); + if (err) + goto err_unlink_sub_flow2; + err = rhashtable_insert_fast(&priv->flow_table, &merge_flow->fl_node, + nfp_flower_table_params); + if (err) + goto err_release_metadata; + + err = nfp_flower_xmit_flow(app, merge_flow, + NFP_FLOWER_CMSG_TYPE_FLOW_MOD); + if (err) + goto err_remove_rhash; + + merge_flow->in_hw = true; + sub_flow1->in_hw = false; + + return 0; + +err_remove_rhash: + WARN_ON_ONCE(rhashtable_remove_fast(&priv->flow_table, + &merge_flow->fl_node, + nfp_flower_table_params)); +err_release_metadata: + nfp_modify_flow_metadata(app, merge_flow); +err_unlink_sub_flow2: nfp_flower_unlink_flows(merge_flow, sub_flow2); err_unlink_sub_flow1: nfp_flower_unlink_flows(merge_flow, sub_flow1); @@ -889,6 +918,8 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev, if (port) port->tc_offload_cnt++; + flow_pay->in_hw = true; + /* Deallocate flow payload when flower rule has been destroyed. */ kfree(key_layer); @@ -910,6 +941,75 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev, return err; } +static void +nfp_flower_remove_merge_flow(struct nfp_app *app, + struct nfp_fl_payload *del_sub_flow, + struct nfp_fl_payload *merge_flow) +{ + struct nfp_flower_priv *priv = app->priv; + struct nfp_fl_payload_link *link, *temp; + struct nfp_fl_payload *origin; + bool mod = false; + int err; + + link = list_first_entry(&merge_flow->linked_flows, + struct nfp_fl_payload_link, merge_flow.list); + origin = link->sub_flow.flow; + + /* Re-add rule the merge had overwritten if it has not been deleted. */ + if (origin != del_sub_flow) + mod = true; + + err = nfp_modify_flow_metadata(app, merge_flow); + if (err) { + nfp_flower_cmsg_warn(app, "Metadata fail for merge flow delete.\n"); + goto err_free_links; + } + + if (!mod) { + err = nfp_flower_xmit_flow(app, merge_flow, + NFP_FLOWER_CMSG_TYPE_FLOW_DEL); + if (err) { + nfp_flower_cmsg_warn(app, "Failed to delete merged flow.\n"); + goto err_free_links; + } + } else { + __nfp_modify_flow_metadata(priv, origin); + err = nfp_flower_xmit_flow(app, origin, + NFP_FLOWER_CMSG_TYPE_FLOW_MOD); + if (err) + nfp_flower_cmsg_warn(app, "Failed to revert merge flow.\n"); + origin->in_hw = true; + } + +err_free_links: + /* Clean any links connected with the merged flow. */ + list_for_each_entry_safe(link, temp, &merge_flow->linked_flows, + merge_flow.list) + nfp_flower_unlink_flow(link); + + kfree(merge_flow->action_data); + kfree(merge_flow->mask_data); + kfree(merge_flow->unmasked_data); + WARN_ON_ONCE(rhashtable_remove_fast(&priv->flow_table, + &merge_flow->fl_node, + nfp_flower_table_params)); + kfree_rcu(merge_flow, rcu); +} + +static void +nfp_flower_del_linked_merge_flows(struct nfp_app *app, + struct nfp_fl_payload *sub_flow) +{ + struct nfp_fl_payload_link *link, *temp; + + /* Remove any merge flow formed from the deleted sub_flow. */ + list_for_each_entry_safe(link, temp, &sub_flow->linked_flows, + sub_flow.list) + nfp_flower_remove_merge_flow(app, sub_flow, + link->merge_flow.flow); +} + /** * nfp_flower_del_offload() - Removes a flow from hardware. * @app: Pointer to the APP handle @@ -917,7 +1017,7 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev, * @flow: TC flower classifier offload structure * * Removes a flow from the repeated hash structure and clears the - * action payload. + * action payload. Any flows merged from this are also deleted. * * Return: negative value on error, 0 if removed successfully. */ @@ -939,17 +1039,22 @@ nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev, err = nfp_modify_flow_metadata(app, nfp_flow); if (err) - goto err_free_flow; + goto err_free_merge_flow; if (nfp_flow->nfp_tun_ipv4_addr) nfp_tunnel_del_ipv4_off(app, nfp_flow->nfp_tun_ipv4_addr); + if (!nfp_flow->in_hw) { + err = 0; + goto err_free_merge_flow; + } + err = nfp_flower_xmit_flow(app, nfp_flow, NFP_FLOWER_CMSG_TYPE_FLOW_DEL); - if (err) - goto err_free_flow; + /* Fall through on error. */ -err_free_flow: +err_free_merge_flow: + nfp_flower_del_linked_merge_flows(app, nfp_flow); if (port) port->tc_offload_cnt--; kfree(nfp_flow->action_data);