diff options
author | rik <rik@FreeBSD.org> | 2007-03-18 23:28:53 +0000 |
---|---|---|
committer | rik <rik@FreeBSD.org> | 2007-03-18 23:28:53 +0000 |
commit | 4e46a492aaeb535e8b90e719dc930d2b49290ab2 (patch) | |
tree | e74b1d93a30552790a40b4dd3e9727bf3d96de1d /sys/net/if_bridge.c | |
parent | b7e4c9974400c687352d82bff237079493bee8e9 (diff) | |
download | FreeBSD-src-4e46a492aaeb535e8b90e719dc930d2b49290ab2.zip FreeBSD-src-4e46a492aaeb535e8b90e719dc930d2b49290ab2.tar.gz |
Give a chance for packet to appear with a correct input interfaces
in case of multiple interfaces with the same MAC in the same bridge.
This commit do not solve the entire problem. Only case where packet
arrived from such interface.
PR: kern/109815
MFC after: 7 days
Submitted by: Eygene Ryabinkin and rik@
Discussed with: bms@, thompsa@, yar@
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r-- | sys/net/if_bridge.c | 80 |
1 files changed, 50 insertions, 30 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index f3bf6ac..8768557 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -2119,42 +2119,62 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) return (m); } +#ifdef DEV_CARP +# define OR_CARP_CHECK_WE_ARE_DST(iface) \ + || ((iface)->if_carp \ + && carp_forus((iface)->if_carp, eh->ether_dhost)) +# define OR_CARP_CHECK_WE_ARE_SRC(iface) \ + || ((iface)->if_carp \ + && carp_forus((iface)->if_carp, eh->ether_shost)) +#else +# define OR_CARP_CHECK_WE_ARE_DST(iface) +# define OR_CARP_CHECK_WE_ARE_SRC(iface) +#endif + +#define GRAB_OUR_PACKETS(iface) \ + if ((iface)->if_type == IFT_GIF) \ + continue; \ + /* It is destined for us. */ \ + if (memcmp(IF_LLADDR((iface)), eh->ether_dhost, ETHER_ADDR_LEN) == 0 \ + OR_CARP_CHECK_WE_ARE_DST((iface)) \ + ) { \ + if (bif->bif_flags & IFBIF_LEARNING) \ + (void) bridge_rtupdate(sc, \ + eh->ether_shost, bif, 0, IFBAF_DYNAMIC); \ + m->m_pkthdr.rcvif = iface; \ + BRIDGE_UNLOCK(sc); \ + return (m); \ + } \ + \ + /* We just received a packet that we sent out. */ \ + if (memcmp(IF_LLADDR((iface)), eh->ether_shost, ETHER_ADDR_LEN) == 0 \ + OR_CARP_CHECK_WE_ARE_SRC((iface)) \ + ) { \ + BRIDGE_UNLOCK(sc); \ + m_freem(m); \ + return (NULL); \ + } + /* * Unicast. Make sure it's not for us. + * + * Give a chance for ifp at first priority. This will help when the + * packet comes through the interface like VLAN's with the same MACs + * on several interfaces from the same bridge. This also will save + * some CPU cycles in case the destination interface and the input + * interface (eq ifp) are the same. */ - LIST_FOREACH(bif2, &sc->sc_iflist, bif_next) { - if (bif2->bif_ifp->if_type == IFT_GIF) - continue; - /* It is destined for us. */ - if (memcmp(IF_LLADDR(bif2->bif_ifp), eh->ether_dhost, - ETHER_ADDR_LEN) == 0 -#ifdef DEV_CARP - || (bif2->bif_ifp->if_carp - && carp_forus(bif2->bif_ifp->if_carp, eh->ether_dhost)) -#endif - ) { - if (bif->bif_flags & IFBIF_LEARNING) - (void) bridge_rtupdate(sc, - eh->ether_shost, bif, 0, IFBAF_DYNAMIC); - m->m_pkthdr.rcvif = bif2->bif_ifp; - BRIDGE_UNLOCK(sc); - return (m); - } + do { GRAB_OUR_PACKETS(ifp) } while (0); - /* We just received a packet that we sent out. */ - if (memcmp(IF_LLADDR(bif2->bif_ifp), eh->ether_shost, - ETHER_ADDR_LEN) == 0 -#ifdef DEV_CARP - || (bif2->bif_ifp->if_carp - && carp_forus(bif2->bif_ifp->if_carp, eh->ether_shost)) -#endif - ) { - BRIDGE_UNLOCK(sc); - m_freem(m); - return (NULL); - } + /* Now check the all bridge members. */ + LIST_FOREACH(bif2, &sc->sc_iflist, bif_next) { + GRAB_OUR_PACKETS(bif2->bif_ifp) } +#undef OR_CARP_CHECK_WE_ARE_DST +#undef OR_CARP_CHECK_WE_ARE_SRC +#undef GRAB_OUR_PACKETS + /* Perform the bridge forwarding function. */ bridge_forward(sc, m); |