Thu Jul 23 10:52:34 2015 UTC ()
Fix PR 48104

So far bridge cannot receive frames via a member interface when the frames
come from another member interface. So when we assign an IP address to
a member interface, hosts connected to another member interface cannot
ping to the IP address. That behavior isn't expected. See PR 48104 for
more realistic examples of this issue.

The change does:
- drop M_PROMISC before ether_input, which allows a bridge member interface
  to receive a frame coming from another bridge member interface
- receive broadcast/multicast frames via all bridge member interfaces,
  which is required to receive IPv6 multicast packets destined to a
  multicast group belonging to a bridge member interface that is different
  from a packet arrival interface

roy@ helped testing of the fix, thanks!


(ozaki-r)
diff -r1.99 -r1.100 src/sys/net/if_bridge.c

cvs diff -r1.99 -r1.100 src/sys/net/if_bridge.c (expand / switch to unified diff)

--- src/sys/net/if_bridge.c 2015/06/01 06:14:43 1.99
+++ src/sys/net/if_bridge.c 2015/07/23 10:52:34 1.100
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_bridge.c,v 1.99 2015/06/01 06:14:43 matt Exp $ */ 1/* $NetBSD: if_bridge.c,v 1.100 2015/07/23 10:52:34 ozaki-r Exp $ */
2 2
3/* 3/*
4 * Copyright 2001 Wasabi Systems, Inc. 4 * Copyright 2001 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -70,27 +70,27 @@ @@ -70,27 +70,27 @@
70 70
71/* 71/*
72 * Network interface bridge support. 72 * Network interface bridge support.
73 * 73 *
74 * TODO: 74 * TODO:
75 * 75 *
76 * - Currently only supports Ethernet-like interfaces (Ethernet, 76 * - Currently only supports Ethernet-like interfaces (Ethernet,
77 * 802.11, VLANs on Ethernet, etc.) Figure out a nice way 77 * 802.11, VLANs on Ethernet, etc.) Figure out a nice way
78 * to bridge other types of interfaces (FDDI-FDDI, and maybe 78 * to bridge other types of interfaces (FDDI-FDDI, and maybe
79 * consider heterogenous bridges). 79 * consider heterogenous bridges).
80 */ 80 */
81 81
82#include <sys/cdefs.h> 82#include <sys/cdefs.h>
83__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.99 2015/06/01 06:14:43 matt Exp $"); 83__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.100 2015/07/23 10:52:34 ozaki-r Exp $");
84 84
85#ifdef _KERNEL_OPT 85#ifdef _KERNEL_OPT
86#include "opt_bridge_ipf.h" 86#include "opt_bridge_ipf.h"
87#include "opt_inet.h" 87#include "opt_inet.h"
88#endif /* _KERNEL_OPT */ 88#endif /* _KERNEL_OPT */
89 89
90#include <sys/param.h> 90#include <sys/param.h>
91#include <sys/kernel.h> 91#include <sys/kernel.h>
92#include <sys/mbuf.h> 92#include <sys/mbuf.h>
93#include <sys/queue.h> 93#include <sys/queue.h>
94#include <sys/socket.h> 94#include <sys/socket.h>
95#include <sys/socketvar.h> /* for softnet_lock */ 95#include <sys/socketvar.h> /* for softnet_lock */
96#include <sys/sockio.h> 96#include <sys/sockio.h>
@@ -1932,29 +1932,30 @@ bridge_input(struct ifnet *ifp, struct m @@ -1932,29 +1932,30 @@ bridge_input(struct ifnet *ifp, struct m
1932 bridge_release_member(sc, _bif); 1932 bridge_release_member(sc, _bif);
1933 goto out; 1933 goto out;
1934 } 1934 }
1935 1935
1936 /* We just received a packet that we sent out. */ 1936 /* We just received a packet that we sent out. */
1937 if (bridge_ourether(_bif, eh, 1)) 1937 if (bridge_ourether(_bif, eh, 1))
1938 break; 1938 break;
1939 } 1939 }
1940 BRIDGE_PSZ_REXIT(s); 1940 BRIDGE_PSZ_REXIT(s);
1941out: 1941out:
1942 1942
1943 if (_bif != NULL) { 1943 if (_bif != NULL) {
1944 bridge_release_member(sc, bif); 1944 bridge_release_member(sc, bif);
1945 if (_ifp != NULL) 1945 if (_ifp != NULL) {
 1946 m->m_flags &= ~M_PROMISC;
1946 ether_input(_ifp, m); 1947 ether_input(_ifp, m);
1947 else 1948 } else
1948 m_freem(m); 1949 m_freem(m);
1949 return; 1950 return;
1950 } 1951 }
1951 } 1952 }
1952 1953
1953 /* Tap off 802.1D packets; they do not get forwarded. */ 1954 /* Tap off 802.1D packets; they do not get forwarded. */
1954 if (bif->bif_flags & IFBIF_STP && 1955 if (bif->bif_flags & IFBIF_STP &&
1955 memcmp(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN) == 0) { 1956 memcmp(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN) == 0) {
1956 bstp_input(sc, bif, m); 1957 bstp_input(sc, bif, m);
1957 bridge_release_member(sc, bif); 1958 bridge_release_member(sc, bif);
1958 return; 1959 return;
1959 } 1960 }
1960 1961
@@ -1979,78 +1980,81 @@ out: @@ -1979,78 +1980,81 @@ out:
1979 * bridge_broadcast: 1980 * bridge_broadcast:
1980 * 1981 *
1981 * Send a frame to all interfaces that are members of 1982 * Send a frame to all interfaces that are members of
1982 * the bridge, except for the one on which the packet 1983 * the bridge, except for the one on which the packet
1983 * arrived. 1984 * arrived.
1984 */ 1985 */
1985static void 1986static void
1986bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if, 1987bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
1987 struct mbuf *m) 1988 struct mbuf *m)
1988{ 1989{
1989 struct bridge_iflist *bif; 1990 struct bridge_iflist *bif;
1990 struct mbuf *mc; 1991 struct mbuf *mc;
1991 struct ifnet *dst_if; 1992 struct ifnet *dst_if;
1992 bool used, bmcast; 1993 bool bmcast;
1993 int s; 1994 int s;
1994 1995
1995 used = bmcast = m->m_flags & (M_BCAST|M_MCAST); 1996 bmcast = m->m_flags & (M_BCAST|M_MCAST);
1996 1997
1997 BRIDGE_PSZ_RENTER(s); 1998 BRIDGE_PSZ_RENTER(s);
1998 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { 1999 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1999 bif = bridge_try_hold_bif(bif); 2000 bif = bridge_try_hold_bif(bif);
2000 if (bif == NULL) 2001 if (bif == NULL)
2001 continue; 2002 continue;
2002 BRIDGE_PSZ_REXIT(s); 2003 BRIDGE_PSZ_REXIT(s);
2003 2004
2004 dst_if = bif->bif_ifp; 2005 dst_if = bif->bif_ifp;
2005 if (dst_if == src_if) 
2006 goto next; 
2007 2006
2008 if (bif->bif_flags & IFBIF_STP) { 2007 if (bif->bif_flags & IFBIF_STP) {
2009 switch (bif->bif_state) { 2008 switch (bif->bif_state) {
2010 case BSTP_IFSTATE_BLOCKING: 2009 case BSTP_IFSTATE_BLOCKING:
2011 case BSTP_IFSTATE_DISABLED: 2010 case BSTP_IFSTATE_DISABLED:
2012 goto next; 2011 goto next;
2013 } 2012 }
2014 } 2013 }
2015 2014
2016 if ((bif->bif_flags & IFBIF_DISCOVER) == 0 && !bmcast) 2015 if ((bif->bif_flags & IFBIF_DISCOVER) == 0 && !bmcast)
2017 goto next; 2016 goto next;
2018 2017
2019 if ((dst_if->if_flags & IFF_RUNNING) == 0) 2018 if ((dst_if->if_flags & IFF_RUNNING) == 0)
2020 goto next; 2019 goto next;
2021 2020
2022 if (!used && LIST_NEXT(bif, bif_next) == NULL) { 2021 if (dst_if != src_if) {
2023 mc = m; 
2024 used = true; 
2025 } else { 
2026 mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT); 2022 mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
2027 if (mc == NULL) { 2023 if (mc == NULL) {
2028 sc->sc_if.if_oerrors++; 2024 sc->sc_if.if_oerrors++;
2029 goto next; 2025 goto next;
2030 } 2026 }
 2027 bridge_enqueue(sc, dst_if, mc, 1);
2031 } 2028 }
2032 2029
2033 bridge_enqueue(sc, dst_if, mc, 1); 2030 if (bmcast) {
 2031 mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
 2032 if (mc == NULL) {
 2033 sc->sc_if.if_oerrors++;
 2034 goto next;
 2035 }
 2036
 2037 mc->m_pkthdr.rcvif = dst_if;
 2038 mc->m_flags &= ~M_PROMISC;
 2039 ether_input(dst_if, mc);
 2040 }
2034next: 2041next:
2035 bridge_release_member(sc, bif); 2042 bridge_release_member(sc, bif);
2036 BRIDGE_PSZ_RENTER(s); 2043 BRIDGE_PSZ_RENTER(s);
2037 } 2044 }
2038 BRIDGE_PSZ_REXIT(s); 2045 BRIDGE_PSZ_REXIT(s);
2039 2046
2040 if (bmcast) 2047 m_freem(m);
2041 ether_input(src_if, m); 
2042 else if (!used) 
2043 m_freem(m); 
2044} 2048}
2045 2049
2046static int 2050static int
2047bridge_rtalloc(struct bridge_softc *sc, const uint8_t *dst, 2051bridge_rtalloc(struct bridge_softc *sc, const uint8_t *dst,
2048 struct bridge_rtnode **brtp) 2052 struct bridge_rtnode **brtp)
2049{ 2053{
2050 struct bridge_rtnode *brt; 2054 struct bridge_rtnode *brt;
2051 int error; 2055 int error;
2052 2056
2053 if (sc->sc_brtcnt >= sc->sc_brtmax) 2057 if (sc->sc_brtcnt >= sc->sc_brtmax)
2054 return ENOSPC; 2058 return ENOSPC;
2055 2059
2056 /* 2060 /*