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