| @@ -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); |
1941 | out: | | 1941 | out: |
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 | */ |
1985 | static void | | 1986 | static void |
1986 | bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if, | | 1987 | bridge_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 | } |
2034 | next: | | 2041 | next: |
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 | |
2046 | static int | | 2050 | static int |
2047 | bridge_rtalloc(struct bridge_softc *sc, const uint8_t *dst, | | 2051 | bridge_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 | /* |