diff options
| author | Roy Marples <roy@marples.name> | 2020-09-28 17:09:38 +0100 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2020-09-28 17:09:38 +0100 |
| commit | 96702451aea98a8d682ebac5a46e14802e05f624 (patch) | |
| tree | 9b0c7f51d54fbc2ff00de0cfc3dc6b1f0bf87edf /src/if.c | |
| parent | 91df57a59de1ac2f7d9db9f30eccd25513f1a61e (diff) | |
| download | dhcpcd-96702451aea98a8d682ebac5a46e14802e05f624.tar.xz | |
BSD: struct if_data->ifi_link_state is the single source of truth
Vastly improve and simplify link detection on BSD.
dhcpcd either examines the whole system via getifaddrs(3) or
reacts to events via route(4).
In both cases we have struct if_data which has ifi_link_state.
Armed with this knowledge, we no longer need SIOCGIFDATA or
SIOCGIFMEDIA.
To solve the issue of newly attached interfaces having
LINK_STATE_UNKNOWN or some interfaces not even changing it,
we only change the local knowledge of interface flags when
reports them by getifaddrs(3) or route(4) when we change them.
For example, if we set IFF_UP and it succeeds we don't set this
internally until reported by the kernel as above.
This keeps flags and link state in sync with each other.
The hope is that the kernel can set the real link state before
it reports IFF_UP.
As such, we no longer require the poll option or need to enter a
tight loop for old interfaces.
Diffstat (limited to 'src/if.c')
| -rw-r--r-- | src/if.c | 32 |
1 files changed, 6 insertions, 26 deletions
@@ -185,7 +185,11 @@ if_setflag(struct interface *ifp, short setflag, short unsetflag) if_ioctl(ifp->ctx, SIOCSIFFLAGS, &ifr, sizeof(ifr)) == -1) return -1; - ifp->flags = (unsigned int)ifr.ifr_flags; + /* + * Do NOT set ifp->flags here. + * We need to listen for flag updates from the kernel as they + * need to sync with carrier. + */ return 0; } @@ -687,37 +691,13 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs, #endif ifp->active = active; - ifp->carrier = if_carrier_ifadata(ifp, ifa->ifa_data); + ifp->carrier = if_carrier(ifp, ifa->ifa_data); TAILQ_INSERT_TAIL(ifs, ifp, next); } return ifs; } -static void -if_poll(void *arg) -{ - struct interface *ifp = arg; - unsigned int flags = ifp->flags; - int carrier; - - carrier = if_carrier(ifp); /* if_carrier will update ifp->flags */ - if (ifp->carrier != carrier || ifp->flags != flags) - dhcpcd_handlecarrier(ifp->ctx, carrier, ifp->flags, ifp->name); - - if (ifp->options->poll != 0 || ifp->carrier != LINK_UP) - if_pollinit(ifp); -} - -int -if_pollinit(struct interface *ifp) -{ - unsigned long msec; - - msec = ifp->options->poll != 0 ? ifp->options->poll : IF_POLL_UP; - return eloop_timeout_add_msec(ifp->ctx->eloop, msec, if_poll, ifp); -} - /* * eth0.100:2 OR eth0i100:2 (seems to be NetBSD xvif(4) only) * |
