From: Justin Cinkelj <[email protected]>
Committer: Nadav Har'El <[email protected]>
Branch: master
dhcp: do not release assigned IP just to update DNS name
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 <[email protected]>
Message-Id: <[email protected]>
---
diff --git a/core/dhcp.cc b/core/dhcp.cc
--- 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(bool wait)
{
- net_dhcp_worker.release();
- net_dhcp_worker.start(wait);
+ net_dhcp_worker.renew(wait);
}
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);
@@ -692,13 +710,14 @@ namespace dhcp {
_dhcp_thread->start();
}
- void dhcp_worker::start(bool wait)
+ void dhcp_worker::_send_and_wait(bool wait,
dhcp_interface_state_send_packet iface_func)
{
- // FIXME: clear routing table (use case run dhclient 2nd time)
+ // When doing renew, we still have IP, but want to reuse the flag.
+ _have_ip = false;
do {
- // Send discover packets!
+ // Send discover or renew packets!
for (auto &it: _universe) {
- it.second->discover();
+ (it.second->*iface_func)();
}
if (wait) {
@@ -714,6 +733,12 @@ namespace dhcp {
} while (!_have_ip && wait);
}
+ void dhcp_worker::start(bool wait)
+ {
+ // FIXME: clear routing table (use case run dhclient 2nd time)
+ _send_and_wait(wait, &dhcp_interface_state::discover);
+ }
+
void dhcp_worker::release()
{
for (auto &it: _universe) {
@@ -724,6 +749,11 @@ namespace dhcp {
usleep(1000);
}
+ void dhcp_worker::renew(bool wait)
+ {
+ _send_and_wait(wait, &dhcp_interface_state::renew);
+ }
+
void dhcp_worker::dhcp_worker_fn()
{
while (true) {
diff --git a/include/osv/dhcp.hh b/include/osv/dhcp.hh
--- 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(bool wait);
}
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);
@@ -242,6 +243,8 @@ namespace dhcp {
// Transaction id
u32 _xid;
};
+ // typedef for discover/renew functions
+ typedef void (dhcp_interface_state::*dhcp_interface_state_send_packet)
(void);
///////////////////////////////////////////////////////////////////////////
@@ -256,6 +259,7 @@ namespace dhcp {
void start(bool wait);
// Send release packet for all DHCP IPs.
void release();
+ void renew(bool wait);
void dhcp_worker_fn();
void queue_packet(struct mbuf* m);
@@ -270,6 +274,7 @@ namespace dhcp {
// Wait for IP
bool _have_ip;
sched::thread * _waiter;
+ void _send_and_wait(bool wait, dhcp_interface_state_send_packet
iface_func);
};
} // namespace dhcp
diff --git a/modules/cloud-init/cloud-init.cc
b/modules/cloud-init/cloud-init.cc
--- 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(bool wait);
// 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(true);
}
}
}
@@ -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();
--
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 [email protected].
For more options, visit https://groups.google.com/d/optout.