kernel: drop the conntrack rtcache patch
It's in backports-5.4, but it wasn't ever merged. Upstream followed another
approach, with flow offloading, which has much better performance. Drop this
obsolete patch and refresh the kernel patches.
Signed-off-by: Rui Salvaterra <rsalvaterra@gmail.com>
Acked-by: Stijn Tintel <stijn@linux-ipv6.be>
Acked-by: Felix Fietkau <nbd@nbd.name>
(cherry picked from commit 17576b1b2a)
			
			
This commit is contained in:
		 Rui Salvaterra
					Rui Salvaterra
				
			
				
					committed by
					
						 Kevin Darbyshire-Bryant
						Kevin Darbyshire-Bryant
					
				
			
			
				
	
			
			
			 Kevin Darbyshire-Bryant
						Kevin Darbyshire-Bryant
					
				
			
						parent
						
							15cd9a5d5c
						
					
				
				
					commit
					6f053e5b4f
				
			| @@ -1,558 +0,0 @@ | |||||||
| From 1bb0c3ec899827cfa4668bb63a08713a40744d21 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Florian Westphal <fw@strlen.de> |  | ||||||
| Date: Sun, 9 Jul 2017 08:58:30 +0200 |  | ||||||
| Subject: [PATCH] netfilter: conntrack: cache route for forwarded connections |  | ||||||
|  |  | ||||||
| ... to avoid per-packet FIB lookup if possible. |  | ||||||
|  |  | ||||||
| The cached dst is re-used provided the input interface |  | ||||||
| is the same as that of the previous packet in the same direction. |  | ||||||
|  |  | ||||||
| If not, the cached dst is invalidated. |  | ||||||
|  |  | ||||||
| For ipv6 we also need to store sernum, else dst_check doesn't work, |  | ||||||
| pointed out by Eric Dumazet. |  | ||||||
|  |  | ||||||
| This should speed up forwarding when conntrack is already in use |  | ||||||
| anyway, especially when using reverse path filtering -- active RPF |  | ||||||
| enforces two FIB lookups for each packet. |  | ||||||
|  |  | ||||||
| Before the routing cache removal this didn't matter since RPF was performed |  | ||||||
| only when route cache didn't yield a result; but without route cache it |  | ||||||
| comes at higher price. |  | ||||||
|  |  | ||||||
| Julian Anastasov suggested to add NETDEV_UNREGISTER handler to |  | ||||||
| avoid holding on to dsts of 'frozen' conntracks. |  | ||||||
|  |  | ||||||
| Signed-off-by: Florian Westphal <fw@strlen.de> |  | ||||||
| --- |  | ||||||
|  include/net/netfilter/nf_conntrack_extend.h  |   4 + |  | ||||||
|  include/net/netfilter/nf_conntrack_rtcache.h |  34 +++ |  | ||||||
|  net/netfilter/Kconfig                        |  12 + |  | ||||||
|  net/netfilter/Makefile                       |   3 + |  | ||||||
|  net/netfilter/nf_conntrack_rtcache.c         | 428 +++++++++++++++++++++++++++ |  | ||||||
|  5 files changed, 481 insertions(+) |  | ||||||
|  create mode 100644 include/net/netfilter/nf_conntrack_rtcache.h |  | ||||||
|  create mode 100644 net/netfilter/nf_conntrack_rtcache.c |  | ||||||
|  |  | ||||||
| --- a/include/net/netfilter/nf_conntrack_extend.h |  | ||||||
| +++ b/include/net/netfilter/nf_conntrack_extend.h |  | ||||||
| @@ -28,6 +28,9 @@ enum nf_ct_ext_id { |  | ||||||
|  #if IS_ENABLED(CONFIG_NETFILTER_SYNPROXY) |  | ||||||
|  	NF_CT_EXT_SYNPROXY, |  | ||||||
|  #endif |  | ||||||
| +#if IS_ENABLED(CONFIG_NF_CONNTRACK_RTCACHE) |  | ||||||
| +	NF_CT_EXT_RTCACHE, |  | ||||||
| +#endif |  | ||||||
|  	NF_CT_EXT_NUM, |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
| @@ -40,6 +43,7 @@ enum nf_ct_ext_id { |  | ||||||
|  #define NF_CT_EXT_TIMEOUT_TYPE struct nf_conn_timeout |  | ||||||
|  #define NF_CT_EXT_LABELS_TYPE struct nf_conn_labels |  | ||||||
|  #define NF_CT_EXT_SYNPROXY_TYPE struct nf_conn_synproxy |  | ||||||
| +#define NF_CT_EXT_RTCACHE_TYPE struct nf_conn_rtcache |  | ||||||
|   |  | ||||||
|  /* Extensions: optional stuff which isn't permanently in struct. */ |  | ||||||
|  struct nf_ct_ext { |  | ||||||
| --- /dev/null |  | ||||||
| +++ b/include/net/netfilter/nf_conntrack_rtcache.h |  | ||||||
| @@ -0,0 +1,34 @@ |  | ||||||
| +#include <linux/gfp.h> |  | ||||||
| +#include <net/netfilter/nf_conntrack.h> |  | ||||||
| +#include <net/netfilter/nf_conntrack_extend.h> |  | ||||||
| + |  | ||||||
| +struct dst_entry; |  | ||||||
| + |  | ||||||
| +struct nf_conn_dst_cache { |  | ||||||
| +	struct dst_entry *dst; |  | ||||||
| +	int iif; |  | ||||||
| +#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) |  | ||||||
| +	u32 cookie; |  | ||||||
| +#endif |  | ||||||
| + |  | ||||||
| +}; |  | ||||||
| + |  | ||||||
| +struct nf_conn_rtcache { |  | ||||||
| +	struct nf_conn_dst_cache cached_dst[IP_CT_DIR_MAX]; |  | ||||||
| +}; |  | ||||||
| + |  | ||||||
| +static inline |  | ||||||
| +struct nf_conn_rtcache *nf_ct_rtcache_find(const struct nf_conn *ct) |  | ||||||
| +{ |  | ||||||
| +#if IS_ENABLED(CONFIG_NF_CONNTRACK_RTCACHE) |  | ||||||
| +	return nf_ct_ext_find(ct, NF_CT_EXT_RTCACHE); |  | ||||||
| +#else |  | ||||||
| +	return NULL; |  | ||||||
| +#endif |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static inline int nf_conn_rtcache_iif_get(const struct nf_conn_rtcache *rtc, |  | ||||||
| +					  enum ip_conntrack_dir dir) |  | ||||||
| +{ |  | ||||||
| +	return rtc->cached_dst[dir].iif; |  | ||||||
| +} |  | ||||||
| --- a/net/netfilter/Kconfig |  | ||||||
| +++ b/net/netfilter/Kconfig |  | ||||||
| @@ -136,6 +136,18 @@ config NF_CONNTRACK_EVENTS |  | ||||||
|   |  | ||||||
|  	  If unsure, say `N'. |  | ||||||
|   |  | ||||||
| +config NF_CONNTRACK_RTCACHE |  | ||||||
| +	tristate "Cache route entries in conntrack objects" |  | ||||||
| +	depends on NETFILTER_ADVANCED |  | ||||||
| +	depends on NF_CONNTRACK |  | ||||||
| +	help |  | ||||||
| +	  If this option is enabled, the connection tracking code will |  | ||||||
| +	  cache routing information for each connection that is being |  | ||||||
| +	  forwarded, at a cost of 32 bytes per conntrack object. |  | ||||||
| + |  | ||||||
| +	  To compile it as a module, choose M here.  If unsure, say N. |  | ||||||
| +	  The module will be called nf_conntrack_rtcache. |  | ||||||
| + |  | ||||||
|  config NF_CONNTRACK_TIMEOUT |  | ||||||
|  	bool  'Connection tracking timeout' |  | ||||||
|  	depends on NETFILTER_ADVANCED |  | ||||||
| --- a/net/netfilter/Makefile |  | ||||||
| +++ b/net/netfilter/Makefile |  | ||||||
| @@ -26,6 +26,9 @@ obj-$(CONFIG_NETFILTER_NETLINK_OSF) += n |  | ||||||
|  # connection tracking |  | ||||||
|  obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o |  | ||||||
|   |  | ||||||
| +# optional conntrack route cache extension |  | ||||||
| +obj-$(CONFIG_NF_CONNTRACK_RTCACHE) += nf_conntrack_rtcache.o |  | ||||||
| + |  | ||||||
|  # netlink interface for nf_conntrack |  | ||||||
|  obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o |  | ||||||
|  obj-$(CONFIG_NF_CT_NETLINK_TIMEOUT) += nfnetlink_cttimeout.o |  | ||||||
| --- /dev/null |  | ||||||
| +++ b/net/netfilter/nf_conntrack_rtcache.c |  | ||||||
| @@ -0,0 +1,428 @@ |  | ||||||
| +/* route cache for netfilter. |  | ||||||
| + * |  | ||||||
| + * (C) 2014 Red Hat GmbH |  | ||||||
| + * |  | ||||||
| + * This program is free software; you can redistribute it and/or modify |  | ||||||
| + * it under the terms of the GNU General Public License version 2 as |  | ||||||
| + * published by the Free Software Foundation. |  | ||||||
| + */ |  | ||||||
| + |  | ||||||
| +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |  | ||||||
| + |  | ||||||
| +#include <linux/types.h> |  | ||||||
| +#include <linux/netfilter.h> |  | ||||||
| +#include <linux/skbuff.h> |  | ||||||
| +#include <linux/stddef.h> |  | ||||||
| +#include <linux/kernel.h> |  | ||||||
| +#include <linux/netdevice.h> |  | ||||||
| +#include <linux/export.h> |  | ||||||
| +#include <linux/module.h> |  | ||||||
| + |  | ||||||
| +#include <net/dst.h> |  | ||||||
| + |  | ||||||
| +#include <net/netfilter/nf_conntrack.h> |  | ||||||
| +#include <net/netfilter/nf_conntrack_core.h> |  | ||||||
| +#include <net/netfilter/nf_conntrack_extend.h> |  | ||||||
| +#include <net/netfilter/nf_conntrack_rtcache.h> |  | ||||||
| + |  | ||||||
| +#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) |  | ||||||
| +#include <net/ip6_fib.h> |  | ||||||
| +#endif |  | ||||||
| + |  | ||||||
| +static void __nf_conn_rtcache_destroy(struct nf_conn_rtcache *rtc, |  | ||||||
| +				      enum ip_conntrack_dir dir) |  | ||||||
| +{ |  | ||||||
| +	struct dst_entry *dst = rtc->cached_dst[dir].dst; |  | ||||||
| + |  | ||||||
| +	dst_release(dst); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static void nf_conn_rtcache_destroy(struct nf_conn *ct) |  | ||||||
| +{ |  | ||||||
| +	struct nf_conn_rtcache *rtc = nf_ct_rtcache_find(ct); |  | ||||||
| + |  | ||||||
| +	if (!rtc) |  | ||||||
| +		return; |  | ||||||
| + |  | ||||||
| +	__nf_conn_rtcache_destroy(rtc, IP_CT_DIR_ORIGINAL); |  | ||||||
| +	__nf_conn_rtcache_destroy(rtc, IP_CT_DIR_REPLY); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static void nf_ct_rtcache_ext_add(struct nf_conn *ct) |  | ||||||
| +{ |  | ||||||
| +	struct nf_conn_rtcache *rtc; |  | ||||||
| + |  | ||||||
| +	rtc = nf_ct_ext_add(ct, NF_CT_EXT_RTCACHE, GFP_ATOMIC); |  | ||||||
| +	if (rtc) { |  | ||||||
| +		rtc->cached_dst[IP_CT_DIR_ORIGINAL].iif = -1; |  | ||||||
| +		rtc->cached_dst[IP_CT_DIR_ORIGINAL].dst = NULL; |  | ||||||
| +		rtc->cached_dst[IP_CT_DIR_REPLY].iif = -1; |  | ||||||
| +		rtc->cached_dst[IP_CT_DIR_REPLY].dst = NULL; |  | ||||||
| +	} |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static struct nf_conn_rtcache *nf_ct_rtcache_find_usable(struct nf_conn *ct) |  | ||||||
| +{ |  | ||||||
| +	return nf_ct_rtcache_find(ct); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static struct dst_entry * |  | ||||||
| +nf_conn_rtcache_dst_get(const struct nf_conn_rtcache *rtc, |  | ||||||
| +			enum ip_conntrack_dir dir) |  | ||||||
| +{ |  | ||||||
| +	return rtc->cached_dst[dir].dst; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static u32 nf_rtcache_get_cookie(int pf, const struct dst_entry *dst) |  | ||||||
| +{ |  | ||||||
| +#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) |  | ||||||
| +	if (pf == NFPROTO_IPV6) { |  | ||||||
| +		const struct rt6_info *rt = (const struct rt6_info *)dst; |  | ||||||
| + |  | ||||||
| +		if (rt->from && rt->from->fib6_node) |  | ||||||
| +			return (u32)rt->from->fib6_node->fn_sernum; |  | ||||||
| +	} |  | ||||||
| +#endif |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static void nf_conn_rtcache_dst_set(int pf, |  | ||||||
| +				    struct nf_conn_rtcache *rtc, |  | ||||||
| +				    struct dst_entry *dst, |  | ||||||
| +				    enum ip_conntrack_dir dir, int iif) |  | ||||||
| +{ |  | ||||||
| +	if (rtc->cached_dst[dir].iif != iif) |  | ||||||
| +		rtc->cached_dst[dir].iif = iif; |  | ||||||
| + |  | ||||||
| +	if (rtc->cached_dst[dir].dst != dst) { |  | ||||||
| +		struct dst_entry *old; |  | ||||||
| + |  | ||||||
| +		dst_hold(dst); |  | ||||||
| + |  | ||||||
| +		old = xchg(&rtc->cached_dst[dir].dst, dst); |  | ||||||
| +		dst_release(old); |  | ||||||
| + |  | ||||||
| +#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) |  | ||||||
| +		if (pf == NFPROTO_IPV6) |  | ||||||
| +			rtc->cached_dst[dir].cookie = |  | ||||||
| +				nf_rtcache_get_cookie(pf, dst); |  | ||||||
| +#endif |  | ||||||
| +	} |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static void nf_conn_rtcache_dst_obsolete(struct nf_conn_rtcache *rtc, |  | ||||||
| +					 enum ip_conntrack_dir dir) |  | ||||||
| +{ |  | ||||||
| +	struct dst_entry *old; |  | ||||||
| + |  | ||||||
| +	pr_debug("Invalidate iif %d for dir %d on cache %p\n", |  | ||||||
| +		 rtc->cached_dst[dir].iif, dir, rtc); |  | ||||||
| + |  | ||||||
| +	old = xchg(&rtc->cached_dst[dir].dst, NULL); |  | ||||||
| +	dst_release(old); |  | ||||||
| +	rtc->cached_dst[dir].iif = -1; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static unsigned int nf_rtcache_in(u_int8_t pf, |  | ||||||
| +				  struct sk_buff *skb, |  | ||||||
| +				  const struct nf_hook_state *state) |  | ||||||
| +{ |  | ||||||
| +	struct nf_conn_rtcache *rtc; |  | ||||||
| +	enum ip_conntrack_info ctinfo; |  | ||||||
| +	enum ip_conntrack_dir dir; |  | ||||||
| +	struct dst_entry *dst; |  | ||||||
| +	struct nf_conn *ct; |  | ||||||
| +	int iif; |  | ||||||
| +	u32 cookie; |  | ||||||
| + |  | ||||||
| +	if (skb_dst(skb) || skb->sk) |  | ||||||
| +		return NF_ACCEPT; |  | ||||||
| + |  | ||||||
| +	ct = nf_ct_get(skb, &ctinfo); |  | ||||||
| +	if (!ct) |  | ||||||
| +		return NF_ACCEPT; |  | ||||||
| + |  | ||||||
| +	rtc = nf_ct_rtcache_find_usable(ct); |  | ||||||
| +	if (!rtc) |  | ||||||
| +		return NF_ACCEPT; |  | ||||||
| + |  | ||||||
| +	/* if iif changes, don't use cache and let ip stack |  | ||||||
| +	 * do route lookup. |  | ||||||
| +	 * |  | ||||||
| +	 * If rp_filter is enabled it might toss skb, so |  | ||||||
| +	 * we don't want to avoid these checks. |  | ||||||
| +	 */ |  | ||||||
| +	dir = CTINFO2DIR(ctinfo); |  | ||||||
| +	iif = nf_conn_rtcache_iif_get(rtc, dir); |  | ||||||
| +	if (state->in->ifindex != iif) { |  | ||||||
| +		pr_debug("ct %p, iif %d, cached iif %d, skip cached entry\n", |  | ||||||
| +			 ct, iif, state->in->ifindex); |  | ||||||
| +		return NF_ACCEPT; |  | ||||||
| +	} |  | ||||||
| +	dst = nf_conn_rtcache_dst_get(rtc, dir); |  | ||||||
| +	if (dst == NULL) |  | ||||||
| +		return NF_ACCEPT; |  | ||||||
| + |  | ||||||
| +	cookie = nf_rtcache_get_cookie(pf, dst); |  | ||||||
| + |  | ||||||
| +	dst = dst_check(dst, cookie); |  | ||||||
| +	pr_debug("obtained dst %p for skb %p, cookie %d\n", dst, skb, cookie); |  | ||||||
| +	if (likely(dst)) |  | ||||||
| +		skb_dst_set_noref(skb, dst); |  | ||||||
| +	else |  | ||||||
| +		nf_conn_rtcache_dst_obsolete(rtc, dir); |  | ||||||
| + |  | ||||||
| +	return NF_ACCEPT; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static unsigned int nf_rtcache_forward(u_int8_t pf, |  | ||||||
| +				       struct sk_buff *skb, |  | ||||||
| +				       const struct nf_hook_state *state) |  | ||||||
| +{ |  | ||||||
| +	struct nf_conn_rtcache *rtc; |  | ||||||
| +	enum ip_conntrack_info ctinfo; |  | ||||||
| +	enum ip_conntrack_dir dir; |  | ||||||
| +	struct nf_conn *ct; |  | ||||||
| +	struct dst_entry *dst = skb_dst(skb); |  | ||||||
| +	int iif; |  | ||||||
| + |  | ||||||
| +	ct = nf_ct_get(skb, &ctinfo); |  | ||||||
| +	if (!ct) |  | ||||||
| +		return NF_ACCEPT; |  | ||||||
| + |  | ||||||
| +	if (dst && dst_xfrm(dst)) |  | ||||||
| +		return NF_ACCEPT; |  | ||||||
| + |  | ||||||
| +	if (!nf_ct_is_confirmed(ct)) { |  | ||||||
| +		if (WARN_ON(nf_ct_rtcache_find(ct))) |  | ||||||
| +			return NF_ACCEPT; |  | ||||||
| +		nf_ct_rtcache_ext_add(ct); |  | ||||||
| +		return NF_ACCEPT; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	rtc = nf_ct_rtcache_find_usable(ct); |  | ||||||
| +	if (!rtc) |  | ||||||
| +		return NF_ACCEPT; |  | ||||||
| + |  | ||||||
| +	dir = CTINFO2DIR(ctinfo); |  | ||||||
| +	iif = nf_conn_rtcache_iif_get(rtc, dir); |  | ||||||
| +	pr_debug("ct %p, skb %p, dir %d, iif %d, cached iif %d\n", |  | ||||||
| +		 ct, skb, dir, iif, state->in->ifindex); |  | ||||||
| +	if (likely(state->in->ifindex == iif)) |  | ||||||
| +		return NF_ACCEPT; |  | ||||||
| + |  | ||||||
| +	nf_conn_rtcache_dst_set(pf, rtc, skb_dst(skb), dir, state->in->ifindex); |  | ||||||
| +	return NF_ACCEPT; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static unsigned int nf_rtcache_in4(void *priv, |  | ||||||
| +				  struct sk_buff *skb, |  | ||||||
| +				  const struct nf_hook_state *state) |  | ||||||
| +{ |  | ||||||
| +	return nf_rtcache_in(NFPROTO_IPV4, skb, state); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static unsigned int nf_rtcache_forward4(void *priv, |  | ||||||
| +				       struct sk_buff *skb, |  | ||||||
| +				       const struct nf_hook_state *state) |  | ||||||
| +{ |  | ||||||
| +	return nf_rtcache_forward(NFPROTO_IPV4, skb, state); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) |  | ||||||
| +static unsigned int nf_rtcache_in6(void *priv, |  | ||||||
| +				  struct sk_buff *skb, |  | ||||||
| +				  const struct nf_hook_state *state) |  | ||||||
| +{ |  | ||||||
| +	return nf_rtcache_in(NFPROTO_IPV6, skb, state); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static unsigned int nf_rtcache_forward6(void *priv, |  | ||||||
| +				       struct sk_buff *skb, |  | ||||||
| +				       const struct nf_hook_state *state) |  | ||||||
| +{ |  | ||||||
| + 	return nf_rtcache_forward(NFPROTO_IPV6, skb, state); |  | ||||||
| +} |  | ||||||
| +#endif |  | ||||||
| + |  | ||||||
| +static int nf_rtcache_dst_remove(struct nf_conn *ct, void *data) |  | ||||||
| +{ |  | ||||||
| +	struct nf_conn_rtcache *rtc = nf_ct_rtcache_find(ct); |  | ||||||
| +	struct net_device *dev = data; |  | ||||||
| + |  | ||||||
| +	if (!rtc) |  | ||||||
| +		return 0; |  | ||||||
| + |  | ||||||
| +	if (dev->ifindex == rtc->cached_dst[IP_CT_DIR_ORIGINAL].iif || |  | ||||||
| +	    dev->ifindex == rtc->cached_dst[IP_CT_DIR_REPLY].iif) { |  | ||||||
| +		nf_conn_rtcache_dst_obsolete(rtc, IP_CT_DIR_ORIGINAL); |  | ||||||
| +		nf_conn_rtcache_dst_obsolete(rtc, IP_CT_DIR_REPLY); |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	return 0; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int nf_rtcache_netdev_event(struct notifier_block *this, |  | ||||||
| +				   unsigned long event, void *ptr) |  | ||||||
| +{ |  | ||||||
| +	struct net_device *dev = netdev_notifier_info_to_dev(ptr); |  | ||||||
| +	struct net *net = dev_net(dev); |  | ||||||
| + |  | ||||||
| +	if (event == NETDEV_DOWN) |  | ||||||
| +		nf_ct_iterate_cleanup_net(net, nf_rtcache_dst_remove, dev, 0, 0); |  | ||||||
| + |  | ||||||
| +	return NOTIFY_DONE; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static struct notifier_block nf_rtcache_notifier = { |  | ||||||
| +	.notifier_call = nf_rtcache_netdev_event, |  | ||||||
| +}; |  | ||||||
| + |  | ||||||
| +static struct nf_hook_ops rtcache_ops[] = { |  | ||||||
| +	{ |  | ||||||
| +		.hook		= nf_rtcache_in4, |  | ||||||
| +		.pf		= NFPROTO_IPV4, |  | ||||||
| +		.hooknum	= NF_INET_PRE_ROUTING, |  | ||||||
| +		.priority       = NF_IP_PRI_LAST, |  | ||||||
| +	}, |  | ||||||
| +	{ |  | ||||||
| +		.hook           = nf_rtcache_forward4, |  | ||||||
| +		.pf             = NFPROTO_IPV4, |  | ||||||
| +		.hooknum        = NF_INET_FORWARD, |  | ||||||
| +		.priority       = NF_IP_PRI_LAST, |  | ||||||
| +	}, |  | ||||||
| +#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) |  | ||||||
| +	{ |  | ||||||
| +		.hook		= nf_rtcache_in6, |  | ||||||
| +		.pf		= NFPROTO_IPV6, |  | ||||||
| +		.hooknum	= NF_INET_PRE_ROUTING, |  | ||||||
| +		.priority       = NF_IP_PRI_LAST, |  | ||||||
| +	}, |  | ||||||
| +	{ |  | ||||||
| +		.hook           = nf_rtcache_forward6, |  | ||||||
| +		.pf             = NFPROTO_IPV6, |  | ||||||
| +		.hooknum        = NF_INET_FORWARD, |  | ||||||
| +		.priority       = NF_IP_PRI_LAST, |  | ||||||
| +	}, |  | ||||||
| +#endif |  | ||||||
| +}; |  | ||||||
| + |  | ||||||
| +static struct nf_ct_ext_type rtcache_extend __read_mostly = { |  | ||||||
| +	.len	= sizeof(struct nf_conn_rtcache), |  | ||||||
| +	.align	= __alignof__(struct nf_conn_rtcache), |  | ||||||
| +	.id	= NF_CT_EXT_RTCACHE, |  | ||||||
| +	.destroy = nf_conn_rtcache_destroy, |  | ||||||
| +}; |  | ||||||
| + |  | ||||||
| +static int __net_init rtcache_net_init(struct net *net) |  | ||||||
| +{ |  | ||||||
| +	return nf_register_net_hooks(net, rtcache_ops, ARRAY_SIZE(rtcache_ops)); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static void __net_exit rtcache_net_exit(struct net *net) |  | ||||||
| +{ |  | ||||||
| +	/* remove hooks so no new connections get rtcache extension */ |  | ||||||
| +	nf_unregister_net_hooks(net, rtcache_ops, ARRAY_SIZE(rtcache_ops)); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static struct pernet_operations rtcache_ops_net_ops = { |  | ||||||
| +	.init	= rtcache_net_init, |  | ||||||
| +	.exit	= rtcache_net_exit, |  | ||||||
| +}; |  | ||||||
| + |  | ||||||
| +static int __init nf_conntrack_rtcache_init(void) |  | ||||||
| +{ |  | ||||||
| +	int ret = nf_ct_extend_register(&rtcache_extend); |  | ||||||
| + |  | ||||||
| +	if (ret < 0) { |  | ||||||
| +		pr_err("nf_conntrack_rtcache: Unable to register extension\n"); |  | ||||||
| +		return ret; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	ret = register_pernet_subsys(&rtcache_ops_net_ops); |  | ||||||
| +	if (ret) { |  | ||||||
| +		nf_ct_extend_unregister(&rtcache_extend); |  | ||||||
| +		return ret; |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	ret = register_netdevice_notifier(&nf_rtcache_notifier); |  | ||||||
| +	if (ret) { |  | ||||||
| +		nf_ct_extend_unregister(&rtcache_extend); |  | ||||||
| +		unregister_pernet_subsys(&rtcache_ops_net_ops); |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	return ret; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static int nf_rtcache_ext_remove(struct nf_conn *ct, void *data) |  | ||||||
| +{ |  | ||||||
| +	struct nf_conn_rtcache *rtc = nf_ct_rtcache_find(ct); |  | ||||||
| + |  | ||||||
| +	return rtc != NULL; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static bool __exit nf_conntrack_rtcache_wait_for_dying(struct net *net) |  | ||||||
| +{ |  | ||||||
| +	bool wait = false; |  | ||||||
| +	int cpu; |  | ||||||
| + |  | ||||||
| +	for_each_possible_cpu(cpu) { |  | ||||||
| +		struct nf_conntrack_tuple_hash *h; |  | ||||||
| +		struct hlist_nulls_node *n; |  | ||||||
| +		struct nf_conn *ct; |  | ||||||
| +		struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); |  | ||||||
| + |  | ||||||
| +		rcu_read_lock(); |  | ||||||
| +		spin_lock_bh(&pcpu->lock); |  | ||||||
| + |  | ||||||
| +		hlist_nulls_for_each_entry(h, n, &pcpu->dying, hnnode) { |  | ||||||
| +			ct = nf_ct_tuplehash_to_ctrack(h); |  | ||||||
| +			if (nf_ct_rtcache_find(ct) != NULL) { |  | ||||||
| +				wait = true; |  | ||||||
| +				break; |  | ||||||
| +			} |  | ||||||
| +		} |  | ||||||
| +		spin_unlock_bh(&pcpu->lock); |  | ||||||
| +		rcu_read_unlock(); |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	return wait; |  | ||||||
| +} |  | ||||||
| + |  | ||||||
| +static void __exit nf_conntrack_rtcache_fini(void) |  | ||||||
| +{ |  | ||||||
| +	struct net *net; |  | ||||||
| +	int count = 0; |  | ||||||
| + |  | ||||||
| +	synchronize_net(); |  | ||||||
| + |  | ||||||
| +	unregister_netdevice_notifier(&nf_rtcache_notifier); |  | ||||||
| +	unregister_pernet_subsys(&rtcache_ops_net_ops); |  | ||||||
| + |  | ||||||
| +	synchronize_net(); |  | ||||||
| + |  | ||||||
| +	rtnl_lock(); |  | ||||||
| + |  | ||||||
| +	/* zap all conntracks with rtcache extension */ |  | ||||||
| +	for_each_net(net) |  | ||||||
| +		nf_ct_iterate_cleanup_net(net, nf_rtcache_ext_remove, NULL, 0, 0); |  | ||||||
| + |  | ||||||
| +	for_each_net(net) { |  | ||||||
| +		/* .. and make sure they're gone from dying list, too */ |  | ||||||
| +		while (nf_conntrack_rtcache_wait_for_dying(net)) { |  | ||||||
| +			msleep(200); |  | ||||||
| +			WARN_ONCE(++count > 25, "Waiting for all rtcache conntracks to go away\n"); |  | ||||||
| +		} |  | ||||||
| +	} |  | ||||||
| + |  | ||||||
| +	rtnl_unlock(); |  | ||||||
| + |  | ||||||
| +	synchronize_net(); |  | ||||||
| +	nf_ct_extend_unregister(&rtcache_extend); |  | ||||||
| +} |  | ||||||
| +module_init(nf_conntrack_rtcache_init); |  | ||||||
| +module_exit(nf_conntrack_rtcache_fini); |  | ||||||
| + |  | ||||||
| +MODULE_LICENSE("GPL"); |  | ||||||
| +MODULE_AUTHOR("Florian Westphal <fw@strlen.de>"); |  | ||||||
| +MODULE_DESCRIPTION("Conntrack route cache extension"); |  | ||||||
| @@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> | |||||||
|  |  | ||||||
| --- a/net/netfilter/Kconfig | --- a/net/netfilter/Kconfig | ||||||
| +++ b/net/netfilter/Kconfig | +++ b/net/netfilter/Kconfig | ||||||
| @@ -240,7 +240,6 @@ config NF_CONNTRACK_FTP | @@ -228,7 +228,6 @@ config NF_CONNTRACK_FTP | ||||||
|   |   | ||||||
|  config NF_CONNTRACK_H323 |  config NF_CONNTRACK_H323 | ||||||
|  	tristate "H.323 protocol support" |  	tristate "H.323 protocol support" | ||||||
| @@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> | |||||||
|  	depends on NETFILTER_ADVANCED |  	depends on NETFILTER_ADVANCED | ||||||
|  	help |  	help | ||||||
|  	  H.323 is a VoIP signalling protocol from ITU-T. As one of the most |  	  H.323 is a VoIP signalling protocol from ITU-T. As one of the most | ||||||
| @@ -1100,7 +1099,6 @@ config NETFILTER_XT_TARGET_SECMARK | @@ -1088,7 +1087,6 @@ config NETFILTER_XT_TARGET_SECMARK | ||||||
|   |   | ||||||
|  config NETFILTER_XT_TARGET_TCPMSS |  config NETFILTER_XT_TARGET_TCPMSS | ||||||
|  	tristate '"TCPMSS" target support' |  	tristate '"TCPMSS" target support' | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> | |||||||
|  	depends on !NF_CONNTRACK || NF_CONNTRACK |  	depends on !NF_CONNTRACK || NF_CONNTRACK | ||||||
| --- a/net/netfilter/Kconfig | --- a/net/netfilter/Kconfig | ||||||
| +++ b/net/netfilter/Kconfig | +++ b/net/netfilter/Kconfig | ||||||
| @@ -702,8 +702,6 @@ config NFT_FIB_NETDEV | @@ -690,8 +690,6 @@ config NFT_FIB_NETDEV | ||||||
|   |   | ||||||
|  endif # NF_TABLES_NETDEV |  endif # NF_TABLES_NETDEV | ||||||
|   |   | ||||||
| @@ -56,7 +56,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> | |||||||
|  config NF_FLOW_TABLE_INET |  config NF_FLOW_TABLE_INET | ||||||
|  	tristate "Netfilter flow table mixed IPv4/IPv6 module" |  	tristate "Netfilter flow table mixed IPv4/IPv6 module" | ||||||
|  	depends on NF_FLOW_TABLE |  	depends on NF_FLOW_TABLE | ||||||
| @@ -712,11 +710,12 @@ config NF_FLOW_TABLE_INET | @@ -700,11 +698,12 @@ config NF_FLOW_TABLE_INET | ||||||
|   |   | ||||||
|  	  To compile it as a module, choose M here. |  	  To compile it as a module, choose M here. | ||||||
|   |   | ||||||
| @@ -70,7 +70,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> | |||||||
|  	help |  	help | ||||||
|  	  This option adds the flow table core infrastructure. |  	  This option adds the flow table core infrastructure. | ||||||
|   |   | ||||||
| @@ -1005,6 +1004,15 @@ config NETFILTER_XT_TARGET_NOTRACK | @@ -993,6 +992,15 @@ config NETFILTER_XT_TARGET_NOTRACK | ||||||
|  	depends on NETFILTER_ADVANCED |  	depends on NETFILTER_ADVANCED | ||||||
|  	select NETFILTER_XT_TARGET_CT |  	select NETFILTER_XT_TARGET_CT | ||||||
|   |   | ||||||
| @@ -88,7 +88,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> | |||||||
|  	depends on NETFILTER_ADVANCED |  	depends on NETFILTER_ADVANCED | ||||||
| --- a/net/netfilter/Makefile | --- a/net/netfilter/Makefile | ||||||
| +++ b/net/netfilter/Makefile | +++ b/net/netfilter/Makefile | ||||||
| @@ -144,6 +144,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIF | @@ -141,6 +141,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIF | ||||||
|  obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o |  obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o | ||||||
|  obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o |  obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o | ||||||
|  obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o |  obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o | ||||||
|   | |||||||
| @@ -128,7 +128,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> | |||||||
|  #define NFTA_FLOWTABLE_MAX	(__NFTA_FLOWTABLE_MAX - 1) |  #define NFTA_FLOWTABLE_MAX	(__NFTA_FLOWTABLE_MAX - 1) | ||||||
| --- a/net/netfilter/Kconfig | --- a/net/netfilter/Kconfig | ||||||
| +++ b/net/netfilter/Kconfig | +++ b/net/netfilter/Kconfig | ||||||
| @@ -723,6 +723,15 @@ config NF_FLOW_TABLE | @@ -711,6 +711,15 @@ config NF_FLOW_TABLE | ||||||
|   |   | ||||||
|  	  To compile it as a module, choose M here. |  	  To compile it as a module, choose M here. | ||||||
|   |   | ||||||
| @@ -146,7 +146,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> | |||||||
|  	default m if NETFILTER_ADVANCED=n |  	default m if NETFILTER_ADVANCED=n | ||||||
| --- a/net/netfilter/Makefile | --- a/net/netfilter/Makefile | ||||||
| +++ b/net/netfilter/Makefile | +++ b/net/netfilter/Makefile | ||||||
| @@ -126,6 +126,7 @@ obj-$(CONFIG_NF_FLOW_TABLE)	+= nf_flow_t | @@ -123,6 +123,7 @@ obj-$(CONFIG_NF_FLOW_TABLE)	+= nf_flow_t | ||||||
|  nf_flow_table-objs := nf_flow_table_core.o nf_flow_table_ip.o |  nf_flow_table-objs := nf_flow_table_core.o nf_flow_table_ip.o | ||||||
|   |   | ||||||
|  obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o |  obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user