if_bridge.c revision 1.2.2.5 1 /* $NetBSD: if_bridge.c,v 1.2.2.5 2002/04/01 07:48:19 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.5 2002/04/01 07:48:19 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_PROPVIRTUAL; /* XXX 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->l_proc; /* 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 (ifs->if_bridge == sc)
561 return (EEXIST);
562
563 if (ifs->if_bridge != NULL)
564 return (EBUSY);
565
566 bif = malloc(sizeof(*bif), M_DEVBUF, M_NOWAIT);
567 if (bif == NULL)
568 return (ENOMEM);
569
570 switch (ifs->if_type) {
571 case IFT_ETHER:
572 /*
573 * Place the interface into promiscuous mode.
574 */
575 error = ifpromisc(ifs, 1);
576 if (error)
577 goto out;
578 break;
579
580 default:
581 error = EINVAL;
582 goto out;
583 }
584
585 bif->bif_ifp = ifs;
586 bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
587 bif->bif_priority = BSTP_DEFAULT_PORT_PRIORITY;
588 bif->bif_path_cost = BSTP_DEFAULT_PATH_COST;
589
590 ifs->if_bridge = sc;
591 LIST_INSERT_HEAD(&sc->sc_iflist, bif, bif_next);
592
593 if (sc->sc_if.if_flags & IFF_RUNNING)
594 bstp_initialization(sc);
595 else
596 bstp_stop(sc);
597
598 out:
599 if (error) {
600 if (bif != NULL)
601 free(bif, M_DEVBUF);
602 }
603 return (error);
604 }
605
606 int
607 bridge_ioctl_del(struct bridge_softc *sc, void *arg)
608 {
609 struct ifbreq *req = arg;
610 struct bridge_iflist *bif;
611
612 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
613 if (bif == NULL)
614 return (ENOENT);
615
616 bridge_delete_member(sc, bif);
617
618 return (0);
619 }
620
621 int
622 bridge_ioctl_gifflags(struct bridge_softc *sc, void *arg)
623 {
624 struct ifbreq *req = arg;
625 struct bridge_iflist *bif;
626
627 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
628 if (bif == NULL)
629 return (ENOENT);
630
631 req->ifbr_ifsflags = bif->bif_flags;
632 req->ifbr_state = bif->bif_state;
633 req->ifbr_priority = bif->bif_priority;
634 req->ifbr_portno = bif->bif_ifp->if_index & 0xff;
635
636 return (0);
637 }
638
639 int
640 bridge_ioctl_sifflags(struct bridge_softc *sc, void *arg)
641 {
642 struct ifbreq *req = arg;
643 struct bridge_iflist *bif;
644
645 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
646 if (bif == NULL)
647 return (ENOENT);
648
649 if (req->ifbr_ifsflags & IFBIF_STP) {
650 switch (bif->bif_ifp->if_type) {
651 case IFT_ETHER:
652 /* These can do spanning tree. */
653 break;
654
655 default:
656 /* Nothing else can. */
657 return (EINVAL);
658 }
659 }
660
661 bif->bif_flags = req->ifbr_ifsflags;
662
663 if (sc->sc_if.if_flags & IFF_RUNNING)
664 bstp_initialization(sc);
665
666 return (0);
667 }
668
669 int
670 bridge_ioctl_scache(struct bridge_softc *sc, void *arg)
671 {
672 struct ifbrparam *param = arg;
673
674 sc->sc_brtmax = param->ifbrp_csize;
675 bridge_rttrim(sc);
676
677 return (0);
678 }
679
680 int
681 bridge_ioctl_gcache(struct bridge_softc *sc, void *arg)
682 {
683 struct ifbrparam *param = arg;
684
685 param->ifbrp_csize = sc->sc_brtmax;
686
687 return (0);
688 }
689
690 int
691 bridge_ioctl_gifs(struct bridge_softc *sc, void *arg)
692 {
693 struct ifbifconf *bifc = arg;
694 struct bridge_iflist *bif;
695 struct ifbreq breq;
696 int count, len, error = 0;
697
698 count = 0;
699 LIST_FOREACH(bif, &sc->sc_iflist, bif_next)
700 count++;
701
702 if (bifc->ifbic_len == 0) {
703 bifc->ifbic_len = sizeof(breq) * count;
704 return (0);
705 }
706
707 count = 0;
708 len = bifc->ifbic_len;
709 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
710 if (len < sizeof(breq))
711 break;
712
713 strcpy(breq.ifbr_ifsname, bif->bif_ifp->if_xname);
714 breq.ifbr_ifsflags = bif->bif_flags;
715 breq.ifbr_state = bif->bif_state;
716 breq.ifbr_priority = bif->bif_priority;
717 breq.ifbr_portno = bif->bif_ifp->if_index & 0xff;
718 error = copyout(&breq, bifc->ifbic_req + count, sizeof(breq));
719 if (error)
720 break;
721 count++;
722 len -= sizeof(breq);
723 }
724
725 bifc->ifbic_len = sizeof(breq) * count;
726 return (error);
727 }
728
729 int
730 bridge_ioctl_rts(struct bridge_softc *sc, void *arg)
731 {
732 struct ifbaconf *bac = arg;
733 struct bridge_rtnode *brt;
734 struct ifbareq bareq;
735 int count = 0, error = 0, len;
736
737 if (bac->ifbac_len == 0)
738 return (0);
739
740 len = bac->ifbac_len;
741 LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) {
742 if (len < sizeof(bareq))
743 goto out;
744 strcpy(bareq.ifba_ifsname, brt->brt_ifp->if_xname);
745 memcpy(bareq.ifba_dst, brt->brt_addr, sizeof(brt->brt_addr));
746 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
747 bareq.ifba_expire = brt->brt_expire - mono_time.tv_sec;
748 else
749 bareq.ifba_expire = 0;
750 bareq.ifba_flags = brt->brt_flags;
751
752 error = copyout(&bareq, bac->ifbac_req + count, sizeof(bareq));
753 if (error)
754 goto out;
755 count++;
756 len -= sizeof(bareq);
757 }
758 out:
759 bac->ifbac_len = sizeof(bareq) * count;
760 return (error);
761 }
762
763 int
764 bridge_ioctl_saddr(struct bridge_softc *sc, void *arg)
765 {
766 struct ifbareq *req = arg;
767 struct bridge_iflist *bif;
768 int error;
769
770 bif = bridge_lookup_member(sc, req->ifba_ifsname);
771 if (bif == NULL)
772 return (ENOENT);
773
774 error = bridge_rtupdate(sc, req->ifba_dst, bif->bif_ifp, 1,
775 req->ifba_flags);
776
777 return (error);
778 }
779
780 int
781 bridge_ioctl_sto(struct bridge_softc *sc, void *arg)
782 {
783 struct ifbrparam *param = arg;
784
785 sc->sc_brttimeout = param->ifbrp_ctime;
786
787 return (0);
788 }
789
790 int
791 bridge_ioctl_gto(struct bridge_softc *sc, void *arg)
792 {
793 struct ifbrparam *param = arg;
794
795 param->ifbrp_ctime = sc->sc_brttimeout;
796
797 return (0);
798 }
799
800 int
801 bridge_ioctl_daddr(struct bridge_softc *sc, void *arg)
802 {
803 struct ifbareq *req = arg;
804
805 return (bridge_rtdaddr(sc, req->ifba_dst));
806 }
807
808 int
809 bridge_ioctl_flush(struct bridge_softc *sc, void *arg)
810 {
811 struct ifbreq *req = arg;
812
813 bridge_rtflush(sc, req->ifbr_ifsflags);
814
815 return (0);
816 }
817
818 int
819 bridge_ioctl_gpri(struct bridge_softc *sc, void *arg)
820 {
821 struct ifbrparam *param = arg;
822
823 param->ifbrp_prio = sc->sc_bridge_priority;
824
825 return (0);
826 }
827
828 int
829 bridge_ioctl_spri(struct bridge_softc *sc, void *arg)
830 {
831 struct ifbrparam *param = arg;
832
833 sc->sc_bridge_priority = param->ifbrp_prio;
834
835 if (sc->sc_if.if_flags & IFF_RUNNING)
836 bstp_initialization(sc);
837
838 return (0);
839 }
840
841 int
842 bridge_ioctl_ght(struct bridge_softc *sc, void *arg)
843 {
844 struct ifbrparam *param = arg;
845
846 param->ifbrp_hellotime = sc->sc_bridge_hello_time >> 8;
847
848 return (0);
849 }
850
851 int
852 bridge_ioctl_sht(struct bridge_softc *sc, void *arg)
853 {
854 struct ifbrparam *param = arg;
855
856 if (param->ifbrp_hellotime == 0)
857 return (EINVAL);
858 sc->sc_bridge_hello_time = param->ifbrp_hellotime << 8;
859
860 if (sc->sc_if.if_flags & IFF_RUNNING)
861 bstp_initialization(sc);
862
863 return (0);
864 }
865
866 int
867 bridge_ioctl_gfd(struct bridge_softc *sc, void *arg)
868 {
869 struct ifbrparam *param = arg;
870
871 param->ifbrp_fwddelay = sc->sc_bridge_forward_delay >> 8;
872
873 return (0);
874 }
875
876 int
877 bridge_ioctl_sfd(struct bridge_softc *sc, void *arg)
878 {
879 struct ifbrparam *param = arg;
880
881 if (param->ifbrp_fwddelay == 0)
882 return (EINVAL);
883 sc->sc_bridge_forward_delay = param->ifbrp_fwddelay << 8;
884
885 if (sc->sc_if.if_flags & IFF_RUNNING)
886 bstp_initialization(sc);
887
888 return (0);
889 }
890
891 int
892 bridge_ioctl_gma(struct bridge_softc *sc, void *arg)
893 {
894 struct ifbrparam *param = arg;
895
896 param->ifbrp_maxage = sc->sc_bridge_max_age >> 8;
897
898 return (0);
899 }
900
901 int
902 bridge_ioctl_sma(struct bridge_softc *sc, void *arg)
903 {
904 struct ifbrparam *param = arg;
905
906 if (param->ifbrp_maxage == 0)
907 return (EINVAL);
908 sc->sc_bridge_max_age = param->ifbrp_maxage << 8;
909
910 if (sc->sc_if.if_flags & IFF_RUNNING)
911 bstp_initialization(sc);
912
913 return (0);
914 }
915
916 int
917 bridge_ioctl_sifprio(struct bridge_softc *sc, void *arg)
918 {
919 struct ifbreq *req = arg;
920 struct bridge_iflist *bif;
921
922 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
923 if (bif == NULL)
924 return (ENOENT);
925
926 bif->bif_priority = req->ifbr_priority;
927
928 if (sc->sc_if.if_flags & IFF_RUNNING)
929 bstp_initialization(sc);
930
931 return (0);
932 }
933
934 /*
935 * bridge_ifdetach:
936 *
937 * Detach an interface from a bridge. Called when a member
938 * interface is detaching.
939 */
940 void
941 bridge_ifdetach(struct ifnet *ifp)
942 {
943 struct bridge_softc *sc = ifp->if_bridge;
944 struct ifbreq breq;
945
946 memset(&breq, 0, sizeof(breq));
947 sprintf(breq.ifbr_ifsname, ifp->if_xname);
948
949 (void) bridge_ioctl_del(sc, &breq);
950 }
951
952 /*
953 * bridge_init:
954 *
955 * Initialize a bridge interface.
956 */
957 int
958 bridge_init(struct ifnet *ifp)
959 {
960 struct bridge_softc *sc = ifp->if_softc;
961
962 if (ifp->if_flags & IFF_RUNNING)
963 return (0);
964
965 callout_reset(&sc->sc_brcallout, bridge_rtable_prune_period * hz,
966 bridge_timer, sc);
967
968 ifp->if_flags |= IFF_RUNNING;
969 return (0);
970 }
971
972 /*
973 * bridge_stop:
974 *
975 * Stop the bridge interface.
976 */
977 void
978 bridge_stop(struct ifnet *ifp, int disable)
979 {
980 struct bridge_softc *sc = ifp->if_softc;
981
982 if ((ifp->if_flags & IFF_RUNNING) == 0)
983 return;
984
985 callout_stop(&sc->sc_brcallout);
986 bstp_stop(sc);
987
988 IF_PURGE(&ifp->if_snd);
989
990 bridge_rtflush(sc, IFBF_FLUSHDYN);
991
992 ifp->if_flags &= ~IFF_RUNNING;
993 }
994
995 /*
996 * bridge_enqueue:
997 *
998 * Enqueue a packet on a bridge member interface.
999 *
1000 * NOTE: must be called at splnet().
1001 */
1002 __inline void
1003 bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m)
1004 {
1005 ALTQ_DECL(struct altq_pktattr pktattr;)
1006 int len, error;
1007 short mflags;
1008
1009 #ifdef ALTQ
1010 /*
1011 * If ALTQ is enabled on the member interface, do
1012 * classification; the queueing discipline might
1013 * not require classification, but might require
1014 * the address family/header pointer in the pktattr.
1015 */
1016 if (ALTQ_IS_ENABLED(&dst_ifp->if_snd)) {
1017 /* XXX IFT_ETHER */
1018 altq_etherclassify(&dst_ifp->if_snd, m, &pktattr);
1019 }
1020 #endif /* ALTQ */
1021
1022 len = m->m_pkthdr.len;
1023 mflags = m->m_flags;
1024 IFQ_ENQUEUE(&dst_ifp->if_snd, m, &pktattr, error);
1025 if (error) {
1026 /* mbuf is already freed */
1027 sc->sc_if.if_oerrors++;
1028 return;
1029 }
1030
1031 sc->sc_if.if_opackets++;
1032 sc->sc_if.if_obytes += len;
1033
1034 dst_ifp->if_obytes += len;
1035
1036 if (mflags & M_MCAST) {
1037 sc->sc_if.if_omcasts++;
1038 dst_ifp->if_omcasts++;
1039 }
1040
1041 if ((dst_ifp->if_flags & IFF_OACTIVE) == 0)
1042 (*dst_ifp->if_start)(dst_ifp);
1043 }
1044
1045 /*
1046 * bridge_output:
1047 *
1048 * Send output from a bridge member interface. This
1049 * performs the bridging function for locally originated
1050 * packets.
1051 *
1052 * The mbuf has the Ethernet header already attached. We must
1053 * enqueue or free the mbuf before returning.
1054 */
1055 int
1056 bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
1057 struct rtentry *rt)
1058 {
1059 struct ether_header *eh;
1060 struct ifnet *dst_if;
1061 struct bridge_softc *sc;
1062 int s;
1063
1064 if (m->m_len < ETHER_HDR_LEN) {
1065 m = m_pullup(m, ETHER_HDR_LEN);
1066 if (m == NULL)
1067 return (0);
1068 }
1069
1070 eh = mtod(m, struct ether_header *);
1071 sc = ifp->if_bridge;
1072
1073 s = splnet();
1074
1075 /*
1076 * If bridge is down, but the original output interface is up,
1077 * go ahead and send out that interface. Otherwise, the packet
1078 * is dropped below.
1079 */
1080 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
1081 dst_if = ifp;
1082 goto sendunicast;
1083 }
1084
1085 /*
1086 * If the packet is a multicast, or we don't know a better way to
1087 * get there, send to all interfaces.
1088 */
1089 if (ETHER_IS_MULTICAST(eh->ether_dhost))
1090 dst_if = NULL;
1091 else
1092 dst_if = bridge_rtlookup(sc, eh->ether_dhost);
1093 if (dst_if == NULL) {
1094 struct bridge_iflist *bif;
1095 struct mbuf *mc;
1096 int used = 0;
1097
1098 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1099 dst_if = bif->bif_ifp;
1100 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1101 continue;
1102
1103 /*
1104 * If this is not the original output interface,
1105 * and the interface is participating in spanning
1106 * tree, make sure the port is in a state that
1107 * allows forwarding.
1108 */
1109 if (dst_if != ifp &&
1110 (bif->bif_flags & IFBIF_STP) != 0) {
1111 switch (bif->bif_state) {
1112 case BSTP_IFSTATE_BLOCKING:
1113 case BSTP_IFSTATE_LISTENING:
1114 case BSTP_IFSTATE_DISABLED:
1115 continue;
1116 }
1117 }
1118
1119 if (LIST_NEXT(bif, bif_next) == NULL) {
1120 used = 1;
1121 mc = m;
1122 } else {
1123 mc = m_copym(m, 0, M_COPYALL, M_NOWAIT);
1124 if (mc == NULL) {
1125 sc->sc_if.if_oerrors++;
1126 continue;
1127 }
1128 }
1129
1130 bridge_enqueue(sc, dst_if, mc);
1131 }
1132 if (used == 0)
1133 m_freem(m);
1134 splx(s);
1135 return (0);
1136 }
1137
1138 sendunicast:
1139 /*
1140 * XXX Spanning tree consideration here?
1141 */
1142
1143 if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1144 m_freem(m);
1145 splx(s);
1146 return (0);
1147 }
1148
1149 bridge_enqueue(sc, dst_if, m);
1150
1151 splx(s);
1152 return (0);
1153 }
1154
1155 /*
1156 * bridge_start:
1157 *
1158 * Start output on a bridge.
1159 *
1160 * NOTE: This routine should never be called in this implementation.
1161 */
1162 void
1163 bridge_start(struct ifnet *ifp)
1164 {
1165
1166 printf("%s: bridge_start() called\n", ifp->if_xname);
1167 }
1168
1169 /*
1170 * bridge_forward:
1171 *
1172 * The fowarding function of the bridge.
1173 */
1174 void
1175 bridge_forward(struct bridge_softc *sc, struct mbuf *m)
1176 {
1177 struct bridge_iflist *bif;
1178 struct ifnet *src_if, *dst_if;
1179 struct ether_header *eh;
1180
1181 src_if = m->m_pkthdr.rcvif;
1182
1183 sc->sc_if.if_ipackets++;
1184 sc->sc_if.if_ibytes += m->m_pkthdr.len;
1185
1186 /*
1187 * Look up the bridge_iflist.
1188 * XXX This should be more efficient.
1189 */
1190 bif = bridge_lookup_member(sc, src_if->if_xname);
1191 if (bif == NULL) {
1192 /* Interface is not a bridge member (anymore?) */
1193 m_freem(m);
1194 return;
1195 }
1196
1197 if (bif->bif_flags & IFBIF_STP) {
1198 switch (bif->bif_state) {
1199 case BSTP_IFSTATE_BLOCKING:
1200 case BSTP_IFSTATE_LISTENING:
1201 case BSTP_IFSTATE_DISABLED:
1202 m_freem(m);
1203 return;
1204 }
1205 }
1206
1207 eh = mtod(m, struct ether_header *);
1208
1209 /*
1210 * If the interface is learning, and the source
1211 * address is valid and not multicast, record
1212 * the address.
1213 */
1214 if ((bif->bif_flags & IFBIF_LEARNING) != 0 &&
1215 ETHER_IS_MULTICAST(eh->ether_shost) == 0 &&
1216 (eh->ether_shost[0] == 0 &&
1217 eh->ether_shost[1] == 0 &&
1218 eh->ether_shost[2] == 0 &&
1219 eh->ether_shost[3] == 0 &&
1220 eh->ether_shost[4] == 0 &&
1221 eh->ether_shost[5] == 0) == 0) {
1222 (void) bridge_rtupdate(sc, eh->ether_shost,
1223 src_if, 0, IFBAF_DYNAMIC);
1224 }
1225
1226 if ((bif->bif_flags & IFBIF_STP) != 0 &&
1227 bif->bif_state == BSTP_IFSTATE_LEARNING) {
1228 m_freem(m);
1229 return;
1230 }
1231
1232 /*
1233 * At this point, the port either doesn't participate
1234 * in spanning tree or it is in the forwarding state.
1235 */
1236
1237 /*
1238 * If the packet is unicast, destined for someone on
1239 * "this" side of the bridge, drop it.
1240 */
1241 if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) {
1242 dst_if = bridge_rtlookup(sc, eh->ether_dhost);
1243 if (src_if == dst_if) {
1244 m_freem(m);
1245 return;
1246 }
1247 } else {
1248 /* ...forward it to all interfaces. */
1249 sc->sc_if.if_imcasts++;
1250 dst_if = NULL;
1251 }
1252
1253 if (dst_if == NULL) {
1254 bridge_broadcast(sc, src_if, m);
1255 return;
1256 }
1257
1258 /*
1259 * At this point, we're dealing with a unicast frame
1260 * going to a different interface.
1261 */
1262 if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1263 m_freem(m);
1264 return;
1265 }
1266 /* XXX This needs to be more efficient. */
1267 bif = bridge_lookup_member(sc, dst_if->if_xname);
1268 if (bif == NULL) {
1269 /* Not a member of the bridge (anymore?) */
1270 m_freem(m);
1271 return;
1272 }
1273
1274 if (bif->bif_flags & IFBIF_STP) {
1275 switch (bif->bif_state) {
1276 case BSTP_IFSTATE_DISABLED:
1277 case BSTP_IFSTATE_BLOCKING:
1278 m_freem(m);
1279 return;
1280 }
1281 }
1282
1283 bridge_enqueue(sc, dst_if, m);
1284 }
1285
1286 /*
1287 * bridge_input:
1288 *
1289 * Receive input from a member interface. Queue the packet for
1290 * bridging if it is not for us.
1291 */
1292 struct mbuf *
1293 bridge_input(struct ifnet *ifp, struct mbuf *m)
1294 {
1295 struct bridge_softc *sc = ifp->if_bridge;
1296 struct bridge_iflist *bif;
1297 struct ether_header *eh;
1298 struct mbuf *mc;
1299
1300 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
1301 return (m);
1302
1303 /* XXX This needs to be more efficient. */
1304 bif = bridge_lookup_member(sc, ifp->if_xname);
1305 if (bif == NULL)
1306 return (m);
1307
1308 eh = mtod(m, struct ether_header *);
1309
1310 if (m->m_flags & (M_BCAST|M_MCAST)) {
1311 /* Tap off 802.1D packets; they do not get forwarded. */
1312 if (memcmp(eh->ether_dhost, bstp_etheraddr,
1313 ETHER_ADDR_LEN) == 0) {
1314 m = bstp_input(ifp, m);
1315 if (m == NULL)
1316 return (NULL);
1317 }
1318
1319 if (bif->bif_flags & IFBIF_STP) {
1320 switch (bif->bif_state) {
1321 case BSTP_IFSTATE_BLOCKING:
1322 case BSTP_IFSTATE_LISTENING:
1323 case BSTP_IFSTATE_DISABLED:
1324 return (m);
1325 }
1326 }
1327
1328 /*
1329 * Make a deep copy of the packet and enqueue the copy
1330 * for bridge processing; return the original packet for
1331 * local processing.
1332 */
1333 mc = m_dup(m, 0, M_COPYALL, M_NOWAIT);
1334 if (mc == NULL)
1335 return (m);
1336
1337 /* Perform the bridge forwarding function with the copy. */
1338 bridge_forward(sc, mc);
1339
1340 /* Return the original packet for local processing. */
1341 return (m);
1342 }
1343
1344 if (bif->bif_flags & IFBIF_STP) {
1345 switch (bif->bif_state) {
1346 case BSTP_IFSTATE_BLOCKING:
1347 case BSTP_IFSTATE_LISTENING:
1348 case BSTP_IFSTATE_DISABLED:
1349 return (m);
1350 }
1351 }
1352
1353 /*
1354 * Unicast. Make sure it's not for us.
1355 */
1356 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1357 /* It is destined for us. */
1358 if (memcmp(LLADDR(bif->bif_ifp->if_sadl), eh->ether_dhost,
1359 ETHER_ADDR_LEN) == 0) {
1360 if (bif->bif_flags & IFBIF_LEARNING)
1361 (void) bridge_rtupdate(sc,
1362 eh->ether_shost, ifp, 0, IFBAF_DYNAMIC);
1363 m->m_pkthdr.rcvif = bif->bif_ifp;
1364 return (m);
1365 }
1366
1367 /* We just received a packet that we sent out. */
1368 if (memcmp(LLADDR(bif->bif_ifp->if_sadl), eh->ether_shost,
1369 ETHER_ADDR_LEN) == 0) {
1370 m_freem(m);
1371 return (NULL);
1372 }
1373 }
1374
1375 /* Perform the bridge forwarding function. */
1376 bridge_forward(sc, m);
1377
1378 return (NULL);
1379 }
1380
1381 /*
1382 * bridge_broadcast:
1383 *
1384 * Send a frame to all interfaces that are members of
1385 * the bridge, except for the one on which the packet
1386 * arrived.
1387 */
1388 void
1389 bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
1390 struct mbuf *m)
1391 {
1392 struct bridge_iflist *bif;
1393 struct mbuf *mc;
1394 struct ifnet *dst_if;
1395 int used = 0;
1396
1397 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1398 dst_if = bif->bif_ifp;
1399 if (dst_if == src_if)
1400 continue;
1401
1402 if (bif->bif_flags & IFBIF_STP) {
1403 switch (bif->bif_state) {
1404 case BSTP_IFSTATE_BLOCKING:
1405 case BSTP_IFSTATE_DISABLED:
1406 continue;
1407 }
1408 }
1409
1410 if ((bif->bif_flags & IFBIF_DISCOVER) == 0 &&
1411 (m->m_flags & (M_BCAST|M_MCAST)) == 0)
1412 continue;
1413
1414 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1415 continue;
1416
1417 if (LIST_NEXT(bif, bif_next) == NULL) {
1418 mc = m;
1419 used = 1;
1420 } else {
1421 mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
1422 if (mc == NULL) {
1423 sc->sc_if.if_oerrors++;
1424 continue;
1425 }
1426 }
1427
1428 bridge_enqueue(sc, dst_if, mc);
1429 }
1430 if (used == 0)
1431 m_freem(m);
1432 }
1433
1434 /*
1435 * bridge_rtupdate:
1436 *
1437 * Add a bridge routing entry.
1438 */
1439 int
1440 bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst,
1441 struct ifnet *dst_if, int setflags, uint8_t flags)
1442 {
1443 struct bridge_rtnode *brt;
1444 int error;
1445
1446 /*
1447 * A route for this destination might already exist. If so,
1448 * update it, otherwise create a new one.
1449 */
1450 if ((brt = bridge_rtnode_lookup(sc, dst)) == NULL) {
1451 if (sc->sc_brtcnt >= sc->sc_brtmax)
1452 return (ENOSPC);
1453
1454 /*
1455 * Allocate a new bridge forwarding node, and
1456 * initialize the expiration time and Ethernet
1457 * address.
1458 */
1459 brt = pool_get(&bridge_rtnode_pool, PR_NOWAIT);
1460 if (brt == NULL)
1461 return (ENOMEM);
1462
1463 memset(brt, 0, sizeof(*brt));
1464 brt->brt_expire = mono_time.tv_sec + sc->sc_brttimeout;
1465 brt->brt_flags = IFBAF_DYNAMIC;
1466 memcpy(brt->brt_addr, dst, ETHER_ADDR_LEN);
1467
1468 if ((error = bridge_rtnode_insert(sc, brt)) != 0) {
1469 pool_put(&bridge_rtnode_pool, brt);
1470 return (error);
1471 }
1472 }
1473
1474 brt->brt_ifp = dst_if;
1475 if (setflags) {
1476 brt->brt_flags = flags;
1477 brt->brt_expire = (flags & IFBAF_STATIC) ? 0 :
1478 mono_time.tv_sec + sc->sc_brttimeout;
1479 }
1480
1481 return (0);
1482 }
1483
1484 /*
1485 * bridge_rtlookup:
1486 *
1487 * Lookup the destination interface for an address.
1488 */
1489 struct ifnet *
1490 bridge_rtlookup(struct bridge_softc *sc, const uint8_t *addr)
1491 {
1492 struct bridge_rtnode *brt;
1493
1494 if ((brt = bridge_rtnode_lookup(sc, addr)) == NULL)
1495 return (NULL);
1496
1497 return (brt->brt_ifp);
1498 }
1499
1500 /*
1501 * bridge_rttrim:
1502 *
1503 * Trim the routine table so that we have a number
1504 * of routing entries less than or equal to the
1505 * maximum number.
1506 */
1507 void
1508 bridge_rttrim(struct bridge_softc *sc)
1509 {
1510 struct bridge_rtnode *brt, *nbrt;
1511
1512 /* Make sure we actually need to do this. */
1513 if (sc->sc_brtcnt <= sc->sc_brtmax)
1514 return;
1515
1516 /* Force an aging cycle; this might trim enough addresses. */
1517 bridge_rtage(sc);
1518 if (sc->sc_brtcnt <= sc->sc_brtmax)
1519 return;
1520
1521 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1522 nbrt = LIST_NEXT(brt, brt_list);
1523 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
1524 bridge_rtnode_destroy(sc, brt);
1525 if (sc->sc_brtcnt <= sc->sc_brtmax)
1526 return;
1527 }
1528 }
1529 }
1530
1531 /*
1532 * bridge_timer:
1533 *
1534 * Aging timer for the bridge.
1535 */
1536 void
1537 bridge_timer(void *arg)
1538 {
1539 struct bridge_softc *sc = arg;
1540 int s;
1541
1542 s = splnet();
1543 bridge_rtage(sc);
1544 splx(s);
1545
1546 if (sc->sc_if.if_flags & IFF_RUNNING)
1547 callout_reset(&sc->sc_brcallout,
1548 bridge_rtable_prune_period * hz, bridge_timer, sc);
1549 }
1550
1551 /*
1552 * bridge_rtage:
1553 *
1554 * Perform an aging cycle.
1555 */
1556 void
1557 bridge_rtage(struct bridge_softc *sc)
1558 {
1559 struct bridge_rtnode *brt, *nbrt;
1560
1561 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1562 nbrt = LIST_NEXT(brt, brt_list);
1563 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
1564 if (mono_time.tv_sec >= brt->brt_expire)
1565 bridge_rtnode_destroy(sc, brt);
1566 }
1567 }
1568 }
1569
1570 /*
1571 * bridge_rtflush:
1572 *
1573 * Remove all dynamic addresses from the bridge.
1574 */
1575 void
1576 bridge_rtflush(struct bridge_softc *sc, int full)
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 (full || (brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
1583 bridge_rtnode_destroy(sc, brt);
1584 }
1585 }
1586
1587 /*
1588 * bridge_rtdaddr:
1589 *
1590 * Remove an address from the table.
1591 */
1592 int
1593 bridge_rtdaddr(struct bridge_softc *sc, const uint8_t *addr)
1594 {
1595 struct bridge_rtnode *brt;
1596
1597 if ((brt = bridge_rtnode_lookup(sc, addr)) == NULL)
1598 return (ENOENT);
1599
1600 bridge_rtnode_destroy(sc, brt);
1601 return (0);
1602 }
1603
1604 /*
1605 * bridge_rtdelete:
1606 *
1607 * Delete routes to a speicifc member interface.
1608 */
1609 void
1610 bridge_rtdelete(struct bridge_softc *sc, struct ifnet *ifp)
1611 {
1612 struct bridge_rtnode *brt, *nbrt;
1613
1614 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1615 nbrt = LIST_NEXT(brt, brt_list);
1616 if (brt->brt_ifp == ifp)
1617 bridge_rtnode_destroy(sc, brt);
1618 }
1619 }
1620
1621 /*
1622 * bridge_rtable_init:
1623 *
1624 * Initialize the route table for this bridge.
1625 */
1626 int
1627 bridge_rtable_init(struct bridge_softc *sc)
1628 {
1629 int i;
1630
1631 sc->sc_rthash = malloc(sizeof(*sc->sc_rthash) * BRIDGE_RTHASH_SIZE,
1632 M_DEVBUF, M_NOWAIT);
1633 if (sc->sc_rthash == NULL)
1634 return (ENOMEM);
1635
1636 for (i = 0; i < BRIDGE_RTHASH_SIZE; i++)
1637 LIST_INIT(&sc->sc_rthash[i]);
1638
1639 #if NRND > 0
1640 rnd_extract_data(&sc->sc_rthash_key, sizeof(sc->sc_rthash_key),
1641 RND_EXTRACT_ANY);
1642 #else
1643 sc->sc_rthash_key = random();
1644 #endif /* NRND > 0 */
1645
1646 LIST_INIT(&sc->sc_rtlist);
1647
1648 return (0);
1649 }
1650
1651 /*
1652 * bridge_rtable_fini:
1653 *
1654 * Deconstruct the route table for this bridge.
1655 */
1656 void
1657 bridge_rtable_fini(struct bridge_softc *sc)
1658 {
1659
1660 free(sc->sc_rthash, M_DEVBUF);
1661 }
1662
1663 /*
1664 * The following hash function is adapted from "Hash Functions" by Bob Jenkins
1665 * ("Algorithm Alley", Dr. Dobbs Journal, September 1997).
1666 */
1667 #define mix(a, b, c) \
1668 do { \
1669 a -= b; a -= c; a ^= (c >> 13); \
1670 b -= c; b -= a; b ^= (a << 8); \
1671 c -= a; c -= b; c ^= (b >> 13); \
1672 a -= b; a -= c; a ^= (c >> 12); \
1673 b -= c; b -= a; b ^= (a << 16); \
1674 c -= a; c -= b; c ^= (b >> 5); \
1675 a -= b; a -= c; a ^= (c >> 3); \
1676 b -= c; b -= a; b ^= (a << 10); \
1677 c -= a; c -= b; c ^= (b >> 15); \
1678 } while (/*CONSTCOND*/0)
1679
1680 static __inline uint32_t
1681 bridge_rthash(struct bridge_softc *sc, const uint8_t *addr)
1682 {
1683 uint32_t a = 0x9e3779b9, b = 0x9e3779b9, c = sc->sc_rthash_key;
1684
1685 b += addr[5] << 8;
1686 b += addr[4];
1687 a += addr[3] << 24;
1688 a += addr[2] << 16;
1689 a += addr[1] << 8;
1690 a += addr[0];
1691
1692 mix(a, b, c);
1693
1694 return (c & BRIDGE_RTHASH_MASK);
1695 }
1696
1697 #undef mix
1698
1699 /*
1700 * bridge_rtnode_lookup:
1701 *
1702 * Look up a bridge route node for the specified destination.
1703 */
1704 struct bridge_rtnode *
1705 bridge_rtnode_lookup(struct bridge_softc *sc, const uint8_t *addr)
1706 {
1707 struct bridge_rtnode *brt;
1708 uint32_t hash;
1709 int dir;
1710
1711 hash = bridge_rthash(sc, addr);
1712 LIST_FOREACH(brt, &sc->sc_rthash[hash], brt_hash) {
1713 dir = memcmp(addr, brt->brt_addr, ETHER_ADDR_LEN);
1714 if (dir == 0)
1715 return (brt);
1716 if (dir > 0)
1717 return (NULL);
1718 }
1719
1720 return (NULL);
1721 }
1722
1723 /*
1724 * bridge_rtnode_insert:
1725 *
1726 * Insert the specified bridge node into the route table. We
1727 * assume the entry is not already in the table.
1728 */
1729 int
1730 bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt)
1731 {
1732 struct bridge_rtnode *lbrt;
1733 uint32_t hash;
1734 int dir;
1735
1736 hash = bridge_rthash(sc, brt->brt_addr);
1737
1738 lbrt = LIST_FIRST(&sc->sc_rthash[hash]);
1739 if (lbrt == NULL) {
1740 LIST_INSERT_HEAD(&sc->sc_rthash[hash], brt, brt_hash);
1741 goto out;
1742 }
1743
1744 do {
1745 dir = memcmp(brt->brt_addr, lbrt->brt_addr, ETHER_ADDR_LEN);
1746 if (dir == 0)
1747 return (EEXIST);
1748 if (dir > 0) {
1749 LIST_INSERT_BEFORE(lbrt, brt, brt_hash);
1750 goto out;
1751 }
1752 if (LIST_NEXT(lbrt, brt_hash) == NULL) {
1753 LIST_INSERT_AFTER(lbrt, brt, brt_hash);
1754 goto out;
1755 }
1756 lbrt = LIST_NEXT(lbrt, brt_hash);
1757 } while (lbrt != NULL);
1758
1759 #ifdef DIAGNOSTIC
1760 panic("bridge_rtnode_insert: impossible");
1761 #endif
1762
1763 out:
1764 LIST_INSERT_HEAD(&sc->sc_rtlist, brt, brt_list);
1765 sc->sc_brtcnt++;
1766
1767 return (0);
1768 }
1769
1770 /*
1771 * bridge_rtnode_destroy:
1772 *
1773 * Destroy a bridge rtnode.
1774 */
1775 void
1776 bridge_rtnode_destroy(struct bridge_softc *sc, struct bridge_rtnode *brt)
1777 {
1778
1779 LIST_REMOVE(brt, brt_hash);
1780
1781 LIST_REMOVE(brt, brt_list);
1782 sc->sc_brtcnt--;
1783 pool_put(&bridge_rtnode_pool, brt);
1784 }
1785