From 8088d27eb47debe53e9ce76c32bf76aafa3dbcad Mon Sep 17 00:00:00 2001 From: kp Date: Sun, 5 Apr 2020 17:15:20 +0000 Subject: [PATCH 2/3] bridge: Change lists to CK_LIST as a peparation for epochification Prepare the ground for a rework of the bridge locking approach. We will use an epoch-based approach in the datapath and making it safe to iterate over the interface, span and rtnode lists without holding the BRIDGE_LOCK. Replace the relevant lists by their ConcurrencyKit equivalents. No functional change in this commit. Reviewed by: emaste, ae, philip (previous version) Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D24249 --- sys/net/if_bridge.c | 130 ++++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 64 deletions(-) diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 60c3c4d86d8..84786875889 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -229,7 +229,7 @@ extern void nd6_setmtu(struct ifnet *); * Bridge interface list entry. */ struct bridge_iflist { - LIST_ENTRY(bridge_iflist) bif_next; + CK_LIST_ENTRY(bridge_iflist) bif_next; struct ifnet *bif_ifp; /* member if */ struct bstp_port bif_stp; /* STP state */ uint32_t bif_flags; /* member if flags */ @@ -243,8 +243,8 @@ struct bridge_iflist { * Bridge route node. */ struct bridge_rtnode { - LIST_ENTRY(bridge_rtnode) brt_hash; /* hash table linkage */ - LIST_ENTRY(bridge_rtnode) brt_list; /* list linkage */ + CK_LIST_ENTRY(bridge_rtnode) brt_hash; /* hash table linkage */ + CK_LIST_ENTRY(bridge_rtnode) brt_list; /* list linkage */ struct bridge_iflist *brt_dst; /* destination if */ unsigned long brt_expire; /* expiration time */ uint8_t brt_flags; /* address flags */ @@ -267,11 +267,11 @@ struct bridge_softc { struct callout sc_brcallout; /* bridge callout */ uint32_t sc_iflist_ref; /* refcount for sc_iflist */ uint32_t sc_iflist_xcnt; /* refcount for sc_iflist */ - LIST_HEAD(, bridge_iflist) sc_iflist; /* member interface list */ - LIST_HEAD(, bridge_rtnode) *sc_rthash; /* our forwarding table */ - LIST_HEAD(, bridge_rtnode) sc_rtlist; /* list version of above */ + CK_LIST_HEAD(, bridge_iflist) sc_iflist; /* member interface list */ + CK_LIST_HEAD(, bridge_rtnode) *sc_rthash; /* our forwarding table */ + CK_LIST_HEAD(, bridge_rtnode) sc_rtlist; /* list version of above */ uint32_t sc_rthash_key; /* key for hash */ - LIST_HEAD(, bridge_iflist) sc_spanlist; /* span ports list */ + CK_LIST_HEAD(, bridge_iflist) sc_spanlist; /* span ports list */ struct bstp_state sc_stp; /* STP state */ uint32_t sc_brtexceeded; /* # of cache drops */ struct ifnet *sc_ifaddr; /* member mac copied from */ @@ -696,8 +696,8 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params) callout_init_mtx(&sc->sc_brcallout, &sc->sc_mtx, 0); - LIST_INIT(&sc->sc_iflist); - LIST_INIT(&sc->sc_spanlist); + CK_LIST_INIT(&sc->sc_iflist); + CK_LIST_INIT(&sc->sc_spanlist); ifp->if_softc = sc; if_initname(ifp, bridge_name, unit); @@ -773,10 +773,10 @@ bridge_clone_destroy(struct ifnet *ifp) bridge_stop(ifp, 1); ifp->if_flags &= ~IFF_UP; - while ((bif = LIST_FIRST(&sc->sc_iflist)) != NULL) + while ((bif = CK_LIST_FIRST(&sc->sc_iflist)) != NULL) bridge_delete_member(sc, bif, 0); - while ((bif = LIST_FIRST(&sc->sc_spanlist)) != NULL) { + while ((bif = CK_LIST_FIRST(&sc->sc_spanlist)) != NULL) { bridge_delete_span(sc, bif); } @@ -915,12 +915,12 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = EINVAL; break; } - if (LIST_EMPTY(&sc->sc_iflist)) { + if (CK_LIST_EMPTY(&sc->sc_iflist)) { sc->sc_ifp->if_mtu = ifr->ifr_mtu; break; } BRIDGE_LOCK(sc); - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { if (bif->bif_ifp->if_mtu != ifr->ifr_mtu) { log(LOG_NOTICE, "%s: invalid MTU: %u(%s)" " != %d\n", sc->sc_ifp->if_xname, @@ -960,13 +960,13 @@ bridge_mutecaps(struct bridge_softc *sc) /* Initial bitmask of capabilities to test */ mask = BRIDGE_IFCAPS_MASK; - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { /* Every member must support it or its disabled */ mask &= bif->bif_savedcaps; } BRIDGE_XLOCK(sc); - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { enabled = bif->bif_ifp->if_capenable; enabled &= ~BRIDGE_IFCAPS_STRIP; /* strip off mask bits and enable them again if allowed */ @@ -1020,7 +1020,7 @@ bridge_lookup_member(struct bridge_softc *sc, const char *name) BRIDGE_LOCK_ASSERT(sc); - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { ifp = bif->bif_ifp; if (strcmp(ifp->if_xname, name) == 0) return (bif); @@ -1041,7 +1041,7 @@ bridge_lookup_member_if(struct bridge_softc *sc, struct ifnet *member_ifp) BRIDGE_LOCK_ASSERT(sc); - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { if (bif->bif_ifp == member_ifp) return (bif); } @@ -1060,6 +1060,7 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif, { struct ifnet *ifs = bif->bif_ifp; struct ifnet *fif = NULL; + struct bridge_iflist *bifl; BRIDGE_LOCK_ASSERT(sc); @@ -1068,7 +1069,7 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif, ifs->if_bridge = NULL; BRIDGE_XLOCK(sc); - LIST_REMOVE(bif, bif_next); + CK_LIST_REMOVE(bif, bif_next); BRIDGE_XDROP(sc); /* @@ -1077,12 +1078,13 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif, * to its default address if no members are left. */ if (V_bridge_inherit_mac && sc->sc_ifaddr == ifs) { - if (LIST_EMPTY(&sc->sc_iflist)) { + if (CK_LIST_EMPTY(&sc->sc_iflist)) { bcopy(&sc->sc_defaddr, IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); sc->sc_ifaddr = NULL; } else { - fif = LIST_FIRST(&sc->sc_iflist)->bif_ifp; + bifl = CK_LIST_FIRST(&sc->sc_iflist); + fif = bifl->bif_ifp; bcopy(IF_LLADDR(fif), IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); sc->sc_ifaddr = fif; @@ -1143,7 +1145,7 @@ bridge_delete_span(struct bridge_softc *sc, struct bridge_iflist *bif) KASSERT(bif->bif_ifp->if_bridge == NULL, ("%s: not a span interface", __func__)); - LIST_REMOVE(bif, bif_next); + CK_LIST_REMOVE(bif, bif_next); free(bif, M_DEVBUF); } @@ -1162,7 +1164,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) return (EINVAL); /* If it's in the span list, it can't be a member. */ - LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) + CK_LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) if (ifs == bif->bif_ifp) return (EBUSY); @@ -1201,7 +1203,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) * interfaces. */ BRIDGE_XLOCK(sc); - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { if (in6ifa_llaonifp(bif->bif_ifp)) { BRIDGE_UNLOCK(sc); in6_ifdetach(bif->bif_ifp); @@ -1227,7 +1229,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) } #endif /* Allow the first Ethernet member to define the MTU */ - if (LIST_EMPTY(&sc->sc_iflist)) + if (CK_LIST_EMPTY(&sc->sc_iflist)) sc->sc_ifp->if_mtu = ifs->if_mtu; else if (sc->sc_ifp->if_mtu != ifs->if_mtu) { if_printf(sc->sc_ifp, "invalid MTU: %u(%s) != %u\n", @@ -1248,7 +1250,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) * member and the MAC address of the bridge has not been changed from * the default randomly generated one. */ - if (V_bridge_inherit_mac && LIST_EMPTY(&sc->sc_iflist) && + if (V_bridge_inherit_mac && CK_LIST_EMPTY(&sc->sc_iflist) && !memcmp(IF_LLADDR(sc->sc_ifp), sc->sc_defaddr.octet, ETHER_ADDR_LEN)) { bcopy(IF_LLADDR(ifs), IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); sc->sc_ifaddr = ifs; @@ -1265,7 +1267,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) * * NOTE: insert_***HEAD*** should be safe for the traversals. */ - LIST_INSERT_HEAD(&sc->sc_iflist, bif, bif_next); + CK_LIST_INSERT_HEAD(&sc->sc_iflist, bif, bif_next); /* Set interface capabilities to the intersection set of all members */ bridge_mutecaps(sc); @@ -1412,9 +1414,9 @@ bridge_ioctl_gifs(struct bridge_softc *sc, void *arg) int count, buflen, len, error = 0; count = 0; - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) + CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) count++; - LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) + CK_LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) count++; buflen = sizeof(breq) * count; @@ -1430,7 +1432,7 @@ bridge_ioctl_gifs(struct bridge_softc *sc, void *arg) buf = outbuf; len = min(bifc->ifbic_len, buflen); bzero(&breq, sizeof(breq)); - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { if (len < sizeof(breq)) break; @@ -1445,7 +1447,7 @@ bridge_ioctl_gifs(struct bridge_softc *sc, void *arg) buf += sizeof(breq); len -= sizeof(breq); } - LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) { + CK_LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) { if (len < sizeof(breq)) break; @@ -1480,7 +1482,7 @@ bridge_ioctl_rts(struct bridge_softc *sc, void *arg) return (0); count = 0; - LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) + CK_LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) count++; buflen = sizeof(bareq) * count; @@ -1492,7 +1494,7 @@ bridge_ioctl_rts(struct bridge_softc *sc, void *arg) buf = outbuf; len = min(bac->ifbac_len, buflen); bzero(&bareq, sizeof(bareq)); - LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) { + CK_LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) { if (len < sizeof(bareq)) goto out; strlcpy(bareq.ifba_ifsname, brt->brt_ifp->if_xname, @@ -1695,7 +1697,7 @@ bridge_ioctl_addspan(struct bridge_softc *sc, void *arg) if (ifs == NULL) return (ENOENT); - LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) + CK_LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) if (ifs == bif->bif_ifp) return (EBUSY); @@ -1718,7 +1720,7 @@ bridge_ioctl_addspan(struct bridge_softc *sc, void *arg) bif->bif_ifp = ifs; bif->bif_flags = IFBIF_SPAN; - LIST_INSERT_HEAD(&sc->sc_spanlist, bif, bif_next); + CK_LIST_INSERT_HEAD(&sc->sc_spanlist, bif, bif_next); return (0); } @@ -1734,7 +1736,7 @@ bridge_ioctl_delspan(struct bridge_softc *sc, void *arg) if (ifs == NULL) return (ENOENT); - LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) + CK_LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) if (ifs == bif->bif_ifp) break; @@ -1796,7 +1798,7 @@ bridge_ioctl_gifsstp(struct bridge_softc *sc, void *arg) int count, buflen, len, error = 0; count = 0; - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { if ((bif->bif_flags & IFBIF_STP) != 0) count++; } @@ -1815,7 +1817,7 @@ bridge_ioctl_gifsstp(struct bridge_softc *sc, void *arg) buf = outbuf; len = min(bifstp->ifbpstp_len, buflen); bzero(&bpreq, sizeof(bpreq)); - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { if (len < sizeof(bpreq)) break; @@ -1897,7 +1899,7 @@ bridge_ifdetach(void *arg __unused, struct ifnet *ifp) BRIDGE_LIST_LOCK(); LIST_FOREACH(sc, &V_bridge_list, sc_list) { BRIDGE_LOCK(sc); - LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) + CK_LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) if (ifp == bif->bif_ifp) { bridge_delete_span(sc, bif); break; @@ -2108,7 +2110,7 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, return (0); } - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { dst_if = bif->bif_ifp; if (dst_if->if_type == IFT_GIF) @@ -2126,7 +2128,7 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, bif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING) continue; - if (LIST_NEXT(bif, bif_next) == NULL) { + if (CK_LIST_NEXT(bif, bif_next) == NULL) { used = 1; mc = m; } else { @@ -2537,7 +2539,7 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) do { GRAB_OUR_PACKETS(ifp) } while (0); /* Now check the all bridge members. */ - LIST_FOREACH(bif2, &sc->sc_iflist, bif_next) { + CK_LIST_FOREACH(bif2, &sc->sc_iflist, bif_next) { GRAB_OUR_PACKETS(bif2->bif_ifp) } @@ -2590,7 +2592,7 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if, goto out; } - LIST_FOREACH(dbif, &sc->sc_iflist, bif_next) { + CK_LIST_FOREACH(dbif, &sc->sc_iflist, bif_next) { dst_if = dbif->bif_ifp; if (dst_if == src_if) continue; @@ -2610,7 +2612,7 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if, if ((dst_if->if_drv_flags & IFF_DRV_RUNNING) == 0) continue; - if (LIST_NEXT(dbif, bif_next) == NULL) { + if (CK_LIST_NEXT(dbif, bif_next) == NULL) { mc = m; used = 1; } else { @@ -2668,10 +2670,10 @@ bridge_span(struct bridge_softc *sc, struct mbuf *m) struct ifnet *dst_if; struct mbuf *mc; - if (LIST_EMPTY(&sc->sc_spanlist)) + if (CK_LIST_EMPTY(&sc->sc_spanlist)) return; - LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) { + CK_LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) { dst_if = bif->bif_ifp; if ((dst_if->if_drv_flags & IFF_DRV_RUNNING) == 0) @@ -2807,7 +2809,7 @@ bridge_rttrim(struct bridge_softc *sc) if (sc->sc_brtcnt <= sc->sc_brtmax) return; - LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) { + CK_LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) { if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) { bridge_rtnode_destroy(sc, brt); if (sc->sc_brtcnt <= sc->sc_brtmax) @@ -2850,7 +2852,7 @@ bridge_rtage(struct bridge_softc *sc) BRIDGE_LOCK_ASSERT(sc); - LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) { + CK_LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) { if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) { if (time_uptime >= brt->brt_expire) bridge_rtnode_destroy(sc, brt); @@ -2870,7 +2872,7 @@ bridge_rtflush(struct bridge_softc *sc, int full) BRIDGE_LOCK_ASSERT(sc); - LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) { + CK_LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) { if (full || (brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) bridge_rtnode_destroy(sc, brt); } @@ -2913,7 +2915,7 @@ bridge_rtdelete(struct bridge_softc *sc, struct ifnet *ifp, int full) BRIDGE_LOCK_ASSERT(sc); - LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) { + CK_LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) { if (brt->brt_ifp == ifp && (full || (brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)) bridge_rtnode_destroy(sc, brt); @@ -2934,10 +2936,10 @@ bridge_rtable_init(struct bridge_softc *sc) M_DEVBUF, M_WAITOK); for (i = 0; i < BRIDGE_RTHASH_SIZE; i++) - LIST_INIT(&sc->sc_rthash[i]); + CK_LIST_INIT(&sc->sc_rthash[i]); sc->sc_rthash_key = arc4random(); - LIST_INIT(&sc->sc_rtlist); + CK_LIST_INIT(&sc->sc_rtlist); } /* @@ -3018,7 +3020,7 @@ bridge_rtnode_lookup(struct bridge_softc *sc, const uint8_t *addr, uint16_t vlan BRIDGE_LOCK_ASSERT(sc); hash = bridge_rthash(sc, addr); - LIST_FOREACH(brt, &sc->sc_rthash[hash], brt_hash) { + CK_LIST_FOREACH(brt, &sc->sc_rthash[hash], brt_hash) { dir = bridge_rtnode_addr_cmp(addr, brt->brt_addr); if (dir == 0 && (brt->brt_vlan == vlan || vlan == 0)) return (brt); @@ -3046,9 +3048,9 @@ bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt) hash = bridge_rthash(sc, brt->brt_addr); - lbrt = LIST_FIRST(&sc->sc_rthash[hash]); + lbrt = CK_LIST_FIRST(&sc->sc_rthash[hash]); if (lbrt == NULL) { - LIST_INSERT_HEAD(&sc->sc_rthash[hash], brt, brt_hash); + CK_LIST_INSERT_HEAD(&sc->sc_rthash[hash], brt, brt_hash); goto out; } @@ -3057,14 +3059,14 @@ bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt) if (dir == 0 && brt->brt_vlan == lbrt->brt_vlan) return (EEXIST); if (dir > 0) { - LIST_INSERT_BEFORE(lbrt, brt, brt_hash); + CK_LIST_INSERT_BEFORE(lbrt, brt, brt_hash); goto out; } - if (LIST_NEXT(lbrt, brt_hash) == NULL) { - LIST_INSERT_AFTER(lbrt, brt, brt_hash); + if (CK_LIST_NEXT(lbrt, brt_hash) == NULL) { + CK_LIST_INSERT_AFTER(lbrt, brt, brt_hash); goto out; } - lbrt = LIST_NEXT(lbrt, brt_hash); + lbrt = CK_LIST_NEXT(lbrt, brt_hash); } while (lbrt != NULL); #ifdef DIAGNOSTIC @@ -3072,7 +3074,7 @@ bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt) #endif out: - LIST_INSERT_HEAD(&sc->sc_rtlist, brt, brt_list); + CK_LIST_INSERT_HEAD(&sc->sc_rtlist, brt, brt_list); sc->sc_brtcnt++; return (0); @@ -3088,9 +3090,9 @@ bridge_rtnode_destroy(struct bridge_softc *sc, struct bridge_rtnode *brt) { BRIDGE_LOCK_ASSERT(sc); - LIST_REMOVE(brt, brt_hash); + CK_LIST_REMOVE(brt, brt_hash); - LIST_REMOVE(brt, brt_list); + CK_LIST_REMOVE(brt, brt_list); sc->sc_brtcnt--; brt->brt_dst->bif_addrcnt--; uma_zfree(V_bridge_rtnode_zone, brt); @@ -3117,7 +3119,7 @@ bridge_rtable_expire(struct ifnet *ifp, int age) if (age == 0) bridge_rtdelete(sc, ifp, IFBF_FLUSHDYN); else { - LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) { + CK_LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) { /* Cap the expiry time to 'age' */ if (brt->brt_ifp == ifp && brt->brt_expire > time_uptime + age && @@ -3661,7 +3663,7 @@ bridge_linkcheck(struct bridge_softc *sc) new_link = LINK_STATE_DOWN; hasls = 0; /* Our link is considered up if at least one of our ports is active */ - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { if (bif->bif_ifp->if_capabilities & IFCAP_LINKSTATE) hasls++; if (bif->bif_ifp->if_link_state == LINK_STATE_UP) { @@ -3669,7 +3671,7 @@ bridge_linkcheck(struct bridge_softc *sc) break; } } - if (!LIST_EMPTY(&sc->sc_iflist) && !hasls) { + if (!CK_LIST_EMPTY(&sc->sc_iflist) && !hasls) { /* If no interfaces support link-state then we default to up */ new_link = LINK_STATE_UP; } -- 2.25.2