1 /* $OpenBSD: if_bpe.c,v 1.15 2021/01/19 07:30:19 mvs Exp $ */ 2 /* 3 * Copyright (c) 2018 David Gwynne <dlg@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include "bpfilter.h" 19 #include "pf.h" 20 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/kernel.h> 24 #include <sys/mbuf.h> 25 #include <sys/socket.h> 26 #include <sys/ioctl.h> 27 #include <sys/timeout.h> 28 #include <sys/pool.h> 29 #include <sys/tree.h> 30 31 #include <net/if.h> 32 #include <net/if_var.h> 33 #include <net/if_dl.h> 34 #include <net/if_media.h> 35 #include <net/if_types.h> 36 #include <net/rtable.h> 37 38 #include <netinet/in.h> 39 #include <netinet/if_ether.h> 40 41 /* for bridge stuff */ 42 #include <net/if_bridge.h> 43 44 45 #if NBPFILTER > 0 46 #include <net/bpf.h> 47 #endif 48 49 #include <net/if_bpe.h> 50 51 #define PBB_ITAG_ISID 0x00ffffff 52 #define PBB_ITAG_ISID_MIN 0x00000000 53 #define PBB_ITAG_ISID_MAX 0x00ffffff 54 #define PBB_ITAG_RES2 0x03000000 /* must be zero on input */ 55 #define PBB_ITAG_RES1 0x04000000 /* ignore on input */ 56 #define PBB_ITAG_UCA 0x08000000 57 #define PBB_ITAG_DEI 0x10000000 58 #define PBB_ITAG_PCP_SHIFT 29 59 #define PBB_ITAG_PCP_MASK (0x7U << PBB_ITAG_PCP_SHIFT) 60 61 #define BPE_BRIDGE_AGE_TMO 100 /* seconds */ 62 63 struct bpe_key { 64 int k_if; 65 uint32_t k_isid; 66 67 RBT_ENTRY(bpe_tunnel) k_entry; 68 }; 69 70 RBT_HEAD(bpe_tree, bpe_key); 71 72 static inline int bpe_cmp(const struct bpe_key *, const struct bpe_key *); 73 74 RBT_PROTOTYPE(bpe_tree, bpe_key, k_entry, bpe_cmp); 75 RBT_GENERATE(bpe_tree, bpe_key, k_entry, bpe_cmp); 76 77 struct bpe_entry { 78 struct ether_addr be_c_da; /* customer address - must be first */ 79 struct ether_addr be_b_da; /* bridge address */ 80 unsigned int be_type; 81 #define BPE_ENTRY_DYNAMIC 0 82 #define BPE_ENTRY_STATIC 1 83 struct refcnt be_refs; 84 time_t be_age; 85 86 RBT_ENTRY(bpe_entry) be_entry; 87 }; 88 89 RBT_HEAD(bpe_map, bpe_entry); 90 91 static inline int bpe_entry_cmp(const struct bpe_entry *, 92 const struct bpe_entry *); 93 94 RBT_PROTOTYPE(bpe_map, bpe_entry, be_entry, bpe_entry_cmp); 95 RBT_GENERATE(bpe_map, bpe_entry, be_entry, bpe_entry_cmp); 96 97 struct bpe_softc { 98 struct bpe_key sc_key; /* must be first */ 99 struct arpcom sc_ac; 100 int sc_txhprio; 101 int sc_rxhprio; 102 uint8_t sc_group[ETHER_ADDR_LEN]; 103 104 struct task sc_ltask; 105 struct task sc_dtask; 106 107 struct bpe_map sc_bridge_map; 108 struct rwlock sc_bridge_lock; 109 unsigned int sc_bridge_num; 110 unsigned int sc_bridge_max; 111 int sc_bridge_tmo; /* seconds */ 112 struct timeout sc_bridge_age; 113 }; 114 115 void bpeattach(int); 116 117 static int bpe_clone_create(struct if_clone *, int); 118 static int bpe_clone_destroy(struct ifnet *); 119 120 static void bpe_start(struct ifnet *); 121 static int bpe_ioctl(struct ifnet *, u_long, caddr_t); 122 static int bpe_media_get(struct bpe_softc *, struct ifreq *); 123 static int bpe_up(struct bpe_softc *); 124 static int bpe_down(struct bpe_softc *); 125 static int bpe_multi(struct bpe_softc *, struct ifnet *, u_long); 126 static int bpe_set_vnetid(struct bpe_softc *, const struct ifreq *); 127 static void bpe_set_group(struct bpe_softc *, uint32_t); 128 static int bpe_set_parent(struct bpe_softc *, const struct if_parent *); 129 static int bpe_get_parent(struct bpe_softc *, struct if_parent *); 130 static int bpe_del_parent(struct bpe_softc *); 131 static void bpe_link_hook(void *); 132 static void bpe_link_state(struct bpe_softc *, u_char, uint64_t); 133 static void bpe_detach_hook(void *); 134 135 static void bpe_input_map(struct bpe_softc *, 136 const uint8_t *, const uint8_t *); 137 static void bpe_bridge_age(void *); 138 139 static struct if_clone bpe_cloner = 140 IF_CLONE_INITIALIZER("bpe", bpe_clone_create, bpe_clone_destroy); 141 142 static struct bpe_tree bpe_interfaces = RBT_INITIALIZER(); 143 static struct rwlock bpe_lock = RWLOCK_INITIALIZER("bpeifs"); 144 static struct pool bpe_entry_pool; 145 146 void 147 bpeattach(int count) 148 { 149 if_clone_attach(&bpe_cloner); 150 } 151 152 static int 153 bpe_clone_create(struct if_clone *ifc, int unit) 154 { 155 struct bpe_softc *sc; 156 struct ifnet *ifp; 157 158 if (bpe_entry_pool.pr_size == 0) { 159 pool_init(&bpe_entry_pool, sizeof(struct bpe_entry), 0, 160 IPL_NONE, 0, "bpepl", NULL); 161 } 162 163 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); 164 ifp = &sc->sc_ac.ac_if; 165 166 snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", 167 ifc->ifc_name, unit); 168 169 sc->sc_key.k_if = 0; 170 sc->sc_key.k_isid = 0; 171 bpe_set_group(sc, 0); 172 173 sc->sc_txhprio = IF_HDRPRIO_PACKET; 174 sc->sc_rxhprio = IF_HDRPRIO_OUTER; 175 176 task_set(&sc->sc_ltask, bpe_link_hook, sc); 177 task_set(&sc->sc_dtask, bpe_detach_hook, sc); 178 179 rw_init(&sc->sc_bridge_lock, "bpebr"); 180 RBT_INIT(bpe_map, &sc->sc_bridge_map); 181 sc->sc_bridge_num = 0; 182 sc->sc_bridge_max = 100; /* XXX */ 183 sc->sc_bridge_tmo = 240; 184 timeout_set_proc(&sc->sc_bridge_age, bpe_bridge_age, sc); 185 186 ifp->if_softc = sc; 187 ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN; 188 ifp->if_ioctl = bpe_ioctl; 189 ifp->if_start = bpe_start; 190 ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST; 191 ifp->if_xflags = IFXF_CLONED; 192 ether_fakeaddr(ifp); 193 194 if_counters_alloc(ifp); 195 if_attach(ifp); 196 ether_ifattach(ifp); 197 198 return (0); 199 } 200 201 static int 202 bpe_clone_destroy(struct ifnet *ifp) 203 { 204 struct bpe_softc *sc = ifp->if_softc; 205 206 NET_LOCK(); 207 if (ISSET(ifp->if_flags, IFF_RUNNING)) 208 bpe_down(sc); 209 NET_UNLOCK(); 210 211 ether_ifdetach(ifp); 212 if_detach(ifp); 213 214 free(sc, M_DEVBUF, sizeof(*sc)); 215 216 return (0); 217 } 218 219 static inline int 220 bpe_entry_valid(struct bpe_softc *sc, const struct bpe_entry *be) 221 { 222 time_t diff; 223 224 if (be == NULL) 225 return (0); 226 227 if (be->be_type == BPE_ENTRY_STATIC) 228 return (1); 229 230 diff = getuptime() - be->be_age; 231 if (diff < sc->sc_bridge_tmo) 232 return (1); 233 234 return (0); 235 } 236 237 static void 238 bpe_start(struct ifnet *ifp) 239 { 240 struct bpe_softc *sc = ifp->if_softc; 241 struct ifnet *ifp0; 242 struct mbuf *m0, *m; 243 struct ether_header *ceh; 244 struct ether_header *beh; 245 uint32_t itag, *itagp; 246 int hlen = sizeof(*beh) + sizeof(*itagp); 247 #if NBPFILTER > 0 248 caddr_t if_bpf; 249 #endif 250 int txprio; 251 uint8_t prio; 252 253 ifp0 = if_get(sc->sc_key.k_if); 254 if (ifp0 == NULL || !ISSET(ifp0->if_flags, IFF_RUNNING)) { 255 ifq_purge(&ifp->if_snd); 256 goto done; 257 } 258 259 txprio = sc->sc_txhprio; 260 261 while ((m0 = ifq_dequeue(&ifp->if_snd)) != NULL) { 262 #if NBPFILTER > 0 263 if_bpf = ifp->if_bpf; 264 if (if_bpf) 265 bpf_mtap_ether(if_bpf, m0, BPF_DIRECTION_OUT); 266 #endif 267 268 ceh = mtod(m0, struct ether_header *); 269 270 /* force prepend of a whole mbuf because of alignment */ 271 m = m_get(M_DONTWAIT, m0->m_type); 272 if (m == NULL) { 273 m_freem(m0); 274 continue; 275 } 276 277 M_MOVE_PKTHDR(m, m0); 278 m->m_next = m0; 279 280 m_align(m, 0); 281 m->m_len = 0; 282 283 m = m_prepend(m, hlen, M_DONTWAIT); 284 if (m == NULL) 285 continue; 286 287 beh = mtod(m, struct ether_header *); 288 289 if (ETHER_IS_BROADCAST(ceh->ether_dhost)) { 290 memcpy(beh->ether_dhost, sc->sc_group, 291 sizeof(beh->ether_dhost)); 292 } else { 293 struct bpe_entry *be; 294 295 rw_enter_read(&sc->sc_bridge_lock); 296 be = RBT_FIND(bpe_map, &sc->sc_bridge_map, 297 (struct bpe_entry *)ceh->ether_dhost); 298 if (bpe_entry_valid(sc, be)) { 299 memcpy(beh->ether_dhost, &be->be_b_da, 300 sizeof(beh->ether_dhost)); 301 } else { 302 /* "flood" to unknown hosts */ 303 memcpy(beh->ether_dhost, sc->sc_group, 304 sizeof(beh->ether_dhost)); 305 } 306 rw_exit_read(&sc->sc_bridge_lock); 307 } 308 309 memcpy(beh->ether_shost, ((struct arpcom *)ifp0)->ac_enaddr, 310 sizeof(beh->ether_shost)); 311 beh->ether_type = htons(ETHERTYPE_PBB); 312 313 prio = (txprio == IF_HDRPRIO_PACKET) ? 314 m->m_pkthdr.pf.prio : txprio; 315 316 itag = sc->sc_key.k_isid; 317 itag |= prio << PBB_ITAG_PCP_SHIFT; 318 itagp = (uint32_t *)(beh + 1); 319 320 htobem32(itagp, itag); 321 322 if_enqueue(ifp0, m); 323 } 324 325 done: 326 if_put(ifp0); 327 } 328 329 static void 330 bpe_bridge_age(void *arg) 331 { 332 struct bpe_softc *sc = arg; 333 struct bpe_entry *be, *nbe; 334 time_t diff; 335 336 timeout_add_sec(&sc->sc_bridge_age, BPE_BRIDGE_AGE_TMO); 337 338 rw_enter_write(&sc->sc_bridge_lock); 339 RBT_FOREACH_SAFE(be, bpe_map, &sc->sc_bridge_map, nbe) { 340 if (be->be_type != BPE_ENTRY_DYNAMIC) 341 continue; 342 343 diff = getuptime() - be->be_age; 344 if (diff < sc->sc_bridge_tmo) 345 continue; 346 347 sc->sc_bridge_num--; 348 RBT_REMOVE(bpe_map, &sc->sc_bridge_map, be); 349 if (refcnt_rele(&be->be_refs)) 350 pool_put(&bpe_entry_pool, be); 351 } 352 rw_exit_write(&sc->sc_bridge_lock); 353 } 354 355 static int 356 bpe_rtfind(struct bpe_softc *sc, struct ifbaconf *baconf) 357 { 358 struct ifnet *ifp = &sc->sc_ac.ac_if; 359 struct bpe_entry *be; 360 struct ifbareq bareq; 361 caddr_t uaddr, end; 362 int error; 363 time_t age; 364 struct sockaddr_dl *sdl; 365 366 if (baconf->ifbac_len == 0) { 367 /* single read is atomic */ 368 baconf->ifbac_len = sc->sc_bridge_num * sizeof(bareq); 369 return (0); 370 } 371 372 uaddr = baconf->ifbac_buf; 373 end = uaddr + baconf->ifbac_len; 374 375 rw_enter_read(&sc->sc_bridge_lock); 376 RBT_FOREACH(be, bpe_map, &sc->sc_bridge_map) { 377 if (uaddr >= end) 378 break; 379 380 memcpy(bareq.ifba_name, ifp->if_xname, 381 sizeof(bareq.ifba_name)); 382 memcpy(bareq.ifba_ifsname, ifp->if_xname, 383 sizeof(bareq.ifba_ifsname)); 384 memcpy(&bareq.ifba_dst, &be->be_c_da, 385 sizeof(bareq.ifba_dst)); 386 387 memset(&bareq.ifba_dstsa, 0, sizeof(bareq.ifba_dstsa)); 388 389 bzero(&bareq.ifba_dstsa, sizeof(bareq.ifba_dstsa)); 390 sdl = (struct sockaddr_dl *)&bareq.ifba_dstsa; 391 sdl->sdl_len = sizeof(sdl); 392 sdl->sdl_family = AF_LINK; 393 sdl->sdl_index = 0; 394 sdl->sdl_type = IFT_ETHER; 395 sdl->sdl_nlen = 0; 396 sdl->sdl_alen = sizeof(be->be_b_da); 397 CTASSERT(sizeof(sdl->sdl_data) >= sizeof(be->be_b_da)); 398 memcpy(sdl->sdl_data, &be->be_b_da, sizeof(be->be_b_da)); 399 400 switch (be->be_type) { 401 case BPE_ENTRY_DYNAMIC: 402 age = getuptime() - be->be_age; 403 bareq.ifba_age = MIN(age, 0xff); 404 bareq.ifba_flags = IFBAF_DYNAMIC; 405 break; 406 case BPE_ENTRY_STATIC: 407 bareq.ifba_age = 0; 408 bareq.ifba_flags = IFBAF_STATIC; 409 break; 410 } 411 412 error = copyout(&bareq, uaddr, sizeof(bareq)); 413 if (error != 0) { 414 rw_exit_read(&sc->sc_bridge_lock); 415 return (error); 416 } 417 418 uaddr += sizeof(bareq); 419 } 420 baconf->ifbac_len = sc->sc_bridge_num * sizeof(bareq); 421 rw_exit_read(&sc->sc_bridge_lock); 422 423 return (0); 424 } 425 426 static void 427 bpe_flush_map(struct bpe_softc *sc, uint32_t flags) 428 { 429 struct bpe_entry *be, *nbe; 430 431 rw_enter_write(&sc->sc_bridge_lock); 432 RBT_FOREACH_SAFE(be, bpe_map, &sc->sc_bridge_map, nbe) { 433 if (flags == IFBF_FLUSHDYN && 434 be->be_type != BPE_ENTRY_DYNAMIC) 435 continue; 436 437 RBT_REMOVE(bpe_map, &sc->sc_bridge_map, be); 438 if (refcnt_rele(&be->be_refs)) 439 pool_put(&bpe_entry_pool, be); 440 } 441 rw_exit_write(&sc->sc_bridge_lock); 442 } 443 444 static int 445 bpe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 446 { 447 struct bpe_softc *sc = ifp->if_softc; 448 struct ifreq *ifr = (struct ifreq *)data; 449 struct ifbrparam *bparam = (struct ifbrparam *)data; 450 int error = 0; 451 452 switch (cmd) { 453 case SIOCSIFFLAGS: 454 if (ISSET(ifp->if_flags, IFF_UP)) { 455 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 456 error = bpe_up(sc); 457 else 458 error = 0; 459 } else { 460 if (ISSET(ifp->if_flags, IFF_RUNNING)) 461 error = bpe_down(sc); 462 } 463 break; 464 465 case SIOCSVNETID: 466 error = bpe_set_vnetid(sc, ifr); 467 break; 468 case SIOCGVNETID: 469 ifr->ifr_vnetid = sc->sc_key.k_isid; 470 break; 471 472 case SIOCSIFPARENT: 473 error = bpe_set_parent(sc, (struct if_parent *)data); 474 break; 475 case SIOCGIFPARENT: 476 error = bpe_get_parent(sc, (struct if_parent *)data); 477 break; 478 case SIOCDIFPARENT: 479 error = bpe_del_parent(sc); 480 break; 481 482 case SIOCSTXHPRIO: 483 error = if_txhprio_l2_check(ifr->ifr_hdrprio); 484 if (error != 0) 485 break; 486 487 sc->sc_txhprio = ifr->ifr_hdrprio; 488 break; 489 case SIOCGTXHPRIO: 490 ifr->ifr_hdrprio = sc->sc_txhprio; 491 break; 492 493 case SIOCSRXHPRIO: 494 error = if_rxhprio_l2_check(ifr->ifr_hdrprio); 495 if (error != 0) 496 break; 497 498 sc->sc_rxhprio = ifr->ifr_hdrprio; 499 break; 500 case SIOCGRXHPRIO: 501 ifr->ifr_hdrprio = sc->sc_rxhprio; 502 break; 503 504 case SIOCGIFMEDIA: 505 error = bpe_media_get(sc, ifr); 506 break; 507 508 case SIOCBRDGSCACHE: 509 error = suser(curproc); 510 if (error != 0) 511 break; 512 513 if (bparam->ifbrp_csize < 1) { 514 error = EINVAL; 515 break; 516 } 517 518 /* commit */ 519 sc->sc_bridge_max = bparam->ifbrp_csize; 520 break; 521 case SIOCBRDGGCACHE: 522 bparam->ifbrp_csize = sc->sc_bridge_max; 523 break; 524 525 case SIOCBRDGSTO: 526 error = suser(curproc); 527 if (error != 0) 528 break; 529 530 if (bparam->ifbrp_ctime < 8 || 531 bparam->ifbrp_ctime > 3600) { 532 error = EINVAL; 533 break; 534 } 535 sc->sc_bridge_tmo = bparam->ifbrp_ctime; 536 break; 537 case SIOCBRDGGTO: 538 bparam->ifbrp_ctime = sc->sc_bridge_tmo; 539 break; 540 541 case SIOCBRDGRTS: 542 error = bpe_rtfind(sc, (struct ifbaconf *)data); 543 break; 544 case SIOCBRDGFLUSH: 545 error = suser(curproc); 546 if (error != 0) 547 break; 548 549 bpe_flush_map(sc, 550 ((struct ifbreq *)data)->ifbr_ifsflags); 551 break; 552 553 default: 554 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); 555 break; 556 } 557 558 return (error); 559 } 560 561 static int 562 bpe_media_get(struct bpe_softc *sc, struct ifreq *ifr) 563 { 564 struct ifnet *ifp0; 565 int error; 566 567 ifp0 = if_get(sc->sc_key.k_if); 568 if (ifp0 != NULL) 569 error = (*ifp0->if_ioctl)(ifp0, SIOCGIFMEDIA, (caddr_t)ifr); 570 else 571 error = ENOTTY; 572 if_put(ifp0); 573 574 return (error); 575 } 576 577 static int 578 bpe_up(struct bpe_softc *sc) 579 { 580 struct ifnet *ifp = &sc->sc_ac.ac_if; 581 struct ifnet *ifp0; 582 struct bpe_softc *osc; 583 int error = 0; 584 u_int hardmtu; 585 u_int hlen = sizeof(struct ether_header) + sizeof(uint32_t); 586 587 KASSERT(!ISSET(ifp->if_flags, IFF_RUNNING)); 588 NET_ASSERT_LOCKED(); 589 590 ifp0 = if_get(sc->sc_key.k_if); 591 if (ifp0 == NULL) 592 return (ENXIO); 593 594 /* check again if bpe will work on top of the parent */ 595 if (ifp0->if_type != IFT_ETHER) { 596 error = EPROTONOSUPPORT; 597 goto put; 598 } 599 600 hardmtu = ifp0->if_hardmtu; 601 if (hardmtu < hlen) { 602 error = ENOBUFS; 603 goto put; 604 } 605 hardmtu -= hlen; 606 if (ifp->if_mtu > hardmtu) { 607 error = ENOBUFS; 608 goto put; 609 } 610 611 /* parent is fine, let's prepare the bpe to handle packets */ 612 ifp->if_hardmtu = hardmtu; 613 SET(ifp->if_flags, ifp0->if_flags & IFF_SIMPLEX); 614 615 /* commit the interface */ 616 error = rw_enter(&bpe_lock, RW_WRITE | RW_INTR); 617 if (error != 0) 618 goto scrub; 619 620 osc = (struct bpe_softc *)RBT_INSERT(bpe_tree, &bpe_interfaces, 621 (struct bpe_key *)sc); 622 rw_exit(&bpe_lock); 623 624 if (osc != NULL) { 625 error = EADDRINUSE; 626 goto scrub; 627 } 628 629 if (bpe_multi(sc, ifp0, SIOCADDMULTI) != 0) { 630 error = ENOTCONN; 631 goto remove; 632 } 633 634 /* Register callback for physical link state changes */ 635 if_linkstatehook_add(ifp0, &sc->sc_ltask); 636 637 /* Register callback if parent wants to unregister */ 638 if_detachhook_add(ifp0, &sc->sc_dtask); 639 640 /* we're running now */ 641 SET(ifp->if_flags, IFF_RUNNING); 642 bpe_link_state(sc, ifp0->if_link_state, ifp0->if_baudrate); 643 644 if_put(ifp0); 645 646 timeout_add_sec(&sc->sc_bridge_age, BPE_BRIDGE_AGE_TMO); 647 648 return (0); 649 650 remove: 651 rw_enter(&bpe_lock, RW_WRITE); 652 RBT_REMOVE(bpe_tree, &bpe_interfaces, (struct bpe_key *)sc); 653 rw_exit(&bpe_lock); 654 scrub: 655 CLR(ifp->if_flags, IFF_SIMPLEX); 656 ifp->if_hardmtu = 0xffff; 657 put: 658 if_put(ifp0); 659 660 return (error); 661 } 662 663 static int 664 bpe_down(struct bpe_softc *sc) 665 { 666 struct ifnet *ifp = &sc->sc_ac.ac_if; 667 struct ifnet *ifp0; 668 669 NET_ASSERT_LOCKED(); 670 671 CLR(ifp->if_flags, IFF_RUNNING); 672 673 ifp0 = if_get(sc->sc_key.k_if); 674 if (ifp0 != NULL) { 675 if_detachhook_del(ifp0, &sc->sc_dtask); 676 if_linkstatehook_del(ifp0, &sc->sc_ltask); 677 bpe_multi(sc, ifp0, SIOCDELMULTI); 678 } 679 if_put(ifp0); 680 681 rw_enter(&bpe_lock, RW_WRITE); 682 RBT_REMOVE(bpe_tree, &bpe_interfaces, (struct bpe_key *)sc); 683 rw_exit(&bpe_lock); 684 685 CLR(ifp->if_flags, IFF_SIMPLEX); 686 ifp->if_hardmtu = 0xffff; 687 688 return (0); 689 } 690 691 static int 692 bpe_multi(struct bpe_softc *sc, struct ifnet *ifp0, u_long cmd) 693 { 694 struct ifreq ifr; 695 struct sockaddr *sa; 696 697 /* make it convincing */ 698 CTASSERT(sizeof(ifr.ifr_name) == sizeof(ifp0->if_xname)); 699 memcpy(ifr.ifr_name, ifp0->if_xname, sizeof(ifr.ifr_name)); 700 701 sa = &ifr.ifr_addr; 702 CTASSERT(sizeof(sa->sa_data) >= sizeof(sc->sc_group)); 703 704 sa->sa_family = AF_UNSPEC; 705 memcpy(sa->sa_data, sc->sc_group, sizeof(sc->sc_group)); 706 707 return ((*ifp0->if_ioctl)(ifp0, cmd, (caddr_t)&ifr)); 708 } 709 710 static void 711 bpe_set_group(struct bpe_softc *sc, uint32_t isid) 712 { 713 uint8_t *group = sc->sc_group; 714 715 group[0] = 0x01; 716 group[1] = 0x1e; 717 group[2] = 0x83; 718 group[3] = isid >> 16; 719 group[4] = isid >> 8; 720 group[5] = isid >> 0; 721 } 722 723 static int 724 bpe_set_vnetid(struct bpe_softc *sc, const struct ifreq *ifr) 725 { 726 struct ifnet *ifp = &sc->sc_ac.ac_if; 727 uint32_t isid; 728 729 if (ifr->ifr_vnetid < PBB_ITAG_ISID_MIN || 730 ifr->ifr_vnetid > PBB_ITAG_ISID_MAX) 731 return (EINVAL); 732 733 isid = ifr->ifr_vnetid; 734 if (isid == sc->sc_key.k_isid) 735 return (0); 736 737 if (ISSET(ifp->if_flags, IFF_RUNNING)) 738 return (EBUSY); 739 740 /* commit */ 741 sc->sc_key.k_isid = isid; 742 bpe_set_group(sc, isid); 743 bpe_flush_map(sc, IFBF_FLUSHALL); 744 745 return (0); 746 } 747 748 static int 749 bpe_set_parent(struct bpe_softc *sc, const struct if_parent *p) 750 { 751 struct ifnet *ifp = &sc->sc_ac.ac_if; 752 struct ifnet *ifp0; 753 int error = 0; 754 755 ifp0 = if_unit(p->ifp_parent); 756 if (ifp0 == NULL) 757 return (ENXIO); 758 759 if (ifp0->if_type != IFT_ETHER) { 760 error = ENXIO; 761 goto put; 762 } 763 764 if (ifp0->if_index == sc->sc_key.k_if) 765 goto put; 766 767 if (ISSET(ifp->if_flags, IFF_RUNNING)) { 768 error = EBUSY; 769 goto put; 770 } 771 772 /* commit */ 773 sc->sc_key.k_if = ifp0->if_index; 774 bpe_flush_map(sc, IFBF_FLUSHALL); 775 776 put: 777 if_put(ifp0); 778 return (error); 779 } 780 781 static int 782 bpe_get_parent(struct bpe_softc *sc, struct if_parent *p) 783 { 784 struct ifnet *ifp0; 785 int error = 0; 786 787 ifp0 = if_get(sc->sc_key.k_if); 788 if (ifp0 == NULL) 789 error = EADDRNOTAVAIL; 790 else 791 memcpy(p->ifp_parent, ifp0->if_xname, sizeof(p->ifp_parent)); 792 if_put(ifp0); 793 794 return (error); 795 } 796 797 static int 798 bpe_del_parent(struct bpe_softc *sc) 799 { 800 struct ifnet *ifp = &sc->sc_ac.ac_if; 801 802 if (ISSET(ifp->if_flags, IFF_RUNNING)) 803 return (EBUSY); 804 805 /* commit */ 806 sc->sc_key.k_if = 0; 807 bpe_flush_map(sc, IFBF_FLUSHALL); 808 809 return (0); 810 } 811 812 static inline struct bpe_softc * 813 bpe_find(struct ifnet *ifp0, uint32_t isid) 814 { 815 struct bpe_key k = { .k_if = ifp0->if_index, .k_isid = isid }; 816 struct bpe_softc *sc; 817 818 rw_enter_read(&bpe_lock); 819 sc = (struct bpe_softc *)RBT_FIND(bpe_tree, &bpe_interfaces, &k); 820 rw_exit_read(&bpe_lock); 821 822 return (sc); 823 } 824 825 static void 826 bpe_input_map(struct bpe_softc *sc, const uint8_t *ba, const uint8_t *ca) 827 { 828 struct bpe_entry *be; 829 int new = 0; 830 831 if (ETHER_IS_MULTICAST(ca)) 832 return; 833 834 /* remember where it came from */ 835 rw_enter_read(&sc->sc_bridge_lock); 836 be = RBT_FIND(bpe_map, &sc->sc_bridge_map, (struct bpe_entry *)ca); 837 if (be == NULL) 838 new = 1; 839 else { 840 be->be_age = getuptime(); /* only a little bit racy */ 841 842 if (be->be_type != BPE_ENTRY_DYNAMIC || 843 ETHER_IS_EQ(ba, &be->be_b_da)) 844 be = NULL; 845 else 846 refcnt_take(&be->be_refs); 847 } 848 rw_exit_read(&sc->sc_bridge_lock); 849 850 if (new) { 851 struct bpe_entry *obe; 852 unsigned int num; 853 854 be = pool_get(&bpe_entry_pool, PR_NOWAIT); 855 if (be == NULL) { 856 /* oh well */ 857 return; 858 } 859 860 memcpy(&be->be_c_da, ca, sizeof(be->be_c_da)); 861 memcpy(&be->be_b_da, ba, sizeof(be->be_b_da)); 862 be->be_type = BPE_ENTRY_DYNAMIC; 863 refcnt_init(&be->be_refs); 864 be->be_age = getuptime(); 865 866 rw_enter_write(&sc->sc_bridge_lock); 867 num = sc->sc_bridge_num; 868 if (++num > sc->sc_bridge_max) 869 obe = be; 870 else { 871 /* try and give the ref to the map */ 872 obe = RBT_INSERT(bpe_map, &sc->sc_bridge_map, be); 873 if (obe == NULL) { 874 /* count the insert */ 875 sc->sc_bridge_num = num; 876 } 877 } 878 rw_exit_write(&sc->sc_bridge_lock); 879 880 if (obe != NULL) 881 pool_put(&bpe_entry_pool, obe); 882 } else if (be != NULL) { 883 rw_enter_write(&sc->sc_bridge_lock); 884 memcpy(&be->be_b_da, ba, sizeof(be->be_b_da)); 885 rw_exit_write(&sc->sc_bridge_lock); 886 887 if (refcnt_rele(&be->be_refs)) { 888 /* ioctl may have deleted the entry */ 889 pool_put(&bpe_entry_pool, be); 890 } 891 } 892 } 893 894 void 895 bpe_input(struct ifnet *ifp0, struct mbuf *m) 896 { 897 struct bpe_softc *sc; 898 struct ifnet *ifp; 899 struct ether_header *beh, *ceh; 900 uint32_t *itagp, itag; 901 unsigned int hlen = sizeof(*beh) + sizeof(*itagp) + sizeof(*ceh); 902 struct mbuf *n; 903 int off; 904 int prio; 905 906 if (m->m_len < hlen) { 907 m = m_pullup(m, hlen); 908 if (m == NULL) { 909 /* pbb short ++ */ 910 return; 911 } 912 } 913 914 beh = mtod(m, struct ether_header *); 915 itagp = (uint32_t *)(beh + 1); 916 itag = bemtoh32(itagp); 917 918 if (itag & PBB_ITAG_RES2) { 919 /* dropped by res2 ++ */ 920 goto drop; 921 } 922 923 sc = bpe_find(ifp0, itag & PBB_ITAG_ISID); 924 if (sc == NULL) { 925 /* no interface found */ 926 goto drop; 927 } 928 929 ceh = (struct ether_header *)(itagp + 1); 930 931 bpe_input_map(sc, beh->ether_shost, ceh->ether_shost); 932 933 m_adj(m, sizeof(*beh) + sizeof(*itagp)); 934 935 n = m_getptr(m, sizeof(*ceh), &off); 936 if (n == NULL) { 937 /* no data ++ */ 938 goto drop; 939 } 940 941 if (!ALIGNED_POINTER(mtod(n, caddr_t) + off, uint32_t)) { 942 /* unaligned ++ */ 943 n = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT); 944 m_freem(m); 945 if (n == NULL) 946 return; 947 948 m = n; 949 } 950 951 ifp = &sc->sc_ac.ac_if; 952 953 prio = sc->sc_rxhprio; 954 switch (prio) { 955 case IF_HDRPRIO_PACKET: 956 break; 957 case IF_HDRPRIO_OUTER: 958 m->m_pkthdr.pf.prio = (itag & PBB_ITAG_PCP_MASK) >> 959 PBB_ITAG_PCP_SHIFT; 960 break; 961 default: 962 m->m_pkthdr.pf.prio = prio; 963 break; 964 } 965 966 m->m_flags &= ~(M_BCAST|M_MCAST); 967 m->m_pkthdr.ph_ifidx = ifp->if_index; 968 m->m_pkthdr.ph_rtableid = ifp->if_rdomain; 969 970 #if NPF > 0 971 pf_pkt_addr_changed(m); 972 #endif 973 974 if_vinput(ifp, m); 975 return; 976 977 drop: 978 m_freem(m); 979 } 980 981 void 982 bpe_detach_hook(void *arg) 983 { 984 struct bpe_softc *sc = arg; 985 struct ifnet *ifp = &sc->sc_ac.ac_if; 986 987 if (ISSET(ifp->if_flags, IFF_RUNNING)) { 988 bpe_down(sc); 989 CLR(ifp->if_flags, IFF_UP); 990 } 991 992 sc->sc_key.k_if = 0; 993 } 994 995 static void 996 bpe_link_hook(void *arg) 997 { 998 struct bpe_softc *sc = arg; 999 struct ifnet *ifp0; 1000 u_char link = LINK_STATE_DOWN; 1001 uint64_t baud = 0; 1002 1003 ifp0 = if_get(sc->sc_key.k_if); 1004 if (ifp0 != NULL) { 1005 link = ifp0->if_link_state; 1006 baud = ifp0->if_baudrate; 1007 } 1008 if_put(ifp0); 1009 1010 bpe_link_state(sc, link, baud); 1011 } 1012 1013 void 1014 bpe_link_state(struct bpe_softc *sc, u_char link, uint64_t baud) 1015 { 1016 struct ifnet *ifp = &sc->sc_ac.ac_if; 1017 1018 if (ifp->if_link_state == link) 1019 return; 1020 1021 ifp->if_link_state = link; 1022 ifp->if_baudrate = baud; 1023 1024 if_link_state_change(ifp); 1025 } 1026 1027 static inline int 1028 bpe_cmp(const struct bpe_key *a, const struct bpe_key *b) 1029 { 1030 if (a->k_if > b->k_if) 1031 return (1); 1032 if (a->k_if < b->k_if) 1033 return (-1); 1034 if (a->k_isid > b->k_isid) 1035 return (1); 1036 if (a->k_isid < b->k_isid) 1037 return (-1); 1038 1039 return (0); 1040 } 1041 1042 static inline int 1043 bpe_entry_cmp(const struct bpe_entry *a, const struct bpe_entry *b) 1044 { 1045 return memcmp(&a->be_c_da, &b->be_c_da, sizeof(a->be_c_da)); 1046 } 1047