On 20/02/16 12:51, Legacy, Allain wrote:
> We recently encountered a scenario where 2 different client machines sent 
> discover packets at the exact same time and ended up getting offer responses 
> for the same IP address.   I confirmed that the algorithm in 
> dhcp.c::address_allocate() would use the same start value for both of these 
> MAC addresses so it would appear as though we got unlucky and had a collision 
> on the MAC address for these two specific clients.
> 
> This is the config entry:
> 
> dhcp-range=set:xyz,192.168.29.2,192.168.29.254,255.255.255.0,1d
> 
> These are the logs (first 4 bytes of MAC addresses obfuscated to 02:11:22:33 
> from their actual values):
> 
> daemon.log:2016-02-16T13:55:57.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPDISCOVER(eth0) 02:11:22:33:1c:83
> daemon.log:2016-02-16T13:55:57.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPOFFER(eth0) 192.168.29.40 02:11:22:33:1c:83
> daemon.log:2016-02-16T13:55:57.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPDISCOVER(eth0) 02:11:22:33:1b:cc
> daemon.log:2016-02-16T13:55:57.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPOFFER(eth0) 192.168.29.40 02:11:22:33:1b:cc
> daemon.log:2016-02-16T13:55:57.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPDISCOVER(eth0) 02:11:22:33:1c:83
> daemon.log:2016-02-16T13:55:57.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPOFFER(eth0) 192.168.29.40 02:11:22:33:1c:83
> daemon.log:2016-02-16T13:55:58.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPREQUEST(eth0) 192.168.29.40 02:11:22:33:1b:cc
> daemon.log:2016-02-16T13:55:58.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPACK(eth0) 192.168.29.40 02:11:22:33:1b:cc
> daemon.log:2016-02-16T13:55:59.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPREQUEST(eth0) 192.168.29.40 02:11:22:33:1c:83
> daemon.log:2016-02-16T13:55:59.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPNAK(eth0) 192.168.29.40 02:11:22:33:1c:83 address in use
> daemon.log:2016-02-16T13:56:03.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPREQUEST(eth0) 192.168.29.40 02:11:22:33:1c:83
> daemon.log:2016-02-16T13:56:03.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPNAK(eth0) 192.168.29.40 02:11:22:33:1c:83 address in use
> daemon.log:2016-02-16T13:56:07.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPDISCOVER(eth0) 02:11:22:33:1c:83
> daemon.log:2016-02-16T13:56:07.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPOFFER(eth0) 192.168.29.41 02:11:22:33:1c:83
> daemon.log:2016-02-16T13:56:11.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPREQUEST(eth0) 192.168.29.41 02:11:22:33:1c:83
> daemon.log:2016-02-16T13:56:11.000 localhost dnsmasq-dhcp[12225]: info 
> DHCPACK(eth0) 192.168.29.41 02:11:22:33:1c:83
> 
> 
>>From a DHCP point of view things seem to have resolved themselves 
>>automatically at both the client and server.  There were ensuing tftp issues 
>>on the client which got the NAK and subsequently got a second IP address but 
>>I don't believe this to be related to dnsmasq.
> 
> My question is about why the duplicate IP address was even offered to the 
> second client.  Looking at the dhcp.c::address_allocate() code it seems that 
> this scenario is avoided only if OPT_CONSEC_ADDR is set (which we do not 
> set).   Unless I am missing something it seems that any time the address 
> matches and (r->hash != j) the loop should be terminated and a new address 
> should be allocated.   Can you comment on whether this is intentional because 
> of RFC requirements or whether this should be changed?
> 
>                     if (r->addr.s_addr == addr.s_addr)
>                      {
>                        /* consec-ip mode: we offered this address for another 
> client
>                           (different hash) recently, don't offer it to this 
> one. */
>                        if (option_bool(OPT_CONSEC_ADDR) && r->hash != j)
>                          break;
> 
>                        return 1;
>                      }
> 
> 
> Regards,
> Allain
> 

The log you include is exactly how it's supposed to work in the case of
a hash collision: whichever client REQUESTs the address first gets it,
and the other one gets a NAK and has to try again.

As to your question: the code doesn't have enough information to
distinguish between the _same_ client sending repeated DHCPDISCOVERs and
two or more clients with MAC addresses that hash to the same value
sending DHCPDISCOVERS.

The code you've found has a different function: in OPT_CONSEC_ADDR mode,
the address offered is simply the first free address in the dhcp-range,
so any two or more clients asking simultaneously would be offered the
same address. In effect, every multiple-client contention would be like
the hash-collision case. This code avoids that as the first client gets
offered the first free address, and that address is soft-reserved via
the ping-results table so that if another client (with different hash)
arrives before the first has had chance to REQUEST the address, the
second client gets offered an address one larger. If there are two
clients which hash to the same value, this mechanism doesn't work, and
they have to fight it out via a race to DHCPREQUEST, in the same way as
when address hashes collide in the NOT OPT_CONSEC_ADDR case. So,  when
OPT_CONSEC_ADDR is set, this mechanism make the race to DHCPREQUEST a
rare event rather than the common case, just like when OPT_CONSEC_ADDR
is NOT set.


Cheers,

Simon.








_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss

Reply via email to