* [PATCH nf-next,RFC 1/5] netfilter: Clean up unnecessary #ifdef
2019-10-31 13:41 [PATCH nf-next,RFC 0/5] Netfilter egress hook Lukas Wunner
@ 2019-10-31 13:41 ` Lukas Wunner
2019-10-31 13:41 ` [PATCH nf-next,RFC 2/5] netfilter: Document ingress hook Lukas Wunner
` (4 subsequent siblings)
5 siblings, 0 replies; 12+ messages in thread
From: Lukas Wunner @ 2019-10-31 13:41 UTC (permalink / raw)
To: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal
Cc: netfilter-devel, coreteam, netdev, Martin Mares, Daniel Borkmann
If CONFIG_NETFILTER_INGRESS is not enabled, nf_ingress() becomes a no-op
because it solely contains an if-clause calling nf_hook_ingress_active(),
for which an empty inline stub exists in <linux/netfilter_ingress.h>.
All the symbols used in the if-clause's body are still available even if
CONFIG_NETFILTER_INGRESS is not enabled.
The additional "#ifdef CONFIG_NETFILTER_INGRESS" in nf_ingress() is thus
unnecessary, so drop it.
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
net/core/dev.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 74f593986524..e555a8656c47 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5013,7 +5013,6 @@ static bool skb_pfmemalloc_protocol(struct sk_buff *skb)
static inline int nf_ingress(struct sk_buff *skb, struct packet_type **pt_prev,
int *ret, struct net_device *orig_dev)
{
-#ifdef CONFIG_NETFILTER_INGRESS
if (nf_hook_ingress_active(skb)) {
int ingress_retval;
@@ -5027,7 +5026,6 @@ static inline int nf_ingress(struct sk_buff *skb, struct packet_type **pt_prev,
rcu_read_unlock();
return ingress_retval;
}
-#endif /* CONFIG_NETFILTER_INGRESS */
return 0;
}
--
2.23.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH nf-next,RFC 2/5] netfilter: Document ingress hook
2019-10-31 13:41 [PATCH nf-next,RFC 0/5] Netfilter egress hook Lukas Wunner
2019-10-31 13:41 ` [PATCH nf-next,RFC 1/5] netfilter: Clean up unnecessary #ifdef Lukas Wunner
@ 2019-10-31 13:41 ` Lukas Wunner
2019-10-31 13:41 ` [PATCH nf-next,RFC 3/5] netfilter: Rename ingress hook include file Lukas Wunner
` (3 subsequent siblings)
5 siblings, 0 replies; 12+ messages in thread
From: Lukas Wunner @ 2019-10-31 13:41 UTC (permalink / raw)
To: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal
Cc: netfilter-devel, coreteam, netdev, Martin Mares, Daniel Borkmann
Amend kerneldoc of struct net_device to fix a "make htmldocs" warning:
include/linux/netdevice.h:2045: warning: Function parameter or member 'nf_hooks_ingress' not described in 'net_device'
Reported-by: kbuild test robot <lkp@intel.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
include/linux/netdevice.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3207e0b9ec4e..bc6914ea3faf 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1701,6 +1701,7 @@ enum netdev_priv_flags {
* @miniq_ingress: ingress/clsact qdisc specific data for
* ingress processing
* @ingress_queue: XXX: need comments on this one
+ * @nf_hooks_ingress: netfilter hooks executed for ingress packets
* @broadcast: hw bcast address
*
* @rx_cpu_rmap: CPU reverse-mapping for RX completion interrupts,
--
2.23.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH nf-next,RFC 3/5] netfilter: Rename ingress hook include file
2019-10-31 13:41 [PATCH nf-next,RFC 0/5] Netfilter egress hook Lukas Wunner
2019-10-31 13:41 ` [PATCH nf-next,RFC 1/5] netfilter: Clean up unnecessary #ifdef Lukas Wunner
2019-10-31 13:41 ` [PATCH nf-next,RFC 2/5] netfilter: Document ingress hook Lukas Wunner
@ 2019-10-31 13:41 ` Lukas Wunner
2019-10-31 13:41 ` [PATCH nf-next,RFC 4/5] netfilter: Generalize ingress hook Lukas Wunner
` (2 subsequent siblings)
5 siblings, 0 replies; 12+ messages in thread
From: Lukas Wunner @ 2019-10-31 13:41 UTC (permalink / raw)
To: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal
Cc: netfilter-devel, coreteam, netdev, Martin Mares, Daniel Borkmann
Prepare for addition of a netfilter egress hook by renaming
<linux/netfilter_ingress.h> to <linux/netfilter_netdev.h>.
The egress hook also necessitates a refactoring of the include file,
but that is done in a separate commit to ease reviewing.
No functional change intended.
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
include/linux/{netfilter_ingress.h => netfilter_netdev.h} | 0
net/core/dev.c | 2 +-
2 files changed, 1 insertion(+), 1 deletion(-)
rename include/linux/{netfilter_ingress.h => netfilter_netdev.h} (100%)
diff --git a/include/linux/netfilter_ingress.h b/include/linux/netfilter_netdev.h
similarity index 100%
rename from include/linux/netfilter_ingress.h
rename to include/linux/netfilter_netdev.h
diff --git a/net/core/dev.c b/net/core/dev.c
index e555a8656c47..c698a0fcfa02 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -135,7 +135,7 @@
#include <linux/if_macvlan.h>
#include <linux/errqueue.h>
#include <linux/hrtimer.h>
-#include <linux/netfilter_ingress.h>
+#include <linux/netfilter_netdev.h>
#include <linux/crash_dump.h>
#include <linux/sctp.h>
#include <net/udp_tunnel.h>
--
2.23.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH nf-next,RFC 4/5] netfilter: Generalize ingress hook
2019-10-31 13:41 [PATCH nf-next,RFC 0/5] Netfilter egress hook Lukas Wunner
` (2 preceding siblings ...)
2019-10-31 13:41 ` [PATCH nf-next,RFC 3/5] netfilter: Rename ingress hook include file Lukas Wunner
@ 2019-10-31 13:41 ` Lukas Wunner
2019-10-31 13:41 ` [PATCH nf-next,RFC 5/5] netfilter: Introduce egress hook Lukas Wunner
2019-11-07 22:51 ` [PATCH nf-next,RFC 0/5] Netfilter " Pablo Neira Ayuso
5 siblings, 0 replies; 12+ messages in thread
From: Lukas Wunner @ 2019-10-31 13:41 UTC (permalink / raw)
To: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal
Cc: netfilter-devel, coreteam, netdev, Martin Mares, Daniel Borkmann
Prepare for addition of a netfilter egress hook by generalizing the
ingress hook introduced by commit e687ad60af09 ("netfilter: add
netfilter ingress hook after handle_ing() under unique static key").
In particular, rename and refactor the ingress hook's static inlines
such that they can be reused for an egress hook.
No functional change intended.
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
include/linux/netfilter_netdev.h | 45 ++++++++++++++++++++++----------
net/core/dev.c | 2 +-
2 files changed, 32 insertions(+), 15 deletions(-)
diff --git a/include/linux/netfilter_netdev.h b/include/linux/netfilter_netdev.h
index a13774be2eb5..49e26479642e 100644
--- a/include/linux/netfilter_netdev.h
+++ b/include/linux/netfilter_netdev.h
@@ -1,34 +1,37 @@
/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _NETFILTER_INGRESS_H_
-#define _NETFILTER_INGRESS_H_
+#ifndef _NETFILTER_NETDEV_H_
+#define _NETFILTER_NETDEV_H_
#include <linux/netfilter.h>
#include <linux/netdevice.h>
-#ifdef CONFIG_NETFILTER_INGRESS
-static inline bool nf_hook_ingress_active(const struct sk_buff *skb)
+#ifdef CONFIG_NETFILTER
+static __always_inline bool nf_hook_netdev_active(enum nf_dev_hooks hooknum,
+ struct nf_hook_entries __rcu *hooks)
{
#ifdef CONFIG_JUMP_LABEL
- if (!static_key_false(&nf_hooks_needed[NFPROTO_NETDEV][NF_NETDEV_INGRESS]))
+ if (!static_key_false(&nf_hooks_needed[NFPROTO_NETDEV][hooknum]))
return false;
#endif
- return rcu_access_pointer(skb->dev->nf_hooks_ingress);
+ return rcu_access_pointer(hooks);
}
/* caller must hold rcu_read_lock */
-static inline int nf_hook_ingress(struct sk_buff *skb)
+static __always_inline int nf_hook_netdev(struct sk_buff *skb,
+ enum nf_dev_hooks hooknum,
+ struct nf_hook_entries __rcu *hooks)
{
- struct nf_hook_entries *e = rcu_dereference(skb->dev->nf_hooks_ingress);
+ struct nf_hook_entries *e = rcu_dereference(hooks);
struct nf_hook_state state;
int ret;
- /* Must recheck the ingress hook head, in the event it became NULL
- * after the check in nf_hook_ingress_active evaluated to true.
+ /* Must recheck the hook head, in the event it became NULL
+ * after the check in nf_hook_netdev_active evaluated to true.
*/
if (unlikely(!e))
return 0;
- nf_hook_state_init(&state, NF_NETDEV_INGRESS,
+ nf_hook_state_init(&state, hooknum,
NFPROTO_NETDEV, skb->dev, NULL, NULL,
dev_net(skb->dev), NULL);
ret = nf_hook_slow(skb, &state, e, 0);
@@ -37,10 +40,26 @@ static inline int nf_hook_ingress(struct sk_buff *skb)
return ret;
}
+#endif /* CONFIG_NETFILTER */
-static inline void nf_hook_ingress_init(struct net_device *dev)
+static inline void nf_hook_netdev_init(struct net_device *dev)
{
+#ifdef CONFIG_NETFILTER_INGRESS
RCU_INIT_POINTER(dev->nf_hooks_ingress, NULL);
+#endif
+}
+
+#ifdef CONFIG_NETFILTER_INGRESS
+static inline bool nf_hook_ingress_active(const struct sk_buff *skb)
+{
+ return nf_hook_netdev_active(NF_NETDEV_INGRESS,
+ skb->dev->nf_hooks_ingress);
+}
+
+static inline int nf_hook_ingress(struct sk_buff *skb)
+{
+ return nf_hook_netdev(skb, NF_NETDEV_INGRESS,
+ skb->dev->nf_hooks_ingress);
}
#else /* CONFIG_NETFILTER_INGRESS */
static inline int nf_hook_ingress_active(struct sk_buff *skb)
@@ -52,7 +71,5 @@ static inline int nf_hook_ingress(struct sk_buff *skb)
{
return 0;
}
-
-static inline void nf_hook_ingress_init(struct net_device *dev) {}
#endif /* CONFIG_NETFILTER_INGRESS */
#endif /* _NETFILTER_INGRESS_H_ */
diff --git a/net/core/dev.c b/net/core/dev.c
index c698a0fcfa02..e4976f68f2dd 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -9478,7 +9478,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
if (!dev->ethtool_ops)
dev->ethtool_ops = &default_ethtool_ops;
- nf_hook_ingress_init(dev);
+ nf_hook_netdev_init(dev);
return dev;
--
2.23.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH nf-next,RFC 5/5] netfilter: Introduce egress hook
2019-10-31 13:41 [PATCH nf-next,RFC 0/5] Netfilter egress hook Lukas Wunner
` (3 preceding siblings ...)
2019-10-31 13:41 ` [PATCH nf-next,RFC 4/5] netfilter: Generalize ingress hook Lukas Wunner
@ 2019-10-31 13:41 ` Lukas Wunner
2019-10-31 22:39 ` Daniel Borkmann
2019-11-07 22:51 ` [PATCH nf-next,RFC 0/5] Netfilter " Pablo Neira Ayuso
5 siblings, 1 reply; 12+ messages in thread
From: Lukas Wunner @ 2019-10-31 13:41 UTC (permalink / raw)
To: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal
Cc: netfilter-devel, coreteam, netdev, Martin Mares, Daniel Borkmann
Commit e687ad60af09 ("netfilter: add netfilter ingress hook after
handle_ing() under unique static key") introduced the ability to
classify packets on ingress.
Allow the same on egress.
The need for this arose because I had to filter egress packets which do
not match a specific ethertype. The most common solution appears to be
to enslave the interface to a bridge and use ebtables, but that's
cumbersome to configure and comes with a (small) performance penalty.
An alternative approach is tc, but that doesn't afford equivalent
matching options as netfilter. A bit of googling reveals that more
people have expressed a desire for egress filtering in the past:
https://www.spinics.net/lists/netfilter/msg50038.html
https://unix.stackexchange.com/questions/512371
An egress hook therefore seems like an obvious addition.
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
include/linux/netdevice.h | 4 ++++
include/linux/netfilter_netdev.h | 27 +++++++++++++++++++++++++++
include/uapi/linux/netfilter.h | 1 +
net/core/dev.c | 25 ++++++++++++++++++++-----
net/netfilter/Kconfig | 8 ++++++++
net/netfilter/core.c | 24 ++++++++++++++++++++----
net/netfilter/nft_chain_filter.c | 4 +++-
7 files changed, 83 insertions(+), 10 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index bc6914ea3faf..111107aed50b 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1720,6 +1720,7 @@ enum netdev_priv_flags {
* @xps_maps: XXX: need comments on this one
* @miniq_egress: clsact qdisc specific data for
* egress processing
+ * @nf_hooks_egress: netfilter hooks executed for egress packets
* @watchdog_timeo: Represents the timeout that is used by
* the watchdog (see dev_watchdog())
* @watchdog_timer: List of timers
@@ -1981,6 +1982,9 @@ struct net_device {
#ifdef CONFIG_NET_CLS_ACT
struct mini_Qdisc __rcu *miniq_egress;
#endif
+#ifdef CONFIG_NETFILTER_EGRESS
+ struct nf_hook_entries __rcu *nf_hooks_egress;
+#endif
/* These may be needed for future network-power-down code. */
struct timer_list watchdog_timer;
diff --git a/include/linux/netfilter_netdev.h b/include/linux/netfilter_netdev.h
index 49e26479642e..92d3611a782e 100644
--- a/include/linux/netfilter_netdev.h
+++ b/include/linux/netfilter_netdev.h
@@ -47,6 +47,9 @@ static inline void nf_hook_netdev_init(struct net_device *dev)
#ifdef CONFIG_NETFILTER_INGRESS
RCU_INIT_POINTER(dev->nf_hooks_ingress, NULL);
#endif
+#ifdef CONFIG_NETFILTER_EGRESS
+ RCU_INIT_POINTER(dev->nf_hooks_egress, NULL);
+#endif
}
#ifdef CONFIG_NETFILTER_INGRESS
@@ -72,4 +75,28 @@ static inline int nf_hook_ingress(struct sk_buff *skb)
return 0;
}
#endif /* CONFIG_NETFILTER_INGRESS */
+
+#ifdef CONFIG_NETFILTER_EGRESS
+static inline bool nf_hook_egress_active(const struct sk_buff *skb)
+{
+ return nf_hook_netdev_active(NF_NETDEV_EGRESS,
+ skb->dev->nf_hooks_egress);
+}
+
+static inline int nf_hook_egress(struct sk_buff *skb)
+{
+ return nf_hook_netdev(skb, NF_NETDEV_EGRESS,
+ skb->dev->nf_hooks_egress);
+}
+#else /* CONFIG_NETFILTER_EGRESS */
+static inline int nf_hook_egress_active(struct sk_buff *skb)
+{
+ return 0;
+}
+
+static inline int nf_hook_egress(struct sk_buff *skb)
+{
+ return 0;
+}
+#endif /* CONFIG_NETFILTER_EGRESS */
#endif /* _NETFILTER_INGRESS_H_ */
diff --git a/include/uapi/linux/netfilter.h b/include/uapi/linux/netfilter.h
index ca9e63d6e0e4..d1616574c54f 100644
--- a/include/uapi/linux/netfilter.h
+++ b/include/uapi/linux/netfilter.h
@@ -50,6 +50,7 @@ enum nf_inet_hooks {
enum nf_dev_hooks {
NF_NETDEV_INGRESS,
+ NF_NETDEV_EGRESS,
NF_NETDEV_NUMHOOKS
};
diff --git a/net/core/dev.c b/net/core/dev.c
index e4976f68f2dd..d1e48fc4ae5c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3811,10 +3811,10 @@ int dev_loopback_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
}
EXPORT_SYMBOL(dev_loopback_xmit);
-#ifdef CONFIG_NET_EGRESS
static struct sk_buff *
sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
{
+#ifdef CONFIG_NET_CLS_ACT
struct mini_Qdisc *miniq = rcu_dereference_bh(dev->miniq_egress);
struct tcf_result cl_res;
@@ -3848,10 +3848,22 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
default:
break;
}
-
+#endif /* CONFIG_NET_CLS_ACT */
return skb;
}
-#endif /* CONFIG_NET_EGRESS */
+
+static int nf_egress(struct sk_buff *skb)
+{
+ if (nf_hook_egress_active(skb)) {
+ int ret;
+
+ rcu_read_lock();
+ ret = nf_hook_egress(skb);
+ rcu_read_unlock();
+ return ret;
+ }
+ return 0;
+}
#ifdef CONFIG_XPS
static int __get_xps_queue_idx(struct net_device *dev, struct sk_buff *skb,
@@ -4039,13 +4051,16 @@ static int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev)
qdisc_pkt_len_init(skb);
#ifdef CONFIG_NET_CLS_ACT
skb->tc_at_ingress = 0;
-# ifdef CONFIG_NET_EGRESS
+#endif
+#ifdef CONFIG_NET_EGRESS
if (static_branch_unlikely(&egress_needed_key)) {
skb = sch_handle_egress(skb, &rc, dev);
if (!skb)
goto out;
+
+ if (nf_egress(skb) < 0)
+ goto out;
}
-# endif
#endif
/* If device/qdisc don't need skb->dst, release it right now while
* its hot in this cpu cache.
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 91efae88e8c2..a6ae141ec77e 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -10,6 +10,14 @@ config NETFILTER_INGRESS
This allows you to classify packets from ingress using the Netfilter
infrastructure.
+config NETFILTER_EGRESS
+ bool "Netfilter egress support"
+ default y
+ select NET_EGRESS
+ help
+ This allows you to classify packets before transmission using the
+ Netfilter infrastructure.
+
config NETFILTER_NETLINK
tristate
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 78f046ec506f..85e9c959aba7 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -306,6 +306,12 @@ nf_hook_entry_head(struct net *net, int pf, unsigned int hooknum,
if (dev && dev_net(dev) == net)
return &dev->nf_hooks_ingress;
}
+#endif
+#ifdef CONFIG_NETFILTER_EGRESS
+ if (hooknum == NF_NETDEV_EGRESS) {
+ if (dev && dev_net(dev) == net)
+ return &dev->nf_hooks_egress;
+ }
#endif
WARN_ON_ONCE(1);
return NULL;
@@ -318,11 +324,13 @@ static int __nf_register_net_hook(struct net *net, int pf,
struct nf_hook_entries __rcu **pp;
if (pf == NFPROTO_NETDEV) {
-#ifndef CONFIG_NETFILTER_INGRESS
- if (reg->hooknum == NF_NETDEV_INGRESS)
+ if ((!IS_ENABLED(CONFIG_NETFILTER_INGRESS) &&
+ reg->hooknum == NF_NETDEV_INGRESS) ||
+ (!IS_ENABLED(CONFIG_NETFILTER_EGRESS) &&
+ reg->hooknum == NF_NETDEV_EGRESS))
return -EOPNOTSUPP;
-#endif
- if (reg->hooknum != NF_NETDEV_INGRESS ||
+ if ((reg->hooknum != NF_NETDEV_INGRESS &&
+ reg->hooknum != NF_NETDEV_EGRESS) ||
!reg->dev || dev_net(reg->dev) != net)
return -EINVAL;
}
@@ -348,6 +356,10 @@ static int __nf_register_net_hook(struct net *net, int pf,
if (pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS)
net_inc_ingress_queue();
#endif
+#ifdef CONFIG_NETFILTER_EGRESS
+ if (pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_EGRESS)
+ net_inc_egress_queue();
+#endif
#ifdef CONFIG_JUMP_LABEL
static_key_slow_inc(&nf_hooks_needed[pf][reg->hooknum]);
#endif
@@ -406,6 +418,10 @@ static void __nf_unregister_net_hook(struct net *net, int pf,
if (pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS)
net_dec_ingress_queue();
#endif
+#ifdef CONFIG_NETFILTER_EGRESS
+ if (pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_EGRESS)
+ net_dec_egress_queue();
+#endif
#ifdef CONFIG_JUMP_LABEL
static_key_slow_dec(&nf_hooks_needed[pf][reg->hooknum]);
#endif
diff --git a/net/netfilter/nft_chain_filter.c b/net/netfilter/nft_chain_filter.c
index c78d01bc02e9..67ce6dbb5496 100644
--- a/net/netfilter/nft_chain_filter.c
+++ b/net/netfilter/nft_chain_filter.c
@@ -277,9 +277,11 @@ static const struct nft_chain_type nft_chain_filter_netdev = {
.name = "filter",
.type = NFT_CHAIN_T_DEFAULT,
.family = NFPROTO_NETDEV,
- .hook_mask = (1 << NF_NETDEV_INGRESS),
+ .hook_mask = (1 << NF_NETDEV_INGRESS) |
+ (1 << NF_NETDEV_EGRESS),
.hooks = {
[NF_NETDEV_INGRESS] = nft_do_chain_netdev,
+ [NF_NETDEV_EGRESS] = nft_do_chain_netdev,
},
};
--
2.23.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH nf-next,RFC 5/5] netfilter: Introduce egress hook
2019-10-31 13:41 ` [PATCH nf-next,RFC 5/5] netfilter: Introduce egress hook Lukas Wunner
@ 2019-10-31 22:39 ` Daniel Borkmann
2019-11-23 14:23 ` Lukas Wunner
0 siblings, 1 reply; 12+ messages in thread
From: Daniel Borkmann @ 2019-10-31 22:39 UTC (permalink / raw)
To: Lukas Wunner
Cc: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal,
netfilter-devel, coreteam, netdev, Martin Mares
On 10/31/19 2:41 PM, Lukas Wunner wrote:
> Commit e687ad60af09 ("netfilter: add netfilter ingress hook after
> handle_ing() under unique static key") introduced the ability to
> classify packets on ingress.
>
> Allow the same on egress.
>
> The need for this arose because I had to filter egress packets which do
> not match a specific ethertype. The most common solution appears to be
This seems like a /very/ weak justification for something that sits in
critical fastpath. NAK.
> to enslave the interface to a bridge and use ebtables, but that's
> cumbersome to configure and comes with a (small) performance penalty.
> An alternative approach is tc, but that doesn't afford equivalent
> matching options as netfilter.
Hmm, have you tried tc BPF on the egress hook (via sch_cls_act -> cls_bpf)?
> people have expressed a desire for egress filtering in the past:
>
> https://www.spinics.net/lists/netfilter/msg50038.html
Adding another hook to catch misconfigurations of NAT in postrouting ...?
> https://unix.stackexchange.com/questions/512371
This talks about filtering / limiting ARP packets which can be done today
easily with existing means, including writing ARP responders sitting on tc
ingress/egress hook.
> An egress hook therefore seems like an obvious addition.
>
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> Cc: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH nf-next,RFC 5/5] netfilter: Introduce egress hook
2019-10-31 22:39 ` Daniel Borkmann
@ 2019-11-23 14:23 ` Lukas Wunner
0 siblings, 0 replies; 12+ messages in thread
From: Lukas Wunner @ 2019-11-23 14:23 UTC (permalink / raw)
To: Daniel Borkmann
Cc: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal,
netfilter-devel, coreteam, netdev, Martin Mares
On Thu, Oct 31, 2019 at 11:39:58PM +0100, Daniel Borkmann wrote:
> On 10/31/19 2:41 PM, Lukas Wunner wrote:
> > Commit e687ad60af09 ("netfilter: add netfilter ingress hook after
> > handle_ing() under unique static key") introduced the ability to
> > classify packets on ingress.
> >
> > Allow the same on egress.
> >
> > The need for this arose because I had to filter egress packets which do
> > not match a specific ethertype. The most common solution appears to be
> > to enslave the interface to a bridge and use ebtables, but that's
> > cumbersome to configure and comes with a (small) performance penalty.
> > An alternative approach is tc, but that doesn't afford equivalent
> > matching options as netfilter.
>
> Hmm, have you tried tc BPF on the egress hook (via sch_cls_act -> cls_bpf)?
There's another reason I chose netfilter over tc: I need to activate the
filter from a kernel module, hence need an in-kernel (rather than user space)
API.
netfilter provides that via nf_register_net_hook(), I couldn't find
anything similar for tc. And an egress netfilter hook seemed like
an obvious missing feature given the presence of an ingress hook.
The module I need this for is out-of-tree:
https://github.com/RevolutionPi/piControl/commit/da199ccd2099
In my experience the argument that a feature is needed for an out-of-tree
module holds zero value upstream. If there's no in-tree user, the feature
isn't merged, I've seen this more than enough. Which is why I didn't mention
it in the first place.
For our use case I wouldn't even need the nft user space support which I
posted separately, I just implemented it for completeness and to increase
acceptability of the present series.
Thanks,
Lukas
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH nf-next,RFC 0/5] Netfilter egress hook
2019-10-31 13:41 [PATCH nf-next,RFC 0/5] Netfilter egress hook Lukas Wunner
` (4 preceding siblings ...)
2019-10-31 13:41 ` [PATCH nf-next,RFC 5/5] netfilter: Introduce egress hook Lukas Wunner
@ 2019-11-07 22:51 ` Pablo Neira Ayuso
2019-11-23 13:11 ` Lukas Wunner
2020-03-04 9:50 ` Lukas Wunner
5 siblings, 2 replies; 12+ messages in thread
From: Pablo Neira Ayuso @ 2019-11-07 22:51 UTC (permalink / raw)
To: Lukas Wunner
Cc: Jozsef Kadlecsik, Florian Westphal, netfilter-devel, coreteam,
netdev, Martin Mares, Daniel Borkmann
Hi,
On Thu, Oct 31, 2019 at 02:41:00PM +0100, Lukas Wunner wrote:
> Introduce a netfilter egress hook to complement the existing ingress hook.
>
> User space support for nft is submitted in a separate patch.
>
> The need for this arose because I had to filter egress packets which do
> not match a specific ethertype. The most common solution appears to be
> to enslave the interface to a bridge and use ebtables, but that's
> cumbersome to configure and comes with a (small) performance penalty.
> An alternative approach is tc, but that doesn't afford equivalent
> matching options as netfilter. A bit of googling reveals that more
> people have expressed a desire for egress filtering in the past:
>
> https://www.spinics.net/lists/netfilter/msg50038.html
> https://unix.stackexchange.com/questions/512371
>
> I am first performing traffic control with sch_handle_egress() before
> performing filtering with nf_egress(). That order is identical to
> ingress processing. I'm wondering whether an inverse order would be
> more logical or more beneficial. Among other things it would allow
> marking packets with netfilter on egress before performing traffic
> control based on that mark. Thoughts?
Would you provide some numbers on the performance impact for this new
hook?
Thanks.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH nf-next,RFC 0/5] Netfilter egress hook
2019-11-07 22:51 ` [PATCH nf-next,RFC 0/5] Netfilter " Pablo Neira Ayuso
@ 2019-11-23 13:11 ` Lukas Wunner
2020-03-04 9:50 ` Lukas Wunner
1 sibling, 0 replies; 12+ messages in thread
From: Lukas Wunner @ 2019-11-23 13:11 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: Jozsef Kadlecsik, Florian Westphal, netfilter-devel, coreteam,
netdev, Martin Mares, Daniel Borkmann
On Thu, Nov 07, 2019 at 11:51:49PM +0100, Pablo Neira Ayuso wrote:
> On Thu, Oct 31, 2019 at 02:41:00PM +0100, Lukas Wunner wrote:
> > Introduce a netfilter egress hook to complement the existing ingress hook.
>
> Would you provide some numbers on the performance impact for this new
> hook?
For some reason the numbers are slightly better with this series.
Could be caused by the __always_inline in patch 4, I'd have to compare
the disassembly to confirm this hunch.
* Without this patch:
Result: OK: 34205373(c34202809+d2564) usec, 100000000 (60byte,0frags)
2923517pps 1403Mb/sec (1403288160bps) errors: 0
* With this patch:
Result: OK: 34106013(c34103172+d2841) usec, 100000000 (60byte,0frags)
2932034pps 1407Mb/sec (1407376320bps) errors: 0
* Without this patch + tc egress:
Result: OK: 37848652(c37846140+d2511) usec, 100000000 (60byte,0frags)
2642102pps 1268Mb/sec (1268208960bps) errors: 0
* With this patch + tc egress:
Result: OK: 37784817(c37782026+d2791) usec, 100000000 (60byte,0frags)
2646565pps 1270Mb/sec (1270351200bps) errors: 0
* With this patch + nft egress:
Result: OK: 43911936(c43908932+d3003) usec, 100000000 (60byte,0frags)
2277285pps 1093Mb/sec (1093096800bps) errors: 0
Tested on a bare-metal Core i7-3615QM, each measurement was performed
twice to verify that the numbers are stable.
Commands to perform a measurement:
modprobe pktgen
echo "add_device lo@3" > /proc/net/pktgen/kpktgend_3
samples/pktgen/pktgen_bench_xmit_mode_queue_xmit.sh -i 'lo@3' -n 100000000
Commands for testing tc egress:
tc qdisc add dev lo clsact
tc filter add dev lo egress protocol ip prio 1 u32 match ip dst 4.3.2.1/32
Commands for testing nft egress:
nft add table netdev t
nft add chain netdev t co \{ type filter hook egress device lo priority 0 \; \}
nft add rule netdev t co ip daddr 4.3.2.1/32 drop
All testing was performed on the loopback interface to avoid distorting
measurements by the packet handling in the low-level Ethernet driver.
This required the following small patch:
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index bb99152..020c825 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2003,8 +2003,8 @@ static int pktgen_setup_dev(const struct pktgen_net *pn,
return -ENODEV;
}
- if (odev->type != ARPHRD_ETHER) {
- pr_err("not an ethernet device: \"%s\"\n", ifname);
+ if (odev->type != ARPHRD_ETHER && odev->type != ARPHRD_LOOPBACK) {
+ pr_err("not an ethernet or loopback device: \"%s\"\n", ifname);
err = -EINVAL;
} else if (!netif_running(odev)) {
pr_err("device is down: \"%s\"\n", ifname);
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH nf-next,RFC 0/5] Netfilter egress hook
2019-11-07 22:51 ` [PATCH nf-next,RFC 0/5] Netfilter " Pablo Neira Ayuso
2019-11-23 13:11 ` Lukas Wunner
@ 2020-03-04 9:50 ` Lukas Wunner
2020-03-04 12:31 ` Pablo Neira Ayuso
1 sibling, 1 reply; 12+ messages in thread
From: Lukas Wunner @ 2020-03-04 9:50 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: Jozsef Kadlecsik, Florian Westphal, netfilter-devel, coreteam,
netdev, Martin Mares, Daniel Borkmann
On Thu, Nov 07, 2019 at 11:51:49PM +0100, Pablo Neira Ayuso wrote:
> On Thu, Oct 31, 2019 at 02:41:00PM +0100, Lukas Wunner wrote:
> > Introduce a netfilter egress hook to complement the existing ingress hook.
> >
> > User space support for nft is submitted in a separate patch.
> >
> > The need for this arose because I had to filter egress packets which do
> > not match a specific ethertype. The most common solution appears to be
> > to enslave the interface to a bridge and use ebtables, but that's
> > cumbersome to configure and comes with a (small) performance penalty.
> > An alternative approach is tc, but that doesn't afford equivalent
> > matching options as netfilter. A bit of googling reveals that more
> > people have expressed a desire for egress filtering in the past:
> >
> > https://www.spinics.net/lists/netfilter/msg50038.html
> > https://unix.stackexchange.com/questions/512371
> >
> > I am first performing traffic control with sch_handle_egress() before
> > performing filtering with nf_egress(). That order is identical to
> > ingress processing. I'm wondering whether an inverse order would be
> > more logical or more beneficial. Among other things it would allow
> > marking packets with netfilter on egress before performing traffic
> > control based on that mark. Thoughts?
>
> Would you provide some numbers on the performance impact for this new
> hook?
Just a gentle ping for this series. I'd still be very interested to
get it upstream. When posting the above-quoted RFC, Daniel NAK'ed it
saying that "weak justification" was provided "for something that sits
in critical fastpath".
However I followed up with numbers showing that the series actually
results in a speedup rather than a slowdown if the feature isn't used:
https://lore.kernel.org/netfilter-devel/20191123131108.dlnrbutabh5i55ix@wunner.de/
So what's the consensus? Shall I post a non-RFC version, rebased on
current nf-next/master?
Thanks!
Lukas
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH nf-next,RFC 0/5] Netfilter egress hook
2020-03-04 9:50 ` Lukas Wunner
@ 2020-03-04 12:31 ` Pablo Neira Ayuso
0 siblings, 0 replies; 12+ messages in thread
From: Pablo Neira Ayuso @ 2020-03-04 12:31 UTC (permalink / raw)
To: Lukas Wunner
Cc: Jozsef Kadlecsik, Florian Westphal, netfilter-devel, coreteam,
netdev, Martin Mares, Daniel Borkmann
On Wed, Mar 04, 2020 at 10:50:32AM +0100, Lukas Wunner wrote:
[...]
> So what's the consensus? Shall I post a non-RFC version, rebased on
> current nf-next/master?
Please, move on and rebase on top of nf-next/master.
Thank you.
^ permalink raw reply [flat|nested] 12+ messages in thread