1 /* $NetBSD: if_bridge.c,v 1.69 2009/05/12 23:03:24 elad Exp $ */
4 * Copyright 2001 Wasabi Systems, Inc.
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
40 * All rights reserved.
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement:
52 * This product includes software developed by Jason L. Wright
53 * 4. The name of the author may not be used to endorse or promote products
54 * derived from this software without specific prior written permission.
56 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
57 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
58 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
59 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
60 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
61 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
62 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
64 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
65 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
66 * POSSIBILITY OF SUCH DAMAGE.
68 * OpenBSD: if_bridge.c,v 1.60 2001/06/15 03:38:33 itojun Exp
72 * Network interface bridge support.
76 * - Currently only supports Ethernet-like interfaces (Ethernet,
77 * 802.11, VLANs on Ethernet, etc.) Figure out a nice way
78 * to bridge other types of interfaces (FDDI-FDDI, and maybe
79 * consider heterogenous bridges).
82 #include <sys/cdefs.h>
83 __KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.69 2009/05/12 23:03:24 elad Exp $");
85 #include "opt_bridge_ipf.h"
87 #include "opt_pfil_hooks.h"
90 #include <sys/param.h>
91 #include <sys/kernel.h>
93 #include <sys/queue.h>
94 #include <sys/socket.h>
95 #include <sys/socketvar.h> /* for softnet_lock */
96 #include <sys/sockio.h>
97 #include <sys/systm.h>
100 #include <sys/kauth.h>
107 #include <net/if_dl.h>
108 #include <net/if_types.h>
109 #include <net/if_llc.h>
111 #include <net/if_ether.h>
112 #include <net/if_bridgevar.h>
114 #if defined(BRIDGE_IPF) && defined(PFIL_HOOKS)
115 /* Used for bridge_ip[6]_checkbasic */
116 #include <netinet/in.h>
117 #include <netinet/in_systm.h>
118 #include <netinet/ip.h>
119 #include <netinet/ip_var.h>
120 #include <netinet/ip_private.h> /* XXX */
122 #include <netinet/ip6.h>
123 #include <netinet6/in6_var.h>
124 #include <netinet6/ip6_var.h>
125 #include <netinet6/ip6_private.h> /* XXX */
126 #endif /* BRIDGE_IPF && PFIL_HOOKS */
129 * Size of the route hash table. Must be a power of two.
131 #ifndef BRIDGE_RTHASH_SIZE
132 #define BRIDGE_RTHASH_SIZE 1024
135 #define BRIDGE_RTHASH_MASK (BRIDGE_RTHASH_SIZE - 1)
139 #include <netinet/in.h>
140 #include <netinet/in_var.h>
141 #include <netinet/ip_carp.h>
145 * Maximum number of addresses to cache.
147 #ifndef BRIDGE_RTABLE_MAX
148 #define BRIDGE_RTABLE_MAX 100
152 * Spanning tree defaults.
154 #define BSTP_DEFAULT_MAX_AGE (20 * 256)
155 #define BSTP_DEFAULT_HELLO_TIME (2 * 256)
156 #define BSTP_DEFAULT_FORWARD_DELAY (15 * 256)
157 #define BSTP_DEFAULT_HOLD_TIME (1 * 256)
158 #define BSTP_DEFAULT_BRIDGE_PRIORITY 0x8000
159 #define BSTP_DEFAULT_PORT_PRIORITY 0x80
160 #define BSTP_DEFAULT_PATH_COST 55
163 * Timeout (in seconds) for entries learned dynamically.
165 #ifndef BRIDGE_RTABLE_TIMEOUT
166 #define BRIDGE_RTABLE_TIMEOUT (20 * 60) /* same as ARP */
170 * Number of seconds between walks of the route list.
172 #ifndef BRIDGE_RTABLE_PRUNE_PERIOD
173 #define BRIDGE_RTABLE_PRUNE_PERIOD (5 * 60)
176 int bridge_rtable_prune_period
= BRIDGE_RTABLE_PRUNE_PERIOD
;
178 static struct pool bridge_rtnode_pool
;
180 void bridgeattach(int);
182 static int bridge_clone_create(struct if_clone
*, int);
183 static int bridge_clone_destroy(struct ifnet
*);
185 static int bridge_ioctl(struct ifnet
*, u_long
, void *);
186 static int bridge_init(struct ifnet
*);
187 static void bridge_stop(struct ifnet
*, int);
188 static void bridge_start(struct ifnet
*);
190 static void bridge_forward(void *);
192 static void bridge_timer(void *);
194 static void bridge_broadcast(struct bridge_softc
*, struct ifnet
*,
197 static int bridge_rtupdate(struct bridge_softc
*, const uint8_t *,
198 struct ifnet
*, int, uint8_t);
199 static struct ifnet
*bridge_rtlookup(struct bridge_softc
*, const uint8_t *);
200 static void bridge_rttrim(struct bridge_softc
*);
201 static void bridge_rtage(struct bridge_softc
*);
202 static void bridge_rtflush(struct bridge_softc
*, int);
203 static int bridge_rtdaddr(struct bridge_softc
*, const uint8_t *);
204 static void bridge_rtdelete(struct bridge_softc
*, struct ifnet
*ifp
);
206 static int bridge_rtable_init(struct bridge_softc
*);
207 static void bridge_rtable_fini(struct bridge_softc
*);
209 static struct bridge_rtnode
*bridge_rtnode_lookup(struct bridge_softc
*,
211 static int bridge_rtnode_insert(struct bridge_softc
*,
212 struct bridge_rtnode
*);
213 static void bridge_rtnode_destroy(struct bridge_softc
*,
214 struct bridge_rtnode
*);
216 static struct bridge_iflist
*bridge_lookup_member(struct bridge_softc
*,
218 static struct bridge_iflist
*bridge_lookup_member_if(struct bridge_softc
*,
220 static void bridge_delete_member(struct bridge_softc
*,
221 struct bridge_iflist
*);
223 static int bridge_ioctl_add(struct bridge_softc
*, void *);
224 static int bridge_ioctl_del(struct bridge_softc
*, void *);
225 static int bridge_ioctl_gifflags(struct bridge_softc
*, void *);
226 static int bridge_ioctl_sifflags(struct bridge_softc
*, void *);
227 static int bridge_ioctl_scache(struct bridge_softc
*, void *);
228 static int bridge_ioctl_gcache(struct bridge_softc
*, void *);
229 static int bridge_ioctl_gifs(struct bridge_softc
*, void *);
230 static int bridge_ioctl_rts(struct bridge_softc
*, void *);
231 static int bridge_ioctl_saddr(struct bridge_softc
*, void *);
232 static int bridge_ioctl_sto(struct bridge_softc
*, void *);
233 static int bridge_ioctl_gto(struct bridge_softc
*, void *);
234 static int bridge_ioctl_daddr(struct bridge_softc
*, void *);
235 static int bridge_ioctl_flush(struct bridge_softc
*, void *);
236 static int bridge_ioctl_gpri(struct bridge_softc
*, void *);
237 static int bridge_ioctl_spri(struct bridge_softc
*, void *);
238 static int bridge_ioctl_ght(struct bridge_softc
*, void *);
239 static int bridge_ioctl_sht(struct bridge_softc
*, void *);
240 static int bridge_ioctl_gfd(struct bridge_softc
*, void *);
241 static int bridge_ioctl_sfd(struct bridge_softc
*, void *);
242 static int bridge_ioctl_gma(struct bridge_softc
*, void *);
243 static int bridge_ioctl_sma(struct bridge_softc
*, void *);
244 static int bridge_ioctl_sifprio(struct bridge_softc
*, void *);
245 static int bridge_ioctl_sifcost(struct bridge_softc
*, void *);
246 #if defined(BRIDGE_IPF) && defined(PFIL_HOOKS)
247 static int bridge_ioctl_gfilt(struct bridge_softc
*, void *);
248 static int bridge_ioctl_sfilt(struct bridge_softc
*, void *);
249 static int bridge_ipf(void *, struct mbuf
**, struct ifnet
*, int);
250 static int bridge_ip_checkbasic(struct mbuf
**mp
);
252 static int bridge_ip6_checkbasic(struct mbuf
**mp
);
254 #endif /* BRIDGE_IPF && PFIL_HOOKS */
256 struct bridge_control
{
257 int (*bc_func
)(struct bridge_softc
*, void *);
262 #define BC_F_COPYIN 0x01 /* copy arguments in */
263 #define BC_F_COPYOUT 0x02 /* copy arguments out */
264 #define BC_F_SUSER 0x04 /* do super-user check */
266 static const struct bridge_control bridge_control_table
[] = {
267 [BRDGADD
] = {bridge_ioctl_add
, sizeof(struct ifbreq
), BC_F_COPYIN
|BC_F_SUSER
},
268 [BRDGDEL
] = {bridge_ioctl_del
, sizeof(struct ifbreq
), BC_F_COPYIN
|BC_F_SUSER
},
270 [BRDGGIFFLGS
] = {bridge_ioctl_gifflags
, sizeof(struct ifbreq
), BC_F_COPYIN
|BC_F_COPYOUT
},
271 [BRDGSIFFLGS
] = {bridge_ioctl_sifflags
, sizeof(struct ifbreq
), BC_F_COPYIN
|BC_F_SUSER
},
273 [BRDGSCACHE
] = {bridge_ioctl_scache
, sizeof(struct ifbrparam
), BC_F_COPYIN
|BC_F_SUSER
},
274 [BRDGGCACHE
] = {bridge_ioctl_gcache
, sizeof(struct ifbrparam
), BC_F_COPYOUT
},
276 [BRDGGIFS
] = {bridge_ioctl_gifs
, sizeof(struct ifbifconf
), BC_F_COPYIN
|BC_F_COPYOUT
},
277 [BRDGRTS
] = {bridge_ioctl_rts
, sizeof(struct ifbaconf
), BC_F_COPYIN
|BC_F_COPYOUT
},
279 [BRDGSADDR
] = {bridge_ioctl_saddr
, sizeof(struct ifbareq
), BC_F_COPYIN
|BC_F_SUSER
},
281 [BRDGSTO
] = {bridge_ioctl_sto
, sizeof(struct ifbrparam
), BC_F_COPYIN
|BC_F_SUSER
},
282 [BRDGGTO
] = {bridge_ioctl_gto
, sizeof(struct ifbrparam
), BC_F_COPYOUT
},
284 [BRDGDADDR
] = {bridge_ioctl_daddr
, sizeof(struct ifbareq
), BC_F_COPYIN
|BC_F_SUSER
},
286 [BRDGFLUSH
] = {bridge_ioctl_flush
, sizeof(struct ifbreq
), BC_F_COPYIN
|BC_F_SUSER
},
288 [BRDGGPRI
] = {bridge_ioctl_gpri
, sizeof(struct ifbrparam
), BC_F_COPYOUT
},
289 [BRDGSPRI
] = {bridge_ioctl_spri
, sizeof(struct ifbrparam
), BC_F_COPYIN
|BC_F_SUSER
},
291 [BRDGGHT
] = {bridge_ioctl_ght
, sizeof(struct ifbrparam
), BC_F_COPYOUT
},
292 [BRDGSHT
] = {bridge_ioctl_sht
, sizeof(struct ifbrparam
), BC_F_COPYIN
|BC_F_SUSER
},
294 [BRDGGFD
] = {bridge_ioctl_gfd
, sizeof(struct ifbrparam
), BC_F_COPYOUT
},
295 [BRDGSFD
] = {bridge_ioctl_sfd
, sizeof(struct ifbrparam
), BC_F_COPYIN
|BC_F_SUSER
},
297 [BRDGGMA
] = {bridge_ioctl_gma
, sizeof(struct ifbrparam
), BC_F_COPYOUT
},
298 [BRDGSMA
] = {bridge_ioctl_sma
, sizeof(struct ifbrparam
), BC_F_COPYIN
|BC_F_SUSER
},
300 [BRDGSIFPRIO
] = {bridge_ioctl_sifprio
, sizeof(struct ifbreq
), BC_F_COPYIN
|BC_F_SUSER
},
302 [BRDGSIFCOST
] = {bridge_ioctl_sifcost
, sizeof(struct ifbreq
), BC_F_COPYIN
|BC_F_SUSER
},
303 #if defined(BRIDGE_IPF) && defined(PFIL_HOOKS)
304 [BRDGGFILT
] = {bridge_ioctl_gfilt
, sizeof(struct ifbrparam
), BC_F_COPYOUT
},
305 [BRDGSFILT
] = {bridge_ioctl_sfilt
, sizeof(struct ifbrparam
), BC_F_COPYIN
|BC_F_SUSER
},
306 #endif /* BRIDGE_IPF && PFIL_HOOKS */
308 static const int bridge_control_table_size
= __arraycount(bridge_control_table
);
310 static LIST_HEAD(, bridge_softc
) bridge_list
;
312 static struct if_clone bridge_cloner
=
313 IF_CLONE_INITIALIZER("bridge", bridge_clone_create
, bridge_clone_destroy
);
318 * Pseudo-device attach routine.
324 pool_init(&bridge_rtnode_pool
, sizeof(struct bridge_rtnode
),
325 0, 0, 0, "brtpl", NULL
, IPL_NET
);
327 LIST_INIT(&bridge_list
);
328 if_clone_attach(&bridge_cloner
);
332 * bridge_clone_create:
334 * Create a new bridge instance.
337 bridge_clone_create(struct if_clone
*ifc
, int unit
)
339 struct bridge_softc
*sc
;
343 sc
= malloc(sizeof(*sc
), M_DEVBUF
, M_WAITOK
|M_ZERO
);
346 sc
->sc_brtmax
= BRIDGE_RTABLE_MAX
;
347 sc
->sc_brttimeout
= BRIDGE_RTABLE_TIMEOUT
;
348 sc
->sc_bridge_max_age
= BSTP_DEFAULT_MAX_AGE
;
349 sc
->sc_bridge_hello_time
= BSTP_DEFAULT_HELLO_TIME
;
350 sc
->sc_bridge_forward_delay
= BSTP_DEFAULT_FORWARD_DELAY
;
351 sc
->sc_bridge_priority
= BSTP_DEFAULT_BRIDGE_PRIORITY
;
352 sc
->sc_hold_time
= BSTP_DEFAULT_HOLD_TIME
;
353 sc
->sc_filter_flags
= 0;
355 /* software interrupt to do the work */
356 sc
->sc_softintr
= softint_establish(SOFTINT_NET
, bridge_forward
, sc
);
357 if (sc
->sc_softintr
== NULL
) {
362 /* Initialize our routing table. */
363 bridge_rtable_init(sc
);
365 callout_init(&sc
->sc_brcallout
, 0);
366 callout_init(&sc
->sc_bstpcallout
, 0);
368 LIST_INIT(&sc
->sc_iflist
);
370 if_initname(ifp
, ifc
->ifc_name
, unit
);
372 ifp
->if_mtu
= ETHERMTU
;
373 ifp
->if_ioctl
= bridge_ioctl
;
374 ifp
->if_output
= bridge_output
;
375 ifp
->if_start
= bridge_start
;
376 ifp
->if_stop
= bridge_stop
;
377 ifp
->if_init
= bridge_init
;
378 ifp
->if_type
= IFT_BRIDGE
;
380 ifp
->if_dlt
= DLT_EN10MB
;
381 ifp
->if_hdrlen
= ETHER_HDR_LEN
;
382 IFQ_SET_READY(&ifp
->if_snd
);
389 LIST_INSERT_HEAD(&bridge_list
, sc
, sc_list
);
396 * bridge_clone_destroy:
398 * Destroy a bridge instance.
401 bridge_clone_destroy(struct ifnet
*ifp
)
403 struct bridge_softc
*sc
= ifp
->if_softc
;
404 struct bridge_iflist
*bif
;
411 while ((bif
= LIST_FIRST(&sc
->sc_iflist
)) != NULL
)
412 bridge_delete_member(sc
, bif
);
414 LIST_REMOVE(sc
, sc_list
);
420 /* Tear down the routing table. */
421 bridge_rtable_fini(sc
);
423 softint_disestablish(sc
->sc_softintr
);
433 * Handle a control request from the operator.
436 bridge_ioctl(struct ifnet
*ifp
, u_long cmd
, void *data
)
438 struct bridge_softc
*sc
= ifp
->if_softc
;
439 struct lwp
*l
= curlwp
; /* XXX */
441 struct ifbreq ifbreq
;
442 struct ifbifconf ifbifconf
;
443 struct ifbareq ifbareq
;
444 struct ifbaconf ifbaconf
;
445 struct ifbrparam ifbrparam
;
447 struct ifdrv
*ifd
= (struct ifdrv
*) data
;
448 const struct bridge_control
*bc
= NULL
; /* XXXGCC */
451 /* Authorize command before calling splnet(). */
455 if (ifd
->ifd_cmd
>= bridge_control_table_size
) {
460 bc
= &bridge_control_table
[ifd
->ifd_cmd
];
462 /* We only care about BC_F_SUSER at this point. */
463 if ((bc
->bc_flags
& BC_F_SUSER
) == 0)
466 error
= kauth_authorize_generic(l
->l_cred
,
467 KAUTH_GENERIC_ISSUSER
, NULL
);
480 if (cmd
== SIOCGDRVSPEC
&&
481 (bc
->bc_flags
& BC_F_COPYOUT
) == 0) {
485 else if (cmd
== SIOCSDRVSPEC
&&
486 (bc
->bc_flags
& BC_F_COPYOUT
) != 0) {
491 /* BC_F_SUSER is checked above, before splnet(). */
493 if (ifd
->ifd_len
!= bc
->bc_argsize
||
494 ifd
->ifd_len
> sizeof(args
)) {
499 memset(&args
, 0, sizeof(args
));
500 if (bc
->bc_flags
& BC_F_COPYIN
) {
501 error
= copyin(ifd
->ifd_data
, &args
, ifd
->ifd_len
);
506 error
= (*bc
->bc_func
)(sc
, &args
);
510 if (bc
->bc_flags
& BC_F_COPYOUT
)
511 error
= copyout(&args
, ifd
->ifd_data
, ifd
->ifd_len
);
516 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
518 switch (ifp
->if_flags
& (IFF_UP
|IFF_RUNNING
)) {
521 * If interface is marked down and it is running,
522 * then stop and disable it.
524 (*ifp
->if_stop
)(ifp
, 1);
528 * If interface is marked up and it is stopped, then
531 error
= (*ifp
->if_init
)(ifp
);
539 error
= ifioctl_common(ifp
, cmd
, data
);
549 * bridge_lookup_member:
551 * Lookup a bridge member interface. Must be called at splnet().
553 static struct bridge_iflist
*
554 bridge_lookup_member(struct bridge_softc
*sc
, const char *name
)
556 struct bridge_iflist
*bif
;
559 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
561 if (strcmp(ifp
->if_xname
, name
) == 0)
569 * bridge_lookup_member_if:
571 * Lookup a bridge member interface by ifnet*. Must be called at splnet().
573 static struct bridge_iflist
*
574 bridge_lookup_member_if(struct bridge_softc
*sc
, struct ifnet
*member_ifp
)
576 struct bridge_iflist
*bif
;
578 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
579 if (bif
->bif_ifp
== member_ifp
)
587 * bridge_delete_member:
589 * Delete the specified member interface.
592 bridge_delete_member(struct bridge_softc
*sc
, struct bridge_iflist
*bif
)
594 struct ifnet
*ifs
= bif
->bif_ifp
;
596 switch (ifs
->if_type
) {
599 * Take the interface out of promiscuous mode.
601 (void) ifpromisc(ifs
, 0);
605 panic("bridge_delete_member: impossible");
610 ifs
->if_bridge
= NULL
;
611 LIST_REMOVE(bif
, bif_next
);
613 bridge_rtdelete(sc
, ifs
);
617 if (sc
->sc_if
.if_flags
& IFF_RUNNING
)
618 bstp_initialization(sc
);
622 bridge_ioctl_add(struct bridge_softc
*sc
, void *arg
)
624 struct ifbreq
*req
= arg
;
625 struct bridge_iflist
*bif
= NULL
;
629 ifs
= ifunit(req
->ifbr_ifsname
);
633 if (sc
->sc_if
.if_mtu
!= ifs
->if_mtu
)
636 if (ifs
->if_bridge
== sc
)
639 if (ifs
->if_bridge
!= NULL
)
642 bif
= malloc(sizeof(*bif
), M_DEVBUF
, M_NOWAIT
);
646 switch (ifs
->if_type
) {
649 * Place the interface into promiscuous mode.
651 error
= ifpromisc(ifs
, 1);
661 bif
->bif_flags
= IFBIF_LEARNING
| IFBIF_DISCOVER
;
662 bif
->bif_priority
= BSTP_DEFAULT_PORT_PRIORITY
;
663 bif
->bif_path_cost
= BSTP_DEFAULT_PATH_COST
;
666 LIST_INSERT_HEAD(&sc
->sc_iflist
, bif
, bif_next
);
668 if (sc
->sc_if
.if_flags
& IFF_RUNNING
)
669 bstp_initialization(sc
);
682 bridge_ioctl_del(struct bridge_softc
*sc
, void *arg
)
684 struct ifbreq
*req
= arg
;
685 struct bridge_iflist
*bif
;
687 bif
= bridge_lookup_member(sc
, req
->ifbr_ifsname
);
691 bridge_delete_member(sc
, bif
);
697 bridge_ioctl_gifflags(struct bridge_softc
*sc
, void *arg
)
699 struct ifbreq
*req
= arg
;
700 struct bridge_iflist
*bif
;
702 bif
= bridge_lookup_member(sc
, req
->ifbr_ifsname
);
706 req
->ifbr_ifsflags
= bif
->bif_flags
;
707 req
->ifbr_state
= bif
->bif_state
;
708 req
->ifbr_priority
= bif
->bif_priority
;
709 req
->ifbr_path_cost
= bif
->bif_path_cost
;
710 req
->ifbr_portno
= bif
->bif_ifp
->if_index
& 0xff;
716 bridge_ioctl_sifflags(struct bridge_softc
*sc
, void *arg
)
718 struct ifbreq
*req
= arg
;
719 struct bridge_iflist
*bif
;
721 bif
= bridge_lookup_member(sc
, req
->ifbr_ifsname
);
725 if (req
->ifbr_ifsflags
& IFBIF_STP
) {
726 switch (bif
->bif_ifp
->if_type
) {
728 /* These can do spanning tree. */
732 /* Nothing else can. */
737 bif
->bif_flags
= req
->ifbr_ifsflags
;
739 if (sc
->sc_if
.if_flags
& IFF_RUNNING
)
740 bstp_initialization(sc
);
746 bridge_ioctl_scache(struct bridge_softc
*sc
, void *arg
)
748 struct ifbrparam
*param
= arg
;
750 sc
->sc_brtmax
= param
->ifbrp_csize
;
757 bridge_ioctl_gcache(struct bridge_softc
*sc
, void *arg
)
759 struct ifbrparam
*param
= arg
;
761 param
->ifbrp_csize
= sc
->sc_brtmax
;
767 bridge_ioctl_gifs(struct bridge_softc
*sc
, void *arg
)
769 struct ifbifconf
*bifc
= arg
;
770 struct bridge_iflist
*bif
;
772 int count
, len
, error
= 0;
775 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
)
778 if (bifc
->ifbic_len
== 0) {
779 bifc
->ifbic_len
= sizeof(breq
) * count
;
784 len
= bifc
->ifbic_len
;
785 memset(&breq
, 0, sizeof breq
);
786 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
787 if (len
< sizeof(breq
))
790 strlcpy(breq
.ifbr_ifsname
, bif
->bif_ifp
->if_xname
,
791 sizeof(breq
.ifbr_ifsname
));
792 breq
.ifbr_ifsflags
= bif
->bif_flags
;
793 breq
.ifbr_state
= bif
->bif_state
;
794 breq
.ifbr_priority
= bif
->bif_priority
;
795 breq
.ifbr_path_cost
= bif
->bif_path_cost
;
796 breq
.ifbr_portno
= bif
->bif_ifp
->if_index
& 0xff;
797 error
= copyout(&breq
, bifc
->ifbic_req
+ count
, sizeof(breq
));
804 bifc
->ifbic_len
= sizeof(breq
) * count
;
809 bridge_ioctl_rts(struct bridge_softc
*sc
, void *arg
)
811 struct ifbaconf
*bac
= arg
;
812 struct bridge_rtnode
*brt
;
813 struct ifbareq bareq
;
814 int count
= 0, error
= 0, len
;
816 if (bac
->ifbac_len
== 0)
819 len
= bac
->ifbac_len
;
820 LIST_FOREACH(brt
, &sc
->sc_rtlist
, brt_list
) {
821 if (len
< sizeof(bareq
))
823 memset(&bareq
, 0, sizeof(bareq
));
824 strlcpy(bareq
.ifba_ifsname
, brt
->brt_ifp
->if_xname
,
825 sizeof(bareq
.ifba_ifsname
));
826 memcpy(bareq
.ifba_dst
, brt
->brt_addr
, sizeof(brt
->brt_addr
));
827 if ((brt
->brt_flags
& IFBAF_TYPEMASK
) == IFBAF_DYNAMIC
) {
828 bareq
.ifba_expire
= brt
->brt_expire
- time_uptime
;
830 bareq
.ifba_expire
= 0;
831 bareq
.ifba_flags
= brt
->brt_flags
;
833 error
= copyout(&bareq
, bac
->ifbac_req
+ count
, sizeof(bareq
));
837 len
-= sizeof(bareq
);
840 bac
->ifbac_len
= sizeof(bareq
) * count
;
845 bridge_ioctl_saddr(struct bridge_softc
*sc
, void *arg
)
847 struct ifbareq
*req
= arg
;
848 struct bridge_iflist
*bif
;
851 bif
= bridge_lookup_member(sc
, req
->ifba_ifsname
);
855 error
= bridge_rtupdate(sc
, req
->ifba_dst
, bif
->bif_ifp
, 1,
862 bridge_ioctl_sto(struct bridge_softc
*sc
, void *arg
)
864 struct ifbrparam
*param
= arg
;
866 sc
->sc_brttimeout
= param
->ifbrp_ctime
;
872 bridge_ioctl_gto(struct bridge_softc
*sc
, void *arg
)
874 struct ifbrparam
*param
= arg
;
876 param
->ifbrp_ctime
= sc
->sc_brttimeout
;
882 bridge_ioctl_daddr(struct bridge_softc
*sc
, void *arg
)
884 struct ifbareq
*req
= arg
;
886 return (bridge_rtdaddr(sc
, req
->ifba_dst
));
890 bridge_ioctl_flush(struct bridge_softc
*sc
, void *arg
)
892 struct ifbreq
*req
= arg
;
894 bridge_rtflush(sc
, req
->ifbr_ifsflags
);
900 bridge_ioctl_gpri(struct bridge_softc
*sc
, void *arg
)
902 struct ifbrparam
*param
= arg
;
904 param
->ifbrp_prio
= sc
->sc_bridge_priority
;
910 bridge_ioctl_spri(struct bridge_softc
*sc
, void *arg
)
912 struct ifbrparam
*param
= arg
;
914 sc
->sc_bridge_priority
= param
->ifbrp_prio
;
916 if (sc
->sc_if
.if_flags
& IFF_RUNNING
)
917 bstp_initialization(sc
);
923 bridge_ioctl_ght(struct bridge_softc
*sc
, void *arg
)
925 struct ifbrparam
*param
= arg
;
927 param
->ifbrp_hellotime
= sc
->sc_bridge_hello_time
>> 8;
933 bridge_ioctl_sht(struct bridge_softc
*sc
, void *arg
)
935 struct ifbrparam
*param
= arg
;
937 if (param
->ifbrp_hellotime
== 0)
939 sc
->sc_bridge_hello_time
= param
->ifbrp_hellotime
<< 8;
941 if (sc
->sc_if
.if_flags
& IFF_RUNNING
)
942 bstp_initialization(sc
);
948 bridge_ioctl_gfd(struct bridge_softc
*sc
, void *arg
)
950 struct ifbrparam
*param
= arg
;
952 param
->ifbrp_fwddelay
= sc
->sc_bridge_forward_delay
>> 8;
958 bridge_ioctl_sfd(struct bridge_softc
*sc
, void *arg
)
960 struct ifbrparam
*param
= arg
;
962 if (param
->ifbrp_fwddelay
== 0)
964 sc
->sc_bridge_forward_delay
= param
->ifbrp_fwddelay
<< 8;
966 if (sc
->sc_if
.if_flags
& IFF_RUNNING
)
967 bstp_initialization(sc
);
973 bridge_ioctl_gma(struct bridge_softc
*sc
, void *arg
)
975 struct ifbrparam
*param
= arg
;
977 param
->ifbrp_maxage
= sc
->sc_bridge_max_age
>> 8;
983 bridge_ioctl_sma(struct bridge_softc
*sc
, void *arg
)
985 struct ifbrparam
*param
= arg
;
987 if (param
->ifbrp_maxage
== 0)
989 sc
->sc_bridge_max_age
= param
->ifbrp_maxage
<< 8;
991 if (sc
->sc_if
.if_flags
& IFF_RUNNING
)
992 bstp_initialization(sc
);
998 bridge_ioctl_sifprio(struct bridge_softc
*sc
, void *arg
)
1000 struct ifbreq
*req
= arg
;
1001 struct bridge_iflist
*bif
;
1003 bif
= bridge_lookup_member(sc
, req
->ifbr_ifsname
);
1007 bif
->bif_priority
= req
->ifbr_priority
;
1009 if (sc
->sc_if
.if_flags
& IFF_RUNNING
)
1010 bstp_initialization(sc
);
1015 #if defined(BRIDGE_IPF) && defined(PFIL_HOOKS)
1017 bridge_ioctl_gfilt(struct bridge_softc
*sc
, void *arg
)
1019 struct ifbrparam
*param
= arg
;
1021 param
->ifbrp_filter
= sc
->sc_filter_flags
;
1027 bridge_ioctl_sfilt(struct bridge_softc
*sc
, void *arg
)
1029 struct ifbrparam
*param
= arg
;
1030 uint32_t nflags
, oflags
;
1032 if (param
->ifbrp_filter
& ~IFBF_FILT_MASK
)
1035 nflags
= param
->ifbrp_filter
;
1036 oflags
= sc
->sc_filter_flags
;
1038 if ((nflags
& IFBF_FILT_USEIPF
) && !(oflags
& IFBF_FILT_USEIPF
)) {
1039 pfil_add_hook((void *)bridge_ipf
, NULL
, PFIL_IN
|PFIL_OUT
,
1040 &sc
->sc_if
.if_pfil
);
1042 if (!(nflags
& IFBF_FILT_USEIPF
) && (oflags
& IFBF_FILT_USEIPF
)) {
1043 pfil_remove_hook((void *)bridge_ipf
, NULL
, PFIL_IN
|PFIL_OUT
,
1044 &sc
->sc_if
.if_pfil
);
1047 sc
->sc_filter_flags
= nflags
;
1051 #endif /* BRIDGE_IPF && PFIL_HOOKS */
1054 bridge_ioctl_sifcost(struct bridge_softc
*sc
, void *arg
)
1056 struct ifbreq
*req
= arg
;
1057 struct bridge_iflist
*bif
;
1059 bif
= bridge_lookup_member(sc
, req
->ifbr_ifsname
);
1063 bif
->bif_path_cost
= req
->ifbr_path_cost
;
1065 if (sc
->sc_if
.if_flags
& IFF_RUNNING
)
1066 bstp_initialization(sc
);
1074 * Detach an interface from a bridge. Called when a member
1075 * interface is detaching.
1078 bridge_ifdetach(struct ifnet
*ifp
)
1080 struct bridge_softc
*sc
= ifp
->if_bridge
;
1083 memset(&breq
, 0, sizeof(breq
));
1084 snprintf(breq
.ifbr_ifsname
, sizeof(breq
.ifbr_ifsname
), ifp
->if_xname
);
1086 (void) bridge_ioctl_del(sc
, &breq
);
1092 * Initialize a bridge interface.
1095 bridge_init(struct ifnet
*ifp
)
1097 struct bridge_softc
*sc
= ifp
->if_softc
;
1099 if (ifp
->if_flags
& IFF_RUNNING
)
1102 callout_reset(&sc
->sc_brcallout
, bridge_rtable_prune_period
* hz
,
1105 ifp
->if_flags
|= IFF_RUNNING
;
1106 bstp_initialization(sc
);
1113 * Stop the bridge interface.
1116 bridge_stop(struct ifnet
*ifp
, int disable
)
1118 struct bridge_softc
*sc
= ifp
->if_softc
;
1120 if ((ifp
->if_flags
& IFF_RUNNING
) == 0)
1123 callout_stop(&sc
->sc_brcallout
);
1126 IF_PURGE(&ifp
->if_snd
);
1128 bridge_rtflush(sc
, IFBF_FLUSHDYN
);
1130 ifp
->if_flags
&= ~IFF_RUNNING
;
1136 * Enqueue a packet on a bridge member interface.
1138 * NOTE: must be called at splnet().
1141 bridge_enqueue(struct bridge_softc
*sc
, struct ifnet
*dst_ifp
, struct mbuf
*m
,
1144 ALTQ_DECL(struct altq_pktattr pktattr
;)
1149 * Clear any in-bound checksum flags for this packet.
1151 m
->m_pkthdr
.csum_flags
= 0;
1155 if (pfil_run_hooks(&sc
->sc_if
.if_pfil
, &m
,
1156 dst_ifp
, PFIL_OUT
) != 0) {
1164 #endif /* PFIL_HOOKS */
1168 * If ALTQ is enabled on the member interface, do
1169 * classification; the queueing discipline might
1170 * not require classification, but might require
1171 * the address family/header pointer in the pktattr.
1173 if (ALTQ_IS_ENABLED(&dst_ifp
->if_snd
)) {
1175 altq_etherclassify(&dst_ifp
->if_snd
, m
, &pktattr
);
1179 len
= m
->m_pkthdr
.len
;
1180 m
->m_flags
|= M_PROTO1
;
1181 mflags
= m
->m_flags
;
1182 IFQ_ENQUEUE(&dst_ifp
->if_snd
, m
, &pktattr
, error
);
1184 /* mbuf is already freed */
1185 sc
->sc_if
.if_oerrors
++;
1189 sc
->sc_if
.if_opackets
++;
1190 sc
->sc_if
.if_obytes
+= len
;
1192 dst_ifp
->if_obytes
+= len
;
1194 if (mflags
& M_MCAST
) {
1195 sc
->sc_if
.if_omcasts
++;
1196 dst_ifp
->if_omcasts
++;
1199 if ((dst_ifp
->if_flags
& IFF_OACTIVE
) == 0)
1200 (*dst_ifp
->if_start
)(dst_ifp
);
1206 * Send output from a bridge member interface. This
1207 * performs the bridging function for locally originated
1210 * The mbuf has the Ethernet header already attached. We must
1211 * enqueue or free the mbuf before returning.
1214 bridge_output(struct ifnet
*ifp
, struct mbuf
*m
, const struct sockaddr
*sa
,
1217 struct ether_header
*eh
;
1218 struct ifnet
*dst_if
;
1219 struct bridge_softc
*sc
;
1222 if (m
->m_len
< ETHER_HDR_LEN
) {
1223 m
= m_pullup(m
, ETHER_HDR_LEN
);
1228 eh
= mtod(m
, struct ether_header
*);
1229 sc
= ifp
->if_bridge
;
1234 * If bridge is down, but the original output interface is up,
1235 * go ahead and send out that interface. Otherwise, the packet
1238 if ((sc
->sc_if
.if_flags
& IFF_RUNNING
) == 0) {
1244 * If the packet is a multicast, or we don't know a better way to
1245 * get there, send to all interfaces.
1247 if (ETHER_IS_MULTICAST(eh
->ether_dhost
))
1250 dst_if
= bridge_rtlookup(sc
, eh
->ether_dhost
);
1251 if (dst_if
== NULL
) {
1252 struct bridge_iflist
*bif
;
1256 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
1257 dst_if
= bif
->bif_ifp
;
1258 if ((dst_if
->if_flags
& IFF_RUNNING
) == 0)
1262 * If this is not the original output interface,
1263 * and the interface is participating in spanning
1264 * tree, make sure the port is in a state that
1265 * allows forwarding.
1267 if (dst_if
!= ifp
&&
1268 (bif
->bif_flags
& IFBIF_STP
) != 0) {
1269 switch (bif
->bif_state
) {
1270 case BSTP_IFSTATE_BLOCKING
:
1271 case BSTP_IFSTATE_LISTENING
:
1272 case BSTP_IFSTATE_DISABLED
:
1277 if (LIST_NEXT(bif
, bif_next
) == NULL
) {
1281 mc
= m_copym(m
, 0, M_COPYALL
, M_NOWAIT
);
1283 sc
->sc_if
.if_oerrors
++;
1288 bridge_enqueue(sc
, dst_if
, mc
, 0);
1298 * XXX Spanning tree consideration here?
1301 if ((dst_if
->if_flags
& IFF_RUNNING
) == 0) {
1307 bridge_enqueue(sc
, dst_if
, m
, 0);
1316 * Start output on a bridge.
1318 * NOTE: This routine should never be called in this implementation.
1321 bridge_start(struct ifnet
*ifp
)
1324 printf("%s: bridge_start() called\n", ifp
->if_xname
);
1330 * The forwarding function of the bridge.
1333 bridge_forward(void *v
)
1335 struct bridge_softc
*sc
= v
;
1337 struct bridge_iflist
*bif
;
1338 struct ifnet
*src_if
, *dst_if
;
1339 struct ether_header
*eh
;
1342 mutex_enter(softnet_lock
);
1343 if ((sc
->sc_if
.if_flags
& IFF_RUNNING
) == 0) {
1344 mutex_exit(softnet_lock
);
1350 IFQ_POLL(&sc
->sc_if
.if_snd
, m
);
1353 IFQ_DEQUEUE(&sc
->sc_if
.if_snd
, m
);
1355 src_if
= m
->m_pkthdr
.rcvif
;
1357 sc
->sc_if
.if_ipackets
++;
1358 sc
->sc_if
.if_ibytes
+= m
->m_pkthdr
.len
;
1361 * Look up the bridge_iflist.
1363 bif
= bridge_lookup_member_if(sc
, src_if
);
1365 /* Interface is not a bridge member (anymore?) */
1370 if (bif
->bif_flags
& IFBIF_STP
) {
1371 switch (bif
->bif_state
) {
1372 case BSTP_IFSTATE_BLOCKING
:
1373 case BSTP_IFSTATE_LISTENING
:
1374 case BSTP_IFSTATE_DISABLED
:
1380 eh
= mtod(m
, struct ether_header
*);
1383 * If the interface is learning, and the source
1384 * address is valid and not multicast, record
1387 if ((bif
->bif_flags
& IFBIF_LEARNING
) != 0 &&
1388 ETHER_IS_MULTICAST(eh
->ether_shost
) == 0 &&
1389 (eh
->ether_shost
[0] == 0 &&
1390 eh
->ether_shost
[1] == 0 &&
1391 eh
->ether_shost
[2] == 0 &&
1392 eh
->ether_shost
[3] == 0 &&
1393 eh
->ether_shost
[4] == 0 &&
1394 eh
->ether_shost
[5] == 0) == 0) {
1395 (void) bridge_rtupdate(sc
, eh
->ether_shost
,
1396 src_if
, 0, IFBAF_DYNAMIC
);
1399 if ((bif
->bif_flags
& IFBIF_STP
) != 0 &&
1400 bif
->bif_state
== BSTP_IFSTATE_LEARNING
) {
1406 * At this point, the port either doesn't participate
1407 * in spanning tree or it is in the forwarding state.
1411 * If the packet is unicast, destined for someone on
1412 * "this" side of the bridge, drop it.
1414 if ((m
->m_flags
& (M_BCAST
|M_MCAST
)) == 0) {
1415 dst_if
= bridge_rtlookup(sc
, eh
->ether_dhost
);
1416 if (src_if
== dst_if
) {
1421 /* ...forward it to all interfaces. */
1422 sc
->sc_if
.if_imcasts
++;
1427 if (pfil_run_hooks(&sc
->sc_if
.if_pfil
, &m
,
1428 m
->m_pkthdr
.rcvif
, PFIL_IN
) != 0) {
1435 #endif /* PFIL_HOOKS */
1437 if (dst_if
== NULL
) {
1438 bridge_broadcast(sc
, src_if
, m
);
1443 * At this point, we're dealing with a unicast frame
1444 * going to a different interface.
1446 if ((dst_if
->if_flags
& IFF_RUNNING
) == 0) {
1450 bif
= bridge_lookup_member_if(sc
, dst_if
);
1452 /* Not a member of the bridge (anymore?) */
1457 if (bif
->bif_flags
& IFBIF_STP
) {
1458 switch (bif
->bif_state
) {
1459 case BSTP_IFSTATE_DISABLED
:
1460 case BSTP_IFSTATE_BLOCKING
:
1466 bridge_enqueue(sc
, dst_if
, m
, 1);
1469 mutex_exit(softnet_lock
);
1475 * Receive input from a member interface. Queue the packet for
1476 * bridging if it is not for us.
1477 * should be called at splnet()
1480 bridge_input(struct ifnet
*ifp
, struct mbuf
*m
)
1482 struct bridge_softc
*sc
= ifp
->if_bridge
;
1483 struct bridge_iflist
*bif
;
1484 struct ether_header
*eh
;
1487 if ((sc
->sc_if
.if_flags
& IFF_RUNNING
) == 0)
1490 bif
= bridge_lookup_member_if(sc
, ifp
);
1494 eh
= mtod(m
, struct ether_header
*);
1496 if (m
->m_flags
& (M_BCAST
|M_MCAST
)) {
1497 if (bif
->bif_flags
& IFBIF_STP
) {
1498 /* Tap off 802.1D packets; they do not get forwarded. */
1499 if (memcmp(eh
->ether_dhost
, bstp_etheraddr
,
1500 ETHER_ADDR_LEN
) == 0) {
1501 m
= bstp_input(sc
, bif
, m
);
1506 switch (bif
->bif_state
) {
1507 case BSTP_IFSTATE_BLOCKING
:
1508 case BSTP_IFSTATE_LISTENING
:
1509 case BSTP_IFSTATE_DISABLED
:
1515 * Make a deep copy of the packet and enqueue the copy
1516 * for bridge processing; return the original packet for
1519 if (IF_QFULL(&sc
->sc_if
.if_snd
)) {
1520 IF_DROP(&sc
->sc_if
.if_snd
);
1523 mc
= m_dup(m
, 0, M_COPYALL
, M_NOWAIT
);
1527 /* Perform the bridge forwarding function with the copy. */
1528 IF_ENQUEUE(&sc
->sc_if
.if_snd
, mc
);
1529 softint_schedule(sc
->sc_softintr
);
1531 /* Return the original packet for local processing. */
1535 if (bif
->bif_flags
& IFBIF_STP
) {
1536 switch (bif
->bif_state
) {
1537 case BSTP_IFSTATE_BLOCKING
:
1538 case BSTP_IFSTATE_LISTENING
:
1539 case BSTP_IFSTATE_DISABLED
:
1545 * Unicast. Make sure it's not for us.
1547 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
1548 /* It is destined for us. */
1549 if (memcmp(CLLADDR(bif
->bif_ifp
->if_sadl
), eh
->ether_dhost
,
1550 ETHER_ADDR_LEN
) == 0
1552 || (bif
->bif_ifp
->if_carp
&& carp_ourether(bif
->bif_ifp
->if_carp
,
1553 eh
, IFT_ETHER
, 0) != NULL
)
1554 #endif /* NCARP > 0 */
1556 if (bif
->bif_flags
& IFBIF_LEARNING
)
1557 (void) bridge_rtupdate(sc
,
1558 eh
->ether_shost
, ifp
, 0, IFBAF_DYNAMIC
);
1559 m
->m_pkthdr
.rcvif
= bif
->bif_ifp
;
1563 /* We just received a packet that we sent out. */
1564 if (memcmp(CLLADDR(bif
->bif_ifp
->if_sadl
), eh
->ether_shost
,
1565 ETHER_ADDR_LEN
) == 0
1567 || (bif
->bif_ifp
->if_carp
&& carp_ourether(bif
->bif_ifp
->if_carp
,
1568 eh
, IFT_ETHER
, 1) != NULL
)
1569 #endif /* NCARP > 0 */
1576 /* Perform the bridge forwarding function. */
1577 if (IF_QFULL(&sc
->sc_if
.if_snd
)) {
1578 IF_DROP(&sc
->sc_if
.if_snd
);
1582 IF_ENQUEUE(&sc
->sc_if
.if_snd
, m
);
1583 softint_schedule(sc
->sc_softintr
);
1591 * Send a frame to all interfaces that are members of
1592 * the bridge, except for the one on which the packet
1596 bridge_broadcast(struct bridge_softc
*sc
, struct ifnet
*src_if
,
1599 struct bridge_iflist
*bif
;
1601 struct ifnet
*dst_if
;
1604 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
1605 dst_if
= bif
->bif_ifp
;
1606 if (dst_if
== src_if
)
1609 if (bif
->bif_flags
& IFBIF_STP
) {
1610 switch (bif
->bif_state
) {
1611 case BSTP_IFSTATE_BLOCKING
:
1612 case BSTP_IFSTATE_DISABLED
:
1617 if ((bif
->bif_flags
& IFBIF_DISCOVER
) == 0 &&
1618 (m
->m_flags
& (M_BCAST
|M_MCAST
)) == 0)
1621 if ((dst_if
->if_flags
& IFF_RUNNING
) == 0)
1624 if (LIST_NEXT(bif
, bif_next
) == NULL
) {
1628 mc
= m_copym(m
, 0, M_COPYALL
, M_DONTWAIT
);
1630 sc
->sc_if
.if_oerrors
++;
1635 bridge_enqueue(sc
, dst_if
, mc
, 1);
1644 * Add a bridge routing entry.
1647 bridge_rtupdate(struct bridge_softc
*sc
, const uint8_t *dst
,
1648 struct ifnet
*dst_if
, int setflags
, uint8_t flags
)
1650 struct bridge_rtnode
*brt
;
1654 * A route for this destination might already exist. If so,
1655 * update it, otherwise create a new one.
1657 if ((brt
= bridge_rtnode_lookup(sc
, dst
)) == NULL
) {
1658 if (sc
->sc_brtcnt
>= sc
->sc_brtmax
)
1662 * Allocate a new bridge forwarding node, and
1663 * initialize the expiration time and Ethernet
1667 brt
= pool_get(&bridge_rtnode_pool
, PR_NOWAIT
);
1672 memset(brt
, 0, sizeof(*brt
));
1673 brt
->brt_expire
= time_uptime
+ sc
->sc_brttimeout
;
1674 brt
->brt_flags
= IFBAF_DYNAMIC
;
1675 memcpy(brt
->brt_addr
, dst
, ETHER_ADDR_LEN
);
1677 if ((error
= bridge_rtnode_insert(sc
, brt
)) != 0) {
1679 pool_put(&bridge_rtnode_pool
, brt
);
1685 brt
->brt_ifp
= dst_if
;
1687 brt
->brt_flags
= flags
;
1688 if (flags
& IFBAF_STATIC
)
1689 brt
->brt_expire
= 0;
1691 brt
->brt_expire
= time_uptime
+ sc
->sc_brttimeout
;
1700 * Lookup the destination interface for an address.
1702 static struct ifnet
*
1703 bridge_rtlookup(struct bridge_softc
*sc
, const uint8_t *addr
)
1705 struct bridge_rtnode
*brt
;
1707 if ((brt
= bridge_rtnode_lookup(sc
, addr
)) == NULL
)
1710 return (brt
->brt_ifp
);
1716 * Trim the routine table so that we have a number
1717 * of routing entries less than or equal to the
1721 bridge_rttrim(struct bridge_softc
*sc
)
1723 struct bridge_rtnode
*brt
, *nbrt
;
1725 /* Make sure we actually need to do this. */
1726 if (sc
->sc_brtcnt
<= sc
->sc_brtmax
)
1729 /* Force an aging cycle; this might trim enough addresses. */
1731 if (sc
->sc_brtcnt
<= sc
->sc_brtmax
)
1734 for (brt
= LIST_FIRST(&sc
->sc_rtlist
); brt
!= NULL
; brt
= nbrt
) {
1735 nbrt
= LIST_NEXT(brt
, brt_list
);
1736 if ((brt
->brt_flags
& IFBAF_TYPEMASK
) == IFBAF_DYNAMIC
) {
1737 bridge_rtnode_destroy(sc
, brt
);
1738 if (sc
->sc_brtcnt
<= sc
->sc_brtmax
)
1747 * Aging timer for the bridge.
1750 bridge_timer(void *arg
)
1752 struct bridge_softc
*sc
= arg
;
1759 if (sc
->sc_if
.if_flags
& IFF_RUNNING
)
1760 callout_reset(&sc
->sc_brcallout
,
1761 bridge_rtable_prune_period
* hz
, bridge_timer
, sc
);
1767 * Perform an aging cycle.
1770 bridge_rtage(struct bridge_softc
*sc
)
1772 struct bridge_rtnode
*brt
, *nbrt
;
1774 for (brt
= LIST_FIRST(&sc
->sc_rtlist
); brt
!= NULL
; brt
= nbrt
) {
1775 nbrt
= LIST_NEXT(brt
, brt_list
);
1776 if ((brt
->brt_flags
& IFBAF_TYPEMASK
) == IFBAF_DYNAMIC
) {
1777 if (time_uptime
>= brt
->brt_expire
)
1778 bridge_rtnode_destroy(sc
, brt
);
1786 * Remove all dynamic addresses from the bridge.
1789 bridge_rtflush(struct bridge_softc
*sc
, int full
)
1791 struct bridge_rtnode
*brt
, *nbrt
;
1793 for (brt
= LIST_FIRST(&sc
->sc_rtlist
); brt
!= NULL
; brt
= nbrt
) {
1794 nbrt
= LIST_NEXT(brt
, brt_list
);
1795 if (full
|| (brt
->brt_flags
& IFBAF_TYPEMASK
) == IFBAF_DYNAMIC
)
1796 bridge_rtnode_destroy(sc
, brt
);
1803 * Remove an address from the table.
1806 bridge_rtdaddr(struct bridge_softc
*sc
, const uint8_t *addr
)
1808 struct bridge_rtnode
*brt
;
1810 if ((brt
= bridge_rtnode_lookup(sc
, addr
)) == NULL
)
1813 bridge_rtnode_destroy(sc
, brt
);
1820 * Delete routes to a speicifc member interface.
1823 bridge_rtdelete(struct bridge_softc
*sc
, struct ifnet
*ifp
)
1825 struct bridge_rtnode
*brt
, *nbrt
;
1827 for (brt
= LIST_FIRST(&sc
->sc_rtlist
); brt
!= NULL
; brt
= nbrt
) {
1828 nbrt
= LIST_NEXT(brt
, brt_list
);
1829 if (brt
->brt_ifp
== ifp
)
1830 bridge_rtnode_destroy(sc
, brt
);
1835 * bridge_rtable_init:
1837 * Initialize the route table for this bridge.
1840 bridge_rtable_init(struct bridge_softc
*sc
)
1844 sc
->sc_rthash
= malloc(sizeof(*sc
->sc_rthash
) * BRIDGE_RTHASH_SIZE
,
1845 M_DEVBUF
, M_NOWAIT
);
1846 if (sc
->sc_rthash
== NULL
)
1849 for (i
= 0; i
< BRIDGE_RTHASH_SIZE
; i
++)
1850 LIST_INIT(&sc
->sc_rthash
[i
]);
1852 sc
->sc_rthash_key
= arc4random();
1854 LIST_INIT(&sc
->sc_rtlist
);
1860 * bridge_rtable_fini:
1862 * Deconstruct the route table for this bridge.
1865 bridge_rtable_fini(struct bridge_softc
*sc
)
1868 free(sc
->sc_rthash
, M_DEVBUF
);
1872 * The following hash function is adapted from "Hash Functions" by Bob Jenkins
1873 * ("Algorithm Alley", Dr. Dobbs Journal, September 1997).
1875 #define mix(a, b, c) \
1877 a -= b; a -= c; a ^= (c >> 13); \
1878 b -= c; b -= a; b ^= (a << 8); \
1879 c -= a; c -= b; c ^= (b >> 13); \
1880 a -= b; a -= c; a ^= (c >> 12); \
1881 b -= c; b -= a; b ^= (a << 16); \
1882 c -= a; c -= b; c ^= (b >> 5); \
1883 a -= b; a -= c; a ^= (c >> 3); \
1884 b -= c; b -= a; b ^= (a << 10); \
1885 c -= a; c -= b; c ^= (b >> 15); \
1886 } while (/*CONSTCOND*/0)
1888 static inline uint32_t
1889 bridge_rthash(struct bridge_softc
*sc
, const uint8_t *addr
)
1891 uint32_t a
= 0x9e3779b9, b
= 0x9e3779b9, c
= sc
->sc_rthash_key
;
1902 return (c
& BRIDGE_RTHASH_MASK
);
1908 * bridge_rtnode_lookup:
1910 * Look up a bridge route node for the specified destination.
1912 static struct bridge_rtnode
*
1913 bridge_rtnode_lookup(struct bridge_softc
*sc
, const uint8_t *addr
)
1915 struct bridge_rtnode
*brt
;
1919 hash
= bridge_rthash(sc
, addr
);
1920 LIST_FOREACH(brt
, &sc
->sc_rthash
[hash
], brt_hash
) {
1921 dir
= memcmp(addr
, brt
->brt_addr
, ETHER_ADDR_LEN
);
1932 * bridge_rtnode_insert:
1934 * Insert the specified bridge node into the route table. We
1935 * assume the entry is not already in the table.
1938 bridge_rtnode_insert(struct bridge_softc
*sc
, struct bridge_rtnode
*brt
)
1940 struct bridge_rtnode
*lbrt
;
1944 hash
= bridge_rthash(sc
, brt
->brt_addr
);
1946 lbrt
= LIST_FIRST(&sc
->sc_rthash
[hash
]);
1948 LIST_INSERT_HEAD(&sc
->sc_rthash
[hash
], brt
, brt_hash
);
1953 dir
= memcmp(brt
->brt_addr
, lbrt
->brt_addr
, ETHER_ADDR_LEN
);
1957 LIST_INSERT_BEFORE(lbrt
, brt
, brt_hash
);
1960 if (LIST_NEXT(lbrt
, brt_hash
) == NULL
) {
1961 LIST_INSERT_AFTER(lbrt
, brt
, brt_hash
);
1964 lbrt
= LIST_NEXT(lbrt
, brt_hash
);
1965 } while (lbrt
!= NULL
);
1968 panic("bridge_rtnode_insert: impossible");
1972 LIST_INSERT_HEAD(&sc
->sc_rtlist
, brt
, brt_list
);
1979 * bridge_rtnode_destroy:
1981 * Destroy a bridge rtnode.
1984 bridge_rtnode_destroy(struct bridge_softc
*sc
, struct bridge_rtnode
*brt
)
1988 LIST_REMOVE(brt
, brt_hash
);
1990 LIST_REMOVE(brt
, brt_list
);
1992 pool_put(&bridge_rtnode_pool
, brt
);
1997 #if defined(BRIDGE_IPF) && defined(PFIL_HOOKS)
1998 extern struct pfil_head inet_pfil_hook
; /* XXX */
1999 extern struct pfil_head inet6_pfil_hook
; /* XXX */
2002 * Send bridge packets through IPF if they are one of the types IPF can deal
2003 * with, or if they are ARP or REVARP. (IPF will pass ARP and REVARP without
2007 bridge_ipf(void *arg
, struct mbuf
**mp
, struct ifnet
*ifp
, int dir
)
2010 struct ether_header
*eh1
, eh2
;
2012 uint16_t ether_type
;
2015 error
= -1; /* Default error if not error == 0 */
2016 eh1
= mtod(*mp
, struct ether_header
*);
2017 ether_type
= ntohs(eh1
->ether_type
);
2020 * Check for SNAP/LLC.
2022 if (ether_type
< ETHERMTU
) {
2023 struct llc
*llc2
= (struct llc
*)(eh1
+ 1);
2025 if ((*mp
)->m_len
>= ETHER_HDR_LEN
+ 8 &&
2026 llc2
->llc_dsap
== LLC_SNAP_LSAP
&&
2027 llc2
->llc_ssap
== LLC_SNAP_LSAP
&&
2028 llc2
->llc_control
== LLC_UI
) {
2029 ether_type
= htons(llc2
->llc_un
.type_snap
.ether_type
);
2035 * If we're trying to filter bridge traffic, don't look at anything
2036 * other than IP and ARP traffic. If the filter doesn't understand
2037 * IPv6, don't allow IPv6 through the bridge either. This is lame
2038 * since if we really wanted, say, an AppleTalk filter, we are hosed,
2039 * but of course we don't have an AppleTalk filter to begin with.
2040 * (Note that since IPF doesn't understand ARP it will pass *ALL*
2043 switch (ether_type
) {
2045 case ETHERTYPE_REVARP
:
2046 return 0; /* Automatically pass */
2049 case ETHERTYPE_IPV6
:
2056 /* Strip off the Ethernet header and keep a copy. */
2057 m_copydata(*mp
, 0, ETHER_HDR_LEN
, (void *) &eh2
);
2058 m_adj(*mp
, ETHER_HDR_LEN
);
2060 /* Strip off snap header, if present */
2062 m_copydata(*mp
, 0, sizeof(struct llc
), (void *) &llc1
);
2063 m_adj(*mp
, sizeof(struct llc
));
2067 * Check basic packet sanity and run IPF through pfil.
2069 KASSERT(!cpu_intr_p());
2073 error
= (dir
== PFIL_IN
) ? bridge_ip_checkbasic(mp
) : 0;
2075 error
= pfil_run_hooks(&inet_pfil_hook
, mp
, ifp
, dir
);
2078 case ETHERTYPE_IPV6
:
2079 error
= (dir
== PFIL_IN
) ? bridge_ip6_checkbasic(mp
) : 0;
2081 error
= pfil_run_hooks(&inet6_pfil_hook
, mp
, ifp
, dir
);
2097 * Finally, put everything back the way it was and return
2100 M_PREPEND(*mp
, sizeof(struct llc
), M_DONTWAIT
);
2103 bcopy(&llc1
, mtod(*mp
, void *), sizeof(struct llc
));
2106 M_PREPEND(*mp
, ETHER_HDR_LEN
, M_DONTWAIT
);
2109 bcopy(&eh2
, mtod(*mp
, void *), ETHER_HDR_LEN
);
2120 * Perform basic checks on header size since
2121 * IPF assumes ip_input has already processed
2122 * it for it. Cut-and-pasted from ip_input.c.
2123 * Given how simple the IPv6 version is,
2124 * does the IPv4 version really need to be
2127 * XXX Should we update ipstat here, or not?
2128 * XXX Right now we update ipstat but not
2132 bridge_ip_checkbasic(struct mbuf
**mp
)
2134 struct mbuf
*m
= *mp
;
2141 if (IP_HDR_ALIGNED_P(mtod(m
, void *)) == 0) {
2142 if ((m
= m_copyup(m
, sizeof(struct ip
),
2143 (max_linkhdr
+ 3) & ~3)) == NULL
) {
2144 /* XXXJRT new stat, please */
2145 ip_statinc(IP_STAT_TOOSMALL
);
2148 } else if (__predict_false(m
->m_len
< sizeof (struct ip
))) {
2149 if ((m
= m_pullup(m
, sizeof (struct ip
))) == NULL
) {
2150 ip_statinc(IP_STAT_TOOSMALL
);
2154 ip
= mtod(m
, struct ip
*);
2155 if (ip
== NULL
) goto bad
;
2157 if (ip
->ip_v
!= IPVERSION
) {
2158 ip_statinc(IP_STAT_BADVERS
);
2161 hlen
= ip
->ip_hl
<< 2;
2162 if (hlen
< sizeof(struct ip
)) { /* minimum header length */
2163 ip_statinc(IP_STAT_BADHLEN
);
2166 if (hlen
> m
->m_len
) {
2167 if ((m
= m_pullup(m
, hlen
)) == 0) {
2168 ip_statinc(IP_STAT_BADHLEN
);
2171 ip
= mtod(m
, struct ip
*);
2172 if (ip
== NULL
) goto bad
;
2175 switch (m
->m_pkthdr
.csum_flags
&
2176 ((m
->m_pkthdr
.rcvif
->if_csum_flags_rx
& M_CSUM_IPv4
) |
2178 case M_CSUM_IPv4
|M_CSUM_IPv4_BAD
:
2179 /* INET_CSUM_COUNTER_INCR(&ip_hwcsum_bad); */
2183 /* Checksum was okay. */
2184 /* INET_CSUM_COUNTER_INCR(&ip_hwcsum_ok); */
2188 /* Must compute it ourselves. */
2189 /* INET_CSUM_COUNTER_INCR(&ip_swcsum); */
2190 if (in_cksum(m
, hlen
) != 0)
2195 /* Retrieve the packet length. */
2196 len
= ntohs(ip
->ip_len
);
2199 * Check for additional length bogosity
2202 ip_statinc(IP_STAT_BADLEN
);
2207 * Check that the amount of data in the buffers
2208 * is as at least much as the IP header would have us expect.
2209 * Drop packet if shorter than we expect.
2211 if (m
->m_pkthdr
.len
< len
) {
2212 ip_statinc(IP_STAT_TOOSHORT
);
2216 /* Checks out, proceed */
2227 * Same as above, but for IPv6.
2228 * Cut-and-pasted from ip6_input.c.
2229 * XXX Should we update ip6stat, or not?
2232 bridge_ip6_checkbasic(struct mbuf
**mp
)
2234 struct mbuf
*m
= *mp
;
2235 struct ip6_hdr
*ip6
;
2238 * If the IPv6 header is not aligned, slurp it up into a new
2239 * mbuf with space for link headers, in the event we forward
2240 * it. Otherwise, if it is aligned, make sure the entire base
2241 * IPv6 header is in the first mbuf of the chain.
2243 if (IP6_HDR_ALIGNED_P(mtod(m
, void *)) == 0) {
2244 struct ifnet
*inifp
= m
->m_pkthdr
.rcvif
;
2245 if ((m
= m_copyup(m
, sizeof(struct ip6_hdr
),
2246 (max_linkhdr
+ 3) & ~3)) == NULL
) {
2247 /* XXXJRT new stat, please */
2248 ip6_statinc(IP6_STAT_TOOSMALL
);
2249 in6_ifstat_inc(inifp
, ifs6_in_hdrerr
);
2252 } else if (__predict_false(m
->m_len
< sizeof(struct ip6_hdr
))) {
2253 struct ifnet
*inifp
= m
->m_pkthdr
.rcvif
;
2254 if ((m
= m_pullup(m
, sizeof(struct ip6_hdr
))) == NULL
) {
2255 ip6_statinc(IP6_STAT_TOOSMALL
);
2256 in6_ifstat_inc(inifp
, ifs6_in_hdrerr
);
2261 ip6
= mtod(m
, struct ip6_hdr
*);
2263 if ((ip6
->ip6_vfc
& IPV6_VERSION_MASK
) != IPV6_VERSION
) {
2264 ip6_statinc(IP6_STAT_BADVERS
);
2265 in6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_hdrerr
);
2269 /* Checks out, proceed */
2278 #endif /* BRIDGE_IPF && PFIL_HOOKS */