We want to propagate new hostname to DNS server via DHCP server.
Previously, a DHCP release followed by a new DORA cycle was used.
This did update DNS name, but VM was for a short period of time
without a valid IP.

Now an early lease renew (with the new hostname included) is sent.
Thus VM does not need to stop using assigned IP address.

Fixes #816

Signed-off-by: Justin Cinkelj <justin.cink...@xlab.si>
---
 core/dhcp.cc                     | 33 +++++++++++++++++++++++++++++----
 include/osv/dhcp.hh              |  4 +++-
 modules/cloud-init/cloud-init.cc | 10 +++++-----
 3 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/core/dhcp.cc b/core/dhcp.cc
index 0436837..b0e9f1e 100644
--- a/core/dhcp.cc
+++ b/core/dhcp.cc
@@ -72,10 +72,9 @@ void dhcp_release()
     net_dhcp_worker.release();
 }
 
-void dhcp_restart(bool wait)
+void dhcp_renew()
 {
-    net_dhcp_worker.release();
-    net_dhcp_worker.start(wait);
+    net_dhcp_worker.renew();
 }
 
 namespace dhcp {
@@ -221,6 +220,9 @@ namespace dhcp {
         pkt->secs = 0;
         pkt->flags = 0;
         memcpy(pkt->chaddr, IF_LLADDR(ifp), ETHER_ADDR_LEN);
+        ulong yip_n = htonl(yip.to_ulong());
+        ulong sip_n = htonl(sip.to_ulong());
+        memcpy(&pkt->ciaddr.s_addr, &yip_n, 4);
 
         // Options
         u8* options_start = reinterpret_cast<u8*>(pkt+1);
@@ -242,7 +244,7 @@ namespace dhcp {
         *options++ = DHCP_OPTION_END;
 
         dhcp_len += options - options_start;
-        build_udp_ip_headers(dhcp_len, INADDR_ANY, INADDR_BROADCAST);
+        build_udp_ip_headers(dhcp_len, yip_n, sip_n);
     }
 
     void dhcp_mbuf::compose_release(struct ifnet* ifp,
@@ -541,6 +543,22 @@ namespace dhcp {
         _client_addr = _server_addr = ipv4_zero;
     }
 
+    void dhcp_interface_state::renew()
+    {
+        // Update state
+        _state = DHCP_REQUEST;
+
+        // Compose a dhcp request packet
+        dhcp_mbuf dm(false);
+        _xid = rand();
+        dm.compose_request(_ifp,
+                           _xid,
+                           _client_addr, _server_addr);
+
+        // Send
+        _sock->dhcp_send(dm);
+    }
+
     void dhcp_interface_state::process_packet(struct mbuf* m)
     {
         dhcp_mbuf dm(true, m);
@@ -724,6 +742,13 @@ namespace dhcp {
         usleep(1000);
     }
 
+    void dhcp_worker::renew()
+    {
+        for (auto &it: _universe) {
+            it.second->renew();
+        }
+    }
+
     void dhcp_worker::dhcp_worker_fn()
     {
         while (true) {
diff --git a/include/osv/dhcp.hh b/include/osv/dhcp.hh
index b286727..166df48 100644
--- a/include/osv/dhcp.hh
+++ b/include/osv/dhcp.hh
@@ -25,7 +25,7 @@
 extern "C" {
 void dhcp_start(bool wait);
 void dhcp_release();
-void dhcp_restart(bool wait);
+void dhcp_renew();
 }
 
 namespace dhcp {
@@ -226,6 +226,7 @@ namespace dhcp {
 
         void discover();
         void release();
+        void renew();
         void process_packet(struct mbuf*);
         void state_discover(dhcp_mbuf &dm);
         void state_request(dhcp_mbuf &dm);
@@ -256,6 +257,7 @@ namespace dhcp {
         void start(bool wait);
         // Send release packet for all DHCP IPs.
         void release();
+        void renew();
 
         void dhcp_worker_fn();
         void queue_packet(struct mbuf* m);
diff --git a/modules/cloud-init/cloud-init.cc b/modules/cloud-init/cloud-init.cc
index e3ec8f8..f9b35de 100644
--- a/modules/cloud-init/cloud-init.cc
+++ b/modules/cloud-init/cloud-init.cc
@@ -17,17 +17,17 @@
 #include <osv/hypervisor.hh>
 
 // we cannot include osv/dhcp.hh, hence direct declaration.
-extern "C" void dhcp_restart(bool wait);
+extern "C" void dhcp_renew();
 
 // Set the hostname to given string.
 // If hostname changes, try to propagate the change to DHCP server too.
-void set_hostname_restart_dhcp(std::string hostname) {
+void set_hostname_renew_dhcp(std::string hostname) {
     if (hostname.length() > 0) {
         char old_hostname[256] = "";
         gethostname(old_hostname, sizeof(old_hostname));
         sethostname(hostname.c_str(), hostname.length());
         if (hostname != old_hostname) {
-            dhcp_restart(true);
+            dhcp_renew();
         }
     }
 }
@@ -245,7 +245,7 @@ void hostname_module::handle(const YAML::Node& doc)
 {
     auto hostname = doc.as<string>();
     debug("cloudinit hostname: %s\n", hostname.c_str());
-    set_hostname_restart_dhcp(hostname);
+    set_hostname_renew_dhcp(hostname);
 }
 
 void osvinit::add_module(std::shared_ptr<config_module> module)
@@ -280,7 +280,7 @@ void osvinit::load_from_cloud(bool ignore_missing_source)
         auto& ds = get_data_source();
 
         // Set the hostname from given data source, if it exists.
-        set_hostname_restart_dhcp(ds.external_hostname());
+        set_hostname_renew_dhcp(ds.external_hostname());
 
         // Load user data.
         user_data = ds.get_user_data();
-- 
2.9.3

-- 
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