Renewing DHCP While Keeping a NetworkManager Connection Up

TL;DR

$ ps ax | grep dhclient | grep <interface>
$ kill <pid-of-dhclient>
$ nmcli device reapply <interface>

Details

I recently changed my DNS setup on my home network and wanted to move all the clients over to the new nameserver before turning down the old one. My DHCP server was already updated to hand out the new DNS nameserver so all I needed to do was refresh the clients. Due to a few other changes in my network, I had a multi-hour file transfer going on between two machines. A common solution is to just bring the interface down and back up:

$ nmcli con down <id>
$ nmcli con up <id>

Doing so would interrupt the file transfer which I really, really wanted to avoid. Searching the web only turned up a chorus of “just restart the interface.” Not good enough. One other approach is to simply restart dhclient:

$ sudo dhclient -r <interface>
$ sudo dhclient <interface>

While that is valid for some system configurations, it doesn’t work if NetworkManager is involved. With NetworkManager, a copy of dhclient is started per-interface by NetworkManager rather than a single system-wide instance via an init script or systemd unit. Even if you tell dhclient which interface to release, it won’t end up stopping the instances launched by NetworkManager. What do we do? Stopping dhclient is the easy part:

$ ps ax | grep dhclient | grep eth0  # Lookup the pid of the instance for the interface
root     29505  0.0  0.0 38196 2728 ?        Ss   Mar07   0:00 dhclient eth0
$ kill 29505  # Kill it

Even though dhclient will stop, the interface is still up, it has an IP, routes are still valid, and the old DNS configuration is still in use. All that changes with dhclient stopped is DHCP lease renewals won’t happen. All good so far. What about getting dhclient restarted? We could manually restart dhclient with the same arguments that NetworkManager used previously but that wouldn’t preserve the parent/child relationship NetworkManager had previously. We need someway to tell NetworkManager to restart dhclient. (aside: I was rather aghast that NetworkManager doesn’t monitor its dhclient instances and restart them automatically. What happens if dhclient terminates for any other reason?) Buried deep in the nmcli man page is the nmcli device reapply command. NetworkManager already knows what the intended configuration is and that hasn’t changed. All it needs to do is reapply the configuration to the device. Since the device is configured to use DHCP, a new dhclient instance will be started which will immediately request updated lease information from the DHCP server. Since the lease IP and route hasn’t changed and the interface already has those configured, only the DNS nameserver will be changed. IPv4 connectivity and the interface as a whole are uninterrupted.