Date: Thu, 14 Jan 2016 01:09:58 +0300 From: Alexander V. Chernikov <melifaro@freebsd.org> To: =?utf-8?B?T2xpdmllciBDb2NoYXJkLUxhYmLDqQ==?= <olivier@cochard.me> Cc: Adrian Chadd <adrian.chadd@gmail.com>, "freebsd-current@freebsd.org" <freebsd-current@freebsd.org>, "freebsd-wireless@freebsd.org" <freebsd-wireless@freebsd.org> Subject: Re: forwarding didn't work if wlan0 is member of a bridge Message-ID: <550651452722998@web11h.yandex.ru> In-Reply-To: <CA%2Bq%2BTcpgA9qpkjyRVyVgh60S%2BUBWeSQa1rVd9%2B_O9OUEAyP1AQ@mail.gmail.com> References: <CA%2Bq%2BTco3MKBvhCQXvVaDkRZQYzX6tye8opD3yKrtnnF3imGDCg@mail.gmail.com> <CA%2Bq%2BTcq-CkyBMxvmWEDu1Ejg_36CDHmhPBE1t7CiV37hDVTvNQ@mail.gmail.com> <CAJ-Vmo=FJGwuaw6y--e3U6GfmtdUo4gnZwvhjeZXGaEmvEj-OQ@mail.gmail.com> <CA%2Bq%2BTcoHXeAmOQ2_-7c0WHMHHB3SvPpGdUiOLteG8tQXxCsQqA@mail.gmail.com> <1223091452631961@web14j.yandex.ru> <CA%2Bq%2BTcpR=jx00yWf%2Bwovk5a2ptdOPz78bpGVe=shr8N631Cdcw@mail.gmail.com> <2985841452674737@web5h.yandex.ru> <CA%2Bq%2BTcpgA9qpkjyRVyVgh60S%2BUBWeSQa1rVd9%2B_O9OUEAyP1AQ@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --] 13.01.2016, 13:02, "Olivier Cochard-Labbé" <olivier@cochard.me>: > On Wed, Jan 13, 2016 at 9:45 AM, Alexander V. Chernikov <melifaro@ipfw.ru> > wrote: > >> I suspect the reason here is link state bridge handling. >> ix0 does not seem to have IFCAP_LINKSTATE option but re(4) does. Probably >> wlan0 doesn't have LINKSTATE option. >> Code in bridge_linkcheck() doesn't handle the case with both "has link >> state" and "no link state" interfaces well: >> if reX is the only interface w/ IFCAP_LINKSTATE and it goes down, bridge >> will also change its link state to down. >> (However, bridge does not seem to have link state option itself, so >> RT_LINK_IS_UP() macro should return true...) > > For validating your "IFCAP_LINKSTATE" hypothesis, I've plug an USB > ethernet adapter ue(4) that didn't support IFCAP_LINKSTATE. > And I've setup the bridge0 with wlan0 and ue0 (in place of re1): same bug > triggered. I need to plug a cable for correct routing. We discussed/investigated this behaviour on IRC. To summarise: 1) ip_tryforward() does check interface linkstate regardless of linkstate capability 2) bridge linkcheck function does not seem to care about linkstate capability. What happened in original case: 802.11 does not provide linkstate cap and actual linkstate value is 0 (unknown). re0 does provide linkstate cap, so on link down, bridge_linkcheck() code decided to set own linkstate as DOWN as well (has non-zero linkstate interface, 0 up). On packet transmission. ip_tryforward() checked bridge0 state, found it to be DOWN so the icmp_error() was triggered. Attached patch fixes the problem, but I'm still thinking about better solution. > > root@fbsd-router:~ # ifconfig bridge0 > bridge0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu > 1500 > ether 02:6b:c0:de:b8:00 > inet 1.1.1.1 netmask 0xffffff00 broadcast 1.1.1.255 > nd6 options=9<PERFORMNUD,IFDISABLED> > groups: bridge > id 00:00:00:00:00:00 priority 32768 hellotime 2 fwddelay 15 > maxage 20 holdcnt 6 proto rstp maxaddr 2000 timeout 1200 > root id 00:00:00:00:00:00 priority 32768 ifcost 0 port 0 > member: ue0 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP> > ifmaxaddr 0 port 7 priority 128 path cost 55 > member: wlan0 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP> > ifmaxaddr 0 port 5 priority 128 path cost 33333 > root@fbsd-router:~ # ifconfig ue0 > ue0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 > mtu 1500 > options=80008<VLAN_MTU,LINKSTATE> > ether 00:19:fd:4e:77:4d > nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL> > media: Ethernet autoselect (none) > status: no carrier > > Regards, > _______________________________________________ > freebsd-current@freebsd.org mailing list > https://lists.freebsd.org/mailman/listinfo/freebsd-current > To unsubscribe, send any mail to "freebsd-current-unsubscribe@freebsd.org" [-- Attachment #2 --] Index: /usr/src/sys/net/if_bridge.c =================================================================== --- /usr/src/sys/net/if_bridge.c (revision 293659) +++ /usr/src/sys/net/if_bridge.c (working copy) @@ -3550,22 +3550,25 @@ static void bridge_linkcheck(struct bridge_softc *sc) { struct bridge_iflist *bif; - int new_link, hasls; + int new_link, nols; BRIDGE_LOCK_ASSERT(sc); new_link = LINK_STATE_DOWN; - hasls = 0; + nols = 0; /* Our link is considered up if at least one of our ports is active */ LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { - if (bif->bif_ifp->if_capabilities & IFCAP_LINKSTATE) - hasls++; + if ((bif->bif_ifp->if_capabilities & IFCAP_LINKSTATE) == 0) { + /* XXX: Handle admin down? */ + nols++; + continue; + } if (bif->bif_ifp->if_link_state == LINK_STATE_UP) { new_link = LINK_STATE_UP; break; } } - if (!LIST_EMPTY(&sc->sc_iflist) && !hasls) { - /* If no interfaces support link-state then we default to up */ + if (!LIST_EMPTY(&sc->sc_iflist) && nols != 0) { + /* If some ifaces don't support link-state then we default to up */ new_link = LINK_STATE_UP; } if_link_state_change(sc->sc_ifp, new_link);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?550651452722998>
