In core/dhcp.cc, osv::start_if() is used to configure an interface based
on a DHCP lease.

Cloud-init calls dhcp_renew() after the hostname has changed (due to
data_source::external_hostname() returning a different hostname than the
current one). This will have the DHCP code renew the lease, and calling
osv::start_if() again, which removes the old IP address from the network
interface even if it is unchanged. Routes using that particular network
interface are also removed.

This will lead to stale entries in the route cache, which might cause
later network connections to fail (I've seen timeout/"Operation
Canceled" problems on EC2 when OSv was trying to fetch user-data after
renewing the DHCP lease).

This commit implements invalidate() for the route cache in
bsd/sys/net/routecache.hh, and have the SIOCDIFADDR handler call this
method when removing the active IP address. This fixes the connection
problems I was seeing.

Note: bug #873 might be related.

Signed-off-by: Vilmos Nebehaj <v.nebe...@gmail.com>
---
 bsd/sys/net/routecache.hh | 7 ++++++-
 bsd/sys/netinet/in.cc     | 7 +++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/bsd/sys/net/routecache.hh b/bsd/sys/net/routecache.hh
index 0dc3f91b..39c05bd8 100644
--- a/bsd/sys/net/routecache.hh
+++ b/bsd/sys/net/routecache.hh
@@ -171,7 +171,12 @@ public:
     }
 
     static void invalidate() {
-
+        WITH_LOCK(cache_mutex) {
+            auto *old_cache = cache.read_by_owner();
+            auto new_cache = new routemap();
+            cache.assign(new_cache);
+            osv::rcu_dispose(old_cache);
+        }
     }
 };
 
diff --git a/bsd/sys/netinet/in.cc b/bsd/sys/netinet/in.cc
index 1520b302..f7c19345 100644
--- a/bsd/sys/netinet/in.cc
+++ b/bsd/sys/netinet/in.cc
@@ -50,6 +50,7 @@
 #include <bsd/sys/net/if_llatbl.h>
 #include <bsd/sys/net/if_types.h>
 #include <bsd/sys/net/route.h>
+#include <bsd/sys/net/routecache.hh>
 #include <bsd/sys/net/vnet.h>
 
 #include <bsd/sys/netinet/in.h>
@@ -562,6 +563,12 @@ in_control(struct socket *so, u_long cmd, caddr_t data, 
struct ifnet *ifp,
                goto out;
 
        case SIOCDIFADDR:
+        /*
+         * Flush the route cache, since it likely contains entries that are
+         * going away here.
+         */
+        route_cache::invalidate();
+
                /*
                 * in_ifscrub kills the interface route.
                 */
-- 
2.11.0

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to