Discussion:
bridge(4) unicast behaviour
(too old to reply)
Masao Uebayashi
2009-03-29 13:29:02 UTC
Permalink
I'm trying to use bridge(4) with tap(4) for emulator's network driver backend.
Multicast packets going from within emulator can reach addresses in the
bridge, but unicast packets "disappear" misteriously. I've tracked this and
found a suspicious code fragment in sys/net/if_bridge.c:bridge_input():

1494 /*
1495 * Unicast. Make sure it's not for us.
1496 */
1497 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1498 /* It is destined for us. */
1499 if (memcmp(CLLADDR(bif->bif_ifp->if_sadl), eh->ether_dhost,
1500 ETHER_ADDR_LEN) == 0
1501 #if NCARP > 0
1502 || (bif->bif_ifp->if_carp && carp_ourether(bif->bif_ifp->if_carp,
1503 eh, IFT_ETHER, 0) != NULL)
1504 #endif /* NCARP > 0 */
1505 ) {
1506 if (bif->bif_flags & IFBIF_LEARNING)
1507 (void) bridge_rtupdate(sc,
1508 eh->ether_shost, ifp, 0, IFBAF_DYNAMIC);
1509 m->m_pkthdr.rcvif = bif->bif_ifp;
1510 return (m);
1511 }
1512
1513 /* We just received a packet that we sent out. */
1514 if (memcmp(CLLADDR(bif->bif_ifp->if_sadl), eh->ether_shost,
1515 ETHER_ADDR_LEN) == 0
1516 #if NCARP > 0
1517 || (bif->bif_ifp->if_carp && carp_ourether(bif->bif_ifp->if_carp,
1518 eh, IFT_ETHER, 1) != NULL)
1519 #endif /* NCARP > 0 */
1520 ) {
1521 m_freem(m);
1522 return (NULL);
1523 }
1524 }

This is a loop looking for a destination interface in a given bridge. The
first if () is to compare if_sadl with packet's eh->ether_dhost, which is
OK. But the 2nd if (), which is comparing a given interface's address with
packet's source address (eh->ether_shost), happens to match, the packet just
"disappears". I don't think that this is intended behaviour.

(Think of the case that if the next interface (bif) in the list is the inteface
which has the matching destination address. This LIST_FOREACH() behaviour
depends on the order of interfaces in the list.)

Masao

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Peter
2009-03-29 20:02:14 UTC
Permalink
Hi,
I wrote all this stuff to put the bridge on a soft interrupt queue,
so that BRIDGE_IPF doesn't cause lock errors. But I've been having
some other weird issues and this might be one of them.

But, just thinking outloud, is it really the case that we wouldn't
want to just ignore any packets that we sent out? In particular note
that bridge_input() is, as far as I know, not called unless the packet
is from outside the machine. So if this code finds a packet with the
our source MAC address, why would we want to do anything with it at
all?

- Peter
Post by Masao Uebayashi
I'm trying to use bridge(4) with tap(4) for emulator's network driver backend.
Multicast packets going from within emulator can reach addresses in the
bridge, but unicast packets "disappear" misteriously. I've tracked this and
1494 /*
1495 * Unicast. Make sure it's not for us.
1496 */
1497 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1498 /* It is destined for us. */
1499 if (memcmp(CLLADDR(bif->bif_ifp->if_sadl), eh->ether_dhost,
1500 ETHER_ADDR_LEN) == 0
1501 #if NCARP > 0
1502 || (bif->bif_ifp->if_carp &&
carp_ourether(bif->bif_ifp->if_carp,
1503 eh, IFT_ETHER, 0) != NULL)
1504 #endif /* NCARP > 0 */
1505 ) {
1506 if (bif->bif_flags & IFBIF_LEARNING)
1507 (void) bridge_rtupdate(sc,
1508 eh->ether_shost, ifp, 0, IFBAF_DYNAMIC);
1509 m->m_pkthdr.rcvif = bif->bif_ifp;
1510 return (m);
1511 }
1512
1513 /* We just received a packet that we sent out. */
1514 if (memcmp(CLLADDR(bif->bif_ifp->if_sadl), eh->ether_shost,
1515 ETHER_ADDR_LEN) == 0
1516 #if NCARP > 0
1517 || (bif->bif_ifp->if_carp &&
carp_ourether(bif->bif_ifp->if_carp,
1518 eh, IFT_ETHER, 1) != NULL)
1519 #endif /* NCARP > 0 */
1520 ) {
1521 m_freem(m);
1522 return (NULL);
1523 }
1524 }
This is a loop looking for a destination interface in a given bridge. The
first if () is to compare if_sadl with packet's eh->ether_dhost, which is
OK. But the 2nd if (), which is comparing a given interface's address with
packet's source address (eh->ether_shost), happens to match, the packet just
"disappears". I don't think that this is intended behaviour.
(Think of the case that if the next interface (bif) in the list is the inteface
which has the matching destination address. This LIST_FOREACH() behaviour
depends on the order of interfaces in the list.)
Masao
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Peter
2009-03-29 21:13:13 UTC
Permalink
Actually, I have thought about it and I do think this is an issue, but
possibly for other reasons. I don't think its losing your unicast
packets there. Could it be something else?
Post by Peter
Hi,
I wrote all this stuff to put the bridge on a soft interrupt queue,
so that BRIDGE_IPF doesn't cause lock errors. But I've been having
some other weird issues and this might be one of them.
But, just thinking outloud, is it really the case that we wouldn't
want to just ignore any packets that we sent out? In particular note
that bridge_input() is, as far as I know, not called unless the packet
is from outside the machine. So if this code finds a packet with the
our source MAC address, why would we want to do anything with it at
all?
- Peter
Post by Masao Uebayashi
I'm trying to use bridge(4) with tap(4) for emulator's network driver backend.
Multicast packets going from within emulator can reach addresses in the
bridge, but unicast packets "disappear" misteriously. I've tracked this and
1494 /*
1495 * Unicast. Make sure it's not for us.
1496 */
1497 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1498 /* It is destined for us. */
1499 if (memcmp(CLLADDR(bif->bif_ifp->if_sadl), eh->ether_dhost,
1500 ETHER_ADDR_LEN) == 0
1501 #if NCARP > 0
1502 || (bif->bif_ifp->if_carp &&
carp_ourether(bif->bif_ifp->if_carp,
1503 eh, IFT_ETHER, 0) != NULL)
1504 #endif /* NCARP > 0 */
1505 ) {
1506 if (bif->bif_flags & IFBIF_LEARNING)
1507 (void) bridge_rtupdate(sc,
1508 eh->ether_shost, ifp, 0, IFBAF_DYNAMIC);
1509 m->m_pkthdr.rcvif = bif->bif_ifp;
1510 return (m);
1511 }
1512
1513 /* We just received a packet that we sent out. */
1514 if (memcmp(CLLADDR(bif->bif_ifp->if_sadl), eh->ether_shost,
1515 ETHER_ADDR_LEN) == 0
1516 #if NCARP > 0
1517 || (bif->bif_ifp->if_carp &&
carp_ourether(bif->bif_ifp->if_carp,
1518 eh, IFT_ETHER, 1) != NULL)
1519 #endif /* NCARP > 0 */
1520 ) {
1521 m_freem(m);
1522 return (NULL);
1523 }
1524 }
This is a loop looking for a destination interface in a given bridge. The
first if () is to compare if_sadl with packet's eh->ether_dhost, which is
OK. But the 2nd if (), which is comparing a given interface's address with
packet's source address (eh->ether_shost), happens to match, the packet just
"disappears". I don't think that this is intended behaviour.
(Think of the case that if the next interface (bif) in the list is the inteface
which has the matching destination address. This LIST_FOREACH() behaviour
depends on the order of interfaces in the list.)
Masao
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Loading...