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