Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca4c3fc2 authored by fan.du's avatar fan.du Committed by David S. Miller
Browse files

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: default avatarFan Du <fan.du@windriver.com>
Acked-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ba361cb3
Loading
Loading
Loading
Loading
+32 −5
Original line number Original line Diff line number Diff line
@@ -119,7 +119,6 @@ struct net {
	struct netns_ipvs	*ipvs;
	struct netns_ipvs	*ipvs;
#endif
#endif
	struct sock		*diag_nlsk;
	struct sock		*diag_nlsk;
	atomic_t		rt_genid;
	atomic_t		fnhe_genid;
	atomic_t		fnhe_genid;
};
};


@@ -333,14 +332,42 @@ static inline void unregister_net_sysctl_table(struct ctl_table_header *header)
}
}
#endif
#endif


static inline int rt_genid(struct net *net)
static inline int rt_genid_ipv4(struct net *net)
{
{
	return atomic_read(&net->rt_genid);
	return atomic_read(&net->ipv4.rt_genid);
}
}


static inline void rt_genid_bump(struct net *net)
static inline void rt_genid_bump_ipv4(struct net *net)
{
{
	atomic_inc(&net->rt_genid);
	atomic_inc(&net->ipv4.rt_genid);
}

#if IS_ENABLED(CONFIG_IPV6)
static inline int rt_genid_ipv6(struct net *net)
{
	return atomic_read(&net->ipv6.rt_genid);
}

static inline void rt_genid_bump_ipv6(struct net *net)
{
	atomic_inc(&net->ipv6.rt_genid);
}
#else
static inline int rt_genid_ipv6(struct net *net)
{
	return 0;
}

static inline void rt_genid_bump_ipv6(struct net *net)
{
}
#endif

/* For callers who don't really care about whether it's IPv4 or IPv6 */
static inline void rt_genid_bump_all(struct net *net)
{
	rt_genid_bump_ipv4(net);
	rt_genid_bump_ipv6(net);
}
}


static inline int fnhe_genid(struct net *net)
static inline int fnhe_genid(struct net *net)
+1 −0
Original line number Original line Diff line number Diff line
@@ -77,5 +77,6 @@ struct netns_ipv4 {
	struct fib_rules_ops	*mr_rules_ops;
	struct fib_rules_ops	*mr_rules_ops;
#endif
#endif
#endif
#endif
	atomic_t	rt_genid;
};
};
#endif
#endif
+1 −0
Original line number Original line Diff line number Diff line
@@ -72,6 +72,7 @@ struct netns_ipv6 {
#endif
#endif
#endif
#endif
	atomic_t		dev_addr_genid;
	atomic_t		dev_addr_genid;
	atomic_t		rt_genid;
};
};


#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
+8 −8
Original line number Original line Diff line number Diff line
@@ -435,12 +435,12 @@ static inline int ip_rt_proc_init(void)


static inline bool rt_is_expired(const struct rtable *rth)
static inline bool rt_is_expired(const struct rtable *rth)
{
{
	return rth->rt_genid != rt_genid(dev_net(rth->dst.dev));
	return rth->rt_genid != rt_genid_ipv4(dev_net(rth->dst.dev));
}
}


void rt_cache_flush(struct net *net)
void rt_cache_flush(struct net *net)
{
{
	rt_genid_bump(net);
	rt_genid_bump_ipv4(net);
}
}


static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
static 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,
#endif
#endif
	rth->dst.output = ip_rt_bug;
	rth->dst.output = ip_rt_bug;


	rth->rt_genid	= rt_genid(dev_net(dev));
	rth->rt_genid	= rt_genid_ipv4(dev_net(dev));
	rth->rt_flags	= RTCF_MULTICAST;
	rth->rt_flags	= RTCF_MULTICAST;
	rth->rt_type	= RTN_MULTICAST;
	rth->rt_type	= RTN_MULTICAST;
	rth->rt_is_input= 1;
	rth->rt_is_input= 1;
@@ -1589,7 +1589,7 @@ static int __mkroute_input(struct sk_buff *skb,
		goto cleanup;
		goto cleanup;
	}
	}


	rth->rt_genid = rt_genid(dev_net(rth->dst.dev));
	rth->rt_genid = rt_genid_ipv4(dev_net(rth->dst.dev));
	rth->rt_flags = flags;
	rth->rt_flags = flags;
	rth->rt_type = res->type;
	rth->rt_type = res->type;
	rth->rt_is_input = 1;
	rth->rt_is_input = 1;
@@ -1760,7 +1760,7 @@ out: return err;
	rth->dst.tclassid = itag;
	rth->dst.tclassid = itag;
#endif
#endif


	rth->rt_genid = rt_genid(net);
	rth->rt_genid = rt_genid_ipv4(net);
	rth->rt_flags 	= flags|RTCF_LOCAL;
	rth->rt_flags 	= flags|RTCF_LOCAL;
	rth->rt_type	= res.type;
	rth->rt_type	= res.type;
	rth->rt_is_input = 1;
	rth->rt_is_input = 1;
@@ -1945,7 +1945,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,


	rth->dst.output = ip_output;
	rth->dst.output = ip_output;


	rth->rt_genid = rt_genid(dev_net(dev_out));
	rth->rt_genid = rt_genid_ipv4(dev_net(dev_out));
	rth->rt_flags	= flags;
	rth->rt_flags	= flags;
	rth->rt_type	= type;
	rth->rt_type	= type;
	rth->rt_is_input = 0;
	rth->rt_is_input = 0;
@@ -2227,7 +2227,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
		rt->rt_iif = ort->rt_iif;
		rt->rt_iif = ort->rt_iif;
		rt->rt_pmtu = ort->rt_pmtu;
		rt->rt_pmtu = ort->rt_pmtu;


		rt->rt_genid = rt_genid(net);
		rt->rt_genid = rt_genid_ipv4(net);
		rt->rt_flags = ort->rt_flags;
		rt->rt_flags = ort->rt_flags;
		rt->rt_type = ort->rt_type;
		rt->rt_type = ort->rt_type;
		rt->rt_gateway = ort->rt_gateway;
		rt->rt_gateway = ort->rt_gateway;
@@ -2665,7 +2665,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = {


static __net_init int rt_genid_init(struct net *net)
static __net_init int rt_genid_init(struct net *net)
{
{
	atomic_set(&net->rt_genid, 0);
	atomic_set(&net->ipv4.rt_genid, 0);
	atomic_set(&net->fnhe_genid, 0);
	atomic_set(&net->fnhe_genid, 0);
	get_random_bytes(&net->ipv4.dev_addr_genid,
	get_random_bytes(&net->ipv4.dev_addr_genid,
			 sizeof(net->ipv4.dev_addr_genid));
			 sizeof(net->ipv4.dev_addr_genid));
+1 −0
Original line number Original line Diff line number Diff line
@@ -766,6 +766,7 @@ static int __net_init inet6_net_init(struct net *net)


	net->ipv6.sysctl.bindv6only = 0;
	net->ipv6.sysctl.bindv6only = 0;
	net->ipv6.sysctl.icmpv6_time = 1*HZ;
	net->ipv6.sysctl.icmpv6_time = 1*HZ;
	atomic_set(&net->ipv6.rt_genid, 0);


	err = ipv6_init_mibs(net);
	err = ipv6_init_mibs(net);
	if (err)
	if (err)
Loading