From patchwork Fri Jan 12 15:46:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pirko X-Patchwork-Id: 860007 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@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; dkim=pass (2048-bit key; unprotected) header.d=resnulli-us.20150623.gappssmtp.com header.i=@resnulli-us.20150623.gappssmtp.com header.b="pf50UObH"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zJ6Z75SPtz9sQm for ; Sat, 13 Jan 2018 02:47:11 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934081AbeALPrK (ORCPT ); Fri, 12 Jan 2018 10:47:10 -0500 Received: from mail-wm0-f68.google.com ([74.125.82.68]:45700 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934004AbeALPrI (ORCPT ); Fri, 12 Jan 2018 10:47:08 -0500 Received: by mail-wm0-f68.google.com with SMTP id i186so12916057wmi.4 for ; Fri, 12 Jan 2018 07:47:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=resnulli-us.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=w0NgEuxwmF21Pu1gQFICFAgd3X9Aa05MWwQCAFEVx6s=; b=pf50UObH2IGhASv4J8G2yaSsOhR2Acyc1cxCL4NxZP4pkuhxBA1CGqvG/1ef8BeIKA URvNH9spqLlKXMFztXYqVL4/ZBr/dzaG4uEbOLmQW2h4jdFDoKcGGwSFVvHiyWJhnXQT uzw2cL4eSwh5DP+ksqpnhOW/gbzU2T45N0jjCGt0YZJ5nM4ZNAjbcM7Lm5o7OjUPMh6S vUd4l6tNnucL9PKnnrtSk6torPYMHvZJTYf/zia/hP+WZs+6bSvWODDDLgsMTR5k1a1g 5TDiIvlMTfzlUik1XBrI8KKO4xmb09HiaP2XYxLukTsp5Pq6ehjrVOEFRX/SSLuH3p64 twJA== 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=w0NgEuxwmF21Pu1gQFICFAgd3X9Aa05MWwQCAFEVx6s=; b=NeMffOv+LVBbLLNgurU/l1MkcSVi0oeb1P9aEufZG3AtEihRlIIMP2z2DqYFQbGewY NZIsIiBkeCq+yTLBx/lNToZNReDwXP5H3t7Rwa5WAV2l82ykxRFPP125kTeCOn1sNpFR WfurMqK9fOfwmFEqWoWQi6hOmdAM86il620zJHrvWRKz7pJdzK/7CdwVSRlFuU5XR1Ge E/zCTSwZcXvMDkOryZFMiQwlpYVjRYwrxpxpK6vIbtdSfCmdHeXT1t7uPTAp0ZWAxZay bq30l+/7aG3GPhf2dCK0/riCOV9OKzXtEvPx/QMxB5UDABZKcgCt57K8k84zSxgSOH/m zpgg== X-Gm-Message-State: AKwxytf94XPo6YLBiyEEqJx5IGcXUrvMo645PIdLm59ixhfZxoEJ8gEA WZ3TUYCp0nh85tVqql6PpKbEMK9x X-Google-Smtp-Source: ACJfBoupqZLdRUyRD86Hlxe4sZ4RYPkcH75U9pPqHMxgd5GHcXdRLzfMWOvAo/f6FbBpAxanyvdofg== X-Received: by 10.28.111.90 with SMTP id k87mr4069339wmc.108.1515772026779; Fri, 12 Jan 2018 07:47:06 -0800 (PST) Received: from localhost (jirka.pirko.cz. [84.16.102.26]) by smtp.gmail.com with ESMTPSA id 36sm11317854wrt.96.2018.01.12.07.47.06 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 12 Jan 2018 07:47:06 -0800 (PST) From: Jiri Pirko To: netdev@vger.kernel.org Cc: davem@davemloft.net, jhs@mojatatu.com, xiyou.wangcong@gmail.com, mlxsw@mellanox.com, andrew@lunn.ch, vivien.didelot@savoirfairelinux.com, f.fainelli@gmail.com, michael.chan@broadcom.com, ganeshgr@chelsio.com, saeedm@mellanox.com, matanb@mellanox.com, leonro@mellanox.com, idosch@mellanox.com, jakub.kicinski@netronome.com, simon.horman@netronome.com, pieter.jansenvanvuuren@netronome.com, john.hurley@netronome.com, alexander.h.duyck@intel.com, ogerlitz@mellanox.com, john.fastabend@gmail.com, daniel@iogearbox.net, dsahern@gmail.com Subject: [patch net-next v8 01/14] net: sched: introduce support for multiple filter chain pointers registration Date: Fri, 12 Jan 2018 16:46:51 +0100 Message-Id: <20180112154704.1694-2-jiri@resnulli.us> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20180112154704.1694-1-jiri@resnulli.us> References: <20180112154704.1694-1-jiri@resnulli.us> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Jiri Pirko So far, there was possible only to register a single filter chain pointer to block->chain[0]. However, when the blocks will get shareable, we need to allow multiple filter chain pointers registration. Signed-off-by: Jiri Pirko --- v6->v7: - unsquashed shared block patch that was previously squashed by mistake - fixed error path in block create - freeing chain 0 v3->v4: - rebased on top of the current net-next - added some extack strings v2->v3: - rebased on top of the current net-next --- include/net/sch_generic.h | 3 +- net/sched/cls_api.c | 77 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index ac029d5..ddb96bb 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -275,8 +275,7 @@ typedef void tcf_chain_head_change_t(struct tcf_proto *tp_head, void *priv); struct tcf_chain { struct tcf_proto __rcu *filter_chain; - tcf_chain_head_change_t *chain_head_change; - void *chain_head_change_priv; + struct list_head filter_chain_list; struct list_head list; struct tcf_block *block; u32 index; /* chain index */ diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 6708b69..e6b16b3 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -179,6 +179,12 @@ static void tcf_proto_destroy(struct tcf_proto *tp) kfree_rcu(tp, rcu); } +struct tcf_filter_chain_list_item { + struct list_head list; + tcf_chain_head_change_t *chain_head_change; + void *chain_head_change_priv; +}; + static struct tcf_chain *tcf_chain_create(struct tcf_block *block, u32 chain_index) { @@ -187,6 +193,7 @@ static struct tcf_chain *tcf_chain_create(struct tcf_block *block, chain = kzalloc(sizeof(*chain), GFP_KERNEL); if (!chain) return NULL; + INIT_LIST_HEAD(&chain->filter_chain_list); list_add_tail(&chain->list, &block->chain_list); chain->block = block; chain->index = chain_index; @@ -194,12 +201,19 @@ static struct tcf_chain *tcf_chain_create(struct tcf_block *block, return chain; } +static void tcf_chain_head_change_item(struct tcf_filter_chain_list_item *item, + struct tcf_proto *tp_head) +{ + if (item->chain_head_change) + item->chain_head_change(tp_head, item->chain_head_change_priv); +} static void tcf_chain_head_change(struct tcf_chain *chain, struct tcf_proto *tp_head) { - if (chain->chain_head_change) - chain->chain_head_change(tp_head, - chain->chain_head_change_priv); + struct tcf_filter_chain_list_item *item; + + list_for_each_entry(item, &chain->filter_chain_list, list) + tcf_chain_head_change_item(item, tp_head); } static void tcf_chain_flush(struct tcf_chain *chain) @@ -280,6 +294,50 @@ static void tcf_block_offload_unbind(struct tcf_block *block, struct Qdisc *q, tcf_block_offload_cmd(block, q, ei, TC_BLOCK_UNBIND); } +static int +tcf_chain_head_change_cb_add(struct tcf_chain *chain, + struct tcf_block_ext_info *ei, + struct netlink_ext_ack *extack) +{ + struct tcf_filter_chain_list_item *item; + + item = kmalloc(sizeof(*item), GFP_KERNEL); + if (!item) { + NL_SET_ERR_MSG(extack, "Memory allocation for head change callback item failed"); + return -ENOMEM; + } + item->chain_head_change = ei->chain_head_change; + item->chain_head_change_priv = ei->chain_head_change_priv; + if (chain->filter_chain) + tcf_chain_head_change_item(item, chain->filter_chain); + list_add(&item->list, &chain->filter_chain_list); + return 0; +} + +static void +tcf_chain_head_change_cb_del(struct tcf_chain *chain, + struct tcf_block_ext_info *ei) +{ + struct tcf_filter_chain_list_item *item; + + list_for_each_entry(item, &chain->filter_chain_list, list) { + if ((!ei->chain_head_change && !ei->chain_head_change_priv) || + (item->chain_head_change == ei->chain_head_change && + item->chain_head_change_priv == ei->chain_head_change_priv)) { + tcf_chain_head_change_item(item, NULL); + list_del(&item->list); + kfree(item); + return; + } + } + WARN_ON(1); +} + +static struct tcf_chain *tcf_block_chain_zero(struct tcf_block *block) +{ + return list_first_entry(&block->chain_list, struct tcf_chain, list); +} + int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, struct tcf_block_ext_info *ei, struct netlink_ext_ack *extack) @@ -302,9 +360,10 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, err = -ENOMEM; goto err_chain_create; } - WARN_ON(!ei->chain_head_change); - chain->chain_head_change = ei->chain_head_change; - chain->chain_head_change_priv = ei->chain_head_change_priv; + err = tcf_chain_head_change_cb_add(tcf_block_chain_zero(block), + ei, extack); + if (err) + goto err_chain_head_change_cb_add; block->net = qdisc_net(q); block->q = q; tcf_block_offload_bind(block, q, ei); @@ -313,6 +372,8 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, err_chain_create: kfree(block); +err_chain_head_change_cb_add: + kfree(chain); return err; } EXPORT_SYMBOL(tcf_block_get_ext); @@ -351,6 +412,7 @@ void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, */ if (!block) return; + tcf_chain_head_change_cb_del(tcf_block_chain_zero(block), ei); list_for_each_entry(chain, &block->chain_list, list) tcf_chain_hold(chain); @@ -364,8 +426,7 @@ void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, tcf_chain_put(chain); /* Finally, put chain 0 and allow block to be freed. */ - chain = list_first_entry(&block->chain_list, struct tcf_chain, list); - tcf_chain_put(chain); + tcf_chain_put(tcf_block_chain_zero(block)); } EXPORT_SYMBOL(tcf_block_put_ext);