From: Andrew Morton <[EMAIL PROTECTED]>
Date: Wed, 27 Jul 2005 14:38:35 -0700

>            Summary: IPSec incompabilty. Linux kernel waits to long to start
>                     using new SA for outbound traffic.

I think this is the known bug where we don't notice that a route
attached to a socket is obsolete.  It was first pointed out to
me last year by Kazunori Miyazawa, CC:'d here.

The problem is that, when we update IPSEC rules, sockets currently
don't have a way to discover that.

Traditionally, the route "obsolete" flag served this purpose, and that
does work properly for normal route entries.  But for IPSEC, we don't
have a way to find all of the stacked routes we created that match a
particular SA, and thus get them fixed up the next time a socket tries
to send a packet.

One idea tossed around between Herbert Xu (also CC:'d) and myself is
to store a generation counter when we attach a route to a socket, then
sk_dst_check() can verify that this generation count matches the
current IPSEC flow cache generation count.

Something like the following, untested patch, demonstrates the
idea.

[NET]: Tie obsolete state of routes also to flow cache generation count.

This fixes the problem wherein IPSEC SA changes do not get noticed
by cached socket routes.

Signed-off-by: David S. Miller <[EMAIL PROTECTED]>

diff --git a/include/net/sock.h b/include/net/sock.h
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -54,6 +54,7 @@
 #include <asm/atomic.h>
 #include <net/dst.h>
 #include <net/checksum.h>
+#include <net/flow.h>
 
 /*
  * This structure really needs to be cleaned up.
@@ -193,6 +194,7 @@ struct sock {
        socket_lock_t           sk_lock;
        wait_queue_head_t       *sk_sleep;
        struct dst_entry        *sk_dst_cache;
+       unsigned int            sk_dst_cache_genid;
        struct xfrm_policy      *sk_policy[2];
        rwlock_t                sk_dst_lock;
        atomic_t                sk_rmem_alloc;
@@ -924,6 +926,9 @@ __sk_dst_set(struct sock *sk, struct dst
 
        old_dst = sk->sk_dst_cache;
        sk->sk_dst_cache = dst;
+#ifdef CONFIG_XFRM
+       sk->sk_dst_cache_genid = atomic_read(&flow_cache_genid);
+#endif
        dst_release(old_dst);
 }
 
@@ -958,7 +963,9 @@ __sk_dst_check(struct sock *sk, u32 cook
 {
        struct dst_entry *dst = sk->sk_dst_cache;
 
-       if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
+       if (dst &&
+           ((dst->obsolete && dst->ops->check(dst, cookie) == NULL) ||
+            (sk->sk_dst_cache_genid != atomic_read(&flow_cache_genid)))) {
                sk->sk_dst_cache = NULL;
                dst_release(dst);
                return NULL;
@@ -972,7 +979,9 @@ sk_dst_check(struct sock *sk, u32 cookie
 {
        struct dst_entry *dst = sk_dst_get(sk);
 
-       if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
+       if (dst &&
+           ((dst->obsolete && dst->ops->check(dst, cookie) == NULL) ||
+            (sk->sk_dst_cache_genid != atomic_read(&flow_cache_genid)))) {
                sk_dst_reset(sk);
                dst_release(dst);
                return NULL;
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to