diff options
Diffstat (limited to 'main/linux-virt-grsec/0005-ipv4-use-separate-genid-for-next-hop-exceptions.patch')
-rw-r--r-- | main/linux-virt-grsec/0005-ipv4-use-separate-genid-for-next-hop-exceptions.patch | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/main/linux-virt-grsec/0005-ipv4-use-separate-genid-for-next-hop-exceptions.patch b/main/linux-virt-grsec/0005-ipv4-use-separate-genid-for-next-hop-exceptions.patch new file mode 100644 index 0000000000..40cd4fc6c1 --- /dev/null +++ b/main/linux-virt-grsec/0005-ipv4-use-separate-genid-for-next-hop-exceptions.patch @@ -0,0 +1,116 @@ +From 4a7dbb238480fac2b1ad02a74240efcf225c1f45 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> +Date: Mon, 27 May 2013 10:55:52 +0300 +Subject: [PATCH 5/6] ipv4: use separate genid for next hop exceptions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 13d82bf5 (ipv4: Fix flushing of cached routing informations) +added the support to flush learned pmtu information. + +However, using rt_genid is quite heavy as it is bumped on route +add/change and multicast events amongst other places. These can +happen quote often, especially if using dynamic routing protocols. + +While this is ok with routes (as they are just recreated locally), +the pmtu information is learned from remote systems and the icmp +notification can come with long delays. It is worthy to have separate +genid to avoid excessive pmtu resets. + +Cc: Steffen Klassert <steffen.klassert@secunet.com> +Signed-off-by: Timo Teräs <timo.teras@iki.fi> +--- + include/net/ip_fib.h | 1 + + include/net/net_namespace.h | 11 +++++++++++ + net/ipv4/route.c | 12 ++++++++++-- + 3 files changed, 22 insertions(+), 2 deletions(-) + +diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h +index e49db91..44424e9 100644 +--- a/include/net/ip_fib.h ++++ b/include/net/ip_fib.h +@@ -51,6 +51,7 @@ struct rtable; + + struct fib_nh_exception { + struct fib_nh_exception __rcu *fnhe_next; ++ int fnhe_genid; + __be32 fnhe_daddr; + u32 fnhe_pmtu; + __be32 fnhe_gw; +diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h +index de644bc..b5a5baf 100644 +--- a/include/net/net_namespace.h ++++ b/include/net/net_namespace.h +@@ -116,6 +116,7 @@ struct net { + struct netns_ipvs *ipvs; + struct sock *diag_nlsk; + atomic_unchecked_t rt_genid; ++ atomic_unchecked_t fnhe_genid; + }; + + /* +@@ -338,4 +339,14 @@ static inline void rt_genid_bump(struct net *net) + atomic_inc_unchecked(&net->rt_genid); + } + ++static inline int fnhe_genid(struct net *net) ++{ ++ return atomic_read_unchecked(&net->fnhe_genid); ++} ++ ++static inline void fnhe_genid_bump(struct net *net) ++{ ++ atomic_inc_unchecked(&net->fnhe_genid); ++} ++ + #endif /* __NET_NET_NAMESPACE_H */ +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 85b9c07..f44a4bb 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -658,6 +658,7 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, + fnhe->fnhe_next = hash->chain; + rcu_assign_pointer(hash->chain, fnhe); + } ++ fnhe->fnhe_genid = fnhe_genid(dev_net(nh->nh_dev)); + fnhe->fnhe_daddr = daddr; + fnhe->fnhe_gw = gw; + fnhe->fnhe_pmtu = pmtu; +@@ -1236,8 +1237,11 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, + spin_lock_bh(&fnhe_lock); + + if (daddr == fnhe->fnhe_daddr) { ++ int genid = fnhe_genid(dev_net(rt->dst.dev)); + struct rtable *orig = rcu_dereference(fnhe->fnhe_rth); +- if (orig && rt_is_expired(orig)) { ++ ++ if (fnhe->fnhe_genid != genid) { ++ fnhe->fnhe_genid = genid; + fnhe->fnhe_gw = 0; + fnhe->fnhe_pmtu = 0; + fnhe->fnhe_expires = 0; +@@ -2443,8 +2447,11 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write, + void __user *buffer, + size_t *lenp, loff_t *ppos) + { ++ struct net *net = (struct net *)__ctl->extra1; ++ + if (write) { +- rt_cache_flush((struct net *)__ctl->extra1); ++ rt_cache_flush(net); ++ fnhe_genid_bump(net); + return 0; + } + +@@ -2619,6 +2626,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = { + static __net_init int rt_genid_init(struct net *net) + { + atomic_set_unchecked(&net->rt_genid, 0); ++ atomic_set_unchecked(&net->fnhe_genid, 0); + get_random_bytes(&net->ipv4.dev_addr_genid, + sizeof(net->ipv4.dev_addr_genid)); + return 0; +-- +1.8.2.3 + |