From patchwork Mon Apr 15 14:56:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Horman X-Patchwork-Id: 1085683 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="p+DlwF+y"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44jWmQ1pdNz9ryj for ; Tue, 16 Apr 2019 00:56:38 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727867AbfDOO4g (ORCPT ); Mon, 15 Apr 2019 10:56:36 -0400 Received: from mail-ed1-f67.google.com ([209.85.208.67]:41997 "EHLO mail-ed1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727837AbfDOO4c (ORCPT ); Mon, 15 Apr 2019 10:56:32 -0400 Received: by mail-ed1-f67.google.com with SMTP id x61so14949749edc.9 for ; Mon, 15 Apr 2019 07:56:30 -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; bh=wEhaYA9MMEKlsHZMtZe9lP9URuSrVY5y5FvPdJTuaYM=; b=p+DlwF+y8h8y1+RtTR9LElfJCyTm+xhps7tlUYOrOt26WloapwQZGpZ9i3Hbkvzyr+ et+Ld1A4pd/ULo4hCUsOO4jFCEDU9SWIRWtKQ7okhRZoW/y+s+qj3vjobp8xYwZxSgGl z52vYwlNmUg59h6gfJJmt4bQ5R7lta3fGM5yCq9LDMQq2UpJ0HJi0RT9GG7pB23KrBkX aPCJbDoAARkhv4L+NNY/e2LUNi8rPrW5gbYc0+hE0p1l5zrgZT/m5MEW0jrB/yL46XWl ycmczNp8RFRzOKtr/ys1APxywhRpqf/L1AUIWTDPuN7NVyUh+yqNa07ahFArqnMNqONx 2G5A== 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; bh=wEhaYA9MMEKlsHZMtZe9lP9URuSrVY5y5FvPdJTuaYM=; b=iYAJUQ6rU6r8/keqG3qL2LKJJRilB925VoWOJgGfsfWbO3gPx3D89WgSig+nvVHjqM w4sG3JztBtHLnywf6FVhut5KxRoRjeIu2rD8RK97S1D53pR9ZfDSMWkXuYoNa9ftgPdR 95snX8VUJoGlPpnOwrkOiPaeXg4uKROitOvi5OfluXcbhTw/2HsEmoVI2cQ4za6j/wn7 vQZawz9d4N4r692haaFLafqAwxg5s+rtr8pxPgIhcYrJQKKbzwRlMzqcpLpBkbaIPvFE 6LGtZmd8X1zbjKurn5olxKwp/CnID1qT+xRHLLxbluXya0o2gyZeXDRZB2mT9cf5kzKT LJtA== X-Gm-Message-State: APjAAAXreWLM36WCjq9GFSZfkRFWYzpzzNh9nPFQ6Gm6U8/5EZkNKbOs kGvjsxa5MPAFtAKkO59yOwkXPw== X-Google-Smtp-Source: APXvYqxbS4vAuebu0566HCWB1dnyPpYBZytiq98yxrkRmMFjw2Uv576jcMdKAvT3LfbIx3xDQN5ybg== X-Received: by 2002:a50:9816:: with SMTP id g22mr14037677edb.236.1555340189535; Mon, 15 Apr 2019 07:56:29 -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.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 15 Apr 2019 07:56:28 -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 10/11] nfp: flower: support stats update for merge flows Date: Mon, 15 Apr 2019 16:56:02 +0200 Message-Id: <20190415145603.32491-11-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> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: John Hurley With the merging of 2 sub flows, a new 'merge' flow will be created and written to FW. The TC layer is unaware that the merge flow exists and will request stats from the sub flows. Conversely, the FW treats a merge rule the same as any other rule and sends stats updates to the NFP driver. Add links between merge flows and their sub flows. Use these links to pass merge flow stats updates from FW to the underlying sub flows, ensuring TC stats requests are handled correctly. The updating of sub flow stats is done on (the less time critcal) TC stats requests rather than on FW stats update. Signed-off-by: John Hurley Signed-off-by: Simon Horman --- drivers/net/ethernet/netronome/nfp/flower/main.h | 18 ++++ .../net/ethernet/netronome/nfp/flower/offload.c | 99 ++++++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index df49cf9d73b3..896f538d6997 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -252,6 +252,24 @@ struct nfp_fl_payload { char *unmasked_data; char *mask_data; char *action_data; + struct list_head linked_flows; +}; + +struct nfp_fl_payload_link { + /* A link contains a pointer to a merge flow and an associated sub_flow. + * Each merge flow will feature in 2 links to its underlying sub_flows. + * A sub_flow will have at least 1 link to a merge flow or more if it + * has been used to create multiple merge flows. + * + * For a merge flow, 'linked_flows' in its nfp_fl_payload struct lists + * all links to sub_flows (sub_flow.flow) via merge.list. + * For a sub_flow, 'linked_flows' gives all links to merge flows it has + * formed (merge_flow.flow) via sub_flow.list. + */ + struct { + struct list_head list; + struct nfp_fl_payload *flow; + } merge_flow, sub_flow; }; extern const struct rhashtable_params nfp_flower_table_params; diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index 1e329667249d..1249b89ba660 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -398,6 +398,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); return flow_pay; @@ -716,6 +717,43 @@ nfp_flower_merge_action(struct nfp_fl_payload *sub_flow1, return 0; } +/* Flow link code should only be accessed under RTNL. */ +static void nfp_flower_unlink_flow(struct nfp_fl_payload_link *link) +{ + list_del(&link->merge_flow.list); + list_del(&link->sub_flow.list); + kfree(link); +} + +static void nfp_flower_unlink_flows(struct nfp_fl_payload *merge_flow, + struct nfp_fl_payload *sub_flow) +{ + struct nfp_fl_payload_link *link; + + list_for_each_entry(link, &merge_flow->linked_flows, merge_flow.list) + if (link->sub_flow.flow == sub_flow) { + nfp_flower_unlink_flow(link); + return; + } +} + +static int nfp_flower_link_flows(struct nfp_fl_payload *merge_flow, + struct nfp_fl_payload *sub_flow) +{ + struct nfp_fl_payload_link *link; + + link = kmalloc(sizeof(*link), GFP_KERNEL); + if (!link) + return -ENOMEM; + + link->merge_flow.flow = merge_flow; + list_add_tail(&link->merge_flow.list, &merge_flow->linked_flows); + link->sub_flow.flow = sub_flow; + list_add_tail(&link->sub_flow.list, &sub_flow->linked_flows); + + return 0; +} + /** * nfp_flower_merge_offloaded_flows() - Merge 2 existing flows to single flow. * @app: Pointer to the APP handle @@ -764,8 +802,19 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app, if (err) goto err_destroy_merge_flow; + err = nfp_flower_link_flows(merge_flow, sub_flow1); + if (err) + goto err_destroy_merge_flow; + + err = nfp_flower_link_flows(merge_flow, sub_flow2); + if (err) + goto err_unlink_sub_flow1; + err = -EOPNOTSUPP; + nfp_flower_unlink_flows(merge_flow, sub_flow2); +err_unlink_sub_flow1: + nfp_flower_unlink_flows(merge_flow, sub_flow1); err_destroy_merge_flow: kfree(merge_flow->action_data); kfree(merge_flow->mask_data); @@ -913,6 +962,52 @@ nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev, return err; } +static void +__nfp_flower_update_merge_stats(struct nfp_app *app, + struct nfp_fl_payload *merge_flow) +{ + struct nfp_flower_priv *priv = app->priv; + struct nfp_fl_payload_link *link; + struct nfp_fl_payload *sub_flow; + u64 pkts, bytes, used; + u32 ctx_id; + + ctx_id = be32_to_cpu(merge_flow->meta.host_ctx_id); + pkts = priv->stats[ctx_id].pkts; + /* Do not cycle subflows if no stats to distribute. */ + if (!pkts) + return; + bytes = priv->stats[ctx_id].bytes; + used = priv->stats[ctx_id].used; + + /* Reset stats for the merge flow. */ + priv->stats[ctx_id].pkts = 0; + priv->stats[ctx_id].bytes = 0; + + /* The merge flow has received stats updates from firmware. + * Distribute these stats to all subflows that form the merge. + * The stats will collected from TC via the subflows. + */ + list_for_each_entry(link, &merge_flow->linked_flows, merge_flow.list) { + sub_flow = link->sub_flow.flow; + ctx_id = be32_to_cpu(sub_flow->meta.host_ctx_id); + priv->stats[ctx_id].pkts += pkts; + priv->stats[ctx_id].bytes += bytes; + max_t(u64, priv->stats[ctx_id].used, used); + } +} + +static void +nfp_flower_update_merge_stats(struct nfp_app *app, + struct nfp_fl_payload *sub_flow) +{ + struct nfp_fl_payload_link *link; + + /* Get merge flows that the subflow forms to distribute their stats. */ + list_for_each_entry(link, &sub_flow->linked_flows, sub_flow.list) + __nfp_flower_update_merge_stats(app, link->merge_flow.flow); +} + /** * nfp_flower_get_stats() - Populates flow stats obtained from hardware. * @app: Pointer to the APP handle @@ -939,6 +1034,10 @@ nfp_flower_get_stats(struct nfp_app *app, struct net_device *netdev, ctx_id = be32_to_cpu(nfp_flow->meta.host_ctx_id); spin_lock_bh(&priv->stats_lock); + /* If request is for a sub_flow, update stats from merged flows. */ + if (!list_empty(&nfp_flow->linked_flows)) + nfp_flower_update_merge_stats(app, nfp_flow); + flow_stats_update(&flow->stats, priv->stats[ctx_id].bytes, priv->stats[ctx_id].pkts, priv->stats[ctx_id].used);