Dnsmasq not responding DHCP requests that don’t follow a DHCP discover

dhcpdhcp-serverdnsmasq

I have an instance of dnsmasq running on network namespace X, and I run dhclient (or any other dhcp client) from within network namespace Y to obtain an IP address on a given interface. The two network namespaces are on the same openvswitch bridge, through which they communicate.

I see that dnsmasq takes ages to reply, somewhere between 10 and 30 seconds, even if a tcpdump shows that all DHCP packets are promptly delivered to the destination namespace.

Why does it take so long? Is there a way to reduce this delay?

Here's an example from /var/log/syslog where the IP address is assigned after 11 seconds:

Apr  4 14:31:27 localhost dhclient: Listening on LPF/_0.ping/ae:ca:22:bc:3c:7b
Apr  4 14:31:27 localhost dhclient: Sending on   LPF/_0.ping/ae:ca:22:bc:3c:7b
Apr  4 14:31:27 localhost dhclient: Sending on   Socket/fallback
Apr  4 14:31:27 localhost dhclient: DHCPREQUEST on _0.ping to 255.255.255.255 port 67
Apr  4 14:31:33 localhost dhclient: DHCPREQUEST on _0.ping to 255.255.255.255 port 67
Apr  4 14:31:48 localhost dhclient: DHCPDISCOVER on _0.ping to 255.255.255.255 port 67 interval 3
Apr  4 14:31:48 localhost dnsmasq-dhcp[11719]: DHCPDISCOVER(_0.dhcp) 192.168.31.110 ae:ca:22:bc:3c:7b 
Apr  4 14:31:48 localhost dnsmasq-dhcp[11719]: DHCPOFFER(_0.dhcp) 192.168.31.110 ae:ca:22:bc:3c:7b 
Apr  4 14:31:48 localhost dhclient: DHCPREQUEST on _0.ping to 255.255.255.255 port 67
Apr  4 14:31:48 localhost dhclient: DHCPOFFER from 192.168.31.1
Apr  4 14:31:48 localhost dnsmasq-dhcp[11719]: DHCPREQUEST(_0.dhcp) 192.168.31.110 ae:ca:22:bc:3c:7b 
Apr  4 14:31:48 localhost dnsmasq-dhcp[11719]: DHCPACK(_0.dhcp) 192.168.31.110 ae:ca:22:bc:3c:7b mymachine
Apr  4 14:31:48 localhost dnsmasq-dhcp[11719]: not giving name mymachine to the DHCP lease of 192.168.31.110 because the name exists in /etc/hosts with address 127.0.0.1
Apr  4 14:31:48 localhost dhclient: DHCPACK from 192.168.31.1
Apr  4 14:31:48 localhost dhclient: ntp-servers: expecting at least 4 bytes; got 0
Apr  4 14:31:48 localhost dhclient: bound to 192.168.31.110 -- renewal in 33935 seconds.

The dnsmasq instance is launched with the following command:

dnsmasq --dhcp-range=set:tag0,192.168.31.100,192.168.31.150,24h -l /tmp/dnsmasq-leasefile.dhcp.dhcp --dhcp-option=tag:tag0,option:router,192.168.31.2 --dhcp-option=tag:tag0,option:dns-server,9.9.9.9 --dhcp-option=tag:tag0,42

EDIT
Ok, I ran it a few more times and I think I see a pattern in there. The DHCP client starts by sending two DHCP requests, which are both unanswered. As soon as a DHCP discover is sent, dnsmasq replies. The reason why dhclient first tries with a DHCP request is that it sees a previous lease for the same interface in /var/lib/dhcp/dhclient.leases and tries requesting the IP address appearing there. As soon as I remove such file, the response from dnsmasq is generated instantly. I see two options:

  • I tell dhclient not use its lease file (not sure how), but this is not really ideal…
  • I instruct dnsmasq to respond to requests that don't follow a discover message. How can I do this?

Best Answer

The answer is to use --dhcp-authoritative option in dnsmasq. The problem was that I was restarting the dnsmasq server each time, so it had no lease file, but dhclient had its own lease file. Not being able to verify requested IP address in its own lease file, dnsmasq waits until a dhcp discover message is issued.