ipv6: use net->rt_genid to check dst validity
authorNicolas Dichtel <nicolas.dichtel@6wind.com>
Mon, 10 Sep 2012 22:09:46 +0000 (22:09 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 18 Sep 2012 19:57:03 +0000 (15:57 -0400)
IPv6 dst should take care of rt_genid too. When a xfrm policy is inserted or
deleted, all dst should be invalidated.
To force the validation, dst entries should be created with ->obsolete set to
DST_OBSOLETE_FORCE_CHK. This was already the case for all functions calling
ip6_dst_alloc(), except for ip6_rt_copy().

As a consequence, we can remove the specific code in inet6_connection_sock.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ip6_fib.h
net/ipv6/inet6_connection_sock.c
net/ipv6/route.c

index 0fedbd8d747a049db1810fdc325b032d62782b1b..9fc7114159e885031550abedebf67c74f08bde76 100644 (file)
@@ -111,9 +111,8 @@ struct rt6_info {
        struct inet6_dev                *rt6i_idev;
        unsigned long                   _rt6i_peer;
 
-#ifdef CONFIG_XFRM
-       u32                             rt6i_flow_cache_genid;
-#endif
+       u32                             rt6i_genid;
+
        /* more non-fragment space at head required */
        unsigned short                  rt6i_nfheader_len;
 
index 0251a6005be8ff8d35cffe7fb0e2611b43296158..c4f934176cabd92ebfb4bba774335427b9f8932a 100644 (file)
@@ -175,33 +175,12 @@ void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst,
                           const struct in6_addr *saddr)
 {
        __ip6_dst_store(sk, dst, daddr, saddr);
-
-#ifdef CONFIG_XFRM
-       {
-               struct rt6_info *rt = (struct rt6_info  *)dst;
-               rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid);
-       }
-#endif
 }
 
 static inline
 struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie)
 {
-       struct dst_entry *dst;
-
-       dst = __sk_dst_check(sk, cookie);
-
-#ifdef CONFIG_XFRM
-       if (dst) {
-               struct rt6_info *rt = (struct rt6_info *)dst;
-               if (rt->rt6i_flow_cache_genid != atomic_read(&flow_cache_genid)) {
-                       __sk_dst_reset(sk);
-                       dst = NULL;
-               }
-       }
-#endif
-
-       return dst;
+       return __sk_dst_check(sk, cookie);
 }
 
 static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
index 8e80fd279100d7d18d111eff1be73f10fdd6eeaf..fb29e2215a19db8c8382d07af00afec47017e1fa 100644 (file)
@@ -281,13 +281,14 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
                                             struct fib6_table *table)
 {
        struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
-                                       0, DST_OBSOLETE_NONE, flags);
+                                       0, DST_OBSOLETE_FORCE_CHK, flags);
 
        if (rt) {
                struct dst_entry *dst = &rt->dst;
 
                memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
                rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
+               rt->rt6i_genid = rt_genid(net);
        }
        return rt;
 }
@@ -1031,6 +1032,13 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
 
        rt = (struct rt6_info *) dst;
 
+       /* All IPV6 dsts are created with ->obsolete set to the value
+        * DST_OBSOLETE_FORCE_CHK which forces validation calls down
+        * into this function always.
+        */
+       if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev)))
+               return NULL;
+
        if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) {
                if (rt->rt6i_peer_genid != rt6_peer_genid()) {
                        if (!rt6_has_peer(rt))
@@ -1397,8 +1405,6 @@ int ip6_route_add(struct fib6_config *cfg)
                goto out;
        }
 
-       rt->dst.obsolete = -1;
-
        if (cfg->fc_flags & RTF_EXPIRES)
                rt6_set_expires(rt, jiffies +
                                clock_t_to_jiffies(cfg->fc_expires));
@@ -2080,7 +2086,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
        rt->dst.input = ip6_input;
        rt->dst.output = ip6_output;
        rt->rt6i_idev = idev;
-       rt->dst.obsolete = -1;
 
        rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
        if (anycast)