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