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