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