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