if_bridge.c revision 1.2.2.9 1 /* $NetBSD: if_bridge.c,v 1.2.2.9 2002/08/27 23:47:51 nathanw Exp $ */
2
3 /*
4 * Copyright 2001 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
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
23 * written permission.
24 *
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.
36 */
37
38 /*
39 * Copyright (c) 1999, 2000 Jason L. Wright (jason (at) thought.net)
40 * All rights reserved.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
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.
55 *
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.
67 *
68 * OpenBSD: if_bridge.c,v 1.60 2001/06/15 03:38:33 itojun Exp
69 */
70
71 /*
72 * Network interface bridge support.
73 *
74 * TODO:
75 *
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).
80 *
81 * - Add packet filter hooks.
82 */
83
84 #include <sys/cdefs.h>
85 __KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.2.2.9 2002/08/27 23:47:51 nathanw Exp $");
86
87 #include "bpfilter.h"
88 #include "rnd.h"
89
90 #include <sys/param.h>
91 #include <sys/kernel.h>
92 #include <sys/mbuf.h>
93 #include <sys/queue.h>
94 #include <sys/socket.h>
95 #include <sys/sockio.h>
96 #include <sys/systm.h>
97 #include <sys/proc.h>
98 #include <sys/pool.h>
99
100 #if NRND > 0
101 #include <sys/rnd.h>
102 #endif
103
104 #if NBPFILTER > 0
105 #include <net/bpf.h>
106 #endif
107 #include <net/if.h>
108 #include <net/if_dl.h>
109 #include <net/if_types.h>
110 #include <net/if_llc.h>
111
112 #include <net/if_ether.h>
113 #include <net/if_bridgevar.h>
114
115 /*
116 * Size of the route hash table. Must be a power of two.
117 */
118 #ifndef BRIDGE_RTHASH_SIZE
119 #define BRIDGE_RTHASH_SIZE 1024
120 #endif
121
122 #define BRIDGE_RTHASH_MASK (BRIDGE_RTHASH_SIZE - 1)
123
124 /*
125 * Maximum number of addresses to cache.
126 */
127 #ifndef BRIDGE_RTABLE_MAX
128 #define BRIDGE_RTABLE_MAX 100
129 #endif
130
131 /*
132 * Spanning tree defaults.
133 */
134 #define BSTP_DEFAULT_MAX_AGE (20 * 256)
135 #define BSTP_DEFAULT_HELLO_TIME (2 * 256)
136 #define BSTP_DEFAULT_FORWARD_DELAY (15 * 256)
137 #define BSTP_DEFAULT_HOLD_TIME (1 * 256)
138 #define BSTP_DEFAULT_BRIDGE_PRIORITY 0x8000
139 #define BSTP_DEFAULT_PORT_PRIORITY 0x80
140 #define BSTP_DEFAULT_PATH_COST 55
141
142 /*
143 * Timeout (in seconds) for entries learned dynamically.
144 */
145 #ifndef BRIDGE_RTABLE_TIMEOUT
146 #define BRIDGE_RTABLE_TIMEOUT (20 * 60) /* same as ARP */
147 #endif
148
149 /*
150 * Number of seconds between walks of the route list.
151 */
152 #ifndef BRIDGE_RTABLE_PRUNE_PERIOD
153 #define BRIDGE_RTABLE_PRUNE_PERIOD (5 * 60)
154 #endif
155
156 int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD;
157
158 struct pool bridge_rtnode_pool;
159
160 void bridgeattach(int);
161
162 int bridge_clone_create(struct if_clone *, int);
163 void bridge_clone_destroy(struct ifnet *);
164
165 int bridge_ioctl(struct ifnet *, u_long, caddr_t);
166 int bridge_init(struct ifnet *);
167 void bridge_stop(struct ifnet *, int);
168 void bridge_start(struct ifnet *);
169
170 void bridge_forward(struct bridge_softc *, struct mbuf *m);
171
172 void bridge_timer(void *);
173
174 void bridge_broadcast(struct bridge_softc *, struct ifnet *, struct mbuf *);
175
176 int bridge_rtupdate(struct bridge_softc *, const uint8_t *,
177 struct ifnet *, int, uint8_t);
178 struct ifnet *bridge_rtlookup(struct bridge_softc *, const uint8_t *);
179 void bridge_rttrim(struct bridge_softc *);
180 void bridge_rtage(struct bridge_softc *);
181 void bridge_rtflush(struct bridge_softc *, int);
182 int bridge_rtdaddr(struct bridge_softc *, const uint8_t *);
183 void bridge_rtdelete(struct bridge_softc *, struct ifnet *ifp);
184
185 int bridge_rtable_init(struct bridge_softc *);
186 void bridge_rtable_fini(struct bridge_softc *);
187
188 struct bridge_rtnode *bridge_rtnode_lookup(struct bridge_softc *,
189 const uint8_t *);
190 int bridge_rtnode_insert(struct bridge_softc *, struct bridge_rtnode *);
191 void bridge_rtnode_destroy(struct bridge_softc *, struct bridge_rtnode *);
192
193 struct bridge_iflist *bridge_lookup_member(struct bridge_softc *,
194 const char *name);
195 struct bridge_iflist *bridge_lookup_member_if(struct bridge_softc *,
196 struct ifnet *ifp);
197 void bridge_delete_member(struct bridge_softc *, struct bridge_iflist *);
198
199 int bridge_ioctl_add(struct bridge_softc *, void *);
200 int bridge_ioctl_del(struct bridge_softc *, void *);
201 int bridge_ioctl_gifflags(struct bridge_softc *, void *);
202 int bridge_ioctl_sifflags(struct bridge_softc *, void *);
203 int bridge_ioctl_scache(struct bridge_softc *, void *);
204 int bridge_ioctl_gcache(struct bridge_softc *, void *);
205 int bridge_ioctl_gifs(struct bridge_softc *, void *);
206 int bridge_ioctl_rts(struct bridge_softc *, void *);
207 int bridge_ioctl_saddr(struct bridge_softc *, void *);
208 int bridge_ioctl_sto(struct bridge_softc *, void *);
209 int bridge_ioctl_gto(struct bridge_softc *, void *);
210 int bridge_ioctl_daddr(struct bridge_softc *, void *);
211 int bridge_ioctl_flush(struct bridge_softc *, void *);
212 int bridge_ioctl_gpri(struct bridge_softc *, void *);
213 int bridge_ioctl_spri(struct bridge_softc *, void *);
214 int bridge_ioctl_ght(struct bridge_softc *, void *);
215 int bridge_ioctl_sht(struct bridge_softc *, void *);
216 int bridge_ioctl_gfd(struct bridge_softc *, void *);
217 int bridge_ioctl_sfd(struct bridge_softc *, void *);
218 int bridge_ioctl_gma(struct bridge_softc *, void *);
219 int bridge_ioctl_sma(struct bridge_softc *, void *);
220 int bridge_ioctl_sifprio(struct bridge_softc *, void *);
221
222 struct bridge_control {
223 int (*bc_func)(struct bridge_softc *, void *);
224 int bc_argsize;
225 int bc_flags;
226 };
227
228 #define BC_F_COPYIN 0x01 /* copy arguments in */
229 #define BC_F_COPYOUT 0x02 /* copy arguments out */
230 #define BC_F_SUSER 0x04 /* do super-user check */
231
232 const struct bridge_control bridge_control_table[] = {
233 { bridge_ioctl_add, sizeof(struct ifbreq),
234 BC_F_COPYIN|BC_F_SUSER },
235 { bridge_ioctl_del, sizeof(struct ifbreq),
236 BC_F_COPYIN|BC_F_SUSER },
237
238 { bridge_ioctl_gifflags, sizeof(struct ifbreq),
239 BC_F_COPYIN|BC_F_COPYOUT },
240 { bridge_ioctl_sifflags, sizeof(struct ifbreq),
241 BC_F_COPYIN|BC_F_SUSER },
242
243 { bridge_ioctl_scache, sizeof(struct ifbrparam),
244 BC_F_COPYIN|BC_F_SUSER },
245 { bridge_ioctl_gcache, sizeof(struct ifbrparam),
246 BC_F_COPYOUT },
247
248 { bridge_ioctl_gifs, sizeof(struct ifbifconf),
249 BC_F_COPYIN|BC_F_COPYOUT },
250 { bridge_ioctl_rts, sizeof(struct ifbaconf),
251 BC_F_COPYIN|BC_F_COPYOUT },
252
253 { bridge_ioctl_saddr, sizeof(struct ifbareq),
254 BC_F_COPYIN|BC_F_SUSER },
255
256 { bridge_ioctl_sto, sizeof(struct ifbrparam),
257 BC_F_COPYIN|BC_F_SUSER },
258 { bridge_ioctl_gto, sizeof(struct ifbrparam),
259 BC_F_COPYOUT },
260
261 { bridge_ioctl_daddr, sizeof(struct ifbareq),
262 BC_F_COPYIN|BC_F_SUSER },
263
264 { bridge_ioctl_flush, sizeof(struct ifbreq),
265 BC_F_COPYIN|BC_F_SUSER },
266
267 { bridge_ioctl_gpri, sizeof(struct ifbrparam),
268 BC_F_COPYOUT },
269 { bridge_ioctl_spri, sizeof(struct ifbrparam),
270 BC_F_COPYIN|BC_F_SUSER },
271
272 { bridge_ioctl_ght, sizeof(struct ifbrparam),
273 BC_F_COPYOUT },
274 { bridge_ioctl_sht, sizeof(struct ifbrparam),
275 BC_F_COPYIN|BC_F_SUSER },
276
277 { bridge_ioctl_gfd, sizeof(struct ifbrparam),
278 BC_F_COPYOUT },
279 { bridge_ioctl_sfd, sizeof(struct ifbrparam),
280 BC_F_COPYIN|BC_F_SUSER },
281
282 { bridge_ioctl_gma, sizeof(struct ifbrparam),
283 BC_F_COPYOUT },
284 { bridge_ioctl_sma, sizeof(struct ifbrparam),
285 BC_F_COPYIN|BC_F_SUSER },
286
287 { bridge_ioctl_sifprio, sizeof(struct ifbreq),
288 BC_F_COPYIN|BC_F_SUSER },
289 };
290 const int bridge_control_table_size =
291 sizeof(bridge_control_table) / sizeof(bridge_control_table[0]);
292
293 LIST_HEAD(, bridge_softc) bridge_list;
294
295 struct if_clone bridge_cloner =
296 IF_CLONE_INITIALIZER("bridge", bridge_clone_create, bridge_clone_destroy);
297
298 /*
299 * bridgeattach:
300 *
301 * Pseudo-device attach routine.
302 */
303 void
304 bridgeattach(int n)
305 {
306
307 pool_init(&bridge_rtnode_pool, sizeof(struct bridge_rtnode),
308 0, 0, 0, "brtpl", NULL);
309
310 LIST_INIT(&bridge_list);
311 if_clone_attach(&bridge_cloner);
312 }
313
314 /*
315 * bridge_clone_create:
316 *
317 * Create a new bridge instance.
318 */
319 int
320 bridge_clone_create(struct if_clone *ifc, int unit)
321 {
322 struct bridge_softc *sc;
323 struct ifnet *ifp;
324 int s;
325
326 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK);
327 memset(sc, 0, sizeof(*sc));
328 ifp = &sc->sc_if;
329
330 sc->sc_brtmax = BRIDGE_RTABLE_MAX;
331 sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT;
332 sc->sc_bridge_max_age = BSTP_DEFAULT_MAX_AGE;
333 sc->sc_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME;
334 sc->sc_bridge_forward_delay = BSTP_DEFAULT_FORWARD_DELAY;
335 sc->sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY;
336 sc->sc_hold_time = BSTP_DEFAULT_HOLD_TIME;
337
338 /* Initialize our routing table. */
339 bridge_rtable_init(sc);
340
341 callout_init(&sc->sc_brcallout);
342 callout_init(&sc->sc_bstpcallout);
343
344 LIST_INIT(&sc->sc_iflist);
345
346 sprintf(ifp->if_xname, "%s%d", ifc->ifc_name, unit);
347 ifp->if_softc = sc;
348 ifp->if_mtu = ETHERMTU;
349 ifp->if_ioctl = bridge_ioctl;
350 ifp->if_output = bridge_output;
351 ifp->if_start = bridge_start;
352 ifp->if_stop = bridge_stop;
353 ifp->if_init = bridge_init;
354 ifp->if_type = IFT_BRIDGE;
355 ifp->if_addrlen = 0;
356 ifp->if_dlt = DLT_EN10MB;
357 ifp->if_hdrlen = ETHER_HDR_LEN;
358
359 if_attach(ifp);
360
361 if_alloc_sadl(ifp);
362
363 s = splnet();
364 LIST_INSERT_HEAD(&bridge_list, sc, sc_list);
365 splx(s);
366
367 return (0);
368 }
369
370 /*
371 * bridge_clone_destroy:
372 *
373 * Destroy a bridge instance.
374 */
375 void
376 bridge_clone_destroy(struct ifnet *ifp)
377 {
378 struct bridge_softc *sc = ifp->if_softc;
379 struct bridge_iflist *bif;
380 int s;
381
382 s = splnet();
383
384 bridge_stop(ifp, 1);
385
386 while ((bif = LIST_FIRST(&sc->sc_iflist)) != NULL)
387 bridge_delete_member(sc, bif);
388
389 LIST_REMOVE(sc, sc_list);
390
391 splx(s);
392
393 if_detach(ifp);
394
395 /* Tear down the routing table. */
396 bridge_rtable_fini(sc);
397
398 free(sc, M_DEVBUF);
399 }
400
401 /*
402 * bridge_ioctl:
403 *
404 * Handle a control request from the operator.
405 */
406 int
407 bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
408 {
409 struct bridge_softc *sc = ifp->if_softc;
410 struct proc *p = curproc; /* XXX */
411 union {
412 struct ifbreq ifbreq;
413 struct ifbifconf ifbifconf;
414 struct ifbareq ifbareq;
415 struct ifbaconf ifbaconf;
416 struct ifbrparam ifbrparam;
417 } args;
418 struct ifdrv *ifd = (struct ifdrv *) data;
419 const struct bridge_control *bc;
420 int s, error = 0;
421
422 s = splnet();
423
424 switch (cmd) {
425 case SIOCGDRVSPEC:
426 case SIOCSDRVSPEC:
427 if (ifd->ifd_cmd >= bridge_control_table_size) {
428 error = EINVAL;
429 break;
430 }
431 bc = &bridge_control_table[ifd->ifd_cmd];
432
433 if (cmd == SIOCGDRVSPEC &&
434 (bc->bc_flags & BC_F_COPYOUT) == 0)
435 return (EINVAL);
436 else if (cmd == SIOCSDRVSPEC &&
437 (bc->bc_flags & BC_F_COPYOUT) != 0)
438 return (EINVAL);
439
440 if (bc->bc_flags & BC_F_SUSER) {
441 error = suser(p->p_ucred, &p->p_acflag);
442 if (error)
443 break;
444 }
445
446 if (ifd->ifd_len != bc->bc_argsize ||
447 ifd->ifd_len > sizeof(args)) {
448 error = EINVAL;
449 break;
450 }
451
452 if (bc->bc_flags & BC_F_COPYIN) {
453 error = copyin(ifd->ifd_data, &args, ifd->ifd_len);
454 if (error)
455 break;
456 }
457
458 error = (*bc->bc_func)(sc, &args);
459 if (error)
460 break;
461
462 if (bc->bc_flags & BC_F_COPYOUT)
463 error = copyout(&args, ifd->ifd_data, ifd->ifd_len);
464
465 break;
466
467 case SIOCSIFFLAGS:
468 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_RUNNING) {
469 /*
470 * If interface is marked down and it is running,
471 * then stop and disable it.
472 */
473 (*ifp->if_stop)(ifp, 1);
474 } else if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_UP) {
475 /*
476 * If interface is marked up and it is stopped, then
477 * start it.
478 */
479 error = (*ifp->if_init)(ifp);
480 }
481 break;
482
483 default:
484 error = ENOTTY;
485 break;
486 }
487
488 splx(s);
489
490 return (error);
491 }
492
493 /*
494 * bridge_lookup_member:
495 *
496 * Lookup a bridge member interface. Must be called at splnet().
497 */
498 struct bridge_iflist *
499 bridge_lookup_member(struct bridge_softc *sc, const char *name)
500 {
501 struct bridge_iflist *bif;
502 struct ifnet *ifp;
503
504 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
505 ifp = bif->bif_ifp;
506 if (strcmp(ifp->if_xname, name) == 0)
507 return (bif);
508 }
509
510 return (NULL);
511 }
512
513 /*
514 * bridge_lookup_member_if:
515 *
516 * Lookup a bridge member interface by ifnet*. Must be called at splnet().
517 */
518 struct bridge_iflist *
519 bridge_lookup_member_if(struct bridge_softc *sc, struct ifnet *member_ifp)
520 {
521 struct bridge_iflist *bif;
522
523 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
524 if (bif->bif_ifp == member_ifp)
525 return (bif);
526 }
527
528 return (NULL);
529 }
530
531 /*
532 * bridge_delete_member:
533 *
534 * Delete the specified member interface.
535 */
536 void
537 bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif)
538 {
539 struct ifnet *ifs = bif->bif_ifp;
540
541 switch (ifs->if_type) {
542 case IFT_ETHER:
543 /*
544 * Take the interface out of promiscuous mode.
545 */
546 (void) ifpromisc(ifs, 0);
547 break;
548
549 default:
550 #ifdef DIAGNOSTIC
551 panic("bridge_delete_member: impossible");
552 #endif
553 break;
554 }
555
556 ifs->if_bridge = NULL;
557 LIST_REMOVE(bif, bif_next);
558
559 bridge_rtdelete(sc, ifs);
560
561 free(bif, M_DEVBUF);
562
563 if (sc->sc_if.if_flags & IFF_RUNNING)
564 bstp_initialization(sc);
565 }
566
567 int
568 bridge_ioctl_add(struct bridge_softc *sc, void *arg)
569 {
570 struct ifbreq *req = arg;
571 struct bridge_iflist *bif = NULL;
572 struct ifnet *ifs;
573 int error = 0;
574
575 ifs = ifunit(req->ifbr_ifsname);
576 if (ifs == NULL)
577 return (ENOENT);
578
579 if (sc->sc_if.if_mtu != ifs->if_mtu)
580 return (EINVAL);
581
582 if (ifs->if_bridge == sc)
583 return (EEXIST);
584
585 if (ifs->if_bridge != NULL)
586 return (EBUSY);
587
588 bif = malloc(sizeof(*bif), M_DEVBUF, M_NOWAIT);
589 if (bif == NULL)
590 return (ENOMEM);
591
592 switch (ifs->if_type) {
593 case IFT_ETHER:
594 /*
595 * Place the interface into promiscuous mode.
596 */
597 error = ifpromisc(ifs, 1);
598 if (error)
599 goto out;
600 break;
601
602 default:
603 error = EINVAL;
604 goto out;
605 }
606
607 bif->bif_ifp = ifs;
608 bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
609 bif->bif_priority = BSTP_DEFAULT_PORT_PRIORITY;
610 bif->bif_path_cost = BSTP_DEFAULT_PATH_COST;
611
612 ifs->if_bridge = sc;
613 LIST_INSERT_HEAD(&sc->sc_iflist, bif, bif_next);
614
615 if (sc->sc_if.if_flags & IFF_RUNNING)
616 bstp_initialization(sc);
617 else
618 bstp_stop(sc);
619
620 out:
621 if (error) {
622 if (bif != NULL)
623 free(bif, M_DEVBUF);
624 }
625 return (error);
626 }
627
628 int
629 bridge_ioctl_del(struct bridge_softc *sc, void *arg)
630 {
631 struct ifbreq *req = arg;
632 struct bridge_iflist *bif;
633
634 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
635 if (bif == NULL)
636 return (ENOENT);
637
638 bridge_delete_member(sc, bif);
639
640 return (0);
641 }
642
643 int
644 bridge_ioctl_gifflags(struct bridge_softc *sc, void *arg)
645 {
646 struct ifbreq *req = arg;
647 struct bridge_iflist *bif;
648
649 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
650 if (bif == NULL)
651 return (ENOENT);
652
653 req->ifbr_ifsflags = bif->bif_flags;
654 req->ifbr_state = bif->bif_state;
655 req->ifbr_priority = bif->bif_priority;
656 req->ifbr_portno = bif->bif_ifp->if_index & 0xff;
657
658 return (0);
659 }
660
661 int
662 bridge_ioctl_sifflags(struct bridge_softc *sc, void *arg)
663 {
664 struct ifbreq *req = arg;
665 struct bridge_iflist *bif;
666
667 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
668 if (bif == NULL)
669 return (ENOENT);
670
671 if (req->ifbr_ifsflags & IFBIF_STP) {
672 switch (bif->bif_ifp->if_type) {
673 case IFT_ETHER:
674 /* These can do spanning tree. */
675 break;
676
677 default:
678 /* Nothing else can. */
679 return (EINVAL);
680 }
681 }
682
683 bif->bif_flags = req->ifbr_ifsflags;
684
685 if (sc->sc_if.if_flags & IFF_RUNNING)
686 bstp_initialization(sc);
687
688 return (0);
689 }
690
691 int
692 bridge_ioctl_scache(struct bridge_softc *sc, void *arg)
693 {
694 struct ifbrparam *param = arg;
695
696 sc->sc_brtmax = param->ifbrp_csize;
697 bridge_rttrim(sc);
698
699 return (0);
700 }
701
702 int
703 bridge_ioctl_gcache(struct bridge_softc *sc, void *arg)
704 {
705 struct ifbrparam *param = arg;
706
707 param->ifbrp_csize = sc->sc_brtmax;
708
709 return (0);
710 }
711
712 int
713 bridge_ioctl_gifs(struct bridge_softc *sc, void *arg)
714 {
715 struct ifbifconf *bifc = arg;
716 struct bridge_iflist *bif;
717 struct ifbreq breq;
718 int count, len, error = 0;
719
720 count = 0;
721 LIST_FOREACH(bif, &sc->sc_iflist, bif_next)
722 count++;
723
724 if (bifc->ifbic_len == 0) {
725 bifc->ifbic_len = sizeof(breq) * count;
726 return (0);
727 }
728
729 count = 0;
730 len = bifc->ifbic_len;
731 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
732 if (len < sizeof(breq))
733 break;
734
735 strcpy(breq.ifbr_ifsname, bif->bif_ifp->if_xname);
736 breq.ifbr_ifsflags = bif->bif_flags;
737 breq.ifbr_state = bif->bif_state;
738 breq.ifbr_priority = bif->bif_priority;
739 breq.ifbr_portno = bif->bif_ifp->if_index & 0xff;
740 error = copyout(&breq, bifc->ifbic_req + count, sizeof(breq));
741 if (error)
742 break;
743 count++;
744 len -= sizeof(breq);
745 }
746
747 bifc->ifbic_len = sizeof(breq) * count;
748 return (error);
749 }
750
751 int
752 bridge_ioctl_rts(struct bridge_softc *sc, void *arg)
753 {
754 struct ifbaconf *bac = arg;
755 struct bridge_rtnode *brt;
756 struct ifbareq bareq;
757 int count = 0, error = 0, len;
758
759 if (bac->ifbac_len == 0)
760 return (0);
761
762 len = bac->ifbac_len;
763 LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) {
764 if (len < sizeof(bareq))
765 goto out;
766 strcpy(bareq.ifba_ifsname, brt->brt_ifp->if_xname);
767 memcpy(bareq.ifba_dst, brt->brt_addr, sizeof(brt->brt_addr));
768 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
769 bareq.ifba_expire = brt->brt_expire - mono_time.tv_sec;
770 else
771 bareq.ifba_expire = 0;
772 bareq.ifba_flags = brt->brt_flags;
773
774 error = copyout(&bareq, bac->ifbac_req + count, sizeof(bareq));
775 if (error)
776 goto out;
777 count++;
778 len -= sizeof(bareq);
779 }
780 out:
781 bac->ifbac_len = sizeof(bareq) * count;
782 return (error);
783 }
784
785 int
786 bridge_ioctl_saddr(struct bridge_softc *sc, void *arg)
787 {
788 struct ifbareq *req = arg;
789 struct bridge_iflist *bif;
790 int error;
791
792 bif = bridge_lookup_member(sc, req->ifba_ifsname);
793 if (bif == NULL)
794 return (ENOENT);
795
796 error = bridge_rtupdate(sc, req->ifba_dst, bif->bif_ifp, 1,
797 req->ifba_flags);
798
799 return (error);
800 }
801
802 int
803 bridge_ioctl_sto(struct bridge_softc *sc, void *arg)
804 {
805 struct ifbrparam *param = arg;
806
807 sc->sc_brttimeout = param->ifbrp_ctime;
808
809 return (0);
810 }
811
812 int
813 bridge_ioctl_gto(struct bridge_softc *sc, void *arg)
814 {
815 struct ifbrparam *param = arg;
816
817 param->ifbrp_ctime = sc->sc_brttimeout;
818
819 return (0);
820 }
821
822 int
823 bridge_ioctl_daddr(struct bridge_softc *sc, void *arg)
824 {
825 struct ifbareq *req = arg;
826
827 return (bridge_rtdaddr(sc, req->ifba_dst));
828 }
829
830 int
831 bridge_ioctl_flush(struct bridge_softc *sc, void *arg)
832 {
833 struct ifbreq *req = arg;
834
835 bridge_rtflush(sc, req->ifbr_ifsflags);
836
837 return (0);
838 }
839
840 int
841 bridge_ioctl_gpri(struct bridge_softc *sc, void *arg)
842 {
843 struct ifbrparam *param = arg;
844
845 param->ifbrp_prio = sc->sc_bridge_priority;
846
847 return (0);
848 }
849
850 int
851 bridge_ioctl_spri(struct bridge_softc *sc, void *arg)
852 {
853 struct ifbrparam *param = arg;
854
855 sc->sc_bridge_priority = param->ifbrp_prio;
856
857 if (sc->sc_if.if_flags & IFF_RUNNING)
858 bstp_initialization(sc);
859
860 return (0);
861 }
862
863 int
864 bridge_ioctl_ght(struct bridge_softc *sc, void *arg)
865 {
866 struct ifbrparam *param = arg;
867
868 param->ifbrp_hellotime = sc->sc_bridge_hello_time >> 8;
869
870 return (0);
871 }
872
873 int
874 bridge_ioctl_sht(struct bridge_softc *sc, void *arg)
875 {
876 struct ifbrparam *param = arg;
877
878 if (param->ifbrp_hellotime == 0)
879 return (EINVAL);
880 sc->sc_bridge_hello_time = param->ifbrp_hellotime << 8;
881
882 if (sc->sc_if.if_flags & IFF_RUNNING)
883 bstp_initialization(sc);
884
885 return (0);
886 }
887
888 int
889 bridge_ioctl_gfd(struct bridge_softc *sc, void *arg)
890 {
891 struct ifbrparam *param = arg;
892
893 param->ifbrp_fwddelay = sc->sc_bridge_forward_delay >> 8;
894
895 return (0);
896 }
897
898 int
899 bridge_ioctl_sfd(struct bridge_softc *sc, void *arg)
900 {
901 struct ifbrparam *param = arg;
902
903 if (param->ifbrp_fwddelay == 0)
904 return (EINVAL);
905 sc->sc_bridge_forward_delay = param->ifbrp_fwddelay << 8;
906
907 if (sc->sc_if.if_flags & IFF_RUNNING)
908 bstp_initialization(sc);
909
910 return (0);
911 }
912
913 int
914 bridge_ioctl_gma(struct bridge_softc *sc, void *arg)
915 {
916 struct ifbrparam *param = arg;
917
918 param->ifbrp_maxage = sc->sc_bridge_max_age >> 8;
919
920 return (0);
921 }
922
923 int
924 bridge_ioctl_sma(struct bridge_softc *sc, void *arg)
925 {
926 struct ifbrparam *param = arg;
927
928 if (param->ifbrp_maxage == 0)
929 return (EINVAL);
930 sc->sc_bridge_max_age = param->ifbrp_maxage << 8;
931
932 if (sc->sc_if.if_flags & IFF_RUNNING)
933 bstp_initialization(sc);
934
935 return (0);
936 }
937
938 int
939 bridge_ioctl_sifprio(struct bridge_softc *sc, void *arg)
940 {
941 struct ifbreq *req = arg;
942 struct bridge_iflist *bif;
943
944 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
945 if (bif == NULL)
946 return (ENOENT);
947
948 bif->bif_priority = req->ifbr_priority;
949
950 if (sc->sc_if.if_flags & IFF_RUNNING)
951 bstp_initialization(sc);
952
953 return (0);
954 }
955
956 /*
957 * bridge_ifdetach:
958 *
959 * Detach an interface from a bridge. Called when a member
960 * interface is detaching.
961 */
962 void
963 bridge_ifdetach(struct ifnet *ifp)
964 {
965 struct bridge_softc *sc = ifp->if_bridge;
966 struct ifbreq breq;
967
968 memset(&breq, 0, sizeof(breq));
969 sprintf(breq.ifbr_ifsname, ifp->if_xname);
970
971 (void) bridge_ioctl_del(sc, &breq);
972 }
973
974 /*
975 * bridge_init:
976 *
977 * Initialize a bridge interface.
978 */
979 int
980 bridge_init(struct ifnet *ifp)
981 {
982 struct bridge_softc *sc = ifp->if_softc;
983
984 if (ifp->if_flags & IFF_RUNNING)
985 return (0);
986
987 callout_reset(&sc->sc_brcallout, bridge_rtable_prune_period * hz,
988 bridge_timer, sc);
989
990 ifp->if_flags |= IFF_RUNNING;
991 return (0);
992 }
993
994 /*
995 * bridge_stop:
996 *
997 * Stop the bridge interface.
998 */
999 void
1000 bridge_stop(struct ifnet *ifp, int disable)
1001 {
1002 struct bridge_softc *sc = ifp->if_softc;
1003
1004 if ((ifp->if_flags & IFF_RUNNING) == 0)
1005 return;
1006
1007 callout_stop(&sc->sc_brcallout);
1008 bstp_stop(sc);
1009
1010 IF_PURGE(&ifp->if_snd);
1011
1012 bridge_rtflush(sc, IFBF_FLUSHDYN);
1013
1014 ifp->if_flags &= ~IFF_RUNNING;
1015 }
1016
1017 /*
1018 * bridge_enqueue:
1019 *
1020 * Enqueue a packet on a bridge member interface.
1021 *
1022 * NOTE: must be called at splnet().
1023 */
1024 __inline void
1025 bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m)
1026 {
1027 ALTQ_DECL(struct altq_pktattr pktattr;)
1028 int len, error;
1029 short mflags;
1030
1031 #ifdef ALTQ
1032 /*
1033 * If ALTQ is enabled on the member interface, do
1034 * classification; the queueing discipline might
1035 * not require classification, but might require
1036 * the address family/header pointer in the pktattr.
1037 */
1038 if (ALTQ_IS_ENABLED(&dst_ifp->if_snd)) {
1039 /* XXX IFT_ETHER */
1040 altq_etherclassify(&dst_ifp->if_snd, m, &pktattr);
1041 }
1042 #endif /* ALTQ */
1043
1044 len = m->m_pkthdr.len;
1045 mflags = m->m_flags;
1046 IFQ_ENQUEUE(&dst_ifp->if_snd, m, &pktattr, error);
1047 if (error) {
1048 /* mbuf is already freed */
1049 sc->sc_if.if_oerrors++;
1050 return;
1051 }
1052
1053 sc->sc_if.if_opackets++;
1054 sc->sc_if.if_obytes += len;
1055
1056 dst_ifp->if_obytes += len;
1057
1058 if (mflags & M_MCAST) {
1059 sc->sc_if.if_omcasts++;
1060 dst_ifp->if_omcasts++;
1061 }
1062
1063 if ((dst_ifp->if_flags & IFF_OACTIVE) == 0)
1064 (*dst_ifp->if_start)(dst_ifp);
1065 }
1066
1067 /*
1068 * bridge_output:
1069 *
1070 * Send output from a bridge member interface. This
1071 * performs the bridging function for locally originated
1072 * packets.
1073 *
1074 * The mbuf has the Ethernet header already attached. We must
1075 * enqueue or free the mbuf before returning.
1076 */
1077 int
1078 bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
1079 struct rtentry *rt)
1080 {
1081 struct ether_header *eh;
1082 struct ifnet *dst_if;
1083 struct bridge_softc *sc;
1084 int s;
1085
1086 if (m->m_len < ETHER_HDR_LEN) {
1087 m = m_pullup(m, ETHER_HDR_LEN);
1088 if (m == NULL)
1089 return (0);
1090 }
1091
1092 eh = mtod(m, struct ether_header *);
1093 sc = ifp->if_bridge;
1094
1095 s = splnet();
1096
1097 /*
1098 * If bridge is down, but the original output interface is up,
1099 * go ahead and send out that interface. Otherwise, the packet
1100 * is dropped below.
1101 */
1102 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
1103 dst_if = ifp;
1104 goto sendunicast;
1105 }
1106
1107 /*
1108 * If the packet is a multicast, or we don't know a better way to
1109 * get there, send to all interfaces.
1110 */
1111 if (ETHER_IS_MULTICAST(eh->ether_dhost))
1112 dst_if = NULL;
1113 else
1114 dst_if = bridge_rtlookup(sc, eh->ether_dhost);
1115 if (dst_if == NULL) {
1116 struct bridge_iflist *bif;
1117 struct mbuf *mc;
1118 int used = 0;
1119
1120 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1121 dst_if = bif->bif_ifp;
1122 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1123 continue;
1124
1125 /*
1126 * If this is not the original output interface,
1127 * and the interface is participating in spanning
1128 * tree, make sure the port is in a state that
1129 * allows forwarding.
1130 */
1131 if (dst_if != ifp &&
1132 (bif->bif_flags & IFBIF_STP) != 0) {
1133 switch (bif->bif_state) {
1134 case BSTP_IFSTATE_BLOCKING:
1135 case BSTP_IFSTATE_LISTENING:
1136 case BSTP_IFSTATE_DISABLED:
1137 continue;
1138 }
1139 }
1140
1141 if (LIST_NEXT(bif, bif_next) == NULL) {
1142 used = 1;
1143 mc = m;
1144 } else {
1145 mc = m_copym(m, 0, M_COPYALL, M_NOWAIT);
1146 if (mc == NULL) {
1147 sc->sc_if.if_oerrors++;
1148 continue;
1149 }
1150 }
1151
1152 bridge_enqueue(sc, dst_if, mc);
1153 }
1154 if (used == 0)
1155 m_freem(m);
1156 splx(s);
1157 return (0);
1158 }
1159
1160 sendunicast:
1161 /*
1162 * XXX Spanning tree consideration here?
1163 */
1164
1165 if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1166 m_freem(m);
1167 splx(s);
1168 return (0);
1169 }
1170
1171 bridge_enqueue(sc, dst_if, m);
1172
1173 splx(s);
1174 return (0);
1175 }
1176
1177 /*
1178 * bridge_start:
1179 *
1180 * Start output on a bridge.
1181 *
1182 * NOTE: This routine should never be called in this implementation.
1183 */
1184 void
1185 bridge_start(struct ifnet *ifp)
1186 {
1187
1188 printf("%s: bridge_start() called\n", ifp->if_xname);
1189 }
1190
1191 /*
1192 * bridge_forward:
1193 *
1194 * The fowarding function of the bridge.
1195 */
1196 void
1197 bridge_forward(struct bridge_softc *sc, struct mbuf *m)
1198 {
1199 struct bridge_iflist *bif;
1200 struct ifnet *src_if, *dst_if;
1201 struct ether_header *eh;
1202
1203 src_if = m->m_pkthdr.rcvif;
1204
1205 sc->sc_if.if_ipackets++;
1206 sc->sc_if.if_ibytes += m->m_pkthdr.len;
1207
1208 /*
1209 * Look up the bridge_iflist.
1210 */
1211 bif = bridge_lookup_member_if(sc, src_if);
1212 if (bif == NULL) {
1213 /* Interface is not a bridge member (anymore?) */
1214 m_freem(m);
1215 return;
1216 }
1217
1218 if (bif->bif_flags & IFBIF_STP) {
1219 switch (bif->bif_state) {
1220 case BSTP_IFSTATE_BLOCKING:
1221 case BSTP_IFSTATE_LISTENING:
1222 case BSTP_IFSTATE_DISABLED:
1223 m_freem(m);
1224 return;
1225 }
1226 }
1227
1228 eh = mtod(m, struct ether_header *);
1229
1230 /*
1231 * If the interface is learning, and the source
1232 * address is valid and not multicast, record
1233 * the address.
1234 */
1235 if ((bif->bif_flags & IFBIF_LEARNING) != 0 &&
1236 ETHER_IS_MULTICAST(eh->ether_shost) == 0 &&
1237 (eh->ether_shost[0] == 0 &&
1238 eh->ether_shost[1] == 0 &&
1239 eh->ether_shost[2] == 0 &&
1240 eh->ether_shost[3] == 0 &&
1241 eh->ether_shost[4] == 0 &&
1242 eh->ether_shost[5] == 0) == 0) {
1243 (void) bridge_rtupdate(sc, eh->ether_shost,
1244 src_if, 0, IFBAF_DYNAMIC);
1245 }
1246
1247 if ((bif->bif_flags & IFBIF_STP) != 0 &&
1248 bif->bif_state == BSTP_IFSTATE_LEARNING) {
1249 m_freem(m);
1250 return;
1251 }
1252
1253 /*
1254 * At this point, the port either doesn't participate
1255 * in spanning tree or it is in the forwarding state.
1256 */
1257
1258 /*
1259 * If the packet is unicast, destined for someone on
1260 * "this" side of the bridge, drop it.
1261 */
1262 if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) {
1263 dst_if = bridge_rtlookup(sc, eh->ether_dhost);
1264 if (src_if == dst_if) {
1265 m_freem(m);
1266 return;
1267 }
1268 } else {
1269 /* ...forward it to all interfaces. */
1270 sc->sc_if.if_imcasts++;
1271 dst_if = NULL;
1272 }
1273
1274 if (dst_if == NULL) {
1275 bridge_broadcast(sc, src_if, m);
1276 return;
1277 }
1278
1279 /*
1280 * At this point, we're dealing with a unicast frame
1281 * going to a different interface.
1282 */
1283 if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1284 m_freem(m);
1285 return;
1286 }
1287 bif = bridge_lookup_member_if(sc, dst_if);
1288 if (bif == NULL) {
1289 /* Not a member of the bridge (anymore?) */
1290 m_freem(m);
1291 return;
1292 }
1293
1294 if (bif->bif_flags & IFBIF_STP) {
1295 switch (bif->bif_state) {
1296 case BSTP_IFSTATE_DISABLED:
1297 case BSTP_IFSTATE_BLOCKING:
1298 m_freem(m);
1299 return;
1300 }
1301 }
1302
1303 bridge_enqueue(sc, dst_if, m);
1304 }
1305
1306 /*
1307 * bridge_input:
1308 *
1309 * Receive input from a member interface. Queue the packet for
1310 * bridging if it is not for us.
1311 */
1312 struct mbuf *
1313 bridge_input(struct ifnet *ifp, struct mbuf *m)
1314 {
1315 struct bridge_softc *sc = ifp->if_bridge;
1316 struct bridge_iflist *bif;
1317 struct ether_header *eh;
1318 struct mbuf *mc;
1319
1320 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
1321 return (m);
1322
1323 bif = bridge_lookup_member_if(sc, ifp);
1324 if (bif == NULL)
1325 return (m);
1326
1327 eh = mtod(m, struct ether_header *);
1328
1329 if (m->m_flags & (M_BCAST|M_MCAST)) {
1330 /* Tap off 802.1D packets; they do not get forwarded. */
1331 if (memcmp(eh->ether_dhost, bstp_etheraddr,
1332 ETHER_ADDR_LEN) == 0) {
1333 m = bstp_input(ifp, m);
1334 if (m == NULL)
1335 return (NULL);
1336 }
1337
1338 if (bif->bif_flags & IFBIF_STP) {
1339 switch (bif->bif_state) {
1340 case BSTP_IFSTATE_BLOCKING:
1341 case BSTP_IFSTATE_LISTENING:
1342 case BSTP_IFSTATE_DISABLED:
1343 return (m);
1344 }
1345 }
1346
1347 /*
1348 * Make a deep copy of the packet and enqueue the copy
1349 * for bridge processing; return the original packet for
1350 * local processing.
1351 */
1352 mc = m_dup(m, 0, M_COPYALL, M_NOWAIT);
1353 if (mc == NULL)
1354 return (m);
1355
1356 /* Perform the bridge forwarding function with the copy. */
1357 bridge_forward(sc, mc);
1358
1359 /* Return the original packet for local processing. */
1360 return (m);
1361 }
1362
1363 if (bif->bif_flags & IFBIF_STP) {
1364 switch (bif->bif_state) {
1365 case BSTP_IFSTATE_BLOCKING:
1366 case BSTP_IFSTATE_LISTENING:
1367 case BSTP_IFSTATE_DISABLED:
1368 return (m);
1369 }
1370 }
1371
1372 /*
1373 * Unicast. Make sure it's not for us.
1374 */
1375 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1376 /* It is destined for us. */
1377 if (memcmp(LLADDR(bif->bif_ifp->if_sadl), eh->ether_dhost,
1378 ETHER_ADDR_LEN) == 0) {
1379 if (bif->bif_flags & IFBIF_LEARNING)
1380 (void) bridge_rtupdate(sc,
1381 eh->ether_shost, ifp, 0, IFBAF_DYNAMIC);
1382 m->m_pkthdr.rcvif = bif->bif_ifp;
1383 return (m);
1384 }
1385
1386 /* We just received a packet that we sent out. */
1387 if (memcmp(LLADDR(bif->bif_ifp->if_sadl), eh->ether_shost,
1388 ETHER_ADDR_LEN) == 0) {
1389 m_freem(m);
1390 return (NULL);
1391 }
1392 }
1393
1394 /* Perform the bridge forwarding function. */
1395 bridge_forward(sc, m);
1396
1397 return (NULL);
1398 }
1399
1400 /*
1401 * bridge_broadcast:
1402 *
1403 * Send a frame to all interfaces that are members of
1404 * the bridge, except for the one on which the packet
1405 * arrived.
1406 */
1407 void
1408 bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
1409 struct mbuf *m)
1410 {
1411 struct bridge_iflist *bif;
1412 struct mbuf *mc;
1413 struct ifnet *dst_if;
1414 int used = 0;
1415
1416 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1417 dst_if = bif->bif_ifp;
1418 if (dst_if == src_if)
1419 continue;
1420
1421 if (bif->bif_flags & IFBIF_STP) {
1422 switch (bif->bif_state) {
1423 case BSTP_IFSTATE_BLOCKING:
1424 case BSTP_IFSTATE_DISABLED:
1425 continue;
1426 }
1427 }
1428
1429 if ((bif->bif_flags & IFBIF_DISCOVER) == 0 &&
1430 (m->m_flags & (M_BCAST|M_MCAST)) == 0)
1431 continue;
1432
1433 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1434 continue;
1435
1436 if (LIST_NEXT(bif, bif_next) == NULL) {
1437 mc = m;
1438 used = 1;
1439 } else {
1440 mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
1441 if (mc == NULL) {
1442 sc->sc_if.if_oerrors++;
1443 continue;
1444 }
1445 }
1446
1447 bridge_enqueue(sc, dst_if, mc);
1448 }
1449 if (used == 0)
1450 m_freem(m);
1451 }
1452
1453 /*
1454 * bridge_rtupdate:
1455 *
1456 * Add a bridge routing entry.
1457 */
1458 int
1459 bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst,
1460 struct ifnet *dst_if, int setflags, uint8_t flags)
1461 {
1462 struct bridge_rtnode *brt;
1463 int error;
1464
1465 /*
1466 * A route for this destination might already exist. If so,
1467 * update it, otherwise create a new one.
1468 */
1469 if ((brt = bridge_rtnode_lookup(sc, dst)) == NULL) {
1470 if (sc->sc_brtcnt >= sc->sc_brtmax)
1471 return (ENOSPC);
1472
1473 /*
1474 * Allocate a new bridge forwarding node, and
1475 * initialize the expiration time and Ethernet
1476 * address.
1477 */
1478 brt = pool_get(&bridge_rtnode_pool, PR_NOWAIT);
1479 if (brt == NULL)
1480 return (ENOMEM);
1481
1482 memset(brt, 0, sizeof(*brt));
1483 brt->brt_expire = mono_time.tv_sec + sc->sc_brttimeout;
1484 brt->brt_flags = IFBAF_DYNAMIC;
1485 memcpy(brt->brt_addr, dst, ETHER_ADDR_LEN);
1486
1487 if ((error = bridge_rtnode_insert(sc, brt)) != 0) {
1488 pool_put(&bridge_rtnode_pool, brt);
1489 return (error);
1490 }
1491 }
1492
1493 brt->brt_ifp = dst_if;
1494 if (setflags) {
1495 brt->brt_flags = flags;
1496 brt->brt_expire = (flags & IFBAF_STATIC) ? 0 :
1497 mono_time.tv_sec + sc->sc_brttimeout;
1498 }
1499
1500 return (0);
1501 }
1502
1503 /*
1504 * bridge_rtlookup:
1505 *
1506 * Lookup the destination interface for an address.
1507 */
1508 struct ifnet *
1509 bridge_rtlookup(struct bridge_softc *sc, const uint8_t *addr)
1510 {
1511 struct bridge_rtnode *brt;
1512
1513 if ((brt = bridge_rtnode_lookup(sc, addr)) == NULL)
1514 return (NULL);
1515
1516 return (brt->brt_ifp);
1517 }
1518
1519 /*
1520 * bridge_rttrim:
1521 *
1522 * Trim the routine table so that we have a number
1523 * of routing entries less than or equal to the
1524 * maximum number.
1525 */
1526 void
1527 bridge_rttrim(struct bridge_softc *sc)
1528 {
1529 struct bridge_rtnode *brt, *nbrt;
1530
1531 /* Make sure we actually need to do this. */
1532 if (sc->sc_brtcnt <= sc->sc_brtmax)
1533 return;
1534
1535 /* Force an aging cycle; this might trim enough addresses. */
1536 bridge_rtage(sc);
1537 if (sc->sc_brtcnt <= sc->sc_brtmax)
1538 return;
1539
1540 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1541 nbrt = LIST_NEXT(brt, brt_list);
1542 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
1543 bridge_rtnode_destroy(sc, brt);
1544 if (sc->sc_brtcnt <= sc->sc_brtmax)
1545 return;
1546 }
1547 }
1548 }
1549
1550 /*
1551 * bridge_timer:
1552 *
1553 * Aging timer for the bridge.
1554 */
1555 void
1556 bridge_timer(void *arg)
1557 {
1558 struct bridge_softc *sc = arg;
1559 int s;
1560
1561 s = splnet();
1562 bridge_rtage(sc);
1563 splx(s);
1564
1565 if (sc->sc_if.if_flags & IFF_RUNNING)
1566 callout_reset(&sc->sc_brcallout,
1567 bridge_rtable_prune_period * hz, bridge_timer, sc);
1568 }
1569
1570 /*
1571 * bridge_rtage:
1572 *
1573 * Perform an aging cycle.
1574 */
1575 void
1576 bridge_rtage(struct bridge_softc *sc)
1577 {
1578 struct bridge_rtnode *brt, *nbrt;
1579
1580 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1581 nbrt = LIST_NEXT(brt, brt_list);
1582 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
1583 if (mono_time.tv_sec >= brt->brt_expire)
1584 bridge_rtnode_destroy(sc, brt);
1585 }
1586 }
1587 }
1588
1589 /*
1590 * bridge_rtflush:
1591 *
1592 * Remove all dynamic addresses from the bridge.
1593 */
1594 void
1595 bridge_rtflush(struct bridge_softc *sc, int full)
1596 {
1597 struct bridge_rtnode *brt, *nbrt;
1598
1599 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1600 nbrt = LIST_NEXT(brt, brt_list);
1601 if (full || (brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
1602 bridge_rtnode_destroy(sc, brt);
1603 }
1604 }
1605
1606 /*
1607 * bridge_rtdaddr:
1608 *
1609 * Remove an address from the table.
1610 */
1611 int
1612 bridge_rtdaddr(struct bridge_softc *sc, const uint8_t *addr)
1613 {
1614 struct bridge_rtnode *brt;
1615
1616 if ((brt = bridge_rtnode_lookup(sc, addr)) == NULL)
1617 return (ENOENT);
1618
1619 bridge_rtnode_destroy(sc, brt);
1620 return (0);
1621 }
1622
1623 /*
1624 * bridge_rtdelete:
1625 *
1626 * Delete routes to a speicifc member interface.
1627 */
1628 void
1629 bridge_rtdelete(struct bridge_softc *sc, struct ifnet *ifp)
1630 {
1631 struct bridge_rtnode *brt, *nbrt;
1632
1633 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1634 nbrt = LIST_NEXT(brt, brt_list);
1635 if (brt->brt_ifp == ifp)
1636 bridge_rtnode_destroy(sc, brt);
1637 }
1638 }
1639
1640 /*
1641 * bridge_rtable_init:
1642 *
1643 * Initialize the route table for this bridge.
1644 */
1645 int
1646 bridge_rtable_init(struct bridge_softc *sc)
1647 {
1648 int i;
1649
1650 sc->sc_rthash = malloc(sizeof(*sc->sc_rthash) * BRIDGE_RTHASH_SIZE,
1651 M_DEVBUF, M_NOWAIT);
1652 if (sc->sc_rthash == NULL)
1653 return (ENOMEM);
1654
1655 for (i = 0; i < BRIDGE_RTHASH_SIZE; i++)
1656 LIST_INIT(&sc->sc_rthash[i]);
1657
1658 #if NRND > 0
1659 rnd_extract_data(&sc->sc_rthash_key, sizeof(sc->sc_rthash_key),
1660 RND_EXTRACT_ANY);
1661 #else
1662 sc->sc_rthash_key = random();
1663 #endif /* NRND > 0 */
1664
1665 LIST_INIT(&sc->sc_rtlist);
1666
1667 return (0);
1668 }
1669
1670 /*
1671 * bridge_rtable_fini:
1672 *
1673 * Deconstruct the route table for this bridge.
1674 */
1675 void
1676 bridge_rtable_fini(struct bridge_softc *sc)
1677 {
1678
1679 free(sc->sc_rthash, M_DEVBUF);
1680 }
1681
1682 /*
1683 * The following hash function is adapted from "Hash Functions" by Bob Jenkins
1684 * ("Algorithm Alley", Dr. Dobbs Journal, September 1997).
1685 */
1686 #define mix(a, b, c) \
1687 do { \
1688 a -= b; a -= c; a ^= (c >> 13); \
1689 b -= c; b -= a; b ^= (a << 8); \
1690 c -= a; c -= b; c ^= (b >> 13); \
1691 a -= b; a -= c; a ^= (c >> 12); \
1692 b -= c; b -= a; b ^= (a << 16); \
1693 c -= a; c -= b; c ^= (b >> 5); \
1694 a -= b; a -= c; a ^= (c >> 3); \
1695 b -= c; b -= a; b ^= (a << 10); \
1696 c -= a; c -= b; c ^= (b >> 15); \
1697 } while (/*CONSTCOND*/0)
1698
1699 static __inline uint32_t
1700 bridge_rthash(struct bridge_softc *sc, const uint8_t *addr)
1701 {
1702 uint32_t a = 0x9e3779b9, b = 0x9e3779b9, c = sc->sc_rthash_key;
1703
1704 b += addr[5] << 8;
1705 b += addr[4];
1706 a += addr[3] << 24;
1707 a += addr[2] << 16;
1708 a += addr[1] << 8;
1709 a += addr[0];
1710
1711 mix(a, b, c);
1712
1713 return (c & BRIDGE_RTHASH_MASK);
1714 }
1715
1716 #undef mix
1717
1718 /*
1719 * bridge_rtnode_lookup:
1720 *
1721 * Look up a bridge route node for the specified destination.
1722 */
1723 struct bridge_rtnode *
1724 bridge_rtnode_lookup(struct bridge_softc *sc, const uint8_t *addr)
1725 {
1726 struct bridge_rtnode *brt;
1727 uint32_t hash;
1728 int dir;
1729
1730 hash = bridge_rthash(sc, addr);
1731 LIST_FOREACH(brt, &sc->sc_rthash[hash], brt_hash) {
1732 dir = memcmp(addr, brt->brt_addr, ETHER_ADDR_LEN);
1733 if (dir == 0)
1734 return (brt);
1735 if (dir > 0)
1736 return (NULL);
1737 }
1738
1739 return (NULL);
1740 }
1741
1742 /*
1743 * bridge_rtnode_insert:
1744 *
1745 * Insert the specified bridge node into the route table. We
1746 * assume the entry is not already in the table.
1747 */
1748 int
1749 bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt)
1750 {
1751 struct bridge_rtnode *lbrt;
1752 uint32_t hash;
1753 int dir;
1754
1755 hash = bridge_rthash(sc, brt->brt_addr);
1756
1757 lbrt = LIST_FIRST(&sc->sc_rthash[hash]);
1758 if (lbrt == NULL) {
1759 LIST_INSERT_HEAD(&sc->sc_rthash[hash], brt, brt_hash);
1760 goto out;
1761 }
1762
1763 do {
1764 dir = memcmp(brt->brt_addr, lbrt->brt_addr, ETHER_ADDR_LEN);
1765 if (dir == 0)
1766 return (EEXIST);
1767 if (dir > 0) {
1768 LIST_INSERT_BEFORE(lbrt, brt, brt_hash);
1769 goto out;
1770 }
1771 if (LIST_NEXT(lbrt, brt_hash) == NULL) {
1772 LIST_INSERT_AFTER(lbrt, brt, brt_hash);
1773 goto out;
1774 }
1775 lbrt = LIST_NEXT(lbrt, brt_hash);
1776 } while (lbrt != NULL);
1777
1778 #ifdef DIAGNOSTIC
1779 panic("bridge_rtnode_insert: impossible");
1780 #endif
1781
1782 out:
1783 LIST_INSERT_HEAD(&sc->sc_rtlist, brt, brt_list);
1784 sc->sc_brtcnt++;
1785
1786 return (0);
1787 }
1788
1789 /*
1790 * bridge_rtnode_destroy:
1791 *
1792 * Destroy a bridge rtnode.
1793 */
1794 void
1795 bridge_rtnode_destroy(struct bridge_softc *sc, struct bridge_rtnode *brt)
1796 {
1797
1798 LIST_REMOVE(brt, brt_hash);
1799
1800 LIST_REMOVE(brt, brt_list);
1801 sc->sc_brtcnt--;
1802 pool_put(&bridge_rtnode_pool, brt);
1803 }
1804