dhcpcd-discuss

Re: dhcpcd kills all connections on Wi-Fi roaming between access points

Roy Marples

Tue Dec 08 17:15:40 2020

Hi Boris

On 07/12/2020 22:18, Boris Krasnovskiy wrote:
Hi Roy,

I did some investigation, and the Roaming event is actually clearly indicated by the Wi-Fi stack. CARRIER events in the dhcpcd are indicated but IFF_RUNNING flag, that is not quite correct for Wi-Fi.

The way it works is:
- when IFF_RUNNING drops, but IFF_LOWER_UP stays Up it is the Roaming event
- when IFF_RUNNING and IFF_LOWER_UP drop, it is the Disconnect event.

I appreciate the conversation about making sure the IP is validated on the Network, but it seems for Wi-Fi it should be the supplicant job to determine if one is on the same network, not dhcpcd.

I tried roaming scenarios and did not observe kernel dumping IPv6 addresses.
And by description it should not be during the Roaming event interface stops Running, but never transitions into down state.

Rebuilding the routing tables in dhcp_abort, does cause IP address discard, once I disable that it works correctly

I still hope you will be interested in fixing the issue.

Attached is a patch to try and deal with this.
It does this by ignoring interface flags without IFF_RUNNING but with IFF_LOWER_UP set in link_netlink().

Otherwise, a lack of IFF_RUNNING is treated by dhcpcd as down by dhcpcd.

The only downside of this approach is that if the netlink socket overflows any interfaces in the roaming state will then be marked down. Hopefully this won't happen.

I've not tested this at all really and will do so on the one machine I run Linux on baremetal with a wireless interface (yay, Pinebook) but that might take a few days to find.

As such I'd appreciate any testing on this by list members if at all possible with both wired and wireless interfaces.

Roy
diff --git a/src/if-linux.c b/src/if-linux.c
index eaa5a4d6..0cfd36b2 100644
--- a/src/if-linux.c
+++ b/src/if-linux.c
@@ -512,6 +512,7 @@ int
 if_carrier(struct interface *ifp, __unused const void *ifadata)
 {
 
+	/* Ignore IFF_LOWER_UP. See link_netlink() as to why. */
 	return ifp->flags & IFF_RUNNING ? LINK_UP : LINK_DOWN;
 }
 
@@ -1014,6 +1015,15 @@ link_netlink(struct dhcpcd_ctx *ctx, void *arg, struct nlmsghdr *nlm)
 		dhcpcd_handlehwaddr(ifp, ifi->ifi_type, hwa, hwl);
 	}
 
+	/*
+	 * Nothing else to do, so handle carrier events.
+	 * IFF_RUNNING means interface is ready to run.
+	 * IFF_LOWER_UP means that interface L1 is up.
+	 * For wireless, IFF_LOWER_UP without IFF_RUNNING indicates roaming.
+	 */
+	if (!(ifi->ifi_flags & IFF_RUNNING) && ifi->ifi_flags & IFF_LOWER_UP)
+		return 0;
+
 	dhcpcd_handlecarrier(ifp,
 	    ifi->ifi_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN,
 	    ifi->ifi_flags);
diff --git a/src/privsep-bpf.c b/src/privsep-bpf.c
index 23da9a07..79c4696d 100644
--- a/src/privsep-bpf.c
+++ b/src/privsep-bpf.c
@@ -73,7 +73,8 @@ ps_bpf_recvbpf(void *arg)
 		if (len == -1) {
 			int error = errno;
 
-			logerr("%s: %s", psp->psp_ifname, __func__);
+			if (errno != ENETDOWN)
+				logerr("%s: %s", psp->psp_ifname, __func__);
 			if (error != ENXIO)
 				break;
 			/* If the interface has departed, close the BPF

Follow-Ups:
Re: dhcpcd kills all connections on Wi-Fi roaming between access pointsBoris Krasnovskiy
References:
dhcpcd kills all connections on Wi-Fi roaming between access pointsBoris Krasnovskiy
Re: dhcpcd kills all connections on Wi-Fi roaming between access pointsRoy Marples
Re: dhcpcd kills all connections on Wi-Fi roaming between access pointsBoris Krasnovskiy
Archive administrator: postmaster@marples.name