All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH nf-next,RFC 00/10] Netfilter core updates
@ 2016-10-13 12:02 Pablo Neira Ayuso
  2016-10-13 12:02 ` [PATCH nf-next,RFC 01/10] netfilter: get rid of useless debugging from core Pablo Neira Ayuso
                   ` (9 more replies)
  0 siblings, 10 replies; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 12:02 UTC (permalink / raw)
  To: netfilter-devel

Hi,

This is a quick RFC that has passed just very basic testing here. This
patchset achieves what it has been discussed during NetDev 1.2:

1) Deprecate NF_STOP, as this is only used by br_netfilter.

2) Remove threshold handling, this is also only used by br_netfilter
   too.

3) Move NF_QUEUE handling away from the core. Adds a new nf_queue()
   function that must be explicitly called to queue packets to userspace.
   This function returns the verdict that is passed down to the core,
   basically NF_DROP if queue is full, NF_ACCEPT if bypass is enabled
   and NF_STOLEN if packet is succesfully enqueued to userspace.

4) Merge nf_iterate() into nf_hook_slow(), then inline the resulting
   function and rename it to nf_hook_iterate().

This patchset also modifies the pktinfo and xt_action_param structures
(that keep context around while performing packet processing) to store
the netfilter hook state. This change was required by the new NF_QUEUE
handling. As side effect, according to pahole, these two now fit into
one single cacheline after this update.

Thanks!

Pablo Neira Ayuso (10):
  netfilter: get rid of useless debugging from core
  netfilter: remove comments that predate rcu days
  netfilter: bridge: kill NF_HOOK_THRESH() and state->tresh
  netfilter: deprecate NF_STOP
  netfilter: x_tables: move hook state into xt_action_param structure
  netfilter: nf_tables: use hook state from xt_action_param structure
  netfilter: use switch() to handle verdict cases from nf_hook_slow()
  netfilter: move NF_QUEUE handling away from core
  netfilter: merge nf_iterate() into nf_hook_slow()
  netfilter: inline nf_hook_slow() and rename it to nf_hook_iterate()

 include/linux/netfilter.h                  | 91 +++++++++++++++++-------------
 include/linux/netfilter/x_tables.h         | 48 ++++++++++++----
 include/linux/netfilter_ingress.h          |  4 +-
 include/net/netfilter/nf_queue.h           |  3 +
 include/net/netfilter/nf_tables.h          | 36 ++++++++----
 include/uapi/linux/netfilter.h             |  2 +-
 net/bridge/br_netfilter_hooks.c            | 18 +++---
 net/bridge/netfilter/ebt_arpreply.c        |  3 +-
 net/bridge/netfilter/ebt_log.c             | 11 ++--
 net/bridge/netfilter/ebt_nflog.c           |  6 +-
 net/bridge/netfilter/ebt_redirect.c        |  6 +-
 net/bridge/netfilter/ebtable_broute.c      |  2 +-
 net/bridge/netfilter/ebtables.c            |  6 +-
 net/bridge/netfilter/nft_meta_bridge.c     |  2 +-
 net/bridge/netfilter/nft_reject_bridge.c   | 30 ++++++----
 net/ipv4/netfilter/arp_tables.c            |  7 +--
 net/ipv4/netfilter/ip_tables.c             | 10 ++--
 net/ipv4/netfilter/ipt_MASQUERADE.c        |  3 +-
 net/ipv4/netfilter/ipt_REJECT.c            |  4 +-
 net/ipv4/netfilter/ipt_SYNPROXY.c          |  4 +-
 net/ipv4/netfilter/ipt_rpfilter.c          |  2 +-
 net/ipv4/netfilter/nft_dup_ipv4.c          |  2 +-
 net/ipv4/netfilter/nft_masq_ipv4.c         |  4 +-
 net/ipv4/netfilter/nft_redir_ipv4.c        |  3 +-
 net/ipv4/netfilter/nft_reject_ipv4.c       |  4 +-
 net/ipv6/netfilter/ip6_tables.c            | 10 ++--
 net/ipv6/netfilter/ip6t_MASQUERADE.c       |  2 +-
 net/ipv6/netfilter/ip6t_REJECT.c           | 23 +++++---
 net/ipv6/netfilter/ip6t_SYNPROXY.c         |  4 +-
 net/ipv6/netfilter/ip6t_rpfilter.c         |  3 +-
 net/ipv6/netfilter/nft_dup_ipv6.c          |  2 +-
 net/ipv6/netfilter/nft_masq_ipv6.c         |  3 +-
 net/ipv6/netfilter/nft_redir_ipv6.c        |  3 +-
 net/ipv6/netfilter/nft_reject_ipv6.c       |  6 +-
 net/netfilter/core.c                       | 75 ------------------------
 net/netfilter/ipset/ip_set_core.c          |  6 +-
 net/netfilter/ipset/ip_set_hash_netiface.c |  2 +-
 net/netfilter/nf_dup_netdev.c              |  2 +-
 net/netfilter/nf_internals.h               |  7 ---
 net/netfilter/nf_queue.c                   | 72 +++++++++++++++++------
 net/netfilter/nf_tables_api.c              |  3 +-
 net/netfilter/nf_tables_core.c             | 13 ++---
 net/netfilter/nf_tables_trace.c            |  8 +--
 net/netfilter/nft_log.c                    |  5 +-
 net/netfilter/nft_lookup.c                 |  5 +-
 net/netfilter/nft_meta.c                   |  6 +-
 net/netfilter/nft_queue.c                  |  8 +--
 net/netfilter/nft_reject_inet.c            | 18 +++---
 net/netfilter/xt_AUDIT.c                   | 10 ++--
 net/netfilter/xt_LOG.c                     |  6 +-
 net/netfilter/xt_NETMAP.c                  | 20 +++----
 net/netfilter/xt_NFLOG.c                   |  6 +-
 net/netfilter/xt_NFQUEUE.c                 | 33 +++++------
 net/netfilter/xt_REDIRECT.c                |  4 +-
 net/netfilter/xt_TCPMSS.c                  |  4 +-
 net/netfilter/xt_TEE.c                     |  4 +-
 net/netfilter/xt_TPROXY.c                  | 16 +++---
 net/netfilter/xt_addrtype.c                | 10 ++--
 net/netfilter/xt_cluster.c                 |  2 +-
 net/netfilter/xt_connlimit.c               |  8 +--
 net/netfilter/xt_conntrack.c               |  8 +--
 net/netfilter/xt_devgroup.c                |  4 +-
 net/netfilter/xt_dscp.c                    |  2 +-
 net/netfilter/xt_ipvs.c                    |  4 +-
 net/netfilter/xt_nfacct.c                  |  2 +-
 net/netfilter/xt_osf.c                     | 10 ++--
 net/netfilter/xt_owner.c                   |  2 +-
 net/netfilter/xt_pkttype.c                 |  4 +-
 net/netfilter/xt_policy.c                  |  4 +-
 net/netfilter/xt_recent.c                  | 10 ++--
 net/netfilter/xt_set.c                     | 26 ++++-----
 net/netfilter/xt_socket.c                  |  4 +-
 net/sched/act_ipt.c                        | 13 +++--
 net/sched/em_ipset.c                       | 18 +++---
 74 files changed, 430 insertions(+), 401 deletions(-)

-- 
2.1.4


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH nf-next,RFC 01/10] netfilter: get rid of useless debugging from core
  2016-10-13 12:02 [PATCH nf-next,RFC 00/10] Netfilter core updates Pablo Neira Ayuso
@ 2016-10-13 12:02 ` Pablo Neira Ayuso
  2016-10-13 12:02 ` [PATCH nf-next,RFC 02/10] netfilter: remove comments that predate rcu days Pablo Neira Ayuso
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 12:02 UTC (permalink / raw)
  To: netfilter-devel

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/core.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index fcb5d1df11e9..7b723bcd2522 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -323,15 +323,6 @@ unsigned int nf_iterate(struct sk_buff *skb,
 repeat:
 		verdict = (*entryp)->ops.hook((*entryp)->ops.priv, skb, state);
 		if (verdict != NF_ACCEPT) {
-#ifdef CONFIG_NETFILTER_DEBUG
-			if (unlikely((verdict & NF_VERDICT_MASK)
-							> NF_MAX_VERDICT)) {
-				NFDEBUG("Evil return from %p(%u).\n",
-					(*entryp)->ops.hook, state->hook);
-				*entryp = rcu_dereference((*entryp)->next);
-				continue;
-			}
-#endif
 			if (verdict != NF_REPEAT)
 				return verdict;
 			goto repeat;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH nf-next,RFC 02/10] netfilter: remove comments that predate rcu days
  2016-10-13 12:02 [PATCH nf-next,RFC 00/10] Netfilter core updates Pablo Neira Ayuso
  2016-10-13 12:02 ` [PATCH nf-next,RFC 01/10] netfilter: get rid of useless debugging from core Pablo Neira Ayuso
@ 2016-10-13 12:02 ` Pablo Neira Ayuso
  2016-10-13 12:02 ` [PATCH nf-next,RFC 03/10] netfilter: bridge: kill NF_HOOK_THRESH() and state->tresh Pablo Neira Ayuso
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 12:02 UTC (permalink / raw)
  To: netfilter-devel

We cannot block/sleep on nf_iterate because netfilter runs under rcu
read lock these days, where blocking is illegal. So let's remove these
old comments.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/core.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 7b723bcd2522..b193bd46ac30 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -308,18 +308,11 @@ unsigned int nf_iterate(struct sk_buff *skb,
 {
 	unsigned int verdict;
 
-	/*
-	 * The caller must not block between calls to this
-	 * function because of risk of continuing from deleted element.
-	 */
 	while (*entryp) {
 		if (state->thresh > (*entryp)->ops.priority) {
 			*entryp = rcu_dereference((*entryp)->next);
 			continue;
 		}
-
-		/* Optimization: we don't need to hold module
-		   reference here, since function can't sleep. --RR */
 repeat:
 		verdict = (*entryp)->ops.hook((*entryp)->ops.priv, skb, state);
 		if (verdict != NF_ACCEPT) {
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH nf-next,RFC 03/10] netfilter: bridge: kill NF_HOOK_THRESH() and state->tresh
  2016-10-13 12:02 [PATCH nf-next,RFC 00/10] Netfilter core updates Pablo Neira Ayuso
  2016-10-13 12:02 ` [PATCH nf-next,RFC 01/10] netfilter: get rid of useless debugging from core Pablo Neira Ayuso
  2016-10-13 12:02 ` [PATCH nf-next,RFC 02/10] netfilter: remove comments that predate rcu days Pablo Neira Ayuso
@ 2016-10-13 12:02 ` Pablo Neira Ayuso
  2016-10-13 12:25   ` Florian Westphal
  2016-10-13 12:02 ` [PATCH nf-next,RFC 04/10] netfilter: deprecate NF_STOP Pablo Neira Ayuso
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 12:02 UTC (permalink / raw)
  To: netfilter-devel

Patch c5136b15ea36 ("netfilter: bridge: add and use br_nf_hook_thresh")
introduced br_nf_hook_thresh().

Replace NF_HOOK_THRESH() by br_nf_hook_thresh from
br_nf_forward_finish(), so we have no more callers for this macro.

As a result, state->thresh and explicit thresh parameter in the hook
state structure is not required anymore.

And we can get rid of fast forward code in nf_iterate() in the core path
that is only used by br_netfilter to search for the filter hook.

Suggested-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/linux/netfilter.h             | 50 +++++++++--------------------------
 include/linux/netfilter_ingress.h     |  2 +-
 net/bridge/br_netfilter_hooks.c       |  8 +++---
 net/bridge/netfilter/ebtable_broute.c |  2 +-
 net/netfilter/core.c                  |  4 ---
 net/netfilter/nf_queue.c              |  1 -
 6 files changed, 19 insertions(+), 48 deletions(-)

diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index abc7fdcb9eb1..e0d000f6c9bf 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -49,7 +49,6 @@ struct sock;
 
 struct nf_hook_state {
 	unsigned int hook;
-	int thresh;
 	u_int8_t pf;
 	struct net_device *in;
 	struct net_device *out;
@@ -84,7 +83,7 @@ struct nf_hook_entry {
 static inline void nf_hook_state_init(struct nf_hook_state *p,
 				      struct nf_hook_entry *hook_entry,
 				      unsigned int hook,
-				      int thresh, u_int8_t pf,
+				      u_int8_t pf,
 				      struct net_device *indev,
 				      struct net_device *outdev,
 				      struct sock *sk,
@@ -92,7 +91,6 @@ static inline void nf_hook_state_init(struct nf_hook_state *p,
 				      int (*okfn)(struct net *, struct sock *, struct sk_buff *))
 {
 	p->hook = hook;
-	p->thresh = thresh;
 	p->pf = pf;
 	p->in = indev;
 	p->out = outdev;
@@ -155,20 +153,16 @@ extern struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
 int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state);
 
 /**
- *	nf_hook_thresh - call a netfilter hook
+ *	nf_hook - call a netfilter hook
  *
  *	Returns 1 if the hook has allowed the packet to pass.  The function
  *	okfn must be invoked by the caller in this case.  Any other return
  *	value indicates the packet has been consumed by the hook.
  */
-static inline int nf_hook_thresh(u_int8_t pf, 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 *),
-				 int thresh)
+static inline int nf_hook(u_int8_t pf, 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_entry *hook_head;
 	int ret = 1;
@@ -185,8 +179,8 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
 	if (hook_head) {
 		struct nf_hook_state state;
 
-		nf_hook_state_init(&state, hook_head, hook, thresh,
-				   pf, indev, outdev, sk, net, okfn);
+		nf_hook_state_init(&state, hook_head, hook, pf, indev, outdev,
+				   sk, net, okfn);
 
 		ret = nf_hook_slow(skb, &state);
 	}
@@ -195,14 +189,6 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
 	return ret;
 }
 
-static inline int nf_hook(u_int8_t pf, 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 *))
-{
-	return nf_hook_thresh(pf, hook, net, sk, skb, indev, outdev, okfn, INT_MIN);
-}
-                   
 /* Activate hook; either okfn or kfree_skb called, unless a hook
    returns NF_STOLEN (in which case, it's up to the hook to deal with
    the consequences).
@@ -221,19 +207,6 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net,
 */
 
 static inline int
-NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk,
-	       struct sk_buff *skb, struct net_device *in,
-	       struct net_device *out,
-	       int (*okfn)(struct net *, struct sock *, struct sk_buff *),
-	       int thresh)
-{
-	int ret = nf_hook_thresh(pf, hook, net, sk, skb, in, out, okfn, thresh);
-	if (ret == 1)
-		ret = okfn(net, sk, skb);
-	return ret;
-}
-
-static inline int
 NF_HOOK_COND(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk,
 	     struct sk_buff *skb, struct net_device *in, struct net_device *out,
 	     int (*okfn)(struct net *, struct sock *, struct sk_buff *),
@@ -242,7 +215,7 @@ NF_HOOK_COND(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk,
 	int ret;
 
 	if (!cond ||
-	    ((ret = nf_hook_thresh(pf, hook, net, sk, skb, in, out, okfn, INT_MIN)) == 1))
+	    ((ret = nf_hook(pf, hook, net, sk, skb, in, out, okfn)) == 1))
 		ret = okfn(net, sk, skb);
 	return ret;
 }
@@ -252,7 +225,10 @@ NF_HOOK(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct
 	struct net_device *in, struct net_device *out,
 	int (*okfn)(struct net *, struct sock *, struct sk_buff *))
 {
-	return NF_HOOK_THRESH(pf, hook, net, sk, skb, in, out, okfn, INT_MIN);
+	int ret = nf_hook(pf, hook, net, sk, skb, in, out, okfn);
+	if (ret == 1)
+		ret = okfn(net, sk, skb);
+	return ret;
 }
 
 /* Call setsockopt() */
diff --git a/include/linux/netfilter_ingress.h b/include/linux/netfilter_ingress.h
index 33e37fb41d5d..fd44e4131710 100644
--- a/include/linux/netfilter_ingress.h
+++ b/include/linux/netfilter_ingress.h
@@ -26,7 +26,7 @@ static inline int nf_hook_ingress(struct sk_buff *skb)
 	if (unlikely(!e))
 		return 0;
 
-	nf_hook_state_init(&state, e, NF_NETDEV_INGRESS, INT_MIN,
+	nf_hook_state_init(&state, e, NF_NETDEV_INGRESS,
 			   NFPROTO_NETDEV, skb->dev, NULL, NULL,
 			   dev_net(skb->dev), NULL);
 	return nf_hook_slow(skb, &state);
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index 2fe9345c1407..d0d66faebe90 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -561,8 +561,8 @@ static int br_nf_forward_finish(struct net *net, struct sock *sk, struct sk_buff
 	}
 	nf_bridge_push_encap_header(skb);
 
-	NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_FORWARD, net, sk, skb,
-		       in, skb->dev, br_forward_finish, 1);
+	br_nf_hook_thresh(NF_BR_FORWARD, net, sk, skb, in, skb->dev,
+			  br_forward_finish);
 	return 0;
 }
 
@@ -1016,8 +1016,8 @@ int br_nf_hook_thresh(unsigned int hook, struct net *net,
 
 	/* We may already have this, but read-locks nest anyway */
 	rcu_read_lock();
-	nf_hook_state_init(&state, elem, hook, NF_BR_PRI_BRNF + 1,
-			   NFPROTO_BRIDGE, indev, outdev, sk, net, okfn);
+	nf_hook_state_init(&state, elem, hook, NFPROTO_BRIDGE, indev, outdev,
+			   sk, net, okfn);
 
 	ret = nf_hook_slow(skb, &state);
 	rcu_read_unlock();
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
index ec94c6f1ae88..599679e3498d 100644
--- a/net/bridge/netfilter/ebtable_broute.c
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -53,7 +53,7 @@ static int ebt_broute(struct sk_buff *skb)
 	struct nf_hook_state state;
 	int ret;
 
-	nf_hook_state_init(&state, NULL, NF_BR_BROUTING, INT_MIN,
+	nf_hook_state_init(&state, NULL, NF_BR_BROUTING,
 			   NFPROTO_BRIDGE, skb->dev, NULL, NULL,
 			   dev_net(skb->dev), NULL);
 
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index b193bd46ac30..6b09d9ed2646 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -309,10 +309,6 @@ unsigned int nf_iterate(struct sk_buff *skb,
 	unsigned int verdict;
 
 	while (*entryp) {
-		if (state->thresh > (*entryp)->ops.priority) {
-			*entryp = rcu_dereference((*entryp)->next);
-			continue;
-		}
 repeat:
 		verdict = (*entryp)->ops.hook((*entryp)->ops.priv, skb, state);
 		if (verdict != NF_ACCEPT) {
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 221d7a5c2fec..ebb54facd6b5 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -185,7 +185,6 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
 	}
 
 	hook_entry = rcu_dereference(hook_entry->next);
-	entry->state.thresh = INT_MIN;
 
 	if (verdict == NF_ACCEPT) {
 	next_hook:
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH nf-next,RFC 04/10] netfilter: deprecate NF_STOP
  2016-10-13 12:02 [PATCH nf-next,RFC 00/10] Netfilter core updates Pablo Neira Ayuso
                   ` (2 preceding siblings ...)
  2016-10-13 12:02 ` [PATCH nf-next,RFC 03/10] netfilter: bridge: kill NF_HOOK_THRESH() and state->tresh Pablo Neira Ayuso
@ 2016-10-13 12:02 ` Pablo Neira Ayuso
  2016-10-13 12:02 ` [PATCH nf-next,RFC 05/10] netfilter: x_tables: move hook state into xt_action_param structure Pablo Neira Ayuso
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 12:02 UTC (permalink / raw)
  To: netfilter-devel

NF_STOP is only used by br_netfilter these days, and it can be emulated
with a combination of NF_STOLEN plus explicit call to the ->okfn()
function as Florian suggests.

To retain binary compatibility with userspace nf_queue application, we
have to keep NF_STOP around, so libnetfilter_queue userspace userspace
applications still work if they use NF_STOP for some exotic reason.

Out of tree modules using NF_STOP would break, we don't care about
those.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/uapi/linux/netfilter.h  | 2 +-
 net/bridge/br_netfilter_hooks.c | 6 ++++--
 net/netfilter/core.c            | 2 +-
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/include/uapi/linux/netfilter.h b/include/uapi/linux/netfilter.h
index d93f949d1d9a..7550e9176a54 100644
--- a/include/uapi/linux/netfilter.h
+++ b/include/uapi/linux/netfilter.h
@@ -13,7 +13,7 @@
 #define NF_STOLEN 2
 #define NF_QUEUE 3
 #define NF_REPEAT 4
-#define NF_STOP 5
+#define NF_STOP 5	/* Deprecated, for userspace nf_queue compatibility. */
 #define NF_MAX_VERDICT NF_STOP
 
 /* we overload the higher bits for encoding auxiliary data such as the queue
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index d0d66faebe90..7e3645fa6339 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -845,8 +845,10 @@ static unsigned int ip_sabotage_in(void *priv,
 				   struct sk_buff *skb,
 				   const struct nf_hook_state *state)
 {
-	if (skb->nf_bridge && !skb->nf_bridge->in_prerouting)
-		return NF_STOP;
+	if (skb->nf_bridge && !skb->nf_bridge->in_prerouting) {
+		state->okfn(state->net, state->sk, skb);
+		return NF_STOLEN;
+	}
 
 	return NF_ACCEPT;
 }
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 6b09d9ed2646..2a6ed7d29c6c 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -333,7 +333,7 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
 	entry = rcu_dereference(state->hook_entries);
 next_hook:
 	verdict = nf_iterate(skb, state, &entry);
-	if (verdict == NF_ACCEPT || verdict == NF_STOP) {
+	if (verdict == NF_ACCEPT) {
 		ret = 1;
 	} else if ((verdict & NF_VERDICT_MASK) == NF_DROP) {
 		kfree_skb(skb);
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH nf-next,RFC 05/10] netfilter: x_tables: move hook state into xt_action_param structure
  2016-10-13 12:02 [PATCH nf-next,RFC 00/10] Netfilter core updates Pablo Neira Ayuso
                   ` (3 preceding siblings ...)
  2016-10-13 12:02 ` [PATCH nf-next,RFC 04/10] netfilter: deprecate NF_STOP Pablo Neira Ayuso
@ 2016-10-13 12:02 ` Pablo Neira Ayuso
  2016-10-13 12:02 ` [PATCH nf-next,RFC 06/10] netfilter: nf_tables: use hook state from " Pablo Neira Ayuso
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 12:02 UTC (permalink / raw)
  To: netfilter-devel

Place pointer to hook state in xt_action_param structure instead of
copying the fields that we need. After this change xt_action_param fits
into one cacheline.

This patch also adds a set of new wrapper functions to fetch relevant
hook state structure fields.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/linux/netfilter/x_tables.h         | 48 +++++++++++++++++++++++-------
 include/net/netfilter/nf_tables.h          | 11 +++----
 net/bridge/netfilter/ebt_arpreply.c        |  3 +-
 net/bridge/netfilter/ebt_log.c             | 11 +++----
 net/bridge/netfilter/ebt_nflog.c           |  6 ++--
 net/bridge/netfilter/ebt_redirect.c        |  6 ++--
 net/bridge/netfilter/ebtables.c            |  6 +---
 net/ipv4/netfilter/arp_tables.c            |  6 +---
 net/ipv4/netfilter/ip_tables.c             |  6 +---
 net/ipv4/netfilter/ipt_MASQUERADE.c        |  3 +-
 net/ipv4/netfilter/ipt_REJECT.c            |  4 +--
 net/ipv4/netfilter/ipt_SYNPROXY.c          |  4 +--
 net/ipv4/netfilter/ipt_rpfilter.c          |  2 +-
 net/ipv6/netfilter/ip6_tables.c            |  6 +---
 net/ipv6/netfilter/ip6t_MASQUERADE.c       |  2 +-
 net/ipv6/netfilter/ip6t_REJECT.c           | 23 ++++++++------
 net/ipv6/netfilter/ip6t_SYNPROXY.c         |  4 +--
 net/ipv6/netfilter/ip6t_rpfilter.c         |  3 +-
 net/netfilter/ipset/ip_set_core.c          |  6 ++--
 net/netfilter/ipset/ip_set_hash_netiface.c |  2 +-
 net/netfilter/xt_AUDIT.c                   | 10 +++----
 net/netfilter/xt_LOG.c                     |  6 ++--
 net/netfilter/xt_NETMAP.c                  | 20 ++++++-------
 net/netfilter/xt_NFLOG.c                   |  6 ++--
 net/netfilter/xt_NFQUEUE.c                 |  4 +--
 net/netfilter/xt_REDIRECT.c                |  4 +--
 net/netfilter/xt_TCPMSS.c                  |  4 +--
 net/netfilter/xt_TEE.c                     |  4 +--
 net/netfilter/xt_TPROXY.c                  | 16 +++++-----
 net/netfilter/xt_addrtype.c                | 10 +++----
 net/netfilter/xt_cluster.c                 |  2 +-
 net/netfilter/xt_connlimit.c               |  8 ++---
 net/netfilter/xt_conntrack.c               |  8 ++---
 net/netfilter/xt_devgroup.c                |  4 +--
 net/netfilter/xt_dscp.c                    |  2 +-
 net/netfilter/xt_ipvs.c                    |  4 +--
 net/netfilter/xt_nfacct.c                  |  2 +-
 net/netfilter/xt_osf.c                     | 10 +++----
 net/netfilter/xt_owner.c                   |  2 +-
 net/netfilter/xt_pkttype.c                 |  4 +--
 net/netfilter/xt_policy.c                  |  4 +--
 net/netfilter/xt_recent.c                  | 10 +++----
 net/netfilter/xt_set.c                     | 26 ++++++++--------
 net/netfilter/xt_socket.c                  |  4 +--
 net/sched/act_ipt.c                        | 13 ++++----
 net/sched/em_ipset.c                       | 18 ++++++-----
 46 files changed, 198 insertions(+), 169 deletions(-)

diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 2ad1a2b289b5..cd4eaf8df445 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -4,6 +4,7 @@
 
 #include <linux/netdevice.h>
 #include <linux/static_key.h>
+#include <linux/netfilter.h>
 #include <uapi/linux/netfilter/x_tables.h>
 
 /* Test a struct->invflags and a boolean for inequality */
@@ -17,14 +18,9 @@
  * @target:	the target extension
  * @matchinfo:	per-match data
  * @targetinfo:	per-target data
- * @net		network namespace through which the action was invoked
- * @in:		input netdevice
- * @out:	output netdevice
+ * @state:	pointer to hook state this packet came from
  * @fragoff:	packet is a fragment, this is the data offset
  * @thoff:	position of transport header relative to skb->data
- * @hook:	hook number given packet came from
- * @family:	Actual NFPROTO_* through which the function is invoked
- * 		(helpful when match->family == NFPROTO_UNSPEC)
  *
  * Fields written to by extensions:
  *
@@ -38,15 +34,47 @@ struct xt_action_param {
 	union {
 		const void *matchinfo, *targinfo;
 	};
-	struct net *net;
-	const struct net_device *in, *out;
+	const struct nf_hook_state *state;
 	int fragoff;
 	unsigned int thoff;
-	unsigned int hooknum;
-	u_int8_t family;
 	bool hotdrop;
 };
 
+static inline struct net *xt_net(const struct xt_action_param *par)
+{
+	return par->state->net;
+}
+
+static inline struct net_device *xt_in(const struct xt_action_param *par)
+{
+	return par->state->in;
+}
+
+static inline const char *xt_inname(const struct xt_action_param *par)
+{
+	return par->state->in->name;
+}
+
+static inline struct net_device *xt_out(const struct xt_action_param *par)
+{
+	return par->state->out;
+}
+
+static inline const char *xt_outname(const struct xt_action_param *par)
+{
+	return par->state->out->name;
+}
+
+static inline unsigned int xt_hooknum(const struct xt_action_param *par)
+{
+	return par->state->hook;
+}
+
+static inline u_int8_t xt_family(const struct xt_action_param *par)
+{
+	return par->state->pf;
+}
+
 /**
  * struct xt_mtchk_param - parameters for match extensions'
  * checkentry functions
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 5031e072567b..44060344f958 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -30,11 +30,12 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
 				   const struct nf_hook_state *state)
 {
 	pkt->skb = skb;
-	pkt->net = pkt->xt.net = state->net;
-	pkt->in = pkt->xt.in = state->in;
-	pkt->out = pkt->xt.out = state->out;
-	pkt->hook = pkt->xt.hooknum = state->hook;
-	pkt->pf = pkt->xt.family = state->pf;
+	pkt->net = state->net;
+	pkt->in = state->in;
+	pkt->out = state->out;
+	pkt->hook = state->hook;
+	pkt->pf = state->pf;
+	pkt->xt.state = state;
 }
 
 static inline void nft_set_pktinfo_proto_unspec(struct nft_pktinfo *pkt,
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
index 070cf134a22f..5929309beaa1 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -51,7 +51,8 @@ ebt_arpreply_tg(struct sk_buff *skb, const struct xt_action_param *par)
 	if (diptr == NULL)
 		return EBT_DROP;
 
-	arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, (struct net_device *)par->in,
+	arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr,
+		 (struct net_device *)xt_in(par),
 		 *diptr, shp, info->mac, shp);
 
 	return info->target;
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 9a11086ba6ff..e88bd4827ac1 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -179,7 +179,7 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct ebt_log_info *info = par->targinfo;
 	struct nf_loginfo li;
-	struct net *net = par->net;
+	struct net *net = xt_net(par);
 
 	li.type = NF_LOG_TYPE_LOG;
 	li.u.log.level = info->loglevel;
@@ -190,11 +190,12 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par)
 	 * nf_log_packet() with NFT_LOG_TYPE_LOG here. --Pablo
 	 */
 	if (info->bitmask & EBT_LOG_NFLOG)
-		nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb,
-			      par->in, par->out, &li, "%s", info->prefix);
+		nf_log_packet(net, NFPROTO_BRIDGE, xt_hooknum(par), skb,
+			      xt_in(par), xt_out(par), &li, "%s",
+			      info->prefix);
 	else
-		ebt_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, par->in,
-			       par->out, &li, info->prefix);
+		ebt_log_packet(net, NFPROTO_BRIDGE, xt_hooknum(par), skb,
+			       xt_in(par), xt_out(par), &li, info->prefix);
 	return EBT_CONTINUE;
 }
 
diff --git a/net/bridge/netfilter/ebt_nflog.c b/net/bridge/netfilter/ebt_nflog.c
index 54816150608e..c1dc48686200 100644
--- a/net/bridge/netfilter/ebt_nflog.c
+++ b/net/bridge/netfilter/ebt_nflog.c
@@ -23,16 +23,16 @@ static unsigned int
 ebt_nflog_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct ebt_nflog_info *info = par->targinfo;
+	struct net *net = xt_net(par);
 	struct nf_loginfo li;
-	struct net *net = par->net;
 
 	li.type = NF_LOG_TYPE_ULOG;
 	li.u.ulog.copy_len = info->len;
 	li.u.ulog.group = info->group;
 	li.u.ulog.qthreshold = info->threshold;
 
-	nf_log_packet(net, PF_BRIDGE, par->hooknum, skb, par->in,
-		      par->out, &li, "%s", info->prefix);
+	nf_log_packet(net, PF_BRIDGE, xt_hooknum(par), skb, xt_in(par),
+		      xt_out(par), &li, "%s", info->prefix);
 	return EBT_CONTINUE;
 }
 
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
index 2e7c4f974340..8d2a85e0594e 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -23,12 +23,12 @@ ebt_redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
 	if (!skb_make_writable(skb, 0))
 		return EBT_DROP;
 
-	if (par->hooknum != NF_BR_BROUTING)
+	if (xt_hooknum(par) != NF_BR_BROUTING)
 		/* rcu_read_lock()ed by nf_hook_thresh */
 		ether_addr_copy(eth_hdr(skb)->h_dest,
-				br_port_get_rcu(par->in)->br->dev->dev_addr);
+				br_port_get_rcu(xt_in(par))->br->dev->dev_addr);
 	else
-		ether_addr_copy(eth_hdr(skb)->h_dest, par->in->dev_addr);
+		ether_addr_copy(eth_hdr(skb)->h_dest, xt_in(par)->dev_addr);
 	skb->pkt_type = PACKET_HOST;
 	return info->target;
 }
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index f5c11bbe27db..1ab6014cf0f8 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -194,12 +194,8 @@ unsigned int ebt_do_table(struct sk_buff *skb,
 	const struct ebt_table_info *private;
 	struct xt_action_param acpar;
 
-	acpar.family  = NFPROTO_BRIDGE;
-	acpar.net     = state->net;
-	acpar.in      = state->in;
-	acpar.out     = state->out;
+	acpar.state   = state;
 	acpar.hotdrop = false;
-	acpar.hooknum = hook;
 
 	read_lock_bh(&table->lock);
 	private = table->private;
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index b31df597fd37..e76ab23a2deb 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -217,11 +217,7 @@ unsigned int arpt_do_table(struct sk_buff *skb,
 	 */
 	e = get_entry(table_base, private->hook_entry[hook]);
 
-	acpar.net     = state->net;
-	acpar.in      = state->in;
-	acpar.out     = state->out;
-	acpar.hooknum = hook;
-	acpar.family  = NFPROTO_ARP;
+	acpar.state   = state;
 	acpar.hotdrop = false;
 
 	arp = arp_hdr(skb);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 7c00ce90adb8..de4fa03f46f3 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -261,11 +261,7 @@ ipt_do_table(struct sk_buff *skb,
 	acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
 	acpar.thoff   = ip_hdrlen(skb);
 	acpar.hotdrop = false;
-	acpar.net     = state->net;
-	acpar.in      = state->in;
-	acpar.out     = state->out;
-	acpar.family  = NFPROTO_IPV4;
-	acpar.hooknum = hook;
+	acpar.state   = state;
 
 	IP_NF_ASSERT(table->valid_hooks & (1 << hook));
 	local_bh_disable();
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index da7f02a0b868..34cfb9b0bc0a 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -55,7 +55,8 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par)
 	range.min_proto = mr->range[0].min;
 	range.max_proto = mr->range[0].max;
 
-	return nf_nat_masquerade_ipv4(skb, par->hooknum, &range, par->out);
+	return nf_nat_masquerade_ipv4(skb, xt_hooknum(par), &range,
+				      xt_out(par));
 }
 
 static struct xt_target masquerade_tg_reg __read_mostly = {
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 1d16c0f28df0..8bd0d7b26632 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -34,7 +34,7 @@ static unsigned int
 reject_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct ipt_reject_info *reject = par->targinfo;
-	int hook = par->hooknum;
+	int hook = xt_hooknum(par);
 
 	switch (reject->with) {
 	case IPT_ICMP_NET_UNREACHABLE:
@@ -59,7 +59,7 @@ reject_tg(struct sk_buff *skb, const struct xt_action_param *par)
 		nf_send_unreach(skb, ICMP_PKT_FILTERED, hook);
 		break;
 	case IPT_TCP_RESET:
-		nf_send_reset(par->net, skb, hook);
+		nf_send_reset(xt_net(par), skb, hook);
 	case IPT_ICMP_ECHOREPLY:
 		/* Doesn't happen. */
 		break;
diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c b/net/ipv4/netfilter/ipt_SYNPROXY.c
index db5b87509446..361411688221 100644
--- a/net/ipv4/netfilter/ipt_SYNPROXY.c
+++ b/net/ipv4/netfilter/ipt_SYNPROXY.c
@@ -263,12 +263,12 @@ static unsigned int
 synproxy_tg4(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_synproxy_info *info = par->targinfo;
-	struct net *net = par->net;
+	struct net *net = xt_net(par);
 	struct synproxy_net *snet = synproxy_pernet(net);
 	struct synproxy_options opts = {};
 	struct tcphdr *th, _th;
 
-	if (nf_ip_checksum(skb, par->hooknum, par->thoff, IPPROTO_TCP))
+	if (nf_ip_checksum(skb, xt_hooknum(par), par->thoff, IPPROTO_TCP))
 		return NF_DROP;
 
 	th = skb_header_pointer(skb, par->thoff, sizeof(_th), &_th);
diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c
index 78cc64eddfc1..59b49945b481 100644
--- a/net/ipv4/netfilter/ipt_rpfilter.c
+++ b/net/ipv4/netfilter/ipt_rpfilter.c
@@ -95,7 +95,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	flow.flowi4_tos = RT_TOS(iph->tos);
 	flow.flowi4_scope = RT_SCOPE_UNIVERSE;
 
-	return rpfilter_lookup_reverse(par->net, &flow, par->in, info->flags) ^ invert;
+	return rpfilter_lookup_reverse(xt_net(par), &flow, xt_in(par), info->flags) ^ invert;
 }
 
 static int rpfilter_check(const struct xt_mtchk_param *par)
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 55aacea24396..7eac01d5d621 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -291,11 +291,7 @@ ip6t_do_table(struct sk_buff *skb,
 	 * rule is also a fragment-specific rule, non-fragments won't
 	 * match it. */
 	acpar.hotdrop = false;
-	acpar.net     = state->net;
-	acpar.in      = state->in;
-	acpar.out     = state->out;
-	acpar.family  = NFPROTO_IPV6;
-	acpar.hooknum = hook;
+	acpar.state   = state;
 
 	IP_NF_ASSERT(table->valid_hooks & (1 << hook));
 
diff --git a/net/ipv6/netfilter/ip6t_MASQUERADE.c b/net/ipv6/netfilter/ip6t_MASQUERADE.c
index 7f9f45d829d2..2b1a15846f9a 100644
--- a/net/ipv6/netfilter/ip6t_MASQUERADE.c
+++ b/net/ipv6/netfilter/ip6t_MASQUERADE.c
@@ -24,7 +24,7 @@
 static unsigned int
 masquerade_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 {
-	return nf_nat_masquerade_ipv6(skb, par->targinfo, par->out);
+	return nf_nat_masquerade_ipv6(skb, par->targinfo, xt_out(par));
 }
 
 static int masquerade_tg6_checkentry(const struct xt_tgchk_param *par)
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index db29bbf41b59..fa51a205918d 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -39,35 +39,40 @@ static unsigned int
 reject_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct ip6t_reject_info *reject = par->targinfo;
-	struct net *net = par->net;
+	struct net *net = xt_net(par);
 
 	switch (reject->with) {
 	case IP6T_ICMP6_NO_ROUTE:
-		nf_send_unreach6(net, skb, ICMPV6_NOROUTE, par->hooknum);
+		nf_send_unreach6(net, skb, ICMPV6_NOROUTE, xt_hooknum(par));
 		break;
 	case IP6T_ICMP6_ADM_PROHIBITED:
-		nf_send_unreach6(net, skb, ICMPV6_ADM_PROHIBITED, par->hooknum);
+		nf_send_unreach6(net, skb, ICMPV6_ADM_PROHIBITED,
+				 xt_hooknum(par));
 		break;
 	case IP6T_ICMP6_NOT_NEIGHBOUR:
-		nf_send_unreach6(net, skb, ICMPV6_NOT_NEIGHBOUR, par->hooknum);
+		nf_send_unreach6(net, skb, ICMPV6_NOT_NEIGHBOUR,
+				 xt_hooknum(par));
 		break;
 	case IP6T_ICMP6_ADDR_UNREACH:
-		nf_send_unreach6(net, skb, ICMPV6_ADDR_UNREACH, par->hooknum);
+		nf_send_unreach6(net, skb, ICMPV6_ADDR_UNREACH,
+				 xt_hooknum(par));
 		break;
 	case IP6T_ICMP6_PORT_UNREACH:
-		nf_send_unreach6(net, skb, ICMPV6_PORT_UNREACH, par->hooknum);
+		nf_send_unreach6(net, skb, ICMPV6_PORT_UNREACH,
+				 xt_hooknum(par));
 		break;
 	case IP6T_ICMP6_ECHOREPLY:
 		/* Do nothing */
 		break;
 	case IP6T_TCP_RESET:
-		nf_send_reset6(net, skb, par->hooknum);
+		nf_send_reset6(net, skb, xt_hooknum(par));
 		break;
 	case IP6T_ICMP6_POLICY_FAIL:
-		nf_send_unreach6(net, skb, ICMPV6_POLICY_FAIL, par->hooknum);
+		nf_send_unreach6(net, skb, ICMPV6_POLICY_FAIL, xt_hooknum(par));
 		break;
 	case IP6T_ICMP6_REJECT_ROUTE:
-		nf_send_unreach6(net, skb, ICMPV6_REJECT_ROUTE, par->hooknum);
+		nf_send_unreach6(net, skb, ICMPV6_REJECT_ROUTE,
+				 xt_hooknum(par));
 		break;
 	}
 
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c
index 06bed74cf5ee..99a1216287c8 100644
--- a/net/ipv6/netfilter/ip6t_SYNPROXY.c
+++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c
@@ -277,12 +277,12 @@ static unsigned int
 synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_synproxy_info *info = par->targinfo;
-	struct net *net = par->net;
+	struct net *net = xt_net(par);
 	struct synproxy_net *snet = synproxy_pernet(net);
 	struct synproxy_options opts = {};
 	struct tcphdr *th, _th;
 
-	if (nf_ip6_checksum(skb, par->hooknum, par->thoff, IPPROTO_TCP))
+	if (nf_ip6_checksum(skb, xt_hooknum(par), par->thoff, IPPROTO_TCP))
 		return NF_DROP;
 
 	th = skb_header_pointer(skb, par->thoff, sizeof(_th), &_th);
diff --git a/net/ipv6/netfilter/ip6t_rpfilter.c b/net/ipv6/netfilter/ip6t_rpfilter.c
index 1ee1b25df096..d5263dc364a9 100644
--- a/net/ipv6/netfilter/ip6t_rpfilter.c
+++ b/net/ipv6/netfilter/ip6t_rpfilter.c
@@ -93,7 +93,8 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	if (unlikely(saddrtype == IPV6_ADDR_ANY))
 		return true ^ invert; /* not routable: forward path will drop it */
 
-	return rpfilter_lookup_reverse6(par->net, skb, par->in, info->flags) ^ invert;
+	return rpfilter_lookup_reverse6(xt_net(par), skb, xt_in(par),
+					info->flags) ^ invert;
 }
 
 static int rpfilter_check(const struct xt_mtchk_param *par)
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index a748b0c2c981..3f1b945a24d5 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -541,7 +541,7 @@ int
 ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
 	    const struct xt_action_param *par, struct ip_set_adt_opt *opt)
 {
-	struct ip_set *set = ip_set_rcu_get(par->net, index);
+	struct ip_set *set = ip_set_rcu_get(xt_net(par), index);
 	int ret = 0;
 
 	BUG_ON(!set);
@@ -579,7 +579,7 @@ int
 ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
 	   const struct xt_action_param *par, struct ip_set_adt_opt *opt)
 {
-	struct ip_set *set = ip_set_rcu_get(par->net, index);
+	struct ip_set *set = ip_set_rcu_get(xt_net(par), index);
 	int ret;
 
 	BUG_ON(!set);
@@ -601,7 +601,7 @@ int
 ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
 	   const struct xt_action_param *par, struct ip_set_adt_opt *opt)
 {
-	struct ip_set *set = ip_set_rcu_get(par->net, index);
+	struct ip_set *set = ip_set_rcu_get(xt_net(par), index);
 	int ret = 0;
 
 	BUG_ON(!set);
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
index f0f688db6213..aa1a776613b9 100644
--- a/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -170,7 +170,7 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
 	ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
 	e.ip &= ip_set_netmask(e.cidr);
 
-#define IFACE(dir)	(par->dir ? par->dir->name : "")
+#define IFACE(dir)	(par->state->dir ? par->state->dir->name : "")
 #define SRCDIR		(opt->flags & IPSET_DIM_TWO_SRC)
 
 	if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index 4973cbddc446..19247a17e511 100644
--- a/net/netfilter/xt_AUDIT.c
+++ b/net/netfilter/xt_AUDIT.c
@@ -132,9 +132,9 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
 		goto errout;
 
 	audit_log_format(ab, "action=%hhu hook=%u len=%u inif=%s outif=%s",
-			 info->type, par->hooknum, skb->len,
-			 par->in ? par->in->name : "?",
-			 par->out ? par->out->name : "?");
+			 info->type, xt_hooknum(par), skb->len,
+			 xt_in(par) ? xt_inname(par) : "?",
+			 xt_out(par) ? xt_outname(par) : "?");
 
 	if (skb->mark)
 		audit_log_format(ab, " mark=%#x", skb->mark);
@@ -144,7 +144,7 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
 				 eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
 				 ntohs(eth_hdr(skb)->h_proto));
 
-		if (par->family == NFPROTO_BRIDGE) {
+		if (xt_family(par) == NFPROTO_BRIDGE) {
 			switch (eth_hdr(skb)->h_proto) {
 			case htons(ETH_P_IP):
 				audit_ip4(ab, skb);
@@ -157,7 +157,7 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
 		}
 	}
 
-	switch (par->family) {
+	switch (xt_family(par)) {
 	case NFPROTO_IPV4:
 		audit_ip4(ab, skb);
 		break;
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
index 1763ab82bcd7..c3b2017ebe41 100644
--- a/net/netfilter/xt_LOG.c
+++ b/net/netfilter/xt_LOG.c
@@ -32,15 +32,15 @@ static unsigned int
 log_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_log_info *loginfo = par->targinfo;
+	struct net *net = xt_net(par);
 	struct nf_loginfo li;
-	struct net *net = par->net;
 
 	li.type = NF_LOG_TYPE_LOG;
 	li.u.log.level = loginfo->level;
 	li.u.log.logflags = loginfo->logflags;
 
-	nf_log_packet(net, par->family, par->hooknum, skb, par->in, par->out,
-		      &li, "%s", loginfo->prefix);
+	nf_log_packet(net, xt_family(par), xt_hooknum(par), skb, xt_in(par),
+		      xt_out(par), &li, "%s", loginfo->prefix);
 	return XT_CONTINUE;
 }
 
diff --git a/net/netfilter/xt_NETMAP.c b/net/netfilter/xt_NETMAP.c
index b253e07cb1c5..94d0b5411192 100644
--- a/net/netfilter/xt_NETMAP.c
+++ b/net/netfilter/xt_NETMAP.c
@@ -33,8 +33,8 @@ netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 		netmask.ip6[i] = ~(range->min_addr.ip6[i] ^
 				   range->max_addr.ip6[i]);
 
-	if (par->hooknum == NF_INET_PRE_ROUTING ||
-	    par->hooknum == NF_INET_LOCAL_OUT)
+	if (xt_hooknum(par) == NF_INET_PRE_ROUTING ||
+	    xt_hooknum(par) == NF_INET_LOCAL_OUT)
 		new_addr.in6 = ipv6_hdr(skb)->daddr;
 	else
 		new_addr.in6 = ipv6_hdr(skb)->saddr;
@@ -51,7 +51,7 @@ netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 	newrange.min_proto	= range->min_proto;
 	newrange.max_proto	= range->max_proto;
 
-	return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
+	return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(xt_hooknum(par)));
 }
 
 static int netmap_tg6_checkentry(const struct xt_tgchk_param *par)
@@ -72,16 +72,16 @@ netmap_tg4(struct sk_buff *skb, const struct xt_action_param *par)
 	const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
 	struct nf_nat_range newrange;
 
-	NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
-		     par->hooknum == NF_INET_POST_ROUTING ||
-		     par->hooknum == NF_INET_LOCAL_OUT ||
-		     par->hooknum == NF_INET_LOCAL_IN);
+	NF_CT_ASSERT(xt_hooknum(par) == NF_INET_PRE_ROUTING ||
+		     xt_hooknum(par) == NF_INET_POST_ROUTING ||
+		     xt_hooknum(par) == NF_INET_LOCAL_OUT ||
+		     xt_hooknum(par) == NF_INET_LOCAL_IN);
 	ct = nf_ct_get(skb, &ctinfo);
 
 	netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
 
-	if (par->hooknum == NF_INET_PRE_ROUTING ||
-	    par->hooknum == NF_INET_LOCAL_OUT)
+	if (xt_hooknum(par) == NF_INET_PRE_ROUTING ||
+	    xt_hooknum(par) == NF_INET_LOCAL_OUT)
 		new_ip = ip_hdr(skb)->daddr & ~netmask;
 	else
 		new_ip = ip_hdr(skb)->saddr & ~netmask;
@@ -96,7 +96,7 @@ netmap_tg4(struct sk_buff *skb, const struct xt_action_param *par)
 	newrange.max_proto   = mr->range[0].max;
 
 	/* Hand modified range to generic setup. */
-	return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
+	return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(xt_hooknum(par)));
 }
 
 static int netmap_tg4_check(const struct xt_tgchk_param *par)
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c
index 018eed7e1ff1..3ce6684e2e56 100644
--- a/net/netfilter/xt_NFLOG.c
+++ b/net/netfilter/xt_NFLOG.c
@@ -25,8 +25,8 @@ static unsigned int
 nflog_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_nflog_info *info = par->targinfo;
+	struct net *net = xt_net(par);
 	struct nf_loginfo li;
-	struct net *net = par->net;
 
 	li.type		     = NF_LOG_TYPE_ULOG;
 	li.u.ulog.copy_len   = info->len;
@@ -36,8 +36,8 @@ nflog_tg(struct sk_buff *skb, const struct xt_action_param *par)
 	if (info->flags & XT_NFLOG_F_COPY_LEN)
 		li.u.ulog.flags |= NF_LOG_F_COPY_LEN;
 
-	nfulnl_log_packet(net, par->family, par->hooknum, skb, par->in,
-			  par->out, &li, info->prefix);
+	nfulnl_log_packet(net, xt_family(par), xt_hooknum(par), skb,
+			  xt_in(par), xt_out(par), &li, info->prefix);
 	return XT_CONTINUE;
 }
 
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 8f1779ff7e30..a360b99a958a 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -43,7 +43,7 @@ nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
 
 	if (info->queues_total > 1) {
 		queue = nfqueue_hash(skb, queue, info->queues_total,
-				     par->family, jhash_initval);
+				     xt_family(par), jhash_initval);
 	}
 	return NF_QUEUE_NR(queue);
 }
@@ -98,7 +98,7 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
 			queue = info->queuenum + cpu % info->queues_total;
 		} else {
 			queue = nfqueue_hash(skb, queue, info->queues_total,
-					     par->family, jhash_initval);
+					     xt_family(par), jhash_initval);
 		}
 	}
 
diff --git a/net/netfilter/xt_REDIRECT.c b/net/netfilter/xt_REDIRECT.c
index 03f0b370e178..651dce65a30b 100644
--- a/net/netfilter/xt_REDIRECT.c
+++ b/net/netfilter/xt_REDIRECT.c
@@ -31,7 +31,7 @@
 static unsigned int
 redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 {
-	return nf_nat_redirect_ipv6(skb, par->targinfo, par->hooknum);
+	return nf_nat_redirect_ipv6(skb, par->targinfo, xt_hooknum(par));
 }
 
 static int redirect_tg6_checkentry(const struct xt_tgchk_param *par)
@@ -62,7 +62,7 @@ static int redirect_tg4_check(const struct xt_tgchk_param *par)
 static unsigned int
 redirect_tg4(struct sk_buff *skb, const struct xt_action_param *par)
 {
-	return nf_nat_redirect_ipv4(skb, par->targinfo, par->hooknum);
+	return nf_nat_redirect_ipv4(skb, par->targinfo, xt_hooknum(par));
 }
 
 static struct xt_target redirect_tg_reg[] __read_mostly = {
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 872db2d0e2a9..27241a767f17 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -108,7 +108,7 @@ tcpmss_mangle_packet(struct sk_buff *skb,
 		return -1;
 
 	if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
-		struct net *net = par->net;
+		struct net *net = xt_net(par);
 		unsigned int in_mtu = tcpmss_reverse_mtu(net, skb, family);
 		unsigned int min_mtu = min(dst_mtu(skb_dst(skb)), in_mtu);
 
@@ -172,7 +172,7 @@ tcpmss_mangle_packet(struct sk_buff *skb,
 	 * length IPv6 header of 60, ergo the default MSS value is 1220
 	 * Since no MSS was provided, we must use the default values
 	 */
-	if (par->family == NFPROTO_IPV4)
+	if (xt_family(par) == NFPROTO_IPV4)
 		newmss = min(newmss, (u16)536);
 	else
 		newmss = min(newmss, (u16)1220);
diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c
index 0471db4032c5..1c57ace75ae6 100644
--- a/net/netfilter/xt_TEE.c
+++ b/net/netfilter/xt_TEE.c
@@ -33,7 +33,7 @@ tee_tg4(struct sk_buff *skb, const struct xt_action_param *par)
 	const struct xt_tee_tginfo *info = par->targinfo;
 	int oif = info->priv ? info->priv->oif : 0;
 
-	nf_dup_ipv4(par->net, skb, par->hooknum, &info->gw.in, oif);
+	nf_dup_ipv4(xt_net(par), skb, xt_hooknum(par), &info->gw.in, oif);
 
 	return XT_CONTINUE;
 }
@@ -45,7 +45,7 @@ tee_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 	const struct xt_tee_tginfo *info = par->targinfo;
 	int oif = info->priv ? info->priv->oif : 0;
 
-	nf_dup_ipv6(par->net, skb, par->hooknum, &info->gw.in6, oif);
+	nf_dup_ipv6(xt_net(par), skb, xt_hooknum(par), &info->gw.in6, oif);
 
 	return XT_CONTINUE;
 }
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index 663c4c3c9072..dbd72cc40e42 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -364,7 +364,8 @@ tproxy_tg4_v0(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_tproxy_target_info *tgi = par->targinfo;
 
-	return tproxy_tg4(par->net, skb, tgi->laddr, tgi->lport, tgi->mark_mask, tgi->mark_value);
+	return tproxy_tg4(xt_net(par), skb, tgi->laddr, tgi->lport,
+			  tgi->mark_mask, tgi->mark_value);
 }
 
 static unsigned int
@@ -372,7 +373,8 @@ tproxy_tg4_v1(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_tproxy_target_info_v1 *tgi = par->targinfo;
 
-	return tproxy_tg4(par->net, skb, tgi->laddr.ip, tgi->lport, tgi->mark_mask, tgi->mark_value);
+	return tproxy_tg4(xt_net(par), skb, tgi->laddr.ip, tgi->lport,
+			  tgi->mark_mask, tgi->mark_value);
 }
 
 #ifdef XT_TPROXY_HAVE_IPV6
@@ -442,7 +444,7 @@ tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff,
 		 * to a listener socket if there's one */
 		struct sock *sk2;
 
-		sk2 = nf_tproxy_get_sock_v6(par->net, skb, thoff, hp, tproto,
+		sk2 = nf_tproxy_get_sock_v6(xt_net(par), skb, thoff, hp, tproto,
 					    &iph->saddr,
 					    tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr),
 					    hp->source,
@@ -485,10 +487,10 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
 	 * addresses, this happens if the redirect already happened
 	 * and the current packet belongs to an already established
 	 * connection */
-	sk = nf_tproxy_get_sock_v6(par->net, skb, thoff, hp, tproto,
+	sk = nf_tproxy_get_sock_v6(xt_net(par), skb, thoff, hp, tproto,
 				   &iph->saddr, &iph->daddr,
 				   hp->source, hp->dest,
-				   par->in, NFT_LOOKUP_ESTABLISHED);
+				   xt_in(par), NFT_LOOKUP_ESTABLISHED);
 
 	laddr = tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr);
 	lport = tgi->lport ? tgi->lport : hp->dest;
@@ -500,10 +502,10 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
 	else if (!sk)
 		/* no there's no established connection, check if
 		 * there's a listener on the redirected addr/port */
-		sk = nf_tproxy_get_sock_v6(par->net, skb, thoff, hp,
+		sk = nf_tproxy_get_sock_v6(xt_net(par), skb, thoff, hp,
 					   tproto, &iph->saddr, laddr,
 					   hp->source, lport,
-					   par->in, NFT_LOOKUP_LISTENER);
+					   xt_in(par), NFT_LOOKUP_LISTENER);
 
 	/* NOTE: assign_sock consumes our sk reference */
 	if (sk && tproxy_sk_is_transparent(sk)) {
diff --git a/net/netfilter/xt_addrtype.c b/net/netfilter/xt_addrtype.c
index 11d6091991a4..e329dabde35f 100644
--- a/net/netfilter/xt_addrtype.c
+++ b/net/netfilter/xt_addrtype.c
@@ -125,7 +125,7 @@ static inline bool match_type(struct net *net, const struct net_device *dev,
 static bool
 addrtype_mt_v0(const struct sk_buff *skb, struct xt_action_param *par)
 {
-	struct net *net = par->net;
+	struct net *net = xt_net(par);
 	const struct xt_addrtype_info *info = par->matchinfo;
 	const struct iphdr *iph = ip_hdr(skb);
 	bool ret = true;
@@ -143,19 +143,19 @@ addrtype_mt_v0(const struct sk_buff *skb, struct xt_action_param *par)
 static bool
 addrtype_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
 {
-	struct net *net = par->net;
+	struct net *net = xt_net(par);
 	const struct xt_addrtype_info_v1 *info = par->matchinfo;
 	const struct iphdr *iph;
 	const struct net_device *dev = NULL;
 	bool ret = true;
 
 	if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN)
-		dev = par->in;
+		dev = xt_in(par);
 	else if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT)
-		dev = par->out;
+		dev = xt_out(par);
 
 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
-	if (par->family == NFPROTO_IPV6)
+	if (xt_family(par) == NFPROTO_IPV6)
 		return addrtype_mt6(net, dev, skb, info);
 #endif
 	iph = ip_hdr(skb);
diff --git a/net/netfilter/xt_cluster.c b/net/netfilter/xt_cluster.c
index 96fa26b20b67..9a9884a39c0e 100644
--- a/net/netfilter/xt_cluster.c
+++ b/net/netfilter/xt_cluster.c
@@ -112,7 +112,7 @@ xt_cluster_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	 * know, matches should not alter packets, but we are doing this here
 	 * because we would need to add a PKTTYPE target for this sole purpose.
 	 */
-	if (!xt_cluster_is_multicast_addr(skb, par->family) &&
+	if (!xt_cluster_is_multicast_addr(skb, xt_family(par)) &&
 	    skb->pkt_type == PACKET_MULTICAST) {
 	    	pskb->pkt_type = PACKET_HOST;
 	}
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index b6dc322593a3..bb3845339efd 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -317,7 +317,7 @@ static int count_them(struct net *net,
 static bool
 connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
-	struct net *net = par->net;
+	struct net *net = xt_net(par);
 	const struct xt_connlimit_info *info = par->matchinfo;
 	union nf_inet_addr addr;
 	struct nf_conntrack_tuple tuple;
@@ -332,11 +332,11 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
 		tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
 		zone = nf_ct_zone(ct);
 	} else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
-				      par->family, net, &tuple)) {
+				      xt_family(par), net, &tuple)) {
 		goto hotdrop;
 	}
 
-	if (par->family == NFPROTO_IPV6) {
+	if (xt_family(par) == NFPROTO_IPV6) {
 		const struct ipv6hdr *iph = ipv6_hdr(skb);
 		memcpy(&addr.ip6, (info->flags & XT_CONNLIMIT_DADDR) ?
 		       &iph->daddr : &iph->saddr, sizeof(addr.ip6));
@@ -347,7 +347,7 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	}
 
 	connections = count_them(net, info->data, tuple_ptr, &addr,
-	                         &info->mask, par->family, zone);
+	                         &info->mask, xt_family(par), zone);
 	if (connections == 0)
 		/* kmalloc failed, drop it entirely */
 		goto hotdrop;
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index a3b8f697cfc5..2dea15ebc55b 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -200,22 +200,22 @@ conntrack_mt(const struct sk_buff *skb, struct xt_action_param *par,
 		return false;
 
 	if (info->match_flags & XT_CONNTRACK_ORIGSRC)
-		if (conntrack_mt_origsrc(ct, info, par->family) ^
+		if (conntrack_mt_origsrc(ct, info, xt_family(par)) ^
 		    !(info->invert_flags & XT_CONNTRACK_ORIGSRC))
 			return false;
 
 	if (info->match_flags & XT_CONNTRACK_ORIGDST)
-		if (conntrack_mt_origdst(ct, info, par->family) ^
+		if (conntrack_mt_origdst(ct, info, xt_family(par)) ^
 		    !(info->invert_flags & XT_CONNTRACK_ORIGDST))
 			return false;
 
 	if (info->match_flags & XT_CONNTRACK_REPLSRC)
-		if (conntrack_mt_replsrc(ct, info, par->family) ^
+		if (conntrack_mt_replsrc(ct, info, xt_family(par)) ^
 		    !(info->invert_flags & XT_CONNTRACK_REPLSRC))
 			return false;
 
 	if (info->match_flags & XT_CONNTRACK_REPLDST)
-		if (conntrack_mt_repldst(ct, info, par->family) ^
+		if (conntrack_mt_repldst(ct, info, xt_family(par)) ^
 		    !(info->invert_flags & XT_CONNTRACK_REPLDST))
 			return false;
 
diff --git a/net/netfilter/xt_devgroup.c b/net/netfilter/xt_devgroup.c
index d9202cdd25c9..96ebe1cdefec 100644
--- a/net/netfilter/xt_devgroup.c
+++ b/net/netfilter/xt_devgroup.c
@@ -24,12 +24,12 @@ static bool devgroup_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	const struct xt_devgroup_info *info = par->matchinfo;
 
 	if (info->flags & XT_DEVGROUP_MATCH_SRC &&
-	    (((info->src_group ^ par->in->group) & info->src_mask ? 1 : 0) ^
+	    (((info->src_group ^ xt_in(par)->group) & info->src_mask ? 1 : 0) ^
 	     ((info->flags & XT_DEVGROUP_INVERT_SRC) ? 1 : 0)))
 		return false;
 
 	if (info->flags & XT_DEVGROUP_MATCH_DST &&
-	    (((info->dst_group ^ par->out->group) & info->dst_mask ? 1 : 0) ^
+	    (((info->dst_group ^ xt_out(par)->group) & info->dst_mask ? 1 : 0) ^
 	     ((info->flags & XT_DEVGROUP_INVERT_DST) ? 1 : 0)))
 		return false;
 
diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c
index 64670fc5d0e1..236ac8008909 100644
--- a/net/netfilter/xt_dscp.c
+++ b/net/netfilter/xt_dscp.c
@@ -58,7 +58,7 @@ static bool tos_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
 	const struct xt_tos_match_info *info = par->matchinfo;
 
-	if (par->family == NFPROTO_IPV4)
+	if (xt_family(par) == NFPROTO_IPV4)
 		return ((ip_hdr(skb)->tos & info->tos_mask) ==
 		       info->tos_value) ^ !!info->invert;
 	else
diff --git a/net/netfilter/xt_ipvs.c b/net/netfilter/xt_ipvs.c
index 71a9d95e0a81..0fdc89064488 100644
--- a/net/netfilter/xt_ipvs.c
+++ b/net/netfilter/xt_ipvs.c
@@ -48,9 +48,9 @@ static bool
 ipvs_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
 	const struct xt_ipvs_mtinfo *data = par->matchinfo;
-	struct netns_ipvs *ipvs = net_ipvs(par->net);
+	struct netns_ipvs *ipvs = net_ipvs(xt_net(par));
 	/* ipvs_mt_check ensures that family is only NFPROTO_IPV[46]. */
-	const u_int8_t family = par->family;
+	const u_int8_t family = xt_family(par);
 	struct ip_vs_iphdr iph;
 	struct ip_vs_protocol *pp;
 	struct ip_vs_conn *cp;
diff --git a/net/netfilter/xt_nfacct.c b/net/netfilter/xt_nfacct.c
index cf327593852a..cc0518fe598e 100644
--- a/net/netfilter/xt_nfacct.c
+++ b/net/netfilter/xt_nfacct.c
@@ -26,7 +26,7 @@ static bool nfacct_mt(const struct sk_buff *skb, struct xt_action_param *par)
 
 	nfnl_acct_update(skb, info->nfacct);
 
-	overquota = nfnl_acct_overquota(par->net, skb, info->nfacct);
+	overquota = nfnl_acct_overquota(xt_net(par), skb, info->nfacct);
 
 	return overquota == NFACCT_UNDERQUOTA ? false : true;
 }
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c
index 2455b69b5810..c05fefcec238 100644
--- a/net/netfilter/xt_osf.c
+++ b/net/netfilter/xt_osf.c
@@ -201,7 +201,7 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p)
 	unsigned char opts[MAX_IPOPTLEN];
 	const struct xt_osf_finger *kf;
 	const struct xt_osf_user_finger *f;
-	struct net *net = p->net;
+	struct net *net = xt_net(p);
 
 	if (!info)
 		return false;
@@ -326,8 +326,8 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p)
 		fcount++;
 
 		if (info->flags & XT_OSF_LOG)
-			nf_log_packet(net, p->family, p->hooknum, skb,
-				      p->in, p->out, NULL,
+			nf_log_packet(net, xt_family(p), xt_hooknum(p), skb,
+				      xt_in(p), xt_out(p), NULL,
 				      "%s [%s:%s] : %pI4:%d -> %pI4:%d hops=%d\n",
 				      f->genre, f->version, f->subtype,
 				      &ip->saddr, ntohs(tcp->source),
@@ -341,8 +341,8 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p)
 	rcu_read_unlock();
 
 	if (!fcount && (info->flags & XT_OSF_LOG))
-		nf_log_packet(net, p->family, p->hooknum, skb, p->in,
-			      p->out, NULL,
+		nf_log_packet(net, xt_family(p), xt_hooknum(p), skb, xt_in(p),
+			      xt_out(p), NULL,
 			"Remote OS is not known: %pI4:%u -> %pI4:%u\n",
 				&ip->saddr, ntohs(tcp->source),
 				&ip->daddr, ntohs(tcp->dest));
diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c
index a20e731b5b6c..16477df45b3b 100644
--- a/net/netfilter/xt_owner.c
+++ b/net/netfilter/xt_owner.c
@@ -63,7 +63,7 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	const struct xt_owner_match_info *info = par->matchinfo;
 	const struct file *filp;
 	struct sock *sk = skb_to_full_sk(skb);
-	struct net *net = par->net;
+	struct net *net = xt_net(par);
 
 	if (sk == NULL || sk->sk_socket == NULL)
 		return (info->match ^ info->invert) == 0;
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index 5b645cb598fc..57efb703ff18 100644
--- a/net/netfilter/xt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -30,10 +30,10 @@ pkttype_mt(const struct sk_buff *skb, struct xt_action_param *par)
 
 	if (skb->pkt_type != PACKET_LOOPBACK)
 		type = skb->pkt_type;
-	else if (par->family == NFPROTO_IPV4 &&
+	else if (xt_family(par) == NFPROTO_IPV4 &&
 	    ipv4_is_multicast(ip_hdr(skb)->daddr))
 		type = PACKET_MULTICAST;
-	else if (par->family == NFPROTO_IPV6 &&
+	else if (xt_family(par) == NFPROTO_IPV6 &&
 	    ipv6_hdr(skb)->daddr.s6_addr[0] == 0xFF)
 		type = PACKET_MULTICAST;
 	else
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index f23e97bb42d7..2b4ab189bba7 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -116,9 +116,9 @@ policy_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	int ret;
 
 	if (info->flags & XT_POLICY_MATCH_IN)
-		ret = match_policy_in(skb, info, par->family);
+		ret = match_policy_in(skb, info, xt_family(par));
 	else
-		ret = match_policy_out(skb, info, par->family);
+		ret = match_policy_out(skb, info, xt_family(par));
 
 	if (ret < 0)
 		ret = info->flags & XT_POLICY_MATCH_NONE ? true : false;
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index e3b7a09b103e..bf250000e084 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -236,7 +236,7 @@ static void recent_table_flush(struct recent_table *t)
 static bool
 recent_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
-	struct net *net = par->net;
+	struct net *net = xt_net(par);
 	struct recent_net *recent_net = recent_pernet(net);
 	const struct xt_recent_mtinfo_v1 *info = par->matchinfo;
 	struct recent_table *t;
@@ -245,7 +245,7 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	u_int8_t ttl;
 	bool ret = info->invert;
 
-	if (par->family == NFPROTO_IPV4) {
+	if (xt_family(par) == NFPROTO_IPV4) {
 		const struct iphdr *iph = ip_hdr(skb);
 
 		if (info->side == XT_RECENT_DEST)
@@ -266,7 +266,7 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	}
 
 	/* use TTL as seen before forwarding */
-	if (par->out != NULL && skb->sk == NULL)
+	if (xt_out(par) != NULL && skb->sk == NULL)
 		ttl++;
 
 	spin_lock_bh(&recent_lock);
@@ -274,12 +274,12 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par)
 
 	nf_inet_addr_mask(&addr, &addr_mask, &t->mask);
 
-	e = recent_entry_lookup(t, &addr_mask, par->family,
+	e = recent_entry_lookup(t, &addr_mask, xt_family(par),
 				(info->check_set & XT_RECENT_TTL) ? ttl : 0);
 	if (e == NULL) {
 		if (!(info->check_set & XT_RECENT_SET))
 			goto out;
-		e = recent_entry_init(t, &addr_mask, par->family, ttl);
+		e = recent_entry_init(t, &addr_mask, xt_family(par), ttl);
 		if (e == NULL)
 			par->hotdrop = true;
 		ret = !ret;
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c
index 5669e5b453f4..1bfede7be418 100644
--- a/net/netfilter/xt_set.c
+++ b/net/netfilter/xt_set.c
@@ -55,7 +55,7 @@ set_match_v0(const struct sk_buff *skb, struct xt_action_param *par)
 {
 	const struct xt_set_info_match_v0 *info = par->matchinfo;
 
-	ADT_OPT(opt, par->family, info->match_set.u.compat.dim,
+	ADT_OPT(opt, xt_family(par), info->match_set.u.compat.dim,
 		info->match_set.u.compat.flags, 0, UINT_MAX);
 
 	return match_set(info->match_set.index, skb, par, &opt,
@@ -118,7 +118,7 @@ set_match_v1(const struct sk_buff *skb, struct xt_action_param *par)
 {
 	const struct xt_set_info_match_v1 *info = par->matchinfo;
 
-	ADT_OPT(opt, par->family, info->match_set.dim,
+	ADT_OPT(opt, xt_family(par), info->match_set.dim,
 		info->match_set.flags, 0, UINT_MAX);
 
 	if (opt.flags & IPSET_RETURN_NOMATCH)
@@ -184,7 +184,7 @@ set_match_v3(const struct sk_buff *skb, struct xt_action_param *par)
 	const struct xt_set_info_match_v3 *info = par->matchinfo;
 	int ret;
 
-	ADT_OPT(opt, par->family, info->match_set.dim,
+	ADT_OPT(opt, xt_family(par), info->match_set.dim,
 		info->match_set.flags, info->flags, UINT_MAX);
 
 	if (info->packets.op != IPSET_COUNTER_NONE ||
@@ -231,7 +231,7 @@ set_match_v4(const struct sk_buff *skb, struct xt_action_param *par)
 	const struct xt_set_info_match_v4 *info = par->matchinfo;
 	int ret;
 
-	ADT_OPT(opt, par->family, info->match_set.dim,
+	ADT_OPT(opt, xt_family(par), info->match_set.dim,
 		info->match_set.flags, info->flags, UINT_MAX);
 
 	if (info->packets.op != IPSET_COUNTER_NONE ||
@@ -259,9 +259,9 @@ set_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_set_info_target_v0 *info = par->targinfo;
 
-	ADT_OPT(add_opt, par->family, info->add_set.u.compat.dim,
+	ADT_OPT(add_opt, xt_family(par), info->add_set.u.compat.dim,
 		info->add_set.u.compat.flags, 0, UINT_MAX);
-	ADT_OPT(del_opt, par->family, info->del_set.u.compat.dim,
+	ADT_OPT(del_opt, xt_family(par), info->del_set.u.compat.dim,
 		info->del_set.u.compat.flags, 0, UINT_MAX);
 
 	if (info->add_set.index != IPSET_INVALID_ID)
@@ -332,9 +332,9 @@ set_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_set_info_target_v1 *info = par->targinfo;
 
-	ADT_OPT(add_opt, par->family, info->add_set.dim,
+	ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
 		info->add_set.flags, 0, UINT_MAX);
-	ADT_OPT(del_opt, par->family, info->del_set.dim,
+	ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
 		info->del_set.flags, 0, UINT_MAX);
 
 	if (info->add_set.index != IPSET_INVALID_ID)
@@ -401,9 +401,9 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_set_info_target_v2 *info = par->targinfo;
 
-	ADT_OPT(add_opt, par->family, info->add_set.dim,
+	ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
 		info->add_set.flags, info->flags, info->timeout);
-	ADT_OPT(del_opt, par->family, info->del_set.dim,
+	ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
 		info->del_set.flags, 0, UINT_MAX);
 
 	/* Normalize to fit into jiffies */
@@ -429,11 +429,11 @@ set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
 	const struct xt_set_info_target_v3 *info = par->targinfo;
 	int ret;
 
-	ADT_OPT(add_opt, par->family, info->add_set.dim,
+	ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
 		info->add_set.flags, info->flags, info->timeout);
-	ADT_OPT(del_opt, par->family, info->del_set.dim,
+	ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
 		info->del_set.flags, 0, UINT_MAX);
-	ADT_OPT(map_opt, par->family, info->map_set.dim,
+	ADT_OPT(map_opt, xt_family(par), info->map_set.dim,
 		info->map_set.flags, 0, UINT_MAX);
 
 	/* Normalize to fit into jiffies */
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index b10ade272b50..d1471d0297a5 100644
--- a/net/netfilter/xt_socket.c
+++ b/net/netfilter/xt_socket.c
@@ -217,7 +217,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
 	struct sock *sk = skb->sk;
 
 	if (!sk)
-		sk = xt_socket_lookup_slow_v4(par->net, skb, par->in);
+		sk = xt_socket_lookup_slow_v4(xt_net(par), skb, xt_in(par));
 	if (sk) {
 		bool wildcard;
 		bool transparent = true;
@@ -399,7 +399,7 @@ socket_mt6_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par)
 	struct sock *sk = skb->sk;
 
 	if (!sk)
-		sk = xt_socket_lookup_slow_v6(par->net, skb, par->in);
+		sk = xt_socket_lookup_slow_v6(xt_net(par), skb, xt_in(par));
 	if (sk) {
 		bool wildcard;
 		bool transparent = true;
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 378c1c976058..e0c62fdf1e79 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -213,6 +213,7 @@ static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,
 	int ret = 0, result = 0;
 	struct tcf_ipt *ipt = to_ipt(a);
 	struct xt_action_param par;
+	struct nf_hook_state state;
 
 	if (skb_unclone(skb, GFP_ATOMIC))
 		return TC_ACT_UNSPEC;
@@ -226,13 +227,15 @@ static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,
 	 * worry later - danger - this API seems to have changed
 	 * from earlier kernels
 	 */
-	par.net	     = dev_net(skb->dev);
-	par.in       = skb->dev;
-	par.out      = NULL;
-	par.hooknum  = ipt->tcfi_hook;
+	memset(&state, 0, sizeof(state));
+	state.net    = dev_net(skb->dev);
+	state.in     = skb->dev;
+	state.out    = NULL;
+	state.hook   = ipt->tcfi_hook;
+	state.pf     = NFPROTO_IPV4;
+	par.state    = &state;
 	par.target   = ipt->tcfi_t->u.kernel.target;
 	par.targinfo = ipt->tcfi_t->data;
-	par.family   = NFPROTO_IPV4;
 	ret = par.target->target(skb, &par);
 
 	switch (ret) {
diff --git a/net/sched/em_ipset.c b/net/sched/em_ipset.c
index c66ca9400ab4..6ae59f07d3b3 100644
--- a/net/sched/em_ipset.c
+++ b/net/sched/em_ipset.c
@@ -57,17 +57,20 @@ static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em,
 	struct xt_action_param acpar;
 	const struct xt_set_info *set = (const void *) em->data;
 	struct net_device *dev, *indev = NULL;
+	struct nf_hook_state state;
 	int ret, network_offset;
 
+	memset(&state, 0, sizeof(state));
+
 	switch (tc_skb_protocol(skb)) {
 	case htons(ETH_P_IP):
-		acpar.family = NFPROTO_IPV4;
+		state.pf = NFPROTO_IPV4;
 		if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
 			return 0;
 		acpar.thoff = ip_hdrlen(skb);
 		break;
 	case htons(ETH_P_IPV6):
-		acpar.family = NFPROTO_IPV6;
+		state.pf = NFPROTO_IPV6;
 		if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
 			return 0;
 		/* doesn't call ipv6_find_hdr() because ipset doesn't use thoff, yet */
@@ -77,9 +80,7 @@ static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em,
 		return 0;
 	}
 
-	acpar.hooknum = 0;
-
-	opt.family = acpar.family;
+	opt.family = state.pf;
 	opt.dim = set->dim;
 	opt.flags = set->flags;
 	opt.cmdflags = 0;
@@ -95,9 +96,10 @@ static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em,
 	if (skb->skb_iif)
 		indev = dev_get_by_index_rcu(em->net, skb->skb_iif);
 
-	acpar.net     = em->net;
-	acpar.in      = indev ? indev : dev;
-	acpar.out     = dev;
+	state.net     = em->net;
+	state.in      = indev ? indev : dev;
+	state.out     = dev;
+	acpar.state   = &state;
 
 	ret = ip_set_test(set->index, skb, &acpar, &opt);
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH nf-next,RFC 06/10] netfilter: nf_tables: use hook state from xt_action_param structure
  2016-10-13 12:02 [PATCH nf-next,RFC 00/10] Netfilter core updates Pablo Neira Ayuso
                   ` (4 preceding siblings ...)
  2016-10-13 12:02 ` [PATCH nf-next,RFC 05/10] netfilter: x_tables: move hook state into xt_action_param structure Pablo Neira Ayuso
@ 2016-10-13 12:02 ` Pablo Neira Ayuso
  2016-10-13 12:02 ` [PATCH nf-next,RFC 07/10] netfilter: use switch() to handle verdict cases from nf_hook_slow() Pablo Neira Ayuso
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 12:02 UTC (permalink / raw)
  To: netfilter-devel

Don't copy relevant fields from hook state structure, instead use the
one that is already available in struct xt_action_param.

This patch also adds a set of new wrapper functions to fetch relevant
hook state structure fields.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/net/netfilter/nf_tables.h        | 35 +++++++++++++++++++++++---------
 net/bridge/netfilter/nft_meta_bridge.c   |  2 +-
 net/bridge/netfilter/nft_reject_bridge.c | 30 ++++++++++++++++-----------
 net/ipv4/netfilter/nft_dup_ipv4.c        |  2 +-
 net/ipv4/netfilter/nft_masq_ipv4.c       |  4 ++--
 net/ipv4/netfilter/nft_redir_ipv4.c      |  3 +--
 net/ipv4/netfilter/nft_reject_ipv4.c     |  4 ++--
 net/ipv6/netfilter/nft_dup_ipv6.c        |  2 +-
 net/ipv6/netfilter/nft_masq_ipv6.c       |  3 ++-
 net/ipv6/netfilter/nft_redir_ipv6.c      |  3 ++-
 net/ipv6/netfilter/nft_reject_ipv6.c     |  6 +++---
 net/netfilter/nf_dup_netdev.c            |  2 +-
 net/netfilter/nf_tables_core.c           | 10 ++++-----
 net/netfilter/nf_tables_trace.c          |  8 ++++----
 net/netfilter/nft_log.c                  |  5 +++--
 net/netfilter/nft_lookup.c               |  5 ++---
 net/netfilter/nft_meta.c                 |  6 +++---
 net/netfilter/nft_queue.c                |  2 +-
 net/netfilter/nft_reject_inet.c          | 18 ++++++++--------
 19 files changed, 86 insertions(+), 64 deletions(-)

diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 44060344f958..ba49f21d62ab 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -14,27 +14,42 @@
 
 struct nft_pktinfo {
 	struct sk_buff			*skb;
-	struct net			*net;
-	const struct net_device		*in;
-	const struct net_device		*out;
-	u8				pf;
-	u8				hook;
 	bool				tprot_set;
 	u8				tprot;
 	/* for x_tables compatibility */
 	struct xt_action_param		xt;
 };
 
+static inline struct net *pkt_net(const struct nft_pktinfo *pkt)
+{
+	return pkt->xt.state->net;
+}
+
+static inline unsigned int pkt_hook(const struct nft_pktinfo *pkt)
+{
+	return pkt->xt.state->hook;
+}
+
+static inline u8 pkt_pf(const struct nft_pktinfo *pkt)
+{
+	return pkt->xt.state->pf;
+}
+
+static inline const struct net_device *pkt_in(const struct nft_pktinfo *pkt)
+{
+	return pkt->xt.state->in;
+}
+
+static inline const struct net_device *pkt_out(const struct nft_pktinfo *pkt)
+{
+	return pkt->xt.state->out;
+}
+
 static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
 				   struct sk_buff *skb,
 				   const struct nf_hook_state *state)
 {
 	pkt->skb = skb;
-	pkt->net = state->net;
-	pkt->in = state->in;
-	pkt->out = state->out;
-	pkt->hook = state->hook;
-	pkt->pf = state->pf;
 	pkt->xt.state = state;
 }
 
diff --git a/net/bridge/netfilter/nft_meta_bridge.c b/net/bridge/netfilter/nft_meta_bridge.c
index ad47a921b701..ea72d56d44b9 100644
--- a/net/bridge/netfilter/nft_meta_bridge.c
+++ b/net/bridge/netfilter/nft_meta_bridge.c
@@ -23,7 +23,7 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
 				     const struct nft_pktinfo *pkt)
 {
 	const struct nft_meta *priv = nft_expr_priv(expr);
-	const struct net_device *in = pkt->in, *out = pkt->out;
+	const struct net_device *in = pkt_in(pkt), *out = pkt_out(pkt);
 	u32 *dest = &regs->data[priv->dreg];
 	const struct net_bridge_port *p;
 
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c
index 4b3df6b0e3b9..e8918a8a1511 100644
--- a/net/bridge/netfilter/nft_reject_bridge.c
+++ b/net/bridge/netfilter/nft_reject_bridge.c
@@ -315,17 +315,20 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr,
 	case htons(ETH_P_IP):
 		switch (priv->type) {
 		case NFT_REJECT_ICMP_UNREACH:
-			nft_reject_br_send_v4_unreach(pkt->net, pkt->skb,
-						      pkt->in, pkt->hook,
+			nft_reject_br_send_v4_unreach(pkt_net(pkt), pkt->skb,
+						      pkt_in(pkt),
+						      pkt_hook(pkt),
 						      priv->icmp_code);
 			break;
 		case NFT_REJECT_TCP_RST:
-			nft_reject_br_send_v4_tcp_reset(pkt->net, pkt->skb,
-							pkt->in, pkt->hook);
+			nft_reject_br_send_v4_tcp_reset(pkt_net(pkt), pkt->skb,
+							pkt_in(pkt),
+							pkt_hook(pkt));
 			break;
 		case NFT_REJECT_ICMPX_UNREACH:
-			nft_reject_br_send_v4_unreach(pkt->net, pkt->skb,
-						      pkt->in, pkt->hook,
+			nft_reject_br_send_v4_unreach(pkt_net(pkt), pkt->skb,
+						      pkt_in(pkt),
+						      pkt_hook(pkt),
 						      nft_reject_icmp_code(priv->icmp_code));
 			break;
 		}
@@ -333,17 +336,20 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr,
 	case htons(ETH_P_IPV6):
 		switch (priv->type) {
 		case NFT_REJECT_ICMP_UNREACH:
-			nft_reject_br_send_v6_unreach(pkt->net, pkt->skb,
-						      pkt->in, pkt->hook,
+			nft_reject_br_send_v6_unreach(pkt_net(pkt), pkt->skb,
+						      pkt_in(pkt),
+						      pkt_hook(pkt),
 						      priv->icmp_code);
 			break;
 		case NFT_REJECT_TCP_RST:
-			nft_reject_br_send_v6_tcp_reset(pkt->net, pkt->skb,
-							pkt->in, pkt->hook);
+			nft_reject_br_send_v6_tcp_reset(pkt_net(pkt), pkt->skb,
+							pkt_in(pkt),
+							pkt_hook(pkt));
 			break;
 		case NFT_REJECT_ICMPX_UNREACH:
-			nft_reject_br_send_v6_unreach(pkt->net, pkt->skb,
-						      pkt->in, pkt->hook,
+			nft_reject_br_send_v6_unreach(pkt_net(pkt), pkt->skb,
+						      pkt_in(pkt),
+						      pkt_hook(pkt),
 						      nft_reject_icmpv6_code(priv->icmp_code));
 			break;
 		}
diff --git a/net/ipv4/netfilter/nft_dup_ipv4.c b/net/ipv4/netfilter/nft_dup_ipv4.c
index bf855e64fc45..b277070031cc 100644
--- a/net/ipv4/netfilter/nft_dup_ipv4.c
+++ b/net/ipv4/netfilter/nft_dup_ipv4.c
@@ -30,7 +30,7 @@ static void nft_dup_ipv4_eval(const struct nft_expr *expr,
 	};
 	int oif = regs->data[priv->sreg_dev];
 
-	nf_dup_ipv4(pkt->net, pkt->skb, pkt->hook, &gw, oif);
+	nf_dup_ipv4(pkt_net(pkt), pkt->skb, pkt_hook(pkt), &gw, oif);
 }
 
 static int nft_dup_ipv4_init(const struct nft_ctx *ctx,
diff --git a/net/ipv4/netfilter/nft_masq_ipv4.c b/net/ipv4/netfilter/nft_masq_ipv4.c
index 51ced81b616c..75cc43f9ef66 100644
--- a/net/ipv4/netfilter/nft_masq_ipv4.c
+++ b/net/ipv4/netfilter/nft_masq_ipv4.c
@@ -31,8 +31,8 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr,
 		range.max_proto.all =
 			*(__be16 *)&regs->data[priv->sreg_proto_max];
 	}
-	regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, pkt->hook,
-						    &range, pkt->out);
+	regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, pkt_hook(pkt),
+						    &range, pkt_out(pkt));
 }
 
 static struct nft_expr_type nft_masq_ipv4_type;
diff --git a/net/ipv4/netfilter/nft_redir_ipv4.c b/net/ipv4/netfilter/nft_redir_ipv4.c
index c09d4381427e..de6b46013da4 100644
--- a/net/ipv4/netfilter/nft_redir_ipv4.c
+++ b/net/ipv4/netfilter/nft_redir_ipv4.c
@@ -35,8 +35,7 @@ static void nft_redir_ipv4_eval(const struct nft_expr *expr,
 
 	mr.range[0].flags |= priv->flags;
 
-	regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr,
-						  pkt->hook);
+	regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr, pkt_hook(pkt));
 }
 
 static struct nft_expr_type nft_redir_ipv4_type;
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c
index 2c2553b9026c..4b0d930c9fdb 100644
--- a/net/ipv4/netfilter/nft_reject_ipv4.c
+++ b/net/ipv4/netfilter/nft_reject_ipv4.c
@@ -27,10 +27,10 @@ static void nft_reject_ipv4_eval(const struct nft_expr *expr,
 
 	switch (priv->type) {
 	case NFT_REJECT_ICMP_UNREACH:
-		nf_send_unreach(pkt->skb, priv->icmp_code, pkt->hook);
+		nf_send_unreach(pkt->skb, priv->icmp_code, pkt_hook(pkt));
 		break;
 	case NFT_REJECT_TCP_RST:
-		nf_send_reset(pkt->net, pkt->skb, pkt->hook);
+		nf_send_reset(pkt_net(pkt), pkt->skb, pkt_hook(pkt));
 		break;
 	default:
 		break;
diff --git a/net/ipv6/netfilter/nft_dup_ipv6.c b/net/ipv6/netfilter/nft_dup_ipv6.c
index 8bfd470cbe72..af50ce95cb39 100644
--- a/net/ipv6/netfilter/nft_dup_ipv6.c
+++ b/net/ipv6/netfilter/nft_dup_ipv6.c
@@ -28,7 +28,7 @@ static void nft_dup_ipv6_eval(const struct nft_expr *expr,
 	struct in6_addr *gw = (struct in6_addr *)&regs->data[priv->sreg_addr];
 	int oif = regs->data[priv->sreg_dev];
 
-	nf_dup_ipv6(pkt->net, pkt->skb, pkt->hook, gw, oif);
+	nf_dup_ipv6(pkt_net(pkt), pkt->skb, pkt_hook(pkt), gw, oif);
 }
 
 static int nft_dup_ipv6_init(const struct nft_ctx *ctx,
diff --git a/net/ipv6/netfilter/nft_masq_ipv6.c b/net/ipv6/netfilter/nft_masq_ipv6.c
index 9597ffb74077..f71b03a3172c 100644
--- a/net/ipv6/netfilter/nft_masq_ipv6.c
+++ b/net/ipv6/netfilter/nft_masq_ipv6.c
@@ -32,7 +32,8 @@ static void nft_masq_ipv6_eval(const struct nft_expr *expr,
 		range.max_proto.all =
 			*(__be16 *)&regs->data[priv->sreg_proto_max];
 	}
-	regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out);
+	regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range,
+						    pkt_out(pkt));
 }
 
 static struct nft_expr_type nft_masq_ipv6_type;
diff --git a/net/ipv6/netfilter/nft_redir_ipv6.c b/net/ipv6/netfilter/nft_redir_ipv6.c
index aca44e89a881..281f727a3d02 100644
--- a/net/ipv6/netfilter/nft_redir_ipv6.c
+++ b/net/ipv6/netfilter/nft_redir_ipv6.c
@@ -35,7 +35,8 @@ static void nft_redir_ipv6_eval(const struct nft_expr *expr,
 
 	range.flags |= priv->flags;
 
-	regs->verdict.code = nf_nat_redirect_ipv6(pkt->skb, &range, pkt->hook);
+	regs->verdict.code = nf_nat_redirect_ipv6(pkt->skb, &range,
+						  pkt_hook(pkt));
 }
 
 static struct nft_expr_type nft_redir_ipv6_type;
diff --git a/net/ipv6/netfilter/nft_reject_ipv6.c b/net/ipv6/netfilter/nft_reject_ipv6.c
index 92bda9908bb9..fa80c277e7ba 100644
--- a/net/ipv6/netfilter/nft_reject_ipv6.c
+++ b/net/ipv6/netfilter/nft_reject_ipv6.c
@@ -27,11 +27,11 @@ static void nft_reject_ipv6_eval(const struct nft_expr *expr,
 
 	switch (priv->type) {
 	case NFT_REJECT_ICMP_UNREACH:
-		nf_send_unreach6(pkt->net, pkt->skb, priv->icmp_code,
-				 pkt->hook);
+		nf_send_unreach6(pkt_net(pkt), pkt->skb, priv->icmp_code,
+				 pkt_hook(pkt));
 		break;
 	case NFT_REJECT_TCP_RST:
-		nf_send_reset6(pkt->net, pkt->skb, pkt->hook);
+		nf_send_reset6(pkt_net(pkt), pkt->skb, pkt_hook(pkt));
 		break;
 	default:
 		break;
diff --git a/net/netfilter/nf_dup_netdev.c b/net/netfilter/nf_dup_netdev.c
index 7ec69723940f..e999fafaca8d 100644
--- a/net/netfilter/nf_dup_netdev.c
+++ b/net/netfilter/nf_dup_netdev.c
@@ -19,7 +19,7 @@ void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif)
 	struct net_device *dev;
 	struct sk_buff *skb;
 
-	dev = dev_get_by_index_rcu(pkt->net, oif);
+	dev = dev_get_by_index_rcu(pkt_net(pkt), oif);
 	if (dev == NULL)
 		return;
 
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 0dd5c695482f..27fa3c2dea8a 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -53,10 +53,10 @@ static noinline void __nft_trace_packet(struct nft_traceinfo *info,
 
 	nft_trace_notify(info);
 
-	nf_log_trace(pkt->net, pkt->pf, pkt->hook, pkt->skb, pkt->in,
-		     pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ",
-		     chain->table->name, chain->name, comments[type],
-		     rulenum);
+	nf_log_trace(pkt_net(pkt), pkt_pf(pkt), pkt_hook(pkt), pkt->skb,
+		     pkt_in(pkt), pkt_out(pkt), &trace_loginfo,
+		     "TRACE: %s:%s:%s:%u ",
+		     chain->table->name, chain->name, comments[type], rulenum);
 }
 
 static inline void nft_trace_packet(struct nft_traceinfo *info,
@@ -124,7 +124,7 @@ unsigned int
 nft_do_chain(struct nft_pktinfo *pkt, void *priv)
 {
 	const struct nft_chain *chain = priv, *basechain = chain;
-	const struct net *net = pkt->net;
+	const struct net *net = pkt->xt.state->net;
 	const struct nft_rule *rule;
 	const struct nft_expr *expr, *last;
 	struct nft_regs regs;
diff --git a/net/netfilter/nf_tables_trace.c b/net/netfilter/nf_tables_trace.c
index ab695f8e2d29..5a09f78a6a4f 100644
--- a/net/netfilter/nf_tables_trace.c
+++ b/net/netfilter/nf_tables_trace.c
@@ -171,7 +171,7 @@ void nft_trace_notify(struct nft_traceinfo *info)
 	unsigned int size;
 	int event = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_TRACE;
 
-	if (!nfnetlink_has_listeners(pkt->net, NFNLGRP_NFTRACE))
+	if (!nfnetlink_has_listeners(pkt_net(pkt), NFNLGRP_NFTRACE))
 		return;
 
 	size = nlmsg_total_size(sizeof(struct nfgenmsg)) +
@@ -207,7 +207,7 @@ void nft_trace_notify(struct nft_traceinfo *info)
 	nfmsg->version		= NFNETLINK_V0;
 	nfmsg->res_id		= 0;
 
-	if (nla_put_be32(skb, NFTA_TRACE_NFPROTO, htonl(pkt->pf)))
+	if (nla_put_be32(skb, NFTA_TRACE_NFPROTO, htonl(pkt_pf(pkt))))
 		goto nla_put_failure;
 
 	if (nla_put_be32(skb, NFTA_TRACE_TYPE, htonl(info->type)))
@@ -249,7 +249,7 @@ void nft_trace_notify(struct nft_traceinfo *info)
 		goto nla_put_failure;
 
 	if (!info->packet_dumped) {
-		if (nf_trace_fill_dev_info(skb, pkt->in, pkt->out))
+		if (nf_trace_fill_dev_info(skb, pkt_in(pkt), pkt_out(pkt)))
 			goto nla_put_failure;
 
 		if (nf_trace_fill_pkt_info(skb, pkt))
@@ -258,7 +258,7 @@ void nft_trace_notify(struct nft_traceinfo *info)
 	}
 
 	nlmsg_end(skb, nlh);
-	nfnetlink_send(skb, pkt->net, 0, NFNLGRP_NFTRACE, 0, GFP_ATOMIC);
+	nfnetlink_send(skb, pkt_net(pkt), 0, NFNLGRP_NFTRACE, 0, GFP_ATOMIC);
 	return;
 
  nla_put_failure:
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c
index 1b01404bb33f..3ffff350e6d6 100644
--- a/net/netfilter/nft_log.c
+++ b/net/netfilter/nft_log.c
@@ -32,8 +32,9 @@ static void nft_log_eval(const struct nft_expr *expr,
 {
 	const struct nft_log *priv = nft_expr_priv(expr);
 
-	nf_log_packet(pkt->net, pkt->pf, pkt->hook, pkt->skb, pkt->in,
-		      pkt->out, &priv->loginfo, "%s", priv->prefix);
+	nf_log_packet(pkt_net(pkt), pkt_pf(pkt), pkt_hook(pkt), pkt->skb,
+		      pkt_in(pkt), pkt_out(pkt), &priv->loginfo, "%s",
+		      priv->prefix);
 }
 
 static const struct nla_policy nft_log_policy[NFTA_LOG_MAX + 1] = {
diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c
index 8166b6994cc7..fb36f967609c 100644
--- a/net/netfilter/nft_lookup.c
+++ b/net/netfilter/nft_lookup.c
@@ -35,9 +35,8 @@ static void nft_lookup_eval(const struct nft_expr *expr,
 	const struct nft_set_ext *ext;
 	bool found;
 
-	found = set->ops->lookup(pkt->net, set, &regs->data[priv->sreg], &ext) ^
-		priv->invert;
-
+	found = set->ops->lookup(pkt_net(pkt), set, &regs->data[priv->sreg],
+				 &ext) ^ priv->invert;
 	if (!found) {
 		regs->verdict.code = NFT_BREAK;
 		return;
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 6c1e0246706e..8270e2cc1513 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -36,7 +36,7 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 {
 	const struct nft_meta *priv = nft_expr_priv(expr);
 	const struct sk_buff *skb = pkt->skb;
-	const struct net_device *in = pkt->in, *out = pkt->out;
+	const struct net_device *in = pkt_in(pkt), *out = pkt_out(pkt);
 	struct sock *sk;
 	u32 *dest = &regs->data[priv->dreg];
 
@@ -49,7 +49,7 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 		*(__be16 *)dest = skb->protocol;
 		break;
 	case NFT_META_NFPROTO:
-		*dest = pkt->pf;
+		*dest = pkt_pf(pkt);
 		break;
 	case NFT_META_L4PROTO:
 		if (!pkt->tprot_set)
@@ -146,7 +146,7 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 			break;
 		}
 
-		switch (pkt->pf) {
+		switch (pkt_pf(pkt)) {
 		case NFPROTO_IPV4:
 			if (ipv4_is_multicast(ip_hdr(skb)->daddr))
 				*dest = PACKET_MULTICAST;
diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
index 393d359a1889..f596a1614daa 100644
--- a/net/netfilter/nft_queue.c
+++ b/net/netfilter/nft_queue.c
@@ -43,7 +43,7 @@ static void nft_queue_eval(const struct nft_expr *expr,
 			queue = priv->queuenum + cpu % priv->queues_total;
 		} else {
 			queue = nfqueue_hash(pkt->skb, queue,
-					     priv->queues_total, pkt->pf,
+					     priv->queues_total, pkt_pf(pkt),
 					     jhash_initval);
 		}
 	}
diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c
index e79d9ca2ffee..7c1418755a21 100644
--- a/net/netfilter/nft_reject_inet.c
+++ b/net/netfilter/nft_reject_inet.c
@@ -23,36 +23,36 @@ static void nft_reject_inet_eval(const struct nft_expr *expr,
 {
 	struct nft_reject *priv = nft_expr_priv(expr);
 
-	switch (pkt->pf) {
+	switch (pkt_pf(pkt)) {
 	case NFPROTO_IPV4:
 		switch (priv->type) {
 		case NFT_REJECT_ICMP_UNREACH:
 			nf_send_unreach(pkt->skb, priv->icmp_code,
-					pkt->hook);
+					pkt_hook(pkt));
 			break;
 		case NFT_REJECT_TCP_RST:
-			nf_send_reset(pkt->net, pkt->skb, pkt->hook);
+			nf_send_reset(pkt_net(pkt), pkt->skb, pkt_hook(pkt));
 			break;
 		case NFT_REJECT_ICMPX_UNREACH:
 			nf_send_unreach(pkt->skb,
 					nft_reject_icmp_code(priv->icmp_code),
-					pkt->hook);
+					pkt_hook(pkt));
 			break;
 		}
 		break;
 	case NFPROTO_IPV6:
 		switch (priv->type) {
 		case NFT_REJECT_ICMP_UNREACH:
-			nf_send_unreach6(pkt->net, pkt->skb, priv->icmp_code,
-					 pkt->hook);
+			nf_send_unreach6(pkt_net(pkt), pkt->skb,
+					 priv->icmp_code, pkt_hook(pkt));
 			break;
 		case NFT_REJECT_TCP_RST:
-			nf_send_reset6(pkt->net, pkt->skb, pkt->hook);
+			nf_send_reset6(pkt_net(pkt), pkt->skb, pkt_hook(pkt));
 			break;
 		case NFT_REJECT_ICMPX_UNREACH:
-			nf_send_unreach6(pkt->net, pkt->skb,
+			nf_send_unreach6(pkt_net(pkt), pkt->skb,
 					 nft_reject_icmpv6_code(priv->icmp_code),
-					 pkt->hook);
+					 pkt_hook(pkt));
 			break;
 		}
 		break;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH nf-next,RFC 07/10] netfilter: use switch() to handle verdict cases from nf_hook_slow()
  2016-10-13 12:02 [PATCH nf-next,RFC 00/10] Netfilter core updates Pablo Neira Ayuso
                   ` (5 preceding siblings ...)
  2016-10-13 12:02 ` [PATCH nf-next,RFC 06/10] netfilter: nf_tables: use hook state from " Pablo Neira Ayuso
@ 2016-10-13 12:02 ` Pablo Neira Ayuso
  2016-10-13 12:02 ` [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core Pablo Neira Ayuso
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 12:02 UTC (permalink / raw)
  To: netfilter-devel

Use switch() for verdict handling and add explicit handling for
NF_STOLEN and other non-conventional verdicts.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/core.c | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 2a6ed7d29c6c..2b3b2f8e39c4 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -328,29 +328,37 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
 {
 	struct nf_hook_entry *entry;
 	unsigned int verdict;
-	int ret = 0;
+	int ret;
 
 	entry = rcu_dereference(state->hook_entries);
 next_hook:
 	verdict = nf_iterate(skb, state, &entry);
-	if (verdict == NF_ACCEPT) {
+	switch (verdict & NF_VERDICT_MASK) {
+	case NF_ACCEPT:
 		ret = 1;
-	} else if ((verdict & NF_VERDICT_MASK) == NF_DROP) {
+		break;
+	case NF_DROP:
 		kfree_skb(skb);
 		ret = NF_DROP_GETERR(verdict);
 		if (ret == 0)
 			ret = -EPERM;
-	} else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
-		int err;
-
+		break;
+	case NF_QUEUE:
 		RCU_INIT_POINTER(state->hook_entries, entry);
-		err = nf_queue(skb, state, verdict >> NF_VERDICT_QBITS);
-		if (err < 0) {
-			if (err == -ESRCH &&
-			   (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
+		ret = nf_queue(skb, state, verdict >> NF_VERDICT_QBITS);
+		if (ret < 0) {
+			if (ret == -ESRCH &&
+			    (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
 				goto next_hook;
 			kfree_skb(skb);
 		}
+		/* Fall through. */
+	default:
+		/* Implicit handling for NF_STOLEN, as well as any other non
+		 * conventional verdicts.
+		 */
+		ret = 0;
+		break;
 	}
 	return ret;
 }
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core
  2016-10-13 12:02 [PATCH nf-next,RFC 00/10] Netfilter core updates Pablo Neira Ayuso
                   ` (6 preceding siblings ...)
  2016-10-13 12:02 ` [PATCH nf-next,RFC 07/10] netfilter: use switch() to handle verdict cases from nf_hook_slow() Pablo Neira Ayuso
@ 2016-10-13 12:02 ` Pablo Neira Ayuso
  2016-10-13 12:38   ` Florian Westphal
  2016-10-14  8:06   ` Liping Zhang
  2016-10-13 12:02 ` [PATCH nf-next,RFC 09/10] netfilter: merge nf_iterate() into nf_hook_slow() Pablo Neira Ayuso
  2016-10-13 12:02 ` [PATCH nf-next,RFC 10/10] netfilter: inline nf_hook_slow() and rename it to nf_hook_iterate() Pablo Neira Ayuso
  9 siblings, 2 replies; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 12:02 UTC (permalink / raw)
  To: netfilter-devel

Export a new nf_queue() function that translates the NF_QUEUE verdict
depending on the scenario:

1) Drop packet if queue is full.
2) Accept packet if bypass is enabled.
3) Return stolen if packet is enqueued.

We can call this function from xt_NFQUEUE and nft_queue. Thus, we
move packet queuing to userspace away from the core path.

We still have to handle the old QUEUE standard target for
{ip,ip6}_tables, which points to queue number zero. Just in case we
still have any user relying on this behaviour. No need to handle this
from arp and ebtables, they never got a native queue target.

After this patch, we have to inconditionally set state->hook_entries
before calling the hook since nf_iterate() since we need this to know
from what hook the packet is escaping to userspace in nf_queue.

>From nft_verdict_init(), disallow NF_QUEUE as verdict since we always
use the nft_queue expression for this and we don't have any userspace
code using this since the beginning.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/net/netfilter/nf_queue.h |  3 +++
 net/ipv4/netfilter/arp_tables.c  |  1 +
 net/ipv4/netfilter/ip_tables.c   |  4 ++++
 net/ipv6/netfilter/ip6_tables.c  |  4 ++++
 net/netfilter/core.c             | 14 ++---------
 net/netfilter/nf_internals.h     |  2 --
 net/netfilter/nf_queue.c         | 51 ++++++++++++++++++++++++++--------------
 net/netfilter/nf_tables_api.c    |  3 +--
 net/netfilter/nf_tables_core.c   |  3 +--
 net/netfilter/nft_queue.c        |  6 ++---
 net/netfilter/xt_NFQUEUE.c       | 29 ++++++++++++-----------
 11 files changed, 67 insertions(+), 53 deletions(-)

diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
index 2280cfe86c56..807b9de72b43 100644
--- a/include/net/netfilter/nf_queue.h
+++ b/include/net/netfilter/nf_queue.h
@@ -29,6 +29,9 @@ struct nf_queue_handler {
 
 void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh);
 void nf_unregister_queue_handler(struct net *net);
+
+int nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
+	     unsigned int queuenum, bool bypass);
 void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
 
 void nf_queue_entry_get_refs(struct nf_queue_entry *entry);
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index e76ab23a2deb..83d82f6be8dd 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -28,6 +28,7 @@
 
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_arp/arp_tables.h>
+#include <net/netfilter/nf_queue.h>
 #include "../../netfilter/xt_repldata.h"
 
 MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index de4fa03f46f3..7040842c34f4 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -29,6 +29,7 @@
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <net/netfilter/nf_log.h>
+#include <net/netfilter/nf_queue.h>
 #include "../../netfilter/xt_repldata.h"
 
 MODULE_LICENSE("GPL");
@@ -329,6 +330,9 @@ ipt_do_table(struct sk_buff *skb,
 				/* Pop from stack? */
 				if (v != XT_RETURN) {
 					verdict = (unsigned int)(-v) - 1;
+					if (verdict == NF_QUEUE)
+						verdict = nf_queue(skb, state,
+								   0, false);
 					break;
 				}
 				if (stackidx == 0) {
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 7eac01d5d621..7119daa19ba6 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -33,6 +33,7 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter/x_tables.h>
 #include <net/netfilter/nf_log.h>
+#include <net/netfilter/nf_queue.h>
 #include "../../netfilter/xt_repldata.h"
 
 MODULE_LICENSE("GPL");
@@ -361,6 +362,9 @@ ip6t_do_table(struct sk_buff *skb,
 				/* Pop from stack? */
 				if (v != XT_RETURN) {
 					verdict = (unsigned int)(-v) - 1;
+					if (verdict == NF_QUEUE)
+						verdict = nf_queue(skb, state,
+								   0, false);
 					break;
 				}
 				if (stackidx == 0)
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 2b3b2f8e39c4..9ae2febd86e3 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -309,6 +309,7 @@ unsigned int nf_iterate(struct sk_buff *skb,
 	unsigned int verdict;
 
 	while (*entryp) {
+		RCU_INIT_POINTER(state->hook_entries, *entryp);
 repeat:
 		verdict = (*entryp)->ops.hook((*entryp)->ops.priv, skb, state);
 		if (verdict != NF_ACCEPT) {
@@ -331,9 +332,8 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
 	int ret;
 
 	entry = rcu_dereference(state->hook_entries);
-next_hook:
 	verdict = nf_iterate(skb, state, &entry);
-	switch (verdict & NF_VERDICT_MASK) {
+	switch (verdict) {
 	case NF_ACCEPT:
 		ret = 1;
 		break;
@@ -343,16 +343,6 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
 		if (ret == 0)
 			ret = -EPERM;
 		break;
-	case NF_QUEUE:
-		RCU_INIT_POINTER(state->hook_entries, entry);
-		ret = nf_queue(skb, state, verdict >> NF_VERDICT_QBITS);
-		if (ret < 0) {
-			if (ret == -ESRCH &&
-			    (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
-				goto next_hook;
-			kfree_skb(skb);
-		}
-		/* Fall through. */
 	default:
 		/* Implicit handling for NF_STOLEN, as well as any other non
 		 * conventional verdicts.
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h
index e0adb5959342..de25d7cdfd42 100644
--- a/net/netfilter/nf_internals.h
+++ b/net/netfilter/nf_internals.h
@@ -17,8 +17,6 @@ unsigned int nf_iterate(struct sk_buff *skb, struct nf_hook_state *state,
 			struct nf_hook_entry **entryp);
 
 /* nf_queue.c */
-int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
-	     unsigned int queuenum);
 void nf_queue_nf_hook_drop(struct net *net, const struct nf_hook_entry *entry);
 int __init netfilter_queue_init(void);
 
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index ebb54facd6b5..c97f4e4e25d9 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -111,9 +111,8 @@ void nf_queue_nf_hook_drop(struct net *net, const struct nf_hook_entry *entry)
  * Any packet that leaves via this function must come back
  * through nf_reinject().
  */
-int nf_queue(struct sk_buff *skb,
-	     struct nf_hook_state *state,
-	     unsigned int queuenum)
+static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
+		      unsigned int queuenum)
 {
 	int status = -ENOENT;
 	struct nf_queue_entry *entry = NULL;
@@ -161,6 +160,23 @@ int nf_queue(struct sk_buff *skb,
 	return status;
 }
 
+int nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
+	     unsigned int queuenum, bool bypass)
+{
+	int ret;
+
+	ret = __nf_queue(skb, state, queuenum);
+	if (ret < 0) {
+		if (ret == -ESRCH && bypass)
+			return NF_ACCEPT;
+		kfree_skb(skb);
+		return NF_DROP;
+	}
+
+	return NF_STOLEN;
+}
+EXPORT_SYMBOL_GPL(nf_queue);
+
 void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
 {
 	struct nf_hook_entry *hook_entry;
@@ -169,6 +185,20 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
 	struct nf_hook_ops *elem;
 	int err;
 
+	/* Userspace may request to enqueue this packet again. */
+	if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
+		err = __nf_queue(skb, &entry->state,
+				 verdict >> NF_VERDICT_QBITS);
+		if (err < 0) {
+			if (err != -ESRCH ||
+			   (!(verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))) {
+				kfree_skb(skb);
+				kfree(entry);
+				return;
+			}
+		}
+	}
+
 	hook_entry = rcu_dereference(entry->state.hook_entries);
 	elem = &hook_entry->ops;
 
@@ -186,10 +216,8 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
 
 	hook_entry = rcu_dereference(hook_entry->next);
 
-	if (verdict == NF_ACCEPT) {
-	next_hook:
+	if (verdict == NF_ACCEPT)
 		verdict = nf_iterate(skb, &entry->state, &hook_entry);
-	}
 
 	switch (verdict & NF_VERDICT_MASK) {
 	case NF_ACCEPT:
@@ -198,17 +226,6 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
 		entry->state.okfn(entry->state.net, entry->state.sk, skb);
 		local_bh_enable();
 		break;
-	case NF_QUEUE:
-		RCU_INIT_POINTER(entry->state.hook_entries, hook_entry);
-		err = nf_queue(skb, &entry->state,
-			       verdict >> NF_VERDICT_QBITS);
-		if (err < 0) {
-			if (err == -ESRCH &&
-			   (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
-				goto next_hook;
-			kfree_skb(skb);
-		}
-		break;
 	case NF_STOLEN:
 		break;
 	default:
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index b70d3ea1430e..5402289b9ea8 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -4583,10 +4583,9 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
 
 	switch (data->verdict.code) {
 	default:
-		switch (data->verdict.code & NF_VERDICT_MASK) {
+		switch (data->verdict.code) {
 		case NF_ACCEPT:
 		case NF_DROP:
-		case NF_QUEUE:
 			break;
 		default:
 			return -EINVAL;
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 27fa3c2dea8a..d91fc90bcd4d 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -174,10 +174,9 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
 		break;
 	}
 
-	switch (regs.verdict.code & NF_VERDICT_MASK) {
+	switch (regs.verdict.code) {
 	case NF_ACCEPT:
 	case NF_DROP:
-	case NF_QUEUE:
 		nft_trace_packet(&info, chain, rule,
 				 rulenum, NFT_TRACETYPE_RULE);
 		return regs.verdict.code;
diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
index f596a1614daa..015053a2643d 100644
--- a/net/netfilter/nft_queue.c
+++ b/net/netfilter/nft_queue.c
@@ -48,10 +48,8 @@ static void nft_queue_eval(const struct nft_expr *expr,
 		}
 	}
 
-	ret = NF_QUEUE_NR(queue);
-	if (priv->flags & NFT_QUEUE_FLAG_BYPASS)
-		ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
-
+	ret = nf_queue(pkt->skb, pkt->xt.state, NF_QUEUE_NR(queue),
+		       priv->flags & NFT_QUEUE_FLAG_BYPASS);
 	regs->verdict.code = ret;
 }
 
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index a360b99a958a..f256a4a173fa 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -32,11 +32,12 @@ nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_NFQ_info *tinfo = par->targinfo;
 
-	return NF_QUEUE_NR(tinfo->queuenum);
+	return nf_queue(skb, par->state, tinfo->queuenum, false);
 }
 
-static unsigned int
-nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
+static unsigned int __nf_queue_tg(struct sk_buff *skb,
+				  const struct xt_action_param *par,
+				  bool bypass)
 {
 	const struct xt_NFQ_info_v1 *info = par->targinfo;
 	u32 queue = info->queuenum;
@@ -45,18 +46,22 @@ nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
 		queue = nfqueue_hash(skb, queue, info->queues_total,
 				     xt_family(par), jhash_initval);
 	}
-	return NF_QUEUE_NR(queue);
+
+	return nf_queue(skb, par->state, info->queuenum, bypass);
+}
+
+static unsigned int
+nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	return __nf_queue_tg(skb, par, false);
 }
 
 static unsigned int
 nfqueue_tg_v2(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_NFQ_info_v2 *info = par->targinfo;
-	unsigned int ret = nfqueue_tg_v1(skb, par);
 
-	if (info->bypass)
-		ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
-	return ret;
+	return __nf_queue_tg(skb, par, info->bypass);
 }
 
 static int nfqueue_tg_check(const struct xt_tgchk_param *par)
@@ -89,7 +94,6 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_NFQ_info_v3 *info = par->targinfo;
 	u32 queue = info->queuenum;
-	int ret;
 
 	if (info->queues_total > 1) {
 		if (info->flags & NFQ_FLAG_CPU_FANOUT) {
@@ -102,11 +106,8 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
 		}
 	}
 
-	ret = NF_QUEUE_NR(queue);
-	if (info->flags & NFQ_FLAG_BYPASS)
-		ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
-
-	return ret;
+	return nf_queue(skb, par->state, NF_QUEUE_NR(queue),
+			info->flags & NFQ_FLAG_BYPASS);
 }
 
 static struct xt_target nfqueue_tg_reg[] __read_mostly = {
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH nf-next,RFC 09/10] netfilter: merge nf_iterate() into nf_hook_slow()
  2016-10-13 12:02 [PATCH nf-next,RFC 00/10] Netfilter core updates Pablo Neira Ayuso
                   ` (7 preceding siblings ...)
  2016-10-13 12:02 ` [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core Pablo Neira Ayuso
@ 2016-10-13 12:02 ` Pablo Neira Ayuso
  2016-10-13 12:02 ` [PATCH nf-next,RFC 10/10] netfilter: inline nf_hook_slow() and rename it to nf_hook_iterate() Pablo Neira Ayuso
  9 siblings, 0 replies; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 12:02 UTC (permalink / raw)
  To: netfilter-devel

nf_iterate() has become rather simple, we can integrate this code into
nf_hook_slow() to reduce the amount of LOC in the core path.

However, we still need nf_iterate() around for nf_queue packet handling,
so move this function there where we only need it. I think it should be
possible to refactor nf_queue code to get rid of it definitely, but
given this is slow path anyway, let's have a look this later.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/core.c         | 64 +++++++++++++++++---------------------------
 net/netfilter/nf_internals.h |  5 ----
 net/netfilter/nf_queue.c     | 20 ++++++++++++++
 3 files changed, 45 insertions(+), 44 deletions(-)

diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 9ae2febd86e3..dceb5f92c6a2 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -302,27 +302,6 @@ void _nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
 }
 EXPORT_SYMBOL(_nf_unregister_hooks);
 
-unsigned int nf_iterate(struct sk_buff *skb,
-			struct nf_hook_state *state,
-			struct nf_hook_entry **entryp)
-{
-	unsigned int verdict;
-
-	while (*entryp) {
-		RCU_INIT_POINTER(state->hook_entries, *entryp);
-repeat:
-		verdict = (*entryp)->ops.hook((*entryp)->ops.priv, skb, state);
-		if (verdict != NF_ACCEPT) {
-			if (verdict != NF_REPEAT)
-				return verdict;
-			goto repeat;
-		}
-		*entryp = rcu_dereference((*entryp)->next);
-	}
-	return NF_ACCEPT;
-}
-
-
 /* Returns 1 if okfn() needs to be executed by the caller,
  * -EPERM for NF_DROP, 0 otherwise.  Caller must hold rcu_read_lock. */
 int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
@@ -332,25 +311,32 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
 	int ret;
 
 	entry = rcu_dereference(state->hook_entries);
-	verdict = nf_iterate(skb, state, &entry);
-	switch (verdict) {
-	case NF_ACCEPT:
-		ret = 1;
-		break;
-	case NF_DROP:
-		kfree_skb(skb);
-		ret = NF_DROP_GETERR(verdict);
-		if (ret == 0)
-			ret = -EPERM;
-		break;
-	default:
-		/* Implicit handling for NF_STOLEN, as well as any other non
-		 * conventional verdicts.
-		 */
-		ret = 0;
-		break;
+	while (entry) {
+		RCU_INIT_POINTER(state->hook_entries, entry);
+repeat:
+		verdict = entry->ops.hook(entry->ops.priv, skb, state);
+		switch (verdict) {
+		case NF_ACCEPT:
+			entry = rcu_dereference(entry->next);
+			break;
+		case NF_DROP:
+			kfree_skb(skb);
+			ret = NF_DROP_GETERR(verdict);
+			if (ret == 0)
+				ret = -EPERM;
+
+			return ret;
+		case NF_REPEAT:
+			goto repeat;
+		default:
+			/* Implicit handling for NF_STOLEN, as well as any
+			 * other non conventional verdicts.
+			 */
+			return 0;
+		}
 	}
-	return ret;
+
+	return 1;
 }
 EXPORT_SYMBOL(nf_hook_slow);
 
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h
index de25d7cdfd42..22b4915c48f4 100644
--- a/net/netfilter/nf_internals.h
+++ b/net/netfilter/nf_internals.h
@@ -11,11 +11,6 @@
 #define NFDEBUG(format, args...)
 #endif
 
-
-/* core.c */
-unsigned int nf_iterate(struct sk_buff *skb, struct nf_hook_state *state,
-			struct nf_hook_entry **entryp);
-
 /* nf_queue.c */
 void nf_queue_nf_hook_drop(struct net *net, const struct nf_hook_entry *entry);
 int __init netfilter_queue_init(void);
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index c97f4e4e25d9..2b5429c969d5 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -177,6 +177,26 @@ int nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
 }
 EXPORT_SYMBOL_GPL(nf_queue);
 
+static unsigned int nf_iterate(struct sk_buff *skb,
+			       struct nf_hook_state *state,
+			       struct nf_hook_entry **entryp)
+{
+	unsigned int verdict;
+
+	while (*entryp) {
+		RCU_INIT_POINTER(state->hook_entries, *entryp);
+repeat:
+		verdict = (*entryp)->ops.hook((*entryp)->ops.priv, skb, state);
+		if (verdict != NF_ACCEPT) {
+			if (verdict != NF_REPEAT)
+				return verdict;
+			goto repeat;
+		}
+		*entryp = rcu_dereference((*entryp)->next);
+	}
+	return NF_ACCEPT;
+}
+
 void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
 {
 	struct nf_hook_entry *hook_entry;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH nf-next,RFC 10/10] netfilter: inline nf_hook_slow() and rename it to nf_hook_iterate()
  2016-10-13 12:02 [PATCH nf-next,RFC 00/10] Netfilter core updates Pablo Neira Ayuso
                   ` (8 preceding siblings ...)
  2016-10-13 12:02 ` [PATCH nf-next,RFC 09/10] netfilter: merge nf_iterate() into nf_hook_slow() Pablo Neira Ayuso
@ 2016-10-13 12:02 ` Pablo Neira Ayuso
  9 siblings, 0 replies; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 12:02 UTC (permalink / raw)
  To: netfilter-devel

Now that this function has become smaller, inline it and use a better
name to describe what this is doing.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/linux/netfilter.h         | 41 +++++++++++++++++++++++++++++++++++++--
 include/linux/netfilter_ingress.h |  2 +-
 net/bridge/br_netfilter_hooks.c   |  4 ++--
 net/netfilter/core.c              | 39 -------------------------------------
 4 files changed, 42 insertions(+), 44 deletions(-)

diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index e0d000f6c9bf..d0beb6072e14 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -150,7 +150,44 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg);
 extern struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
 #endif
 
-int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state);
+/* Returns 1 if okfn() needs to be executed by the caller,
+ * -EPERM for NF_DROP, 0 otherwise.  Caller must hold rcu_read_lock.
+ */
+static inline int nf_hook_iterate(struct sk_buff *skb,
+				  struct nf_hook_state *state)
+{
+	struct nf_hook_entry *entry;
+	unsigned int verdict;
+	int ret;
+
+	entry = rcu_dereference(state->hook_entries);
+	while (entry) {
+		RCU_INIT_POINTER(state->hook_entries, entry);
+repeat:
+		verdict = entry->ops.hook(entry->ops.priv, skb, state);
+		switch (verdict) {
+		case NF_ACCEPT:
+			entry = rcu_dereference(entry->next);
+			break;
+		case NF_DROP:
+			kfree_skb(skb);
+			ret = NF_DROP_GETERR(verdict);
+			if (ret == 0)
+				ret = -EPERM;
+
+			return ret;
+		case NF_REPEAT:
+			goto repeat;
+		default:
+			/* Implicit handling for NF_STOLEN, as well as any
+			 * other non conventional verdicts.
+			 */
+			return 0;
+		}
+	}
+
+	return 1;
+}
 
 /**
  *	nf_hook - call a netfilter hook
@@ -182,7 +219,7 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net,
 		nf_hook_state_init(&state, hook_head, hook, pf, indev, outdev,
 				   sk, net, okfn);
 
-		ret = nf_hook_slow(skb, &state);
+		ret = nf_hook_iterate(skb, &state);
 	}
 	rcu_read_unlock();
 
diff --git a/include/linux/netfilter_ingress.h b/include/linux/netfilter_ingress.h
index fd44e4131710..c7056a1f9d36 100644
--- a/include/linux/netfilter_ingress.h
+++ b/include/linux/netfilter_ingress.h
@@ -29,7 +29,7 @@ static inline int nf_hook_ingress(struct sk_buff *skb)
 	nf_hook_state_init(&state, e, NF_NETDEV_INGRESS,
 			   NFPROTO_NETDEV, skb->dev, NULL, NULL,
 			   dev_net(skb->dev), NULL);
-	return nf_hook_slow(skb, &state);
+	return nf_hook_iterate(skb, &state);
 }
 
 static inline void nf_hook_ingress_init(struct net_device *dev)
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index 7e3645fa6339..d153925ec9ec 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -992,7 +992,7 @@ static struct notifier_block brnf_notifier __read_mostly = {
 	.notifier_call = brnf_device_event,
 };
 
-/* recursively invokes nf_hook_slow (again), skipping already-called
+/* recursively invokes nf_hook_iterate (again), skipping already-called
  * hooks (< NF_BR_PRI_BRNF).
  *
  * Called with rcu read lock held.
@@ -1021,7 +1021,7 @@ int br_nf_hook_thresh(unsigned int hook, struct net *net,
 	nf_hook_state_init(&state, elem, hook, NFPROTO_BRIDGE, indev, outdev,
 			   sk, net, okfn);
 
-	ret = nf_hook_slow(skb, &state);
+	ret = nf_hook_iterate(skb, &state);
 	rcu_read_unlock();
 	if (ret == 1)
 		ret = okfn(net, sk, skb);
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index dceb5f92c6a2..5cf941571ecd 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -302,45 +302,6 @@ void _nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
 }
 EXPORT_SYMBOL(_nf_unregister_hooks);
 
-/* Returns 1 if okfn() needs to be executed by the caller,
- * -EPERM for NF_DROP, 0 otherwise.  Caller must hold rcu_read_lock. */
-int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
-{
-	struct nf_hook_entry *entry;
-	unsigned int verdict;
-	int ret;
-
-	entry = rcu_dereference(state->hook_entries);
-	while (entry) {
-		RCU_INIT_POINTER(state->hook_entries, entry);
-repeat:
-		verdict = entry->ops.hook(entry->ops.priv, skb, state);
-		switch (verdict) {
-		case NF_ACCEPT:
-			entry = rcu_dereference(entry->next);
-			break;
-		case NF_DROP:
-			kfree_skb(skb);
-			ret = NF_DROP_GETERR(verdict);
-			if (ret == 0)
-				ret = -EPERM;
-
-			return ret;
-		case NF_REPEAT:
-			goto repeat;
-		default:
-			/* Implicit handling for NF_STOLEN, as well as any
-			 * other non conventional verdicts.
-			 */
-			return 0;
-		}
-	}
-
-	return 1;
-}
-EXPORT_SYMBOL(nf_hook_slow);
-
-
 int skb_make_writable(struct sk_buff *skb, unsigned int writable_len)
 {
 	if (writable_len > skb->len)
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH nf-next,RFC 03/10] netfilter: bridge: kill NF_HOOK_THRESH() and state->tresh
  2016-10-13 12:02 ` [PATCH nf-next,RFC 03/10] netfilter: bridge: kill NF_HOOK_THRESH() and state->tresh Pablo Neira Ayuso
@ 2016-10-13 12:25   ` Florian Westphal
  2016-10-13 15:01     ` Pablo Neira Ayuso
  0 siblings, 1 reply; 26+ messages in thread
From: Florian Westphal @ 2016-10-13 12:25 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> Patch c5136b15ea36 ("netfilter: bridge: add and use br_nf_hook_thresh")
> introduced br_nf_hook_thresh().
> 
> Replace NF_HOOK_THRESH() by br_nf_hook_thresh from
> br_nf_forward_finish(), so we have no more callers for this macro.
> 
> As a result, state->thresh and explicit thresh parameter in the hook
> state structure is not required anymore.
> 
> And we can get rid of fast forward code in nf_iterate() in the core path
> that is only used by br_netfilter to search for the filter hook.

Note that you will need to move more parts of nf_hook_slow() into
br_nf_hook_thresh(); the bridge netfilter does need to thresh feature
that we have in nf_iterate().


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core
  2016-10-13 12:02 ` [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core Pablo Neira Ayuso
@ 2016-10-13 12:38   ` Florian Westphal
  2016-10-13 15:04     ` Pablo Neira Ayuso
  2016-10-14  8:06   ` Liping Zhang
  1 sibling, 1 reply; 26+ messages in thread
From: Florian Westphal @ 2016-10-13 12:38 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> Export a new nf_queue() function that translates the NF_QUEUE verdict
> depending on the scenario:
> 
> 1) Drop packet if queue is full.
> 2) Accept packet if bypass is enabled.
> 3) Return stolen if packet is enqueued.
> 
> We can call this function from xt_NFQUEUE and nft_queue. Thus, we
> move packet queuing to userspace away from the core path.
> 
> We still have to handle the old QUEUE standard target for
> {ip,ip6}_tables, which points to queue number zero. Just in case we
> still have any user relying on this behaviour. No need to handle this
> from arp and ebtables, they never got a native queue target.
> 
> After this patch, we have to inconditionally set state->hook_entries
> before calling the hook since nf_iterate() since we need this to know
> from what hook the packet is escaping to userspace in nf_queue.
> 
> From nft_verdict_init(), disallow NF_QUEUE as verdict since we always
> use the nft_queue expression for this and we don't have any userspace
> code using this since the beginning.
> 
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> ---
>  include/net/netfilter/nf_queue.h |  3 +++
>  net/ipv4/netfilter/arp_tables.c  |  1 +
>  net/ipv4/netfilter/ip_tables.c   |  4 ++++
>  net/ipv6/netfilter/ip6_tables.c  |  4 ++++
>  net/netfilter/core.c             | 14 ++---------
>  net/netfilter/nf_internals.h     |  2 --
>  net/netfilter/nf_queue.c         | 51 ++++++++++++++++++++++++++--------------
>  net/netfilter/nf_tables_api.c    |  3 +--
>  net/netfilter/nf_tables_core.c   |  3 +--
>  net/netfilter/nft_queue.c        |  6 ++---
>  net/netfilter/xt_NFQUEUE.c       | 29 ++++++++++++-----------
>  11 files changed, 67 insertions(+), 53 deletions(-)
> 
> diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
> index 2280cfe86c56..807b9de72b43 100644
> --- a/include/net/netfilter/nf_queue.h
> +++ b/include/net/netfilter/nf_queue.h
> @@ -29,6 +29,9 @@ struct nf_queue_handler {
>  
>  void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh);
>  void nf_unregister_queue_handler(struct net *net);
> +
> +int nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
> +	     unsigned int queuenum, bool bypass);
>  void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
>  
>  void nf_queue_entry_get_refs(struct nf_queue_entry *entry);
> diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
> index e76ab23a2deb..83d82f6be8dd 100644
> --- a/net/ipv4/netfilter/arp_tables.c
> +++ b/net/ipv4/netfilter/arp_tables.c
> @@ -28,6 +28,7 @@
>  
>  #include <linux/netfilter/x_tables.h>
>  #include <linux/netfilter_arp/arp_tables.h>
> +#include <net/netfilter/nf_queue.h>
>  #include "../../netfilter/xt_repldata.h"
>  
>  MODULE_LICENSE("GPL");

This include looks unneeded.

> diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
> index de4fa03f46f3..7040842c34f4 100644
> --- a/net/ipv4/netfilter/ip_tables.c
> +++ b/net/ipv4/netfilter/ip_tables.c
> @@ -29,6 +29,7 @@
>  #include <linux/netfilter/x_tables.h>
>  #include <linux/netfilter_ipv4/ip_tables.h>
>  #include <net/netfilter/nf_log.h>
> +#include <net/netfilter/nf_queue.h>
>  #include "../../netfilter/xt_repldata.h"
>  
>  MODULE_LICENSE("GPL");
> @@ -329,6 +330,9 @@ ipt_do_table(struct sk_buff *skb,
>  				/* Pop from stack? */
>  				if (v != XT_RETURN) {
>  					verdict = (unsigned int)(-v) - 1;
> +					if (verdict == NF_QUEUE)
> +						verdict = nf_queue(skb, state,
> +								   0, false);

Any reason why this is needed?
AFAICS xt_NFQUEUE will never return NF_QUEUE after this patch.

> diff --git a/net/netfilter/core.c b/net/netfilter/core.c
> index 2b3b2f8e39c4..9ae2febd86e3 100644
> --- a/net/netfilter/core.c
> +++ b/net/netfilter/core.c
> @@ -309,6 +309,7 @@ unsigned int nf_iterate(struct sk_buff *skb,
>  	unsigned int verdict;
>  
>  	while (*entryp) {
> +		RCU_INIT_POINTER(state->hook_entries, *entryp);
>  repeat:
>  		verdict = (*entryp)->ops.hook((*entryp)->ops.priv, skb, state);
>  		if (verdict != NF_ACCEPT) {
> @@ -331,9 +332,8 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
>  	int ret;
>  
>  	entry = rcu_dereference(state->hook_entries);
> -next_hook:
>  	verdict = nf_iterate(skb, state, &entry);
> -	switch (verdict & NF_VERDICT_MASK) {
> +	switch (verdict) {

This looks buggy, verdict might encode errno for NF_DROP case.

What you could do is:

switch (verdict) {
case NF_ACCEPT:
       	/* something */
	break;
case NF_STOLEN:
	break;
case NF_DROP: /* fallthrough */
default: /* drop with error? */
	kfree_skb(skb);
	errno = ...
}


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH nf-next,RFC 03/10] netfilter: bridge: kill NF_HOOK_THRESH() and state->tresh
  2016-10-13 12:25   ` Florian Westphal
@ 2016-10-13 15:01     ` Pablo Neira Ayuso
  2016-10-13 15:10       ` Florian Westphal
  0 siblings, 1 reply; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 15:01 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netfilter-devel

On Thu, Oct 13, 2016 at 02:25:45PM +0200, Florian Westphal wrote:
> Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > Patch c5136b15ea36 ("netfilter: bridge: add and use br_nf_hook_thresh")
> > introduced br_nf_hook_thresh().
> > 
> > Replace NF_HOOK_THRESH() by br_nf_hook_thresh from
> > br_nf_forward_finish(), so we have no more callers for this macro.
> > 
> > As a result, state->thresh and explicit thresh parameter in the hook
> > state structure is not required anymore.
> > 
> > And we can get rid of fast forward code in nf_iterate() in the core path
> > that is only used by br_netfilter to search for the filter hook.
> 
> Note that you will need to move more parts of nf_hook_slow() into
> br_nf_hook_thresh(); the bridge netfilter does need to thresh feature
> that we have in nf_iterate().

br_nf_hook_thresh() is already skipping hooks before NF_BR_PRI_BRNF to
emulate thresh. What else is missing?

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core
  2016-10-13 12:38   ` Florian Westphal
@ 2016-10-13 15:04     ` Pablo Neira Ayuso
  2016-10-13 15:09       ` Florian Westphal
  0 siblings, 1 reply; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 15:04 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netfilter-devel

On Thu, Oct 13, 2016 at 02:38:21PM +0200, Florian Westphal wrote:
> Pablo Neira Ayuso <pablo@netfilter.org> wrote:
[...]
> > diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
> > index de4fa03f46f3..7040842c34f4 100644
> > --- a/net/ipv4/netfilter/ip_tables.c
> > +++ b/net/ipv4/netfilter/ip_tables.c
> > @@ -29,6 +29,7 @@
> >  #include <linux/netfilter/x_tables.h>
> >  #include <linux/netfilter_ipv4/ip_tables.h>
> >  #include <net/netfilter/nf_log.h>
> > +#include <net/netfilter/nf_queue.h>
> >  #include "../../netfilter/xt_repldata.h"
> >  
> >  MODULE_LICENSE("GPL");
> > @@ -329,6 +330,9 @@ ipt_do_table(struct sk_buff *skb,
> >  				/* Pop from stack? */
> >  				if (v != XT_RETURN) {
> >  					verdict = (unsigned int)(-v) - 1;
> > +					if (verdict == NF_QUEUE)
> > +						verdict = nf_queue(skb, state,
> > +								   0, false);
> 
> Any reason why this is needed?
> AFAICS xt_NFQUEUE will never return NF_QUEUE after this patch.

-j QUEUE uses the standard target to return NF_QUEUE. This is very
primitive way to queue packets to userspace queue 0 via nf_queue, but
still may break. I can place this under unlikely() as these days
people should be using NFQUEUE instead.

> > diff --git a/net/netfilter/core.c b/net/netfilter/core.c
> > index 2b3b2f8e39c4..9ae2febd86e3 100644
> > --- a/net/netfilter/core.c
> > +++ b/net/netfilter/core.c
> > @@ -309,6 +309,7 @@ unsigned int nf_iterate(struct sk_buff *skb,
> >  	unsigned int verdict;
> >  
> >  	while (*entryp) {
> > +		RCU_INIT_POINTER(state->hook_entries, *entryp);
> >  repeat:
> >  		verdict = (*entryp)->ops.hook((*entryp)->ops.priv, skb, state);
> >  		if (verdict != NF_ACCEPT) {
> > @@ -331,9 +332,8 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state)
> >  	int ret;
> >  
> >  	entry = rcu_dereference(state->hook_entries);
> > -next_hook:
> >  	verdict = nf_iterate(skb, state, &entry);
> > -	switch (verdict & NF_VERDICT_MASK) {
> > +	switch (verdict) {
> 
> This looks buggy, verdict might encode errno for NF_DROP case.
> 
> What you could do is:
> 
> switch (verdict) {
> case NF_ACCEPT:
>        	/* something */
> 	break;
> case NF_STOLEN:
> 	break;
> case NF_DROP: /* fallthrough */
> default: /* drop with error? */
> 	kfree_skb(skb);
> 	errno = ...
> }

Right, will fix this, thanks. 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core
  2016-10-13 15:04     ` Pablo Neira Ayuso
@ 2016-10-13 15:09       ` Florian Westphal
  0 siblings, 0 replies; 26+ messages in thread
From: Florian Westphal @ 2016-10-13 15:09 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter-devel

Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > Any reason why this is needed?
> > AFAICS xt_NFQUEUE will never return NF_QUEUE after this patch.
> 
> -j QUEUE uses the standard target to return NF_QUEUE. This is very
> primitive way to queue packets to userspace queue 0 via nf_queue, but
> still may break. I can place this under unlikely() as these days
> people should be using NFQUEUE instead.

No need, just add a comment that this handles legacy standard target
QUEUE (i forgot we still have this).

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH nf-next,RFC 03/10] netfilter: bridge: kill NF_HOOK_THRESH() and state->tresh
  2016-10-13 15:01     ` Pablo Neira Ayuso
@ 2016-10-13 15:10       ` Florian Westphal
  2016-10-13 15:21         ` Pablo Neira Ayuso
  0 siblings, 1 reply; 26+ messages in thread
From: Florian Westphal @ 2016-10-13 15:10 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter-devel

Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> On Thu, Oct 13, 2016 at 02:25:45PM +0200, Florian Westphal wrote:
> > Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > > Patch c5136b15ea36 ("netfilter: bridge: add and use br_nf_hook_thresh")
> > > introduced br_nf_hook_thresh().
> > > 
> > > Replace NF_HOOK_THRESH() by br_nf_hook_thresh from
> > > br_nf_forward_finish(), so we have no more callers for this macro.
> > > 
> > > As a result, state->thresh and explicit thresh parameter in the hook
> > > state structure is not required anymore.
> > > 
> > > And we can get rid of fast forward code in nf_iterate() in the core path
> > > that is only used by br_netfilter to search for the filter hook.
> > 
> > Note that you will need to move more parts of nf_hook_slow() into
> > br_nf_hook_thresh(); the bridge netfilter does need to thresh feature
> > that we have in nf_iterate().
> 
> br_nf_hook_thresh() is already skipping hooks before NF_BR_PRI_BRNF to
> emulate thresh. What else is missing?

AFAICS you are removing the NF_BR_PRI_BRNF skipping in this patch,
it relied on nf_hook_slow to do this (plus the state->thresh thing).

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH nf-next,RFC 03/10] netfilter: bridge: kill NF_HOOK_THRESH() and state->tresh
  2016-10-13 15:10       ` Florian Westphal
@ 2016-10-13 15:21         ` Pablo Neira Ayuso
  2016-10-13 15:25           ` Florian Westphal
  0 siblings, 1 reply; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 15:21 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netfilter-devel

On Thu, Oct 13, 2016 at 05:10:55PM +0200, Florian Westphal wrote:
> Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > On Thu, Oct 13, 2016 at 02:25:45PM +0200, Florian Westphal wrote:
> > > Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > > > Patch c5136b15ea36 ("netfilter: bridge: add and use br_nf_hook_thresh")
> > > > introduced br_nf_hook_thresh().
> > > > 
> > > > Replace NF_HOOK_THRESH() by br_nf_hook_thresh from
> > > > br_nf_forward_finish(), so we have no more callers for this macro.
> > > > 
> > > > As a result, state->thresh and explicit thresh parameter in the hook
> > > > state structure is not required anymore.
> > > > 
> > > > And we can get rid of fast forward code in nf_iterate() in the core path
> > > > that is only used by br_netfilter to search for the filter hook.
> > > 
> > > Note that you will need to move more parts of nf_hook_slow() into
> > > br_nf_hook_thresh(); the bridge netfilter does need to thresh feature
> > > that we have in nf_iterate().
> > 
> > br_nf_hook_thresh() is already skipping hooks before NF_BR_PRI_BRNF to
> > emulate thresh. What else is missing?
> 
> AFAICS you are removing the NF_BR_PRI_BRNF skipping in this patch,
> it relied on nf_hook_slow to do this (plus the state->thresh thing).

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_entry *elem;
        struct nf_hook_state state;
        int ret;

        elem = rcu_dereference(net->nf.hooks[NFPROTO_BRIDGE][hook]);

        while (elem && (elem->ops.priority <= NF_BR_PRI_BRNF))
                elem = rcu_dereference(elem->next);

        ...

        nf_hook_state_init(&state, elem, hook, NFPROTO_BRIDGE, indev, ...

Hm, but this code (before actually calling nf_hook_slow) is skipping
the hook until we get to NF_BR_PRI_BRNF + 1.

Then hook state sets hook_entry to elem.

Am I missing anything?

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH nf-next,RFC 03/10] netfilter: bridge: kill NF_HOOK_THRESH() and state->tresh
  2016-10-13 15:21         ` Pablo Neira Ayuso
@ 2016-10-13 15:25           ` Florian Westphal
  0 siblings, 0 replies; 26+ messages in thread
From: Florian Westphal @ 2016-10-13 15:25 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter-devel

Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> 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_entry *elem;
>         struct nf_hook_state state;
>         int ret;
> 
>         elem = rcu_dereference(net->nf.hooks[NFPROTO_BRIDGE][hook]);
> 
>         while (elem && (elem->ops.priority <= NF_BR_PRI_BRNF))
>                 elem = rcu_dereference(elem->next);
> 
>         ...
> 
>         nf_hook_state_init(&state, elem, hook, NFPROTO_BRIDGE, indev, ...
> 
> Hm, but this code (before actually calling nf_hook_slow) is skipping
> the hook until we get to NF_BR_PRI_BRNF + 1.
> 
> Then hook state sets hook_entry to elem.
> 
> Am I missing anything?

Yes, I'm a moron -- Ignore.  I'll turn off the computer now.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core
  2016-10-13 12:02 ` [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core Pablo Neira Ayuso
  2016-10-13 12:38   ` Florian Westphal
@ 2016-10-14  8:06   ` Liping Zhang
  2016-10-14  9:53     ` Pablo Neira Ayuso
  1 sibling, 1 reply; 26+ messages in thread
From: Liping Zhang @ 2016-10-14  8:06 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Netfilter Developer Mailing List

Hi Pablo,

2016-10-13 20:02 GMT+08:00 Pablo Neira Ayuso <pablo@netfilter.org>:
> +int nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
> +            unsigned int queuenum, bool bypass)
> +{
> +       int ret;
> +
> +       ret = __nf_queue(skb, state, queuenum);
> +       if (ret < 0) {
> +               if (ret == -ESRCH && bypass)
> +                       return NF_ACCEPT;
> +               kfree_skb(skb);
> +               return NF_DROP;
> +       }
> +
> +       return NF_STOLEN;

I think this will break something ... Imagine such situation:
# ip route add default dev eth0
# ip rule add fwmark 0x1/0xf lookup eth1
# ip rule add fwmark 0x2/0xf lookup eth2
# iptables -t mangle -A OUTPUT -d 1.1.1.1 -j MARK --set-mark 0x1
# iptables -t mangle -A OUTPUT -d 2.2.2.2 -j MARK --set-mark 0x2
# iptables -t mangle -A OUTPUT -j NFQUEUE

So ip packets with dst 1.1.1.1 will be sent via eth1, ip packets with
dst 2.2.2.2 will be sent via eth2 ...

But apply this patch, after queue the packet with dst 1.1.1.1 to the
userspace and reinject it to the kernel, the packet will be sent via
the wrong interface, i.e. eth0 not eth1.

Because ret is *NF_STOLEN* so we will not call ip_route_me_harder
to do re-route in ipt_mangle_out().

> diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
> index f596a1614daa..015053a2643d 100644
> --- a/net/netfilter/nft_queue.c
> +++ b/net/netfilter/nft_queue.c
> @@ -48,10 +48,8 @@ static void nft_queue_eval(const struct nft_expr *expr,
>                 }
>         }
>
> -       ret = NF_QUEUE_NR(queue);
> -       if (priv->flags & NFT_QUEUE_FLAG_BYPASS)
> -               ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
> -
> +       ret = nf_queue(pkt->skb, pkt->xt.state, NF_QUEUE_NR(queue),
> +                      priv->flags & NFT_QUEUE_FLAG_BYPASS);
>         regs->verdict.code = ret;
>  }

I think here we forget to use nf_queue() in nft_queue_sreg_eval().

And in nfnl_userspace_cthelper(), such conversion was missed also.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core
  2016-10-14  8:06   ` Liping Zhang
@ 2016-10-14  9:53     ` Pablo Neira Ayuso
  2016-10-14 10:28       ` Pablo Neira Ayuso
  2016-10-14 15:38       ` Florian Westphal
  0 siblings, 2 replies; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-14  9:53 UTC (permalink / raw)
  To: Liping Zhang; +Cc: Netfilter Developer Mailing List

On Fri, Oct 14, 2016 at 04:06:15PM +0800, Liping Zhang wrote:
> Hi Pablo,
>
> 2016-10-13 20:02 GMT+08:00 Pablo Neira Ayuso <pablo@netfilter.org>:
> > +int nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
> > +            unsigned int queuenum, bool bypass)
> > +{
> > +       int ret;
> > +
> > +       ret = __nf_queue(skb, state, queuenum);
> > +       if (ret < 0) {
> > +               if (ret == -ESRCH && bypass)
> > +                       return NF_ACCEPT;
> > +               kfree_skb(skb);
> > +               return NF_DROP;
> > +       }
> > +
> > +       return NF_STOLEN;
>
> I think this will break something ... Imagine such situation:
> # ip route add default dev eth0
> # ip rule add fwmark 0x1/0xf lookup eth1
> # ip rule add fwmark 0x2/0xf lookup eth2
> # iptables -t mangle -A OUTPUT -d 1.1.1.1 -j MARK --set-mark 0x1
> # iptables -t mangle -A OUTPUT -d 2.2.2.2 -j MARK --set-mark 0x2
> # iptables -t mangle -A OUTPUT -j NFQUEUE
>
> So ip packets with dst 1.1.1.1 will be sent via eth1, ip packets with
> dst 2.2.2.2 will be sent via eth2 ...
>
> But apply this patch, after queue the packet with dst 1.1.1.1 to the
> userspace and reinject it to the kernel, the packet will be sent via
> the wrong interface, i.e. eth0 not eth1.
>
> Because ret is *NF_STOLEN* so we will not call ip_route_me_harder
> to do re-route in ipt_mangle_out().

Good point. Then, we can just return NF_QUEUE here instead, which
would become sort of an alias of NF_STOLEN, but this now just signals
the core that the packet was enqueued to userspace. I mean:

int nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
            unsigned int queuenum, bool bypass)
{
       int ret;

       ret = __nf_queue(skb, state, queuenum);
       if (ret < 0) {
               if (ret == -ESRCH && bypass)
                       return NF_ACCEPT;
               kfree_skb(skb);
               return NF_DROP;
       }

       return NF_QUEUE; <--- this.
}

BTW, looking at ipt_mangle_out():

        ret = ipt_do_table(skb, state, state->net->ipv4.iptable_mangle);
        /* Reroute for ANY change. */
        if (ret != NF_DROP && ret != NF_STOLEN) {
                iph = ip_hdr(skb);

                if (iph->saddr != saddr ||
                    iph->daddr != daddr ||
                    skb->mark != mark ||
                    iph->tos != tos) {
                        err = ip_route_me_harder(state->net, skb, RTN_UNSPEC);
                        if (err < 0)
                                ret = NF_DROP_ERR(err);
                }
        }

It seems that we're triggering an expensive re-reroute for dropped
packets from the mangle table, since ret != NF_DROP evaluates false
given the errno number is encoded in the most significant 16 bits.

> > diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
> > index f596a1614daa..015053a2643d 100644
> > --- a/net/netfilter/nft_queue.c
> > +++ b/net/netfilter/nft_queue.c
> > @@ -48,10 +48,8 @@ static void nft_queue_eval(const struct nft_expr *expr,
> >                 }
> >         }
> >
> > -       ret = NF_QUEUE_NR(queue);
> > -       if (priv->flags & NFT_QUEUE_FLAG_BYPASS)
> > -               ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
> > -
> > +       ret = nf_queue(pkt->skb, pkt->xt.state, NF_QUEUE_NR(queue),
> > +                      priv->flags & NFT_QUEUE_FLAG_BYPASS);
> >         regs->verdict.code = ret;
> >  }
>
> I think here we forget to use nf_queue() in nft_queue_sreg_eval().
>
> And in nfnl_userspace_cthelper(), such conversion was missed also.

Right, thanks, will fix up this spot too.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core
  2016-10-14  9:53     ` Pablo Neira Ayuso
@ 2016-10-14 10:28       ` Pablo Neira Ayuso
  2016-10-14 15:38       ` Florian Westphal
  1 sibling, 0 replies; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-14 10:28 UTC (permalink / raw)
  To: Liping Zhang; +Cc: Netfilter Developer Mailing List

On Fri, Oct 14, 2016 at 11:53:30AM +0200, Pablo Neira Ayuso wrote:
[...] 
> BTW, looking at ipt_mangle_out():
> 
>         ret = ipt_do_table(skb, state, state->net->ipv4.iptable_mangle);
>         /* Reroute for ANY change. */
>         if (ret != NF_DROP && ret != NF_STOLEN) {
>                 iph = ip_hdr(skb);
> 
>                 if (iph->saddr != saddr ||
>                     iph->daddr != daddr ||
>                     skb->mark != mark ||
>                     iph->tos != tos) {
>                         err = ip_route_me_harder(state->net, skb, RTN_UNSPEC);
>                         if (err < 0)
>                                 ret = NF_DROP_ERR(err);
>                 }
>         }
> 
> It seems that we're triggering an expensive re-reroute for dropped
> packets from the mangle table, since ret != NF_DROP evaluates false
> given the errno number is encoded in the most significant 16 bits.

Forget this, we never see errno at this stage, so this is fine.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core
  2016-10-14  9:53     ` Pablo Neira Ayuso
  2016-10-14 10:28       ` Pablo Neira Ayuso
@ 2016-10-14 15:38       ` Florian Westphal
  2016-10-14 16:47         ` Pablo Neira Ayuso
  1 sibling, 1 reply; 26+ messages in thread
From: Florian Westphal @ 2016-10-14 15:38 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Liping Zhang, Netfilter Developer Mailing List

Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> On Fri, Oct 14, 2016 at 04:06:15PM +0800, Liping Zhang wrote:
> > Hi Pablo,
> >
> > 2016-10-13 20:02 GMT+08:00 Pablo Neira Ayuso <pablo@netfilter.org>:
> > > +int nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
> > > +            unsigned int queuenum, bool bypass)
> > > +{
> > > +       int ret;
> > > +
> > > +       ret = __nf_queue(skb, state, queuenum);
> > > +       if (ret < 0) {
> > > +               if (ret == -ESRCH && bypass)
> > > +                       return NF_ACCEPT;
> > > +               kfree_skb(skb);
> > > +               return NF_DROP;
> > > +       }
> > > +
> > > +       return NF_STOLEN;
> >
> > I think this will break something ... Imagine such situation:
> > # ip route add default dev eth0
> > # ip rule add fwmark 0x1/0xf lookup eth1
> > # ip rule add fwmark 0x2/0xf lookup eth2
> > # iptables -t mangle -A OUTPUT -d 1.1.1.1 -j MARK --set-mark 0x1
> > # iptables -t mangle -A OUTPUT -d 2.2.2.2 -j MARK --set-mark 0x2
> > # iptables -t mangle -A OUTPUT -j NFQUEUE
> >
> > So ip packets with dst 1.1.1.1 will be sent via eth1, ip packets with
> > dst 2.2.2.2 will be sent via eth2 ...
> >
> > But apply this patch, after queue the packet with dst 1.1.1.1 to the
> > userspace and reinject it to the kernel, the packet will be sent via
> > the wrong interface, i.e. eth0 not eth1.
> >
> > Because ret is *NF_STOLEN* so we will not call ip_route_me_harder
> > to do re-route in ipt_mangle_out().
> 
> Good point. Then, we can just return NF_QUEUE here instead, which
> would become sort of an alias of NF_STOLEN, but this now just signals
> the core that the packet was enqueued to userspace. I mean:
> 
> int nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
>             unsigned int queuenum, bool bypass)
> {
>        int ret;
> 
>        ret = __nf_queue(skb, state, queuenum);
>        if (ret < 0) {
>                if (ret == -ESRCH && bypass)
>                        return NF_ACCEPT;
>                kfree_skb(skb);
>                return NF_DROP;
>        }
> 
>        return NF_QUEUE; <--- this.
> }

I'm afraid that won't fly.  When This NF_QUEUE is returned here, we're
in a race as skb is already on its way to userspace (or perhaps already
being reinjected/dropped on other cpu).

I think the simplest way out is to always re-route from nf_reinject
in case we were queued from mangle output.

For nft, we might be able to make a note of 'route' chain type in the
nf_hook_state and then have nf_reinject check for that.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core
  2016-10-14 15:38       ` Florian Westphal
@ 2016-10-14 16:47         ` Pablo Neira Ayuso
  2016-10-14 17:22           ` Pablo Neira Ayuso
  0 siblings, 1 reply; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-14 16:47 UTC (permalink / raw)
  To: Florian Westphal; +Cc: Liping Zhang, Netfilter Developer Mailing List

On Fri, Oct 14, 2016 at 05:38:12PM +0200, Florian Westphal wrote:
> Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > On Fri, Oct 14, 2016 at 04:06:15PM +0800, Liping Zhang wrote:
> > > Hi Pablo,
> > >
> > > 2016-10-13 20:02 GMT+08:00 Pablo Neira Ayuso <pablo@netfilter.org>:
> > > > +int nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
> > > > +            unsigned int queuenum, bool bypass)
> > > > +{
> > > > +       int ret;
> > > > +
> > > > +       ret = __nf_queue(skb, state, queuenum);
> > > > +       if (ret < 0) {
> > > > +               if (ret == -ESRCH && bypass)
> > > > +                       return NF_ACCEPT;
> > > > +               kfree_skb(skb);
> > > > +               return NF_DROP;
> > > > +       }
> > > > +
> > > > +       return NF_STOLEN;
> > >
> > > I think this will break something ... Imagine such situation:
> > > # ip route add default dev eth0
> > > # ip rule add fwmark 0x1/0xf lookup eth1
> > > # ip rule add fwmark 0x2/0xf lookup eth2
> > > # iptables -t mangle -A OUTPUT -d 1.1.1.1 -j MARK --set-mark 0x1
> > > # iptables -t mangle -A OUTPUT -d 2.2.2.2 -j MARK --set-mark 0x2
> > > # iptables -t mangle -A OUTPUT -j NFQUEUE
> > >
> > > So ip packets with dst 1.1.1.1 will be sent via eth1, ip packets with
> > > dst 2.2.2.2 will be sent via eth2 ...
> > >
> > > But apply this patch, after queue the packet with dst 1.1.1.1 to the
> > > userspace and reinject it to the kernel, the packet will be sent via
> > > the wrong interface, i.e. eth0 not eth1.
> > >
> > > Because ret is *NF_STOLEN* so we will not call ip_route_me_harder
> > > to do re-route in ipt_mangle_out().
> > 
> > Good point. Then, we can just return NF_QUEUE here instead, which
> > would become sort of an alias of NF_STOLEN, but this now just signals
> > the core that the packet was enqueued to userspace. I mean:
> > 
> > int nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
> >             unsigned int queuenum, bool bypass)
> > {
> >        int ret;
> > 
> >        ret = __nf_queue(skb, state, queuenum);
> >        if (ret < 0) {
> >                if (ret == -ESRCH && bypass)
> >                        return NF_ACCEPT;
> >                kfree_skb(skb);
> >                return NF_DROP;
> >        }
> > 
> >        return NF_QUEUE; <--- this.
> > }
> 
> I'm afraid that won't fly.  When This NF_QUEUE is returned here, we're
> in a race as skb is already on its way to userspace (or perhaps already
> being reinjected/dropped on other cpu).
> 
> I think the simplest way out is to always re-route from nf_reinject
> in case we were queued from mangle output.
> 
> For nft, we might be able to make a note of 'route' chain type in the
> nf_hook_state and then have nf_reinject check for that.

Hm, we already have afinfo->saveroute() and afinfo->reroute() handling
from nf_queue() and nf_reinject() respectively, so returning NF_STOLEN
(as originally proposed) should be fine.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core
  2016-10-14 16:47         ` Pablo Neira Ayuso
@ 2016-10-14 17:22           ` Pablo Neira Ayuso
  0 siblings, 0 replies; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-14 17:22 UTC (permalink / raw)
  To: Florian Westphal; +Cc: Liping Zhang, Netfilter Developer Mailing List

On Fri, Oct 14, 2016 at 06:47:20PM +0200, Pablo Neira Ayuso wrote:
> On Fri, Oct 14, 2016 at 05:38:12PM +0200, Florian Westphal wrote:
> > Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > > On Fri, Oct 14, 2016 at 04:06:15PM +0800, Liping Zhang wrote:
> > > > Hi Pablo,
> > > >
> > > > 2016-10-13 20:02 GMT+08:00 Pablo Neira Ayuso <pablo@netfilter.org>:
> > > > > +int nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
> > > > > +            unsigned int queuenum, bool bypass)
> > > > > +{
> > > > > +       int ret;
> > > > > +
> > > > > +       ret = __nf_queue(skb, state, queuenum);
> > > > > +       if (ret < 0) {
> > > > > +               if (ret == -ESRCH && bypass)
> > > > > +                       return NF_ACCEPT;
> > > > > +               kfree_skb(skb);
> > > > > +               return NF_DROP;
> > > > > +       }
> > > > > +
> > > > > +       return NF_STOLEN;
> > > >
> > > > I think this will break something ... Imagine such situation:
> > > > # ip route add default dev eth0
> > > > # ip rule add fwmark 0x1/0xf lookup eth1
> > > > # ip rule add fwmark 0x2/0xf lookup eth2
> > > > # iptables -t mangle -A OUTPUT -d 1.1.1.1 -j MARK --set-mark 0x1
> > > > # iptables -t mangle -A OUTPUT -d 2.2.2.2 -j MARK --set-mark 0x2
> > > > # iptables -t mangle -A OUTPUT -j NFQUEUE
> > > >
> > > > So ip packets with dst 1.1.1.1 will be sent via eth1, ip packets with
> > > > dst 2.2.2.2 will be sent via eth2 ...
> > > >
> > > > But apply this patch, after queue the packet with dst 1.1.1.1 to the
> > > > userspace and reinject it to the kernel, the packet will be sent via
> > > > the wrong interface, i.e. eth0 not eth1.
> > > >
> > > > Because ret is *NF_STOLEN* so we will not call ip_route_me_harder
> > > > to do re-route in ipt_mangle_out().
> > > 
> > > Good point. Then, we can just return NF_QUEUE here instead, which
> > > would become sort of an alias of NF_STOLEN, but this now just signals
> > > the core that the packet was enqueued to userspace. I mean:
> > > 
> > > int nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
> > >             unsigned int queuenum, bool bypass)
> > > {
> > >        int ret;
> > > 
> > >        ret = __nf_queue(skb, state, queuenum);
> > >        if (ret < 0) {
> > >                if (ret == -ESRCH && bypass)
> > >                        return NF_ACCEPT;
> > >                kfree_skb(skb);
> > >                return NF_DROP;
> > >        }
> > > 
> > >        return NF_QUEUE; <--- this.
> > > }
> > 
> > I'm afraid that won't fly.  When This NF_QUEUE is returned here, we're
> > in a race as skb is already on its way to userspace (or perhaps already
> > being reinjected/dropped on other cpu).
> > 
> > I think the simplest way out is to always re-route from nf_reinject
> > in case we were queued from mangle output.
> > 
> > For nft, we might be able to make a note of 'route' chain type in the
> > nf_hook_state and then have nf_reinject check for that.
> 
> Hm, we already have afinfo->saveroute() and afinfo->reroute() handling
> from nf_queue() and nf_reinject() respectively, so returning NF_STOLEN
> (as originally proposed) should be fine.

Oh I see, but this doesn't cover Liping's usecase above, since the
mark would not be updated from nfqueue userspace application.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH nf-next,RFC 00/10] Netfilter core updates
@ 2016-10-13 12:11 Pablo Neira Ayuso
  0 siblings, 0 replies; 26+ messages in thread
From: Pablo Neira Ayuso @ 2016-10-13 12:11 UTC (permalink / raw)
  To: netfilter-devel

Hi,

This is a quick RFC that has passed just very basic testing here. This
patchset achieves what it has been discussed during NetDev 1.2:

1) Deprecate NF_STOP, as this is only used by br_netfilter.

2) Remove threshold handling, this is also only used by br_netfilter
   too.

3) Move NF_QUEUE handling away from the core. Adds a new nf_queue()
   function that must be explicitly called to queue packets to userspace.
   This function returns the verdict that is passed down to the core,
   basically NF_DROP if queue is full, NF_ACCEPT if bypass is enabled
   and NF_STOLEN if packet is succesfully enqueued to userspace.

4) Merge nf_iterate() into nf_hook_slow(), then inline the resulting
   function and rename it to nf_hook_iterate().

This patchset also modifies the pktinfo and xt_action_param structures
(that keep context around while performing packet processing) to store
the netfilter hook state. This change was required by the new NF_QUEUE
handling. As side effect, according to pahole, these two now fit into
one single cacheline after this update.

Feedback welcome, thanks!

Pablo Neira Ayuso (10):
  netfilter: get rid of useless debugging from core
  netfilter: remove comments that predate rcu days
  netfilter: bridge: kill NF_HOOK_THRESH() and state->tresh
  netfilter: deprecate NF_STOP
  netfilter: x_tables: move hook state into xt_action_param structure
  netfilter: nf_tables: use hook state from xt_action_param structure
  netfilter: use switch() to handle verdict cases from nf_hook_slow()
  netfilter: move NF_QUEUE handling away from core
  netfilter: merge nf_iterate() into nf_hook_slow()
  netfilter: inline nf_hook_slow() and rename it to nf_hook_iterate()

 include/linux/netfilter.h                  | 91 +++++++++++++++++-------------
 include/linux/netfilter/x_tables.h         | 48 ++++++++++++----
 include/linux/netfilter_ingress.h          |  4 +-
 include/net/netfilter/nf_queue.h           |  3 +
 include/net/netfilter/nf_tables.h          | 36 ++++++++----
 include/uapi/linux/netfilter.h             |  2 +-
 net/bridge/br_netfilter_hooks.c            | 18 +++---
 net/bridge/netfilter/ebt_arpreply.c        |  3 +-
 net/bridge/netfilter/ebt_log.c             | 11 ++--
 net/bridge/netfilter/ebt_nflog.c           |  6 +-
 net/bridge/netfilter/ebt_redirect.c        |  6 +-
 net/bridge/netfilter/ebtable_broute.c      |  2 +-
 net/bridge/netfilter/ebtables.c            |  6 +-
 net/bridge/netfilter/nft_meta_bridge.c     |  2 +-
 net/bridge/netfilter/nft_reject_bridge.c   | 30 ++++++----
 net/ipv4/netfilter/arp_tables.c            |  7 +--
 net/ipv4/netfilter/ip_tables.c             | 10 ++--
 net/ipv4/netfilter/ipt_MASQUERADE.c        |  3 +-
 net/ipv4/netfilter/ipt_REJECT.c            |  4 +-
 net/ipv4/netfilter/ipt_SYNPROXY.c          |  4 +-
 net/ipv4/netfilter/ipt_rpfilter.c          |  2 +-
 net/ipv4/netfilter/nft_dup_ipv4.c          |  2 +-
 net/ipv4/netfilter/nft_masq_ipv4.c         |  4 +-
 net/ipv4/netfilter/nft_redir_ipv4.c        |  3 +-
 net/ipv4/netfilter/nft_reject_ipv4.c       |  4 +-
 net/ipv6/netfilter/ip6_tables.c            | 10 ++--
 net/ipv6/netfilter/ip6t_MASQUERADE.c       |  2 +-
 net/ipv6/netfilter/ip6t_REJECT.c           | 23 +++++---
 net/ipv6/netfilter/ip6t_SYNPROXY.c         |  4 +-
 net/ipv6/netfilter/ip6t_rpfilter.c         |  3 +-
 net/ipv6/netfilter/nft_dup_ipv6.c          |  2 +-
 net/ipv6/netfilter/nft_masq_ipv6.c         |  3 +-
 net/ipv6/netfilter/nft_redir_ipv6.c        |  3 +-
 net/ipv6/netfilter/nft_reject_ipv6.c       |  6 +-
 net/netfilter/core.c                       | 75 ------------------------
 net/netfilter/ipset/ip_set_core.c          |  6 +-
 net/netfilter/ipset/ip_set_hash_netiface.c |  2 +-
 net/netfilter/nf_dup_netdev.c              |  2 +-
 net/netfilter/nf_internals.h               |  7 ---
 net/netfilter/nf_queue.c                   | 72 +++++++++++++++++------
 net/netfilter/nf_tables_api.c              |  3 +-
 net/netfilter/nf_tables_core.c             | 13 ++---
 net/netfilter/nf_tables_trace.c            |  8 +--
 net/netfilter/nft_log.c                    |  5 +-
 net/netfilter/nft_lookup.c                 |  5 +-
 net/netfilter/nft_meta.c                   |  6 +-
 net/netfilter/nft_queue.c                  |  8 +--
 net/netfilter/nft_reject_inet.c            | 18 +++---
 net/netfilter/xt_AUDIT.c                   | 10 ++--
 net/netfilter/xt_LOG.c                     |  6 +-
 net/netfilter/xt_NETMAP.c                  | 20 +++----
 net/netfilter/xt_NFLOG.c                   |  6 +-
 net/netfilter/xt_NFQUEUE.c                 | 33 +++++------
 net/netfilter/xt_REDIRECT.c                |  4 +-
 net/netfilter/xt_TCPMSS.c                  |  4 +-
 net/netfilter/xt_TEE.c                     |  4 +-
 net/netfilter/xt_TPROXY.c                  | 16 +++---
 net/netfilter/xt_addrtype.c                | 10 ++--
 net/netfilter/xt_cluster.c                 |  2 +-
 net/netfilter/xt_connlimit.c               |  8 +--
 net/netfilter/xt_conntrack.c               |  8 +--
 net/netfilter/xt_devgroup.c                |  4 +-
 net/netfilter/xt_dscp.c                    |  2 +-
 net/netfilter/xt_ipvs.c                    |  4 +-
 net/netfilter/xt_nfacct.c                  |  2 +-
 net/netfilter/xt_osf.c                     | 10 ++--
 net/netfilter/xt_owner.c                   |  2 +-
 net/netfilter/xt_pkttype.c                 |  4 +-
 net/netfilter/xt_policy.c                  |  4 +-
 net/netfilter/xt_recent.c                  | 10 ++--
 net/netfilter/xt_set.c                     | 26 ++++-----
 net/netfilter/xt_socket.c                  |  4 +-
 net/sched/act_ipt.c                        | 13 +++--
 net/sched/em_ipset.c                       | 18 +++---
 74 files changed, 430 insertions(+), 401 deletions(-)

-- 
2.1.4


^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2016-10-14 17:22 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-13 12:02 [PATCH nf-next,RFC 00/10] Netfilter core updates Pablo Neira Ayuso
2016-10-13 12:02 ` [PATCH nf-next,RFC 01/10] netfilter: get rid of useless debugging from core Pablo Neira Ayuso
2016-10-13 12:02 ` [PATCH nf-next,RFC 02/10] netfilter: remove comments that predate rcu days Pablo Neira Ayuso
2016-10-13 12:02 ` [PATCH nf-next,RFC 03/10] netfilter: bridge: kill NF_HOOK_THRESH() and state->tresh Pablo Neira Ayuso
2016-10-13 12:25   ` Florian Westphal
2016-10-13 15:01     ` Pablo Neira Ayuso
2016-10-13 15:10       ` Florian Westphal
2016-10-13 15:21         ` Pablo Neira Ayuso
2016-10-13 15:25           ` Florian Westphal
2016-10-13 12:02 ` [PATCH nf-next,RFC 04/10] netfilter: deprecate NF_STOP Pablo Neira Ayuso
2016-10-13 12:02 ` [PATCH nf-next,RFC 05/10] netfilter: x_tables: move hook state into xt_action_param structure Pablo Neira Ayuso
2016-10-13 12:02 ` [PATCH nf-next,RFC 06/10] netfilter: nf_tables: use hook state from " Pablo Neira Ayuso
2016-10-13 12:02 ` [PATCH nf-next,RFC 07/10] netfilter: use switch() to handle verdict cases from nf_hook_slow() Pablo Neira Ayuso
2016-10-13 12:02 ` [PATCH nf-next,RFC 08/10] netfilter: move NF_QUEUE handling away from core Pablo Neira Ayuso
2016-10-13 12:38   ` Florian Westphal
2016-10-13 15:04     ` Pablo Neira Ayuso
2016-10-13 15:09       ` Florian Westphal
2016-10-14  8:06   ` Liping Zhang
2016-10-14  9:53     ` Pablo Neira Ayuso
2016-10-14 10:28       ` Pablo Neira Ayuso
2016-10-14 15:38       ` Florian Westphal
2016-10-14 16:47         ` Pablo Neira Ayuso
2016-10-14 17:22           ` Pablo Neira Ayuso
2016-10-13 12:02 ` [PATCH nf-next,RFC 09/10] netfilter: merge nf_iterate() into nf_hook_slow() Pablo Neira Ayuso
2016-10-13 12:02 ` [PATCH nf-next,RFC 10/10] netfilter: inline nf_hook_slow() and rename it to nf_hook_iterate() Pablo Neira Ayuso
2016-10-13 12:11 [PATCH nf-next,RFC 00/10] Netfilter core updates Pablo Neira Ayuso

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.