dhcpcd-discuss

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

Boris Krasnovskiy

Tue Dec 08 20:21:25 2020

Hi Roy,

thank you for the patch. It does work, in a simplest scenario, like roaming
between 2.4 and 5 GHz on the same router, although it does not for
the enterprise networks.

There is another function that needs to be there, on the roaming event it
is prudent:
  - abort any in-progress DHCP/RA negotiations
  - force the RENEW request for the IP addresses on reconnect

The problems are:
- After the roaming client is connected to a different access point, which
is a different network device, with different IP and MAC so routing needs
to change on the infrastructure side. That process takes time and effort,
together with the time client was not accessible during roaming itself. So
likely DHCP/RA messages got lost during disruption. As such it would
be much faster not to wait for the DHCP timeout, but just force restart
DHCP/RA negotiation.
- There is a network misconfiguration (in modern days it's extremely rare
to see it), where after roaming you endup on a different subnet of the same
network.

I attached the patch that implements this functionality and according to
our testing works well.

On Tue, Dec 8, 2020 at 12:15 PM Roy Marples <roy@xxxxxxxxxxxx> wrote:

> 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
>


-- 
Thank you,
Boris Krasnovskiy
--- a/src/dhcp.c	2020-12-07 20:47:19.000000000
+++ b/src/dhcp.c	2020-12-06 12:09:35.000000000
@@ -4204,13 +4204,15 @@

 	eloop_timeout_delete(ifp->ctx->eloop, dhcp_start1, ifp);

-	if (state != NULL && state->added) {
-		rt_build(ifp->ctx, AF_INET);
-#ifdef ARP
-		if (ifp->options->options & DHCPCD_ARP)
-			arp_announceaddr(ifp->ctx, &state->addr->addr);
-#endif
-	}
+/*
+	if (state != NULL && state->added) {
+		rt_build(ifp->ctx, AF_INET);
+#ifdef ARP
+		if (ifp->options->options & DHCPCD_ARP)
+			arp_announceaddr(ifp->ctx, &state->addr->addr);
+#endif
+	}
+*/
 }

 struct ipv4_addr *
--- a/src/dhcpcd.c	2020-11-28 09:12:59.000000000
+++ b/src/dhcpcd.c	2020-12-07 20:49:59.000000000
@@ -708,6 +708,22 @@
 			return;
 		loginfox("%s: carrier lost", ifp->name);
 		script_runreason(ifp, "NOCARRIER");
+
+		if (ifp->flags & IFF_UP && ifp->wireless &&
+			if_lowerup(ifp, NULL) == LINK_UP)
+		{
+#ifdef ARP
+			arp_drop(ifp);
+#endif
+#ifdef INET
+			dhcp_abort(ifp);
+#endif
+#ifdef DHCP6
+			dhcp6_abort(ifp);
+#endif
+			return;
+		}
+
 #ifdef NOCARRIER_PRESERVE_IP
 		if (ifp->flags & IFF_UP &&
 		    !(ifp->options->options & DHCPCD_ANONYMOUS))
@@ -774,9 +791,7 @@
 		    memcmp(ifp->ssid, ossid, ifp->ssid_len)) && ifp->active)
 		{
 			dhcpcd_reportssid(ifp);
-#ifdef NOCARRIER_PRESERVE_IP
 			dhcpcd_drop(ifp, 0);
-#endif
 #ifdef IPV4LL
 			ipv4ll_reset(ifp);
 #endif
@@ -789,11 +804,9 @@
 	dhcpcd_initstate(ifp, 0);
 	script_runreason(ifp, "CARRIER");
 #ifdef INET6
-#ifdef NOCARRIER_PRESERVE_IP
 	/* Set any IPv6 Routers we remembered to expire faster than they
 	 * would normally as we maybe on a new network. */
 	ipv6nd_startexpire(ifp);
-#endif
 #ifdef IPV6_MANAGETEMPADDR
 	/* RFC4941 Section 3.5 */
 	ipv6_regentempaddrs(ifp);
--- a/src/if.h	2020-11-28 09:12:59.000000000
+++ b/src/if.h	2020-12-07 18:40:28.000000000
@@ -161,6 +161,7 @@
 #define if_getmtu(ifp) if_domtu((ifp), 0)
 #define if_setmtu(ifp, mtu) if_domtu((ifp), (mtu))
 int if_carrier(struct interface *, const void *);
+int if_lowerup(struct interface *, const void *);

 #ifdef ALIAS_ADDR
 int if_makealias(char *, size_t, const char *, int);
--- a/src/if-linux.c	2020-11-28 09:12:59.000000000
+++ b/src/if-linux.c	2020-12-07 20:53:00.000000000
@@ -516,6 +516,12 @@
 }

 int
+if_lowerup(struct interface *ifp, __unused const void *ifadata)
+{
+	return ifp->flags & IFF_LOWER_UP ? LINK_UP : LINK_DOWN;
+}
+
+int
 if_getnetlink(struct dhcpcd_ctx *ctx, struct iovec *iov, int fd, int flags,
     int (*cb)(struct dhcpcd_ctx *, void *, struct nlmsghdr *), void *cbarg)
 {

Follow-Ups:
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
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
Re: dhcpcd kills all connections on Wi-Fi roaming between access pointsRoy Marples
Archive administrator: postmaster@marples.name