From patchwork Wed Sep 21 15:35:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Conole X-Patchwork-Id: 672934 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3sfNxd1gtbz9sC7 for ; Thu, 22 Sep 2016 01:35:49 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=bytheb-org.20150623.gappssmtp.com header.i=@bytheb-org.20150623.gappssmtp.com header.b=X/SGnItV; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757830AbcIUPfp (ORCPT ); Wed, 21 Sep 2016 11:35:45 -0400 Received: from mail-yw0-f195.google.com ([209.85.161.195]:34426 "EHLO mail-yw0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757050AbcIUPfn (ORCPT ); Wed, 21 Sep 2016 11:35:43 -0400 Received: by mail-yw0-f195.google.com with SMTP id t67so3073957ywg.1 for ; Wed, 21 Sep 2016 08:35:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytheb-org.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=DEUxbrhzvE1CQdisi115CMEU5o51eLFexAbfKm8gSBU=; b=X/SGnItVbTNqyqZnIOQIQ+mEacDhmaaFugldmiS3e7xjkyuXJdFdD3J0niyhd77tyo 6ppYbBC22rLnRCqg7onueOTF7B3umwiAu4J2yH8AzeqQ/bDs8qQE7vmZR3FCpS962wat nhtztb6p7Y//1fSIg4XYWBnEGcRigxATsHvI8NPWK6vg8beQXFH6o0GELssQ3YY62X6h LkRuJyTpqj/FPrDgQHHW/vvyRlRrZ7J10aJ5VtOkmQjLi3wZlRJD0BcwP/VeXZk4keXW B627QLJojuC9Q/Wq4gowb3e7TNyRbMQrq1hcosc+t8M6QEgSr6hQ5oznM1Fos8x97z9A 8C+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=DEUxbrhzvE1CQdisi115CMEU5o51eLFexAbfKm8gSBU=; b=Apyq0wcYaBBGqcDJug1C6Xx96Cm//1adSYWi5Br4xcsEVoJwMDVrcBlSEtdctCYNj+ AGpiKT+5GOokoy2Bbn/gBdKd9BjJsIXmiEjjhXzXwFd3oB5RbIVYOZkOhBV52+T8mgea j2p0Z1p4vkac+a0DOT4ESW5VdV6DNaFHGz+1r1OqhxXkKhzxGk1jvIej+vlV1s405SuG xJlp9y6rDZWcE8Vz9UEmR2s+5P9UCEDKjcAV4lKBXTk1PoYCqhh7JtXrQQxij2EbDqP1 8JSMV+i9ms+vf0sndaPQ35/npR4/1YuhpmnXVSTAcD4ZE6Qy16N5KNr+Mps9Jap8Z97D l0ig== X-Gm-Message-State: AE9vXwPYDmxOiw+1ALy1uYVf4zWAJtZJniYZ+5B4HWMycvM7Sa/WWkH6Qu2q2yqm6y9dAg== X-Received: by 10.13.234.197 with SMTP id t188mr39518352ywe.79.1474472142370; Wed, 21 Sep 2016 08:35:42 -0700 (PDT) Received: from dhcp-25-97.bos.redhat.com (nat-pool-bos-t.redhat.com. [66.187.233.206]) by smtp.gmail.com with ESMTPSA id 89sm1462088uaz.22.2016.09.21.08.35.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Sep 2016 08:35:41 -0700 (PDT) From: Aaron Conole To: netfilter-devel@vger.kernel.org, netdev@vger.kernel.org Cc: Florian Westphal , Pablo Neira Ayuso Subject: [PATCH nf-next v3 1/7] netfilter: bridge: add and use br_nf_hook_thresh Date: Wed, 21 Sep 2016 11:35:01 -0400 Message-Id: <1474472107-12992-2-git-send-email-aconole@bytheb.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1474472107-12992-1-git-send-email-aconole@bytheb.org> References: <1474472107-12992-1-git-send-email-aconole@bytheb.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Florian Westphal This replaces the last uses of NF_HOOK_THRESH(). Followup patch will remove it and rename nf_hook_thresh. The reason is that inet (non-bridge) netfilter no longer invokes the hooks from hooks, so we do no longer need the thresh value to skip hooks with a lower priority. The bridge netfilter however may need to do this. br_nf_hook_thresh is a wrapper that is supposed to do this, i.e. only call hooks with a priority that exceeds NF_BR_PRI_BRNF. It's used only in the recursion cases of br_netfilter. It invokes nf_hook_slow while holding an rcu read-side critical section to make a future cleanup simpler. Signed-off-by: Florian Westphal Signed-off-by: Aaron Conole --- include/net/netfilter/br_netfilter.h | 6 ++++ net/bridge/br_netfilter_hooks.c | 60 ++++++++++++++++++++++++++++++------ net/bridge/br_netfilter_ipv6.c | 12 +++----- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/include/net/netfilter/br_netfilter.h b/include/net/netfilter/br_netfilter.h index e8d1448..0b0c35c 100644 --- a/include/net/netfilter/br_netfilter.h +++ b/include/net/netfilter/br_netfilter.h @@ -15,6 +15,12 @@ static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) void nf_bridge_update_protocol(struct sk_buff *skb); +int br_nf_hook_thresh(unsigned int hook, struct net *net, struct sock *sk, + struct sk_buff *skb, struct net_device *indev, + struct net_device *outdev, + int (*okfn)(struct net *, struct sock *, + struct sk_buff *)); + static inline struct nf_bridge_info * nf_bridge_info_get(const struct sk_buff *skb) { diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index 77e7f69..6029af4 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -395,11 +396,10 @@ bridged_dnat: skb->dev = nf_bridge->physindev; nf_bridge_update_protocol(skb); nf_bridge_push_encap_header(skb); - NF_HOOK_THRESH(NFPROTO_BRIDGE, - NF_BR_PRE_ROUTING, - net, sk, skb, skb->dev, NULL, - br_nf_pre_routing_finish_bridge, - 1); + br_nf_hook_thresh(NF_BR_PRE_ROUTING, + net, sk, skb, skb->dev, + NULL, + br_nf_pre_routing_finish); return 0; } ether_addr_copy(eth_hdr(skb)->h_dest, dev->dev_addr); @@ -417,10 +417,8 @@ bridged_dnat: skb->dev = nf_bridge->physindev; nf_bridge_update_protocol(skb); nf_bridge_push_encap_header(skb); - NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, net, sk, skb, - skb->dev, NULL, - br_handle_frame_finish, 1); - + br_nf_hook_thresh(NF_BR_PRE_ROUTING, net, sk, skb, skb->dev, NULL, + br_handle_frame_finish); return 0; } @@ -992,6 +990,50 @@ static struct notifier_block brnf_notifier __read_mostly = { .notifier_call = brnf_device_event, }; +/* recursively invokes nf_hook_slow (again), skipping already-called + * hooks (< NF_BR_PRI_BRNF). + * + * Called with rcu read lock held. + */ +int br_nf_hook_thresh(unsigned int hook, struct net *net, + struct sock *sk, struct sk_buff *skb, + struct net_device *indev, + struct net_device *outdev, + int (*okfn)(struct net *, struct sock *, + struct sk_buff *)) +{ + struct nf_hook_ops *elem; + struct nf_hook_state state; + struct list_head *head; + int ret; + + head = &net->nf.hooks[NFPROTO_BRIDGE][hook]; + + list_for_each_entry_rcu(elem, head, list) { + struct nf_hook_ops *next; + + next = list_entry_rcu(list_next_rcu(&elem->list), + struct nf_hook_ops, list); + if (next->priority <= NF_BR_PRI_BRNF) + continue; + } + + if (&elem->list == head) + return okfn(net, sk, skb); + + /* We may already have this, but read-locks nest anyway */ + rcu_read_lock(); + nf_hook_state_init(&state, head, hook, NF_BR_PRI_BRNF + 1, + NFPROTO_BRIDGE, indev, outdev, sk, net, okfn); + + ret = nf_hook_slow(skb, &state); + rcu_read_unlock(); + if (ret == 1) + ret = okfn(net, sk, skb); + + return ret; +} + #ifdef CONFIG_SYSCTL static int brnf_sysctl_call_tables(struct ctl_table *ctl, int write, diff --git a/net/bridge/br_netfilter_ipv6.c b/net/bridge/br_netfilter_ipv6.c index 5e59a84..5989661 100644 --- a/net/bridge/br_netfilter_ipv6.c +++ b/net/bridge/br_netfilter_ipv6.c @@ -187,10 +187,9 @@ static int br_nf_pre_routing_finish_ipv6(struct net *net, struct sock *sk, struc skb->dev = nf_bridge->physindev; nf_bridge_update_protocol(skb); nf_bridge_push_encap_header(skb); - NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, - net, sk, skb, skb->dev, NULL, - br_nf_pre_routing_finish_bridge, - 1); + br_nf_hook_thresh(NF_BR_PRE_ROUTING, + net, sk, skb, skb->dev, NULL, + br_nf_pre_routing_finish_bridge); return 0; } ether_addr_copy(eth_hdr(skb)->h_dest, dev->dev_addr); @@ -207,9 +206,8 @@ static int br_nf_pre_routing_finish_ipv6(struct net *net, struct sock *sk, struc skb->dev = nf_bridge->physindev; nf_bridge_update_protocol(skb); nf_bridge_push_encap_header(skb); - NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, net, sk, skb, - skb->dev, NULL, - br_handle_frame_finish, 1); + br_nf_hook_thresh(NF_BR_PRE_ROUTING, net, sk, skb, + skb->dev, NULL, br_handle_frame_finish); return 0; }