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]> --- core/dhcp.cc | 46 +++++++++++++++++++++++++++++++++------- include/osv/dhcp.hh | 7 +++++- modules/cloud-init/cloud-init.cc | 10 ++++----- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/core/dhcp.cc b/core/dhcp.cc index 0436837..662929c 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(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 index b286727..3db6df8 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(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 index e3ec8f8..acee13d 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(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(); -- 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 [email protected]. For more options, visit https://groups.google.com/d/optout.
