aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorfan.du <fan.du@windriver.com>2013-07-29 20:33:53 -0400
committerDavid S. Miller <davem@davemloft.net>2013-07-31 17:56:36 -0400
commitca4c3fc24e293719fe7410c4e63da9b6bc633b83 (patch)
tree0461841f3d10b11a26ebe1a0adc99c7b00a489a2 /net
parentba361cb3d4c977e2b94b5d97905f66b4d48964de (diff)
net: split rt_genid for ipv4 and ipv6
Current net name space has only one genid for both IPv4 and IPv6, it has below drawbacks: - Add/delete an IPv4 address will invalidate all IPv6 routing table entries. - Insert/remove XFRM policy will also invalidate both IPv4/IPv6 routing table entries even when the policy is only applied for one address family. Thus, this patch attempt to split one genid for two to cater for IPv4 and IPv6 separately in a fine granularity. Signed-off-by: Fan Du <fan.du@windriver.com> Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/route.c16
-rw-r--r--net/ipv6/af_inet6.c1
-rw-r--r--net/ipv6/route.c4
-rw-r--r--net/xfrm/xfrm_policy.c8
4 files changed, 18 insertions, 11 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a9a54a236832..e805481eff72 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -435,12 +435,12 @@ static inline int ip_rt_proc_init(void)
435 435
436static inline bool rt_is_expired(const struct rtable *rth) 436static inline bool rt_is_expired(const struct rtable *rth)
437{ 437{
438 return rth->rt_genid != rt_genid(dev_net(rth->dst.dev)); 438 return rth->rt_genid != rt_genid_ipv4(dev_net(rth->dst.dev));
439} 439}
440 440
441void rt_cache_flush(struct net *net) 441void rt_cache_flush(struct net *net)
442{ 442{
443 rt_genid_bump(net); 443 rt_genid_bump_ipv4(net);
444} 444}
445 445
446static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, 446static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
@@ -1458,7 +1458,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1458#endif 1458#endif
1459 rth->dst.output = ip_rt_bug; 1459 rth->dst.output = ip_rt_bug;
1460 1460
1461 rth->rt_genid = rt_genid(dev_net(dev)); 1461 rth->rt_genid = rt_genid_ipv4(dev_net(dev));
1462 rth->rt_flags = RTCF_MULTICAST; 1462 rth->rt_flags = RTCF_MULTICAST;
1463 rth->rt_type = RTN_MULTICAST; 1463 rth->rt_type = RTN_MULTICAST;
1464 rth->rt_is_input= 1; 1464 rth->rt_is_input= 1;
@@ -1589,7 +1589,7 @@ static int __mkroute_input(struct sk_buff *skb,
1589 goto cleanup; 1589 goto cleanup;
1590 } 1590 }
1591 1591
1592 rth->rt_genid = rt_genid(dev_net(rth->dst.dev)); 1592 rth->rt_genid = rt_genid_ipv4(dev_net(rth->dst.dev));
1593 rth->rt_flags = flags; 1593 rth->rt_flags = flags;
1594 rth->rt_type = res->type; 1594 rth->rt_type = res->type;
1595 rth->rt_is_input = 1; 1595 rth->rt_is_input = 1;
@@ -1760,7 +1760,7 @@ local_input:
1760 rth->dst.tclassid = itag; 1760 rth->dst.tclassid = itag;
1761#endif 1761#endif
1762 1762
1763 rth->rt_genid = rt_genid(net); 1763 rth->rt_genid = rt_genid_ipv4(net);
1764 rth->rt_flags = flags|RTCF_LOCAL; 1764 rth->rt_flags = flags|RTCF_LOCAL;
1765 rth->rt_type = res.type; 1765 rth->rt_type = res.type;
1766 rth->rt_is_input = 1; 1766 rth->rt_is_input = 1;
@@ -1945,7 +1945,7 @@ add:
1945 1945
1946 rth->dst.output = ip_output; 1946 rth->dst.output = ip_output;
1947 1947
1948 rth->rt_genid = rt_genid(dev_net(dev_out)); 1948 rth->rt_genid = rt_genid_ipv4(dev_net(dev_out));
1949 rth->rt_flags = flags; 1949 rth->rt_flags = flags;
1950 rth->rt_type = type; 1950 rth->rt_type = type;
1951 rth->rt_is_input = 0; 1951 rth->rt_is_input = 0;
@@ -2227,7 +2227,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
2227 rt->rt_iif = ort->rt_iif; 2227 rt->rt_iif = ort->rt_iif;
2228 rt->rt_pmtu = ort->rt_pmtu; 2228 rt->rt_pmtu = ort->rt_pmtu;
2229 2229
2230 rt->rt_genid = rt_genid(net); 2230 rt->rt_genid = rt_genid_ipv4(net);
2231 rt->rt_flags = ort->rt_flags; 2231 rt->rt_flags = ort->rt_flags;
2232 rt->rt_type = ort->rt_type; 2232 rt->rt_type = ort->rt_type;
2233 rt->rt_gateway = ort->rt_gateway; 2233 rt->rt_gateway = ort->rt_gateway;
@@ -2665,7 +2665,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = {
2665 2665
2666static __net_init int rt_genid_init(struct net *net) 2666static __net_init int rt_genid_init(struct net *net)
2667{ 2667{
2668 atomic_set(&net->rt_genid, 0); 2668 atomic_set(&net->ipv4.rt_genid, 0);
2669 atomic_set(&net->fnhe_genid, 0); 2669 atomic_set(&net->fnhe_genid, 0);
2670 get_random_bytes(&net->ipv4.dev_addr_genid, 2670 get_random_bytes(&net->ipv4.dev_addr_genid,
2671 sizeof(net->ipv4.dev_addr_genid)); 2671 sizeof(net->ipv4.dev_addr_genid));
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index a5ac969aeefe..0d1a9b153fbb 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -766,6 +766,7 @@ static int __net_init inet6_net_init(struct net *net)
766 766
767 net->ipv6.sysctl.bindv6only = 0; 767 net->ipv6.sysctl.bindv6only = 0;
768 net->ipv6.sysctl.icmpv6_time = 1*HZ; 768 net->ipv6.sysctl.icmpv6_time = 1*HZ;
769 atomic_set(&net->ipv6.rt_genid, 0);
769 770
770 err = ipv6_init_mibs(net); 771 err = ipv6_init_mibs(net);
771 if (err) 772 if (err)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 74ab1f74abcd..ce9616304521 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -283,7 +283,7 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
283 283
284 memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); 284 memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
285 rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); 285 rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
286 rt->rt6i_genid = rt_genid(net); 286 rt->rt6i_genid = rt_genid_ipv6(net);
287 INIT_LIST_HEAD(&rt->rt6i_siblings); 287 INIT_LIST_HEAD(&rt->rt6i_siblings);
288 } 288 }
289 return rt; 289 return rt;
@@ -1061,7 +1061,7 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
1061 * DST_OBSOLETE_FORCE_CHK which forces validation calls down 1061 * DST_OBSOLETE_FORCE_CHK which forces validation calls down
1062 * into this function always. 1062 * into this function always.
1063 */ 1063 */
1064 if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev))) 1064 if (rt->rt6i_genid != rt_genid_ipv6(dev_net(rt->dst.dev)))
1065 return NULL; 1065 return NULL;
1066 1066
1067 if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) 1067 if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie))
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index e52cab3591dd..d8da6b8c6ba8 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -660,7 +660,13 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
660 xfrm_pol_hold(policy); 660 xfrm_pol_hold(policy);
661 net->xfrm.policy_count[dir]++; 661 net->xfrm.policy_count[dir]++;
662 atomic_inc(&flow_cache_genid); 662 atomic_inc(&flow_cache_genid);
663 rt_genid_bump(net); 663
664 /* After previous checking, family can either be AF_INET or AF_INET6 */
665 if (policy->family == AF_INET)
666 rt_genid_bump_ipv4(net);
667 else
668 rt_genid_bump_ipv6(net);
669
664 if (delpol) { 670 if (delpol) {
665 xfrm_policy_requeue(delpol, policy); 671 xfrm_policy_requeue(delpol, policy);
666 __xfrm_policy_unlink(delpol, dir); 672 __xfrm_policy_unlink(delpol, dir);