diff options
-rw-r--r-- | include/net/ip6_fib.h | 4 | ||||
-rw-r--r-- | net/ipv6/inet6_connection_sock.c | 39 |
2 files changed, 41 insertions, 2 deletions
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index c48ea873f1e0..857821360bb6 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h | |||
@@ -105,6 +105,10 @@ struct rt6_info | |||
105 | struct rt6key rt6i_src; | 105 | struct rt6key rt6i_src; |
106 | 106 | ||
107 | u8 rt6i_protocol; | 107 | u8 rt6i_protocol; |
108 | |||
109 | #ifdef CONFIG_XFRM | ||
110 | u32 rt6i_flow_cache_genid; | ||
111 | #endif | ||
108 | }; | 112 | }; |
109 | 113 | ||
110 | static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst) | 114 | static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst) |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 116f94a49071..25b931709749 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -139,6 +139,41 @@ void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr) | |||
139 | 139 | ||
140 | EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr); | 140 | EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr); |
141 | 141 | ||
142 | static inline | ||
143 | void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst, | ||
144 | struct in6_addr *daddr, struct in6_addr *saddr) | ||
145 | { | ||
146 | __ip6_dst_store(sk, dst, daddr, saddr); | ||
147 | |||
148 | #ifdef CONFIG_XFRM | ||
149 | if (dst) { | ||
150 | struct rt6_info *rt = (struct rt6_info *)dst; | ||
151 | rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid); | ||
152 | } | ||
153 | #endif | ||
154 | } | ||
155 | |||
156 | static inline | ||
157 | struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) | ||
158 | { | ||
159 | struct dst_entry *dst; | ||
160 | |||
161 | dst = __sk_dst_check(sk, cookie); | ||
162 | |||
163 | #ifdef CONFIG_XFRM | ||
164 | if (dst) { | ||
165 | struct rt6_info *rt = (struct rt6_info *)dst; | ||
166 | if (rt->rt6i_flow_cache_genid != atomic_read(&flow_cache_genid)) { | ||
167 | sk->sk_dst_cache = NULL; | ||
168 | dst_release(dst); | ||
169 | dst = NULL; | ||
170 | } | ||
171 | } | ||
172 | #endif | ||
173 | |||
174 | return dst; | ||
175 | } | ||
176 | |||
142 | int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) | 177 | int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) |
143 | { | 178 | { |
144 | struct sock *sk = skb->sk; | 179 | struct sock *sk = skb->sk; |
@@ -166,7 +201,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) | |||
166 | final_p = &final; | 201 | final_p = &final; |
167 | } | 202 | } |
168 | 203 | ||
169 | dst = __sk_dst_check(sk, np->dst_cookie); | 204 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); |
170 | 205 | ||
171 | if (dst == NULL) { | 206 | if (dst == NULL) { |
172 | int err = ip6_dst_lookup(sk, &dst, &fl); | 207 | int err = ip6_dst_lookup(sk, &dst, &fl); |
@@ -186,7 +221,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) | |||
186 | return err; | 221 | return err; |
187 | } | 222 | } |
188 | 223 | ||
189 | __ip6_dst_store(sk, dst, NULL, NULL); | 224 | __inet6_csk_dst_store(sk, dst, NULL, NULL); |
190 | } | 225 | } |
191 | 226 | ||
192 | skb->dst = dst_clone(dst); | 227 | skb->dst = dst_clone(dst); |