Re: cleaning DHCP iface address/routes

2016-11-23 Thread Nadav Har'El
On Wed, Nov 23, 2016 at 9:52 PM, Justin Cinkelj 
wrote:

> I wish to ask for comment or two about how to clean DHCP interface routes
> after sending DHCP release.
> It is one thing Nadav suggested (if I understood him correctly) to add.
>

I didn't ask for this, but you're right, it does make sense to stop using
the IP address after we release it.

>
> In DORA cycle, after receiving ACK, the following things are called from
> dhcp_interface_state::state_request
> osv::start_if
> if /32 netmask:
>   osv_route_add_interface
> osv_route_add_network( def_route )
> std::for_each(dm.get_routes()
>   osv_route_add_interface (via cur_route.gw or via
> cur_route.iface)
> set_dns_config
>
> It seems to me that osv_route_add_{interface|network} only send special
> packet out of interface.
> If it is so, there is nothing to cleanup.
>

This code doesn't "send a packet".

The idea is to add this interface to the routing table (which in Linux you
see with the "route" command). The "default route" determines which
interface the packets go out from, by default. The additional /32 (a
256-address subnet) route is useful so if you have several interfaces, so
only one can be the default, but you still want packets to each subnet to
go out their respective interfaces.

The API to change the routing table is through a "routing socket", a socket
on which you send special routing messages, or its Linux expanded version,
the "netlink". Yucky, but that's the API invented at a dark time where 1.
there was a desire to avoid new system calls, and 2. /proc was not yet
invented.

So this code is not really sending a packet, it's modifying the routing
table.

I think that when you later mark the interface down, this should
automatically remove the routes which mention it because those are no
longer possible routes. You won't need to do this explicitly. But I never
checked this.


> set_dns_config - well, that should be inverted too. Current set_dns_config
> code seems to be ok for a single interface only.
> https://github.com/cloudius-systems/osv/blob/master/libc/
> network/__dns.cc#L33
> So if say clear_dns_config() is added, I don't need to bother about more
> than one interface case, where same DNS resolver can be reached from
> multiple interfaces.
>

The DNS configuration is at a whole different layer than the IP address
configuration. It's just the IP address (or list of those) of name servers.
It can be reached through any relevant interface (through the routing
table).

On release we can clear the list of DNS servers, or do nothing.

The whole DNS server setting through DHCP thing doesn't make sense if you
use DHCP on several interfaces, because which one is supposed to set the
DNS server. I don't know what we're supposed to do if only one of those
interfaces are released. Perhaps the best thing to do regarding the DNS is
simply nothing. It won't work anyway if you no longer have an IP address.


>
> The osv::start_if main part is in_control(NULL, SIOCAIFADDR, ...)
> https://github.com/cloudius-systems/osv/blob/master/bsd/
> porting/networking.cc#L113
>
> Simply adding osv::stop_if, which does SIOCDIFADDR seems to be enough.
>

I don't remember if changing the IP address to 0 is enough, or you need to
switch the IFF_UP flag down, but yes, one of those should be enough - it
should also remove the routes automatically, and it's fine not to touch the
DNS configuration, I think.


> With delay added between DHCP release and next DORA cycle, ifconfig.so and
> lsroute.so showed that IP and routes were removed, and VM didn't respond to
> ping any more (until DORA cycle set IP again).
>

Excellent.

>
> Did I miss/misunderstood anything significant?
>

I don't think so.

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


Re: [PATCH 0/2] dhcp: remove IP from interface when DHCP release is send

2016-11-23 Thread Nadav Har'El
I didn't seem to get these patches... Can you please send them again?
Thanks.


--
Nadav Har'El
n...@scylladb.com

On Wed, Nov 23, 2016 at 11:07 PM, Justin Cinkelj 
wrote:

> The first patch removes IP from iface when DHCP release is sent.
> This one is needed, because otherwise we send release, but keep using the
> IP address.
>
> The second one clears DNS configuration at DHCP release event.
>
> Justin Cinkelj (2):
>   dhcp: remove IP from interface when DHCP release is send
>   dhcp: remove DNS resolvers when DHCP release is send
>
>  bsd/porting/networking.cc | 29 +++--
>  bsd/porting/networking.hh |  2 ++
>  core/dhcp.cc  | 22 +-
>  include/osv/dhcp.hh   |  1 +
>  libc/network/__dns.cc |  8 
>  libc/network/__dns.hh |  2 ++
>  6 files changed, 49 insertions(+), 15 deletions(-)
>
> --
> 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.
>

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


[PATCH 0/2] dhcp: remove IP from interface when DHCP release is send

2016-11-23 Thread Justin Cinkelj
The first patch removes IP from iface when DHCP release is sent.
This one is needed, because otherwise we send release, but keep using the
IP address.

The second one clears DNS configuration at DHCP release event.

Justin Cinkelj (2):
  dhcp: remove IP from interface when DHCP release is send
  dhcp: remove DNS resolvers when DHCP release is send

 bsd/porting/networking.cc | 29 +++--
 bsd/porting/networking.hh |  2 ++
 core/dhcp.cc  | 22 +-
 include/osv/dhcp.hh   |  1 +
 libc/network/__dns.cc |  8 
 libc/network/__dns.hh |  2 ++
 6 files changed, 49 insertions(+), 15 deletions(-)

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


cleaning DHCP iface address/routes

2016-11-23 Thread Justin Cinkelj
I wish to ask for comment or two about how to clean DHCP interface routes after 
sending DHCP release.
It is one thing Nadav suggested (if I understood him correctly) to add.

In DORA cycle, after receiving ACK, the following things are called from
dhcp_interface_state::state_request
osv::start_if
if /32 netmask: 
  osv_route_add_interface
osv_route_add_network( def_route )
std::for_each(dm.get_routes()
  osv_route_add_interface (via cur_route.gw or via cur_route.iface)
set_dns_config

It seems to me that osv_route_add_{interface|network} only send special packet 
out of interface.
If it is so, there is nothing to cleanup.

set_dns_config - well, that should be inverted too. Current set_dns_config code 
seems to be ok for a single interface only.
https://github.com/cloudius-systems/osv/blob/master/libc/network/__dns.cc#L33
So if say clear_dns_config() is added, I don't need to bother about more than 
one interface case, where same DNS resolver can be reached from multiple 
interfaces.

The osv::start_if main part is in_control(NULL, SIOCAIFADDR, ...)
https://github.com/cloudius-systems/osv/blob/master/bsd/porting/networking.cc#L113

Simply adding osv::stop_if, which does SIOCDIFADDR seems to be enough.
With delay added between DHCP release and next DORA cycle, ifconfig.so and 
lsroute.so showed that IP and routes were removed, and VM didn't respond to 
ping any more (until DORA cycle set IP again).

Did I miss/misunderstood anything significant?

Justin

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


[COMMIT osv master] cloud-init: trigger dynamic DNS update on hostname change

2016-11-23 Thread Commit Bot

From: Justin Cinkelj 
Committer: Nadav Har'El 
Branch: master

cloud-init: trigger dynamic DNS update on hostname change

When cloud-init changes VM hostname, VM DNS name should be updated too.
We try to do this by releasing DHCP lease and requesting new lease
with new name. This instructs DHCP server to perform dynamic DNS update.
DNS update will/should succeed if
 1) new name is not already claimed by some other VM/IP and
 2) obviously, DHCP and DNS server need to support dynamic DNS updates.

The dhcp_worker::init was split into two parts (::init and ::start), so
that can be discovery-resend logic can be reused.

Signed-off-by: Justin Cinkelj 
Message-Id: <20161123144311.29393-1-justin.cink...@xlab.si>

---
diff --git a/core/dhcp.cc b/core/dhcp.cc
--- a/core/dhcp.cc
+++ b/core/dhcp.cc
@@ -66,7 +66,8 @@ int dhcp_hook_rx(struct mbuf* m)
 void dhcp_start(bool wait)
 {
 // Initialize the global DHCP worker
-net_dhcp_worker.init(wait);
+net_dhcp_worker.init();
+net_dhcp_worker.start(wait);
 }

 // Send DHCP release, for example at shutdown.
@@ -75,6 +76,12 @@ void dhcp_release()
 net_dhcp_worker.release();
 }

+void dhcp_restart(bool wait)
+{
+net_dhcp_worker.release();
+net_dhcp_worker.start(wait);
+}
+
 namespace dhcp {

 const char * dhcp_options_magic = "\x63\x82\x53\x63";
@@ -504,8 +511,6 @@ namespace dhcp {

 void dhcp_interface_state::discover()
 {
-// FIXME: send release packet in case the interface has an address
-
 // Update state
 _state = DHCP_DISCOVER;

@@ -665,12 +670,10 @@ namespace dhcp {
 // FIXME: free packets and states
 }

-void dhcp_worker::init(bool wait)
+void dhcp_worker::init()
 {
 struct ifnet *ifp = nullptr;

-// FIXME: clear routing table (use case run dhclient 2nd time)
-
 // Allocate a state for each interface
 IFNET_RLOCK();
 TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
@@ -686,7 +689,11 @@ namespace dhcp {
 _dhcp_thread = sched::thread::make([&] { dhcp_worker_fn(); });
 _dhcp_thread->set_name("dhcp");
 _dhcp_thread->start();
+}

+void dhcp_worker::start(bool wait)
+{
+// FIXME: clear routing table (use case run dhclient 2nd time)
 do {
 // Send discover packets!
 for (auto &it: _universe) {
@@ -711,6 +718,7 @@ namespace dhcp {
 for (auto &it: _universe) {
 it.second->release();
 }
+_have_ip = false;
 // Wait a bit, so hopefully UDP release packets will be actually  
put on wire.

 usleep(1000);
 }
diff --git a/include/osv/dhcp.hh b/include/osv/dhcp.hh
--- a/include/osv/dhcp.hh
+++ b/include/osv/dhcp.hh
@@ -25,6 +25,7 @@
 extern "C" {
 void dhcp_start(bool wait);
 void dhcp_release();
+void dhcp_restart(bool wait);
 }

 namespace dhcp {
@@ -249,8 +250,11 @@ namespace dhcp {
 dhcp_worker();
 ~dhcp_worker();

-// Initializing a state per interface, sends discover packets
-void init(bool wait);
+// Initializing a state per interface
+void init();
+// Send discover packets
+void start(bool wait);
+// Send release packet for all DHCP IPs.
 void release();

 void dhcp_worker_fn();
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
@@ -16,6 +16,22 @@
 #include 
 #include 

+// we cannot include osv/dhcp.hh, hence direct declaration.
+extern "C" void dhcp_restart(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) {
+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);
+}
+}
+}
+
 namespace init {
 using namespace std;

@@ -229,9 +245,7 @@ void hostname_module::handle(const YAML::Node& doc)
 {
 auto hostname = doc.as();
 debug("cloudinit hostname: %s\n", hostname.c_str());
-if (hostname.size()) {
-sethostname(hostname.c_str(), hostname.size());
-}
+set_hostname_restart_dhcp(hostname);
 }

 void osvinit::add_module(std::shared_ptr module)
@@ -265,11 +279,8 @@ void osvinit::load_from_cloud(bool  
ignore_missing_source)

 try {
 auto& ds = get_data_source();

-std::string hostname = ds.external_hostname();
-if (hostname.length() > 0) {
-// Set the hostname from given data source, if it exists.
-sethostname(hostname.c_str(), hostname.length());
-}
+// Set the hostname from given data source, if it exists.
+set_hostname_restart_dhcp(ds.external_hostname());

 // Load user data.
 user_d

[PATCH v3] cloud-init: trigger dynamic DNS update on hostname change

2016-11-23 Thread Justin Cinkelj
When cloud-init changes VM hostname, VM DNS name should be updated too.
We try to do this by releasing DHCP lease and requesting new lease
with new name. This instructs DHCP server to perform dynamic DNS update.
DNS update will/should succeed if
 1) new name is not already claimed by some other VM/IP and
 2) obviously, DHCP and DNS server need to support dynamic DNS updates.

The dhcp_worker::init was split into two parts (::init and ::start), so
that can be discovery-resend logic can be reused.

Signed-off-by: Justin Cinkelj 
---
 core/dhcp.cc | 20 ++--
 include/osv/dhcp.hh  |  8 ++--
 modules/cloud-init/cloud-init.cc | 27 +++
 3 files changed, 39 insertions(+), 16 deletions(-)

diff --git a/core/dhcp.cc b/core/dhcp.cc
index 27d7aef..add540a 100644
--- a/core/dhcp.cc
+++ b/core/dhcp.cc
@@ -66,7 +66,8 @@ int dhcp_hook_rx(struct mbuf* m)
 void dhcp_start(bool wait)
 {
 // Initialize the global DHCP worker
-net_dhcp_worker.init(wait);
+net_dhcp_worker.init();
+net_dhcp_worker.start(wait);
 }
 
 // Send DHCP release, for example at shutdown.
@@ -75,6 +76,12 @@ void dhcp_release()
 net_dhcp_worker.release();
 }
 
+void dhcp_restart(bool wait)
+{
+net_dhcp_worker.release();
+net_dhcp_worker.start(wait);
+}
+
 namespace dhcp {
 
 const char * dhcp_options_magic = "\x63\x82\x53\x63";
@@ -504,8 +511,6 @@ namespace dhcp {
 
 void dhcp_interface_state::discover()
 {
-// FIXME: send release packet in case the interface has an address
-
 // Update state
 _state = DHCP_DISCOVER;
 
@@ -665,12 +670,10 @@ namespace dhcp {
 // FIXME: free packets and states
 }
 
-void dhcp_worker::init(bool wait)
+void dhcp_worker::init()
 {
 struct ifnet *ifp = nullptr;
 
-// FIXME: clear routing table (use case run dhclient 2nd time)
-
 // Allocate a state for each interface
 IFNET_RLOCK();
 TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
@@ -686,7 +689,11 @@ namespace dhcp {
 _dhcp_thread = sched::thread::make([&] { dhcp_worker_fn(); });
 _dhcp_thread->set_name("dhcp");
 _dhcp_thread->start();
+}
 
+void dhcp_worker::start(bool wait)
+{
+// FIXME: clear routing table (use case run dhclient 2nd time)
 do {
 // Send discover packets!
 for (auto &it: _universe) {
@@ -711,6 +718,7 @@ namespace dhcp {
 for (auto &it: _universe) {
 it.second->release();
 }
+_have_ip = false;
 // Wait a bit, so hopefully UDP release packets will be actually put 
on wire.
 usleep(1000);
 }
diff --git a/include/osv/dhcp.hh b/include/osv/dhcp.hh
index 30ca86f..b286727 100644
--- a/include/osv/dhcp.hh
+++ b/include/osv/dhcp.hh
@@ -25,6 +25,7 @@
 extern "C" {
 void dhcp_start(bool wait);
 void dhcp_release();
+void dhcp_restart(bool wait);
 }
 
 namespace dhcp {
@@ -249,8 +250,11 @@ namespace dhcp {
 dhcp_worker();
 ~dhcp_worker();
 
-// Initializing a state per interface, sends discover packets
-void init(bool wait);
+// Initializing a state per interface
+void init();
+// Send discover packets
+void start(bool wait);
+// Send release packet for all DHCP IPs.
 void release();
 
 void dhcp_worker_fn();
diff --git a/modules/cloud-init/cloud-init.cc b/modules/cloud-init/cloud-init.cc
index 67f477e..e3ec8f8 100644
--- a/modules/cloud-init/cloud-init.cc
+++ b/modules/cloud-init/cloud-init.cc
@@ -16,6 +16,22 @@
 #include 
 #include 
 
+// we cannot include osv/dhcp.hh, hence direct declaration.
+extern "C" void dhcp_restart(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) {
+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);
+}
+}
+}
+
 namespace init {
 using namespace std;
 
@@ -229,9 +245,7 @@ void hostname_module::handle(const YAML::Node& doc)
 {
 auto hostname = doc.as();
 debug("cloudinit hostname: %s\n", hostname.c_str());
-if (hostname.size()) {
-sethostname(hostname.c_str(), hostname.size());
-}
+set_hostname_restart_dhcp(hostname);
 }
 
 void osvinit::add_module(std::shared_ptr module)
@@ -265,11 +279,8 @@ void osvinit::load_from_cloud(bool ignore_missing_source)
 try {
 auto& ds = get_data_source();
 
-std::string hostname = ds.external_hostname();
-if (hostname.length() > 0) {
-// Set the hostname from given data source, if it exists.
-sethostname(hostname.c_str(), hostname.length());
-}
+// Set the hostname f

Re: [PATCH v2 2/2] cloud-init: trigger dynamic DNS update on hostname change

2016-11-23 Thread Nadav Har'El
On Wed, Nov 23, 2016 at 3:42 PM, Justin Cinkelj 
wrote:

>
>
> On 11/23/2016 02:32 PM, Nadav Har'El wrote:
>
>
> On Wed, Nov 23, 2016 at 3:27 PM, Justin Cinkelj 
> wrote:
>
>> When cloud-init changes VM hostname, VM DNS name should be updated too.
>> We try to do this by releasing DHCP lease and requesting new lease
>> with new name. This instructs DHCP server to perform dynamic DNS update.
>> DNS update will/should succeed if
>>  1) new name is not already claimed by some other VM/IP and
>>  2) obviously, DHCP and DNS server need to support dynamic DNS updates.
>>
>> The dhcp_worker::init was split into two parts (::init and ::start), so
>> that can be discovery-resend logic can be reused.
>>
>> Signed-off-by: Justin Cinkelj 
>> ---
>>  core/dhcp.cc | 23 ++-
>>  include/osv/dhcp.hh  |  8 ++--
>>  modules/cloud-init/cloud-init.cc | 27 +++
>>  3 files changed, 43 insertions(+), 15 deletions(-)
>>
>> diff --git a/core/dhcp.cc b/core/dhcp.cc
>> index 27d7aef..d89eb46 100644
>> --- a/core/dhcp.cc
>> +++ b/core/dhcp.cc
>> @@ -66,7 +66,8 @@ int dhcp_hook_rx(struct mbuf* m)
>>  void dhcp_start(bool wait)
>>  {
>>  // Initialize the global DHCP worker
>> -net_dhcp_worker.init(wait);
>> +net_dhcp_worker.init();
>> +net_dhcp_worker.start(wait);
>>  }
>>
>>  // Send DHCP release, for example at shutdown.
>> @@ -75,6 +76,12 @@ void dhcp_release()
>>  net_dhcp_worker.release();
>>  }
>>
>> +void dhcp_restart(bool wait)
>> +{
>> +net_dhcp_worker.release();
>> +net_dhcp_worker.start(wait);
>> +}
>> +
>>  namespace dhcp {
>>
>>  const char * dhcp_options_magic = "\x63\x82\x53\x63";
>> @@ -504,7 +511,10 @@ namespace dhcp {
>>
>>  void dhcp_interface_state::discover()
>>  {
>> -// FIXME: send release packet in case the interface has an
>> address
>> +// send release packet in case the interface has an address
>> +if (_client_addr != ipv4_zero) {
>> +release();
>> +}
>>
>
> I don't know why this FIXME was correct, or why this extra code was
> needed: In both the dhcp_start() and dhcp_restart() cases, we start with
> zero address (in dhcp_restart() you call release() already). So why do we
> need to check it again here?
>
> I just noted the fixme line, and then added the if sentence for
> just-in-case.
> I don't see how current code could send release via this 3 lines; maybe if
> at some later time
> we/I forget to call release before discover;
>
> Maybe I should just remove the fixme comment?
>

Yes, I think that would make sense.
By the way, I already committed the second patch in this series.


>
> Justin
>
>
>  // Update state
>>  _state = DHCP_DISCOVER;
>> @@ -665,12 +675,10 @@ namespace dhcp {
>>  // FIXME: free packets and states
>>  }
>>
>> -void dhcp_worker::init(bool wait)
>> +void dhcp_worker::init()
>>  {
>>  struct ifnet *ifp = nullptr;
>>
>> -// FIXME: clear routing table (use case run dhclient 2nd time)
>> -
>>  // Allocate a state for each interface
>>  IFNET_RLOCK();
>>  TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
>> @@ -686,7 +694,11 @@ namespace dhcp {
>>  _dhcp_thread = sched::thread::make([&] { dhcp_worker_fn(); });
>>  _dhcp_thread->set_name("dhcp");
>>  _dhcp_thread->start();
>> +}
>>
>> +void dhcp_worker::start(bool wait)
>> +{
>> +// FIXME: clear routing table (use case run dhclient 2nd time)
>>  do {
>>  // Send discover packets!
>>  for (auto &it: _universe) {
>> @@ -711,6 +723,7 @@ namespace dhcp {
>>  for (auto &it: _universe) {
>>  it.second->release();
>>  }
>> +_have_ip = false;
>>  // Wait a bit, so hopefully UDP release packets will be actually
>> put on wire.
>>  usleep(1000);
>>  }
>> diff --git a/include/osv/dhcp.hh b/include/osv/dhcp.hh
>> index 30ca86f..b286727 100644
>> --- a/include/osv/dhcp.hh
>> +++ b/include/osv/dhcp.hh
>> @@ -25,6 +25,7 @@
>>  extern "C" {
>>  void dhcp_start(bool wait);
>>  void dhcp_release();
>> +void dhcp_restart(bool wait);
>>  }
>>
>>  namespace dhcp {
>> @@ -249,8 +250,11 @@ namespace dhcp {
>>  dhcp_worker();
>>  ~dhcp_worker();
>>
>> -// Initializing a state per interface, sends discover packets
>> -void init(bool wait);
>> +// Initializing a state per interface
>> +void init();
>> +// Send discover packets
>> +void start(bool wait);
>> +// Send release packet for all DHCP IPs.
>>  void release();
>>
>>  void dhcp_worker_fn();
>> diff --git a/modules/cloud-init/cloud-init.cc
>> b/modules/cloud-init/cloud-init.cc
>> index 67f477e..e3ec8f8 100644
>> --- a/modules/cloud-init/cloud-init.cc
>> +++ b/modules/cloud-init/cloud-init.cc
>> @@ -16,6 +16,22 @@
>>  #include 
>>  #include 
>>
>> +// we cannot include o

[COMMIT osv master] dhcp: set src and dest IP in DHCP release packet

2016-11-23 Thread Commit Bot

From: Justin Cinkelj 
Committer: Nadav Har'El 
Branch: master

dhcp: set src and dest IP in DHCP release packet

DHCP release packet should have valid IP header. There is no need
to use INADDR_ANY/INADDR_BROADCAST as src/dest address.

Signed-off-by: Justin Cinkelj 
Message-Id: <20161123132746.27570-2-justin.cink...@xlab.si>

---
diff --git a/core/dhcp.cc b/core/dhcp.cc
--- a/core/dhcp.cc
+++ b/core/dhcp.cc
@@ -197,7 +197,7 @@ namespace dhcp {
 *options++ = DHCP_OPTION_END;

 dhcp_len += options - options_start;
-build_udp_ip_headers(dhcp_len);
+build_udp_ip_headers(dhcp_len, INADDR_ANY, INADDR_BROADCAST);
 }

 void dhcp_mbuf::compose_request(struct ifnet* ifp,
@@ -239,7 +239,7 @@ namespace dhcp {
 *options++ = DHCP_OPTION_END;

 dhcp_len += options - options_start;
-build_udp_ip_headers(dhcp_len);
+build_udp_ip_headers(dhcp_len, INADDR_ANY, INADDR_BROADCAST);
 }

 void dhcp_mbuf::compose_release(struct ifnet* ifp,
@@ -275,7 +275,7 @@ namespace dhcp {
 *options++ = DHCP_OPTION_END;

 dhcp_len += options - options_start;
-build_udp_ip_headers(dhcp_len);
+build_udp_ip_headers(dhcp_len, yip_n, sip_n);
 }

 u32 dhcp_mbuf::get_xid()
@@ -456,7 +456,7 @@ namespace dhcp {
 return pos + 2 + len;
 }

-void dhcp_mbuf::build_udp_ip_headers(size_t dhcp_len)
+void dhcp_mbuf::build_udp_ip_headers(size_t dhcp_len, in_addr_t  
src_addr, in_addr_t dest_addr)

 {
 struct ip* ip = pip();
 struct udphdr* udp = pudp();
@@ -473,8 +473,8 @@ namespace dhcp {
 ip->ip_ttl = 128;
 ip->ip_p = IPPROTO_UDP;
 ip->ip_sum = 0;
-ip->ip_src.s_addr = INADDR_ANY;
-ip->ip_dst.s_addr = INADDR_BROADCAST;
+ip->ip_src.s_addr = src_addr;
+ip->ip_dst.s_addr = dest_addr;
 ip->ip_sum = in_cksum(_m, min_ip_len);

 // UDP
diff --git a/include/osv/dhcp.hh b/include/osv/dhcp.hh
--- a/include/osv/dhcp.hh
+++ b/include/osv/dhcp.hh
@@ -168,7 +168,7 @@ namespace dhcp {
 u8* add_option(u8* pos, u8 type, u8 len, u8 data); // memset

 // Packet assembly
-void build_udp_ip_headers(size_t dhcp_len);
+void build_udp_ip_headers(size_t dhcp_len, in_addr_t src_addr,  
in_addr_t dest_addr);


 // mbuf related
 void allocate_mbuf();

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


Re: [PATCH v2 2/2] cloud-init: trigger dynamic DNS update on hostname change

2016-11-23 Thread Justin Cinkelj



On 11/23/2016 02:32 PM, Nadav Har'El wrote:


On Wed, Nov 23, 2016 at 3:27 PM, Justin Cinkelj 
mailto:justin.cink...@xlab.si>> wrote:


When cloud-init changes VM hostname, VM DNS name should be updated
too.
We try to do this by releasing DHCP lease and requesting new lease
with new name. This instructs DHCP server to perform dynamic DNS
update.
DNS update will/should succeed if
 1) new name is not already claimed by some other VM/IP and
 2) obviously, DHCP and DNS server need to support dynamic DNS
updates.

The dhcp_worker::init was split into two parts (::init and
::start), so
that can be discovery-resend logic can be reused.

Signed-off-by: Justin Cinkelj mailto:justin.cink...@xlab.si>>
---
 core/dhcp.cc | 23 ++-
 include/osv/dhcp.hh  |  8 ++--
 modules/cloud-init/cloud-init.cc | 27 +++
 3 files changed, 43 insertions(+), 15 deletions(-)

diff --git a/core/dhcp.cc b/core/dhcp.cc
index 27d7aef..d89eb46 100644
--- a/core/dhcp.cc
+++ b/core/dhcp.cc
@@ -66,7 +66,8 @@ int dhcp_hook_rx(struct mbuf* m)
 void dhcp_start(bool wait)
 {
 // Initialize the global DHCP worker
-net_dhcp_worker.init(wait);
+net_dhcp_worker.init();
+net_dhcp_worker.start(wait);
 }

 // Send DHCP release, for example at shutdown.
@@ -75,6 +76,12 @@ void dhcp_release()
 net_dhcp_worker.release();
 }

+void dhcp_restart(bool wait)
+{
+net_dhcp_worker.release();
+net_dhcp_worker.start(wait);
+}
+
 namespace dhcp {

 const char * dhcp_options_magic = "\x63\x82\x53\x63";
@@ -504,7 +511,10 @@ namespace dhcp {

 void dhcp_interface_state::discover()
 {
-// FIXME: send release packet in case the interface has
an address
+// send release packet in case the interface has an address
+if (_client_addr != ipv4_zero) {
+release();
+}


I don't know why this FIXME was correct, or why this extra code was 
needed: In both the dhcp_start() and dhcp_restart() cases, we start 
with zero address (in dhcp_restart() you call release() already). So 
why do we need to check it again here?
I just noted the fixme line, and then added the if sentence for 
just-in-case.
I don't see how current code could send release via this 3 lines; maybe 
if at some later time

we/I forget to call release before discover;

Maybe I should just remove the fixme comment?

Justin


 // Update state
 _state = DHCP_DISCOVER;
@@ -665,12 +675,10 @@ namespace dhcp {
 // FIXME: free packets and states
 }

-void dhcp_worker::init(bool wait)
+void dhcp_worker::init()
 {
 struct ifnet *ifp = nullptr;

-// FIXME: clear routing table (use case run dhclient 2nd
time)
-
 // Allocate a state for each interface
 IFNET_RLOCK();
 TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
@@ -686,7 +694,11 @@ namespace dhcp {
 _dhcp_thread = sched::thread::make([&] {
dhcp_worker_fn(); });
 _dhcp_thread->set_name("dhcp");
 _dhcp_thread->start();
+}

+void dhcp_worker::start(bool wait)
+{
+// FIXME: clear routing table (use case run dhclient 2nd
time)
 do {
 // Send discover packets!
 for (auto &it: _universe) {
@@ -711,6 +723,7 @@ namespace dhcp {
 for (auto &it: _universe) {
 it.second->release();
 }
+_have_ip = false;
 // Wait a bit, so hopefully UDP release packets will be
actually put on wire.
 usleep(1000);
 }
diff --git a/include/osv/dhcp.hh b/include/osv/dhcp.hh
index 30ca86f..b286727 100644
--- a/include/osv/dhcp.hh
+++ b/include/osv/dhcp.hh
@@ -25,6 +25,7 @@
 extern "C" {
 void dhcp_start(bool wait);
 void dhcp_release();
+void dhcp_restart(bool wait);
 }

 namespace dhcp {
@@ -249,8 +250,11 @@ namespace dhcp {
 dhcp_worker();
 ~dhcp_worker();

-// Initializing a state per interface, sends discover packets
-void init(bool wait);
+// Initializing a state per interface
+void init();
+// Send discover packets
+void start(bool wait);
+// Send release packet for all DHCP IPs.
 void release();

 void dhcp_worker_fn();
diff --git a/modules/cloud-init/cloud-init.cc
b/modules/cloud-init/cloud-init.cc
index 67f477e..e3ec8f8 100644
--- a/modules/cloud-init/cloud-init.cc
+++ b/modules/cloud-init/cloud-init.cc
@@ -16,6 +16,22 @@
 #include 
 #include 

+// we cannot include osv/dhcp.hh, hence di

Re: [PATCH v2 2/2] cloud-init: trigger dynamic DNS update on hostname change

2016-11-23 Thread Nadav Har'El
On Wed, Nov 23, 2016 at 3:27 PM, Justin Cinkelj 
wrote:

> When cloud-init changes VM hostname, VM DNS name should be updated too.
> We try to do this by releasing DHCP lease and requesting new lease
> with new name. This instructs DHCP server to perform dynamic DNS update.
> DNS update will/should succeed if
>  1) new name is not already claimed by some other VM/IP and
>  2) obviously, DHCP and DNS server need to support dynamic DNS updates.
>
> The dhcp_worker::init was split into two parts (::init and ::start), so
> that can be discovery-resend logic can be reused.
>
> Signed-off-by: Justin Cinkelj 
> ---
>  core/dhcp.cc | 23 ++-
>  include/osv/dhcp.hh  |  8 ++--
>  modules/cloud-init/cloud-init.cc | 27 +++
>  3 files changed, 43 insertions(+), 15 deletions(-)
>
> diff --git a/core/dhcp.cc b/core/dhcp.cc
> index 27d7aef..d89eb46 100644
> --- a/core/dhcp.cc
> +++ b/core/dhcp.cc
> @@ -66,7 +66,8 @@ int dhcp_hook_rx(struct mbuf* m)
>  void dhcp_start(bool wait)
>  {
>  // Initialize the global DHCP worker
> -net_dhcp_worker.init(wait);
> +net_dhcp_worker.init();
> +net_dhcp_worker.start(wait);
>  }
>
>  // Send DHCP release, for example at shutdown.
> @@ -75,6 +76,12 @@ void dhcp_release()
>  net_dhcp_worker.release();
>  }
>
> +void dhcp_restart(bool wait)
> +{
> +net_dhcp_worker.release();
> +net_dhcp_worker.start(wait);
> +}
> +
>  namespace dhcp {
>
>  const char * dhcp_options_magic = "\x63\x82\x53\x63";
> @@ -504,7 +511,10 @@ namespace dhcp {
>
>  void dhcp_interface_state::discover()
>  {
> -// FIXME: send release packet in case the interface has an address
> +// send release packet in case the interface has an address
> +if (_client_addr != ipv4_zero) {
> +release();
> +}
>

I don't know why this FIXME was correct, or why this extra code was needed:
In both the dhcp_start() and dhcp_restart() cases, we start with zero
address (in dhcp_restart() you call release() already). So why do we need
to check it again here?


>
>  // Update state
>  _state = DHCP_DISCOVER;
> @@ -665,12 +675,10 @@ namespace dhcp {
>  // FIXME: free packets and states
>  }
>
> -void dhcp_worker::init(bool wait)
> +void dhcp_worker::init()
>  {
>  struct ifnet *ifp = nullptr;
>
> -// FIXME: clear routing table (use case run dhclient 2nd time)
> -
>  // Allocate a state for each interface
>  IFNET_RLOCK();
>  TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
> @@ -686,7 +694,11 @@ namespace dhcp {
>  _dhcp_thread = sched::thread::make([&] { dhcp_worker_fn(); });
>  _dhcp_thread->set_name("dhcp");
>  _dhcp_thread->start();
> +}
>
> +void dhcp_worker::start(bool wait)
> +{
> +// FIXME: clear routing table (use case run dhclient 2nd time)
>  do {
>  // Send discover packets!
>  for (auto &it: _universe) {
> @@ -711,6 +723,7 @@ namespace dhcp {
>  for (auto &it: _universe) {
>  it.second->release();
>  }
> +_have_ip = false;
>  // Wait a bit, so hopefully UDP release packets will be actually
> put on wire.
>  usleep(1000);
>  }
> diff --git a/include/osv/dhcp.hh b/include/osv/dhcp.hh
> index 30ca86f..b286727 100644
> --- a/include/osv/dhcp.hh
> +++ b/include/osv/dhcp.hh
> @@ -25,6 +25,7 @@
>  extern "C" {
>  void dhcp_start(bool wait);
>  void dhcp_release();
> +void dhcp_restart(bool wait);
>  }
>
>  namespace dhcp {
> @@ -249,8 +250,11 @@ namespace dhcp {
>  dhcp_worker();
>  ~dhcp_worker();
>
> -// Initializing a state per interface, sends discover packets
> -void init(bool wait);
> +// Initializing a state per interface
> +void init();
> +// Send discover packets
> +void start(bool wait);
> +// Send release packet for all DHCP IPs.
>  void release();
>
>  void dhcp_worker_fn();
> diff --git a/modules/cloud-init/cloud-init.cc b/modules/cloud-init/cloud-
> init.cc
> index 67f477e..e3ec8f8 100644
> --- a/modules/cloud-init/cloud-init.cc
> +++ b/modules/cloud-init/cloud-init.cc
> @@ -16,6 +16,22 @@
>  #include 
>  #include 
>
> +// we cannot include osv/dhcp.hh, hence direct declaration.
> +extern "C" void dhcp_restart(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) {
> +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);
> +}
> +}
> +}
> +
>  namespace init {
>  using namespace std;
>
> @@ -229,9 +245,7 @@ void hostname_mo

[PATCH v2 2/2] cloud-init: trigger dynamic DNS update on hostname change

2016-11-23 Thread Justin Cinkelj
When cloud-init changes VM hostname, VM DNS name should be updated too.
We try to do this by releasing DHCP lease and requesting new lease
with new name. This instructs DHCP server to perform dynamic DNS update.
DNS update will/should succeed if
 1) new name is not already claimed by some other VM/IP and
 2) obviously, DHCP and DNS server need to support dynamic DNS updates.

The dhcp_worker::init was split into two parts (::init and ::start), so
that can be discovery-resend logic can be reused.

Signed-off-by: Justin Cinkelj 
---
 core/dhcp.cc | 23 ++-
 include/osv/dhcp.hh  |  8 ++--
 modules/cloud-init/cloud-init.cc | 27 +++
 3 files changed, 43 insertions(+), 15 deletions(-)

diff --git a/core/dhcp.cc b/core/dhcp.cc
index 27d7aef..d89eb46 100644
--- a/core/dhcp.cc
+++ b/core/dhcp.cc
@@ -66,7 +66,8 @@ int dhcp_hook_rx(struct mbuf* m)
 void dhcp_start(bool wait)
 {
 // Initialize the global DHCP worker
-net_dhcp_worker.init(wait);
+net_dhcp_worker.init();
+net_dhcp_worker.start(wait);
 }
 
 // Send DHCP release, for example at shutdown.
@@ -75,6 +76,12 @@ void dhcp_release()
 net_dhcp_worker.release();
 }
 
+void dhcp_restart(bool wait)
+{
+net_dhcp_worker.release();
+net_dhcp_worker.start(wait);
+}
+
 namespace dhcp {
 
 const char * dhcp_options_magic = "\x63\x82\x53\x63";
@@ -504,7 +511,10 @@ namespace dhcp {
 
 void dhcp_interface_state::discover()
 {
-// FIXME: send release packet in case the interface has an address
+// send release packet in case the interface has an address
+if (_client_addr != ipv4_zero) {
+release();
+}
 
 // Update state
 _state = DHCP_DISCOVER;
@@ -665,12 +675,10 @@ namespace dhcp {
 // FIXME: free packets and states
 }
 
-void dhcp_worker::init(bool wait)
+void dhcp_worker::init()
 {
 struct ifnet *ifp = nullptr;
 
-// FIXME: clear routing table (use case run dhclient 2nd time)
-
 // Allocate a state for each interface
 IFNET_RLOCK();
 TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
@@ -686,7 +694,11 @@ namespace dhcp {
 _dhcp_thread = sched::thread::make([&] { dhcp_worker_fn(); });
 _dhcp_thread->set_name("dhcp");
 _dhcp_thread->start();
+}
 
+void dhcp_worker::start(bool wait)
+{
+// FIXME: clear routing table (use case run dhclient 2nd time)
 do {
 // Send discover packets!
 for (auto &it: _universe) {
@@ -711,6 +723,7 @@ namespace dhcp {
 for (auto &it: _universe) {
 it.second->release();
 }
+_have_ip = false;
 // Wait a bit, so hopefully UDP release packets will be actually put 
on wire.
 usleep(1000);
 }
diff --git a/include/osv/dhcp.hh b/include/osv/dhcp.hh
index 30ca86f..b286727 100644
--- a/include/osv/dhcp.hh
+++ b/include/osv/dhcp.hh
@@ -25,6 +25,7 @@
 extern "C" {
 void dhcp_start(bool wait);
 void dhcp_release();
+void dhcp_restart(bool wait);
 }
 
 namespace dhcp {
@@ -249,8 +250,11 @@ namespace dhcp {
 dhcp_worker();
 ~dhcp_worker();
 
-// Initializing a state per interface, sends discover packets
-void init(bool wait);
+// Initializing a state per interface
+void init();
+// Send discover packets
+void start(bool wait);
+// Send release packet for all DHCP IPs.
 void release();
 
 void dhcp_worker_fn();
diff --git a/modules/cloud-init/cloud-init.cc b/modules/cloud-init/cloud-init.cc
index 67f477e..e3ec8f8 100644
--- a/modules/cloud-init/cloud-init.cc
+++ b/modules/cloud-init/cloud-init.cc
@@ -16,6 +16,22 @@
 #include 
 #include 
 
+// we cannot include osv/dhcp.hh, hence direct declaration.
+extern "C" void dhcp_restart(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) {
+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);
+}
+}
+}
+
 namespace init {
 using namespace std;
 
@@ -229,9 +245,7 @@ void hostname_module::handle(const YAML::Node& doc)
 {
 auto hostname = doc.as();
 debug("cloudinit hostname: %s\n", hostname.c_str());
-if (hostname.size()) {
-sethostname(hostname.c_str(), hostname.size());
-}
+set_hostname_restart_dhcp(hostname);
 }
 
 void osvinit::add_module(std::shared_ptr module)
@@ -265,11 +279,8 @@ void osvinit::load_from_cloud(bool ignore_missing_source)
 try {
 auto& ds = get_data_source();
 
-std::string hostname = ds.external_hostname();
-if (hostname.length() > 0) {
-// Set the hos

[PATCH v2 0/2] cloud-init: trigger dynamic DNS update on hostname change

2016-11-23 Thread Justin Cinkelj
Additional patch 1/2 added, to set src and dest IP in DHCP release packet.

The 2/2 patch is updated. Also on second DORA try is the discovery packet resend
if server doesn't respond in time. The dhcp_worker and dhcp_interface_state
restart function was removed - as Nadav noted, the were not really needed.

The routing table is not cleared on DHCP release. I just have to look a bit 
more at this,
and still wish to send patches early.

Justin Cinkelj (2):
  dhcp: set src and dest IP in DHCP release packet
  cloud-init: trigger dynamic DNS update on hostname change

 core/dhcp.cc | 35 ---
 include/osv/dhcp.hh  | 10 +++---
 modules/cloud-init/cloud-init.cc | 27 +++
 3 files changed, 50 insertions(+), 22 deletions(-)

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


[PATCH v2 1/2] dhcp: set src and dest IP in DHCP release packet

2016-11-23 Thread Justin Cinkelj
DHCP release packet should have valid IP header. There is no need
to use INADDR_ANY/INADDR_BROADCAST as src/dest address.

Signed-off-by: Justin Cinkelj 
---
 core/dhcp.cc| 12 ++--
 include/osv/dhcp.hh |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/core/dhcp.cc b/core/dhcp.cc
index 689a387..27d7aef 100644
--- a/core/dhcp.cc
+++ b/core/dhcp.cc
@@ -197,7 +197,7 @@ namespace dhcp {
 *options++ = DHCP_OPTION_END;
 
 dhcp_len += options - options_start;
-build_udp_ip_headers(dhcp_len);
+build_udp_ip_headers(dhcp_len, INADDR_ANY, INADDR_BROADCAST);
 }
 
 void dhcp_mbuf::compose_request(struct ifnet* ifp,
@@ -239,7 +239,7 @@ namespace dhcp {
 *options++ = DHCP_OPTION_END;
 
 dhcp_len += options - options_start;
-build_udp_ip_headers(dhcp_len);
+build_udp_ip_headers(dhcp_len, INADDR_ANY, INADDR_BROADCAST);
 }
 
 void dhcp_mbuf::compose_release(struct ifnet* ifp,
@@ -275,7 +275,7 @@ namespace dhcp {
 *options++ = DHCP_OPTION_END;
 
 dhcp_len += options - options_start;
-build_udp_ip_headers(dhcp_len);
+build_udp_ip_headers(dhcp_len, yip_n, sip_n);
 }
 
 u32 dhcp_mbuf::get_xid()
@@ -456,7 +456,7 @@ namespace dhcp {
 return pos + 2 + len;
 }
 
-void dhcp_mbuf::build_udp_ip_headers(size_t dhcp_len)
+void dhcp_mbuf::build_udp_ip_headers(size_t dhcp_len, in_addr_t src_addr, 
in_addr_t dest_addr)
 {
 struct ip* ip = pip();
 struct udphdr* udp = pudp();
@@ -473,8 +473,8 @@ namespace dhcp {
 ip->ip_ttl = 128;
 ip->ip_p = IPPROTO_UDP;
 ip->ip_sum = 0;
-ip->ip_src.s_addr = INADDR_ANY;
-ip->ip_dst.s_addr = INADDR_BROADCAST;
+ip->ip_src.s_addr = src_addr;
+ip->ip_dst.s_addr = dest_addr;
 ip->ip_sum = in_cksum(_m, min_ip_len);
 
 // UDP
diff --git a/include/osv/dhcp.hh b/include/osv/dhcp.hh
index 55e0b16..30ca86f 100644
--- a/include/osv/dhcp.hh
+++ b/include/osv/dhcp.hh
@@ -168,7 +168,7 @@ namespace dhcp {
 u8* add_option(u8* pos, u8 type, u8 len, u8 data); // memset
 
 // Packet assembly
-void build_udp_ip_headers(size_t dhcp_len);
+void build_udp_ip_headers(size_t dhcp_len, in_addr_t src_addr, 
in_addr_t dest_addr);
 
 // mbuf related
 void allocate_mbuf();
-- 
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.


Re: [PATCH] cloud-init: trigger dynamic DNS update on hostname change

2016-11-23 Thread Justin Cinkelj



On 11/23/2016 11:39 AM, Nadav Har'El wrote:


On Wed, Nov 23, 2016 at 11:20 AM, Justin Cinkelj 
mailto:justin.cink...@xlab.si>> wrote:




- Original Message -
> From: "Nadav Har'El" mailto:n...@scylladb.com>>
> To: "Justin Cinkelj" mailto:justin.cink...@xlab.si>>
> Cc: "Osv Dev" mailto:osv-dev@googlegroups.com>>
> Sent: Wednesday, November 23, 2016 8:31:01 AM
> Subject: Re: [PATCH] cloud-init: trigger dynamic DNS update on
hostname change
>
> Hi Justin, some comments inline below:
>
> On Tue, Nov 22, 2016 at 11:37 PM, Justin Cinkelj
mailto:justin.cink...@xlab.si>>
> wrote:
>
> > When cloud-init changes VM hostname, VM DNS name should be
updated too.
> > We try to do this by releasing DHCP lease and requesting new lease
> >
>
> Is the "release" part actually necessary? Can't we start the
initialization
> again without a release? (and even more optimized version would
be to
> contact the server directly, but let's not try to optimize this
case too
> much)?

Hm, I didn't think about not doing release. One potential problem
- old name
might not get released.

Optimized version would be to contact the server directly - which
server?


The DHCP server.
I thought that instead of sending a new broadcast (which one does 
before he knows what is the DHCP server) maybe you can send the 
message directly to the server, like we do in the RELEASE case. But 
this optimization is probably not worth it, and I don't know if it's 
even possible.

You are right, sending to server IP is better.


I would like to think that when a DHCP server gets a request from a 
MAC address which it already gave an IP address and/or dns entry for, 
it will remove the old entries before giving out new ones. I didn't 
test this, however. Again, because the "RELEASE" operation is 
considered, also by the DHCP docs, as "optional" because of the fact 
it doesn't have an ack. So I doubt the correct operationof any DHCP 
server can rely on release taking place.


Anyway, I'm not against this release() - it will have a tiny 
performance impact. Feel free to keep it.


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


Re: [PATCH] cloud-init: trigger dynamic DNS update on hostname change

2016-11-23 Thread Nadav Har'El
On Wed, Nov 23, 2016 at 11:20 AM, Justin Cinkelj 
wrote:

>
>
> - Original Message -
> > From: "Nadav Har'El" 
> > To: "Justin Cinkelj" 
> > Cc: "Osv Dev" 
> > Sent: Wednesday, November 23, 2016 8:31:01 AM
> > Subject: Re: [PATCH] cloud-init: trigger dynamic DNS update on hostname
> change
> >
> > Hi Justin, some comments inline below:
> >
> > On Tue, Nov 22, 2016 at 11:37 PM, Justin Cinkelj  >
> > wrote:
> >
> > > When cloud-init changes VM hostname, VM DNS name should be updated too.
> > > We try to do this by releasing DHCP lease and requesting new lease
> > >
> >
> > Is the "release" part actually necessary? Can't we start the
> initialization
> > again without a release? (and even more optimized version would be to
> > contact the server directly, but let's not try to optimize this case too
> > much)?
>
> Hm, I didn't think about not doing release. One potential problem - old
> name
> might not get released.
>
> Optimized version would be to contact the server directly - which server?
>

The DHCP server.
I thought that instead of sending a new broadcast (which one does before he
knows what is the DHCP server) maybe you can send the message directly to
the server, like we do in the RELEASE case. But this optimization is
probably not worth it, and I don't know if it's even possible.

I would like to think that when a DHCP server gets a request from a MAC
address which it already gave an IP address and/or dns entry for, it will
remove the old entries before giving out new ones. I didn't test this,
however. Again, because the "RELEASE" operation is considered, also by the
DHCP docs, as "optional" because of the fact it doesn't have an ack. So I
doubt the correct operationof any DHCP server can rely on release taking
place.

Anyway, I'm not against this release() - it will have a tiny performance
impact. Feel free to keep it.

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


Re: [PATCH] cloud-init: trigger dynamic DNS update on hostname change

2016-11-23 Thread Justin Cinkelj


- Original Message -
> From: "Nadav Har'El" 
> To: "Justin Cinkelj" 
> Cc: "Osv Dev" 
> Sent: Wednesday, November 23, 2016 8:31:01 AM
> Subject: Re: [PATCH] cloud-init: trigger dynamic DNS update on hostname change
> 
> Hi Justin, some comments inline below:
> 
> On Tue, Nov 22, 2016 at 11:37 PM, Justin Cinkelj 
> wrote:
> 
> > When cloud-init changes VM hostname, VM DNS name should be updated too.
> > We try to do this by releasing DHCP lease and requesting new lease
> >
> 
> Is the "release" part actually necessary? Can't we start the initialization
> again without a release? (and even more optimized version would be to
> contact the server directly, but let's not try to optimize this case too
> much)?

Hm, I didn't think about not doing release. One potential problem - old name
might not get released.

Optimized version would be to contact the server directly - which server?
Do you mean that DHCP client would directly talk to DNS server? That cannot
work, DHCP server usually has trusted key allowing it to update the DNS server.

> 
> The reason I'm asking this is that release() is unreliable and cannot be
> assumed to do anything (since it has no acknowledgement). So I wonder if
> it's worth calling at all. Maybe it can't hurt, but it just seems weird to
> me to do something which isn't guaranteed to work.

Its all on UDP anyway. In practice, as we just finished one DORA cycle, network
is working, packet drop is hopefully low, and release will work. If release gets
lost, then there is not much we can do. But I think it is worth to try to
release, just to be kind against DHCP server.

> 
> 
> > with new name. This instructs DHCP server to perform dynamic DNS update.
> > DNS update will/should succeed if
> >  1) new name is not already claimed by some other VM/IP and
> >  2) obviously, DHCP and DNS server need to support dynamic DNS updates.
> >
> > Signed-off-by: Justin Cinkelj 
> > ---
> >  core/dhcp.cc | 17 +
> >  include/osv/dhcp.hh  |  7 +++
> >  modules/cloud-init/cloud-init.cc | 27 +++
> >  3 files changed, 43 insertions(+), 8 deletions(-)
> >
> > diff --git a/core/dhcp.cc b/core/dhcp.cc
> > index 689a387..f33a091 100644
> > --- a/core/dhcp.cc
> > +++ b/core/dhcp.cc
> > @@ -75,6 +75,11 @@ void dhcp_release()
> >  net_dhcp_worker.release();
> >  }
> >
> > +void dhcp_restart()
> > +{
> > +net_dhcp_worker.restart();
> > +}
> > +
> >  namespace dhcp {
> >
> >  const char * dhcp_options_magic = "\x63\x82\x53\x63";
> > @@ -648,6 +653,11 @@ namespace dhcp {
> >  //couple of time
> >  }
> >
> > +void dhcp_interface_state::restart() {
> > +release();
> > +discover();
> >
> 
> 
> Is discover() really what we want to do here?
> It's been a while since I looked at this code, but it seems to me that
> discover() is just an internal function to send a discover packet, once.
> the init() code does more than this - it also waits for an ack, and retries
> if an ack doesn't arrive. Don't we need to call that?
> 
> 
> If we do, then probably we don't need a new restart() function - we could
> justl the existing init() function. I see in init() some FIXME about
> running for a second time, maybe something needs fixing there.
> See also above my question on whether it's worth bothering with the
> release() before this init().
> 

You are right - the second DORA cycle should retry sending discover too.
I will split dhcp_interface_state::init() into two functions (internal
structures allocation + DORA cycle with retry), so second part can be reused.

FIXME: clear routing table (use case run dhclient 2nd time)
dhcp_interface_state::state_request adds them, so 
dhcp_interface_state::release should remove them.

Thank you for review - most helpful :)
Justin

> 
> > +}
> > +
> >  
> > ///
> >
> >  dhcp_worker::dhcp_worker()
> > @@ -706,6 +716,13 @@ namespace dhcp {
> >  } while (!_have_ip && wait);
> >  }
> >
> > +void dhcp_worker::restart()
> > +{
> > +for (auto &it: _universe) {
> > +it.second->restart();
> > +}
> > +}
> > +
> >  void dhcp_worker::release()
> >  {
> >  for (auto &it: _universe) {
> > diff --git a/include/osv/dhcp.hh b/include/osv/dhcp.hh
> > index 55e0b16..374b82f 100644
> > --- a/include/osv/dhcp.hh
> > +++ b/include/osv/dhcp.hh
> > @@ -25,6 +25,7 @@
> >  extern "C" {
> >  void dhcp_start(bool wait);
> >  void dhcp_release();
> > +void dhcp_restart();
> >  }
> >
> >  namespace dhcp {
> > @@ -225,6 +226,7 @@ namespace dhcp {
> >
> >  void discover();
> >  void release();
> > +void restart();
> >  void process_packet(struct mbuf*);
> >  void state_discover(dhcp_mbuf &dm);
> >  void state_request(dhcp_mbuf &dm);
> > @@ -251,7 +253,12 @@ namespace dhcp {
> >
> >  // Ini