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