1 /* $OpenBSD: if_mpw.c,v 1.62 2021/03/26 19:00:21 kn Exp $ */ 2 3 /* 4 * Copyright (c) 2015 Rafael Zalamena <rzalamena@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "bpfilter.h" 20 #include "vlan.h" 21 22 #include <sys/param.h> 23 #include <sys/systm.h> 24 #include <sys/mbuf.h> 25 #include <sys/socket.h> 26 #include <sys/ioctl.h> 27 #include <sys/errno.h> 28 29 #include <net/if.h> 30 #include <net/if_dl.h> 31 #include <net/if_types.h> 32 #include <net/route.h> 33 34 #include <netinet/in.h> 35 36 #include <netinet/if_ether.h> 37 #include <netmpls/mpls.h> 38 39 #if NBPFILTER > 0 40 #include <net/bpf.h> 41 #endif /* NBPFILTER */ 42 43 #if NVLAN > 0 44 #include <net/if_vlan_var.h> 45 #endif 46 47 struct mpw_neighbor { 48 struct shim_hdr n_rshim; 49 struct sockaddr_storage n_nexthop; 50 }; 51 52 struct mpw_softc { 53 struct arpcom sc_ac; 54 #define sc_if sc_ac.ac_if 55 56 int sc_txhprio; 57 int sc_rxhprio; 58 unsigned int sc_rdomain; 59 struct ifaddr sc_ifa; 60 struct sockaddr_mpls sc_smpls; /* Local label */ 61 62 unsigned int sc_cword; 63 unsigned int sc_fword; 64 uint32_t sc_flow; 65 uint32_t sc_type; 66 struct mpw_neighbor *sc_neighbor; 67 68 unsigned int sc_dead; 69 }; 70 71 void mpwattach(int); 72 int mpw_clone_create(struct if_clone *, int); 73 int mpw_clone_destroy(struct ifnet *); 74 int mpw_ioctl(struct ifnet *, u_long, caddr_t); 75 int mpw_output(struct ifnet *, struct mbuf *, struct sockaddr *, 76 struct rtentry *); 77 void mpw_start(struct ifnet *); 78 #if NVLAN > 0 79 struct mbuf *mpw_vlan_handle(struct mbuf *, struct mpw_softc *); 80 #endif /* NVLAN */ 81 82 struct if_clone mpw_cloner = 83 IF_CLONE_INITIALIZER("mpw", mpw_clone_create, mpw_clone_destroy); 84 85 void 86 mpwattach(int n) 87 { 88 if_clone_attach(&mpw_cloner); 89 } 90 91 int 92 mpw_clone_create(struct if_clone *ifc, int unit) 93 { 94 struct mpw_softc *sc; 95 struct ifnet *ifp; 96 97 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_CANFAIL|M_ZERO); 98 if (sc == NULL) 99 return (ENOMEM); 100 101 sc->sc_flow = arc4random(); 102 sc->sc_neighbor = NULL; 103 104 ifp = &sc->sc_if; 105 snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", 106 ifc->ifc_name, unit); 107 ifp->if_softc = sc; 108 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 109 ifp->if_xflags = IFXF_CLONED; 110 ifp->if_ioctl = mpw_ioctl; 111 ifp->if_output = mpw_output; 112 ifp->if_start = mpw_start; 113 ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN; 114 ether_fakeaddr(ifp); 115 116 sc->sc_dead = 0; 117 118 if_counters_alloc(ifp); 119 if_attach(ifp); 120 ether_ifattach(ifp); 121 122 sc->sc_txhprio = 0; 123 sc->sc_rxhprio = IF_HDRPRIO_PACKET; 124 sc->sc_rdomain = 0; 125 sc->sc_ifa.ifa_ifp = ifp; 126 sc->sc_ifa.ifa_addr = sdltosa(ifp->if_sadl); 127 sc->sc_smpls.smpls_len = sizeof(sc->sc_smpls); 128 sc->sc_smpls.smpls_family = AF_MPLS; 129 130 return (0); 131 } 132 133 int 134 mpw_clone_destroy(struct ifnet *ifp) 135 { 136 struct mpw_softc *sc = ifp->if_softc; 137 138 NET_LOCK(); 139 ifp->if_flags &= ~IFF_RUNNING; 140 sc->sc_dead = 1; 141 142 if (sc->sc_smpls.smpls_label) { 143 rt_ifa_del(&sc->sc_ifa, RTF_MPLS|RTF_LOCAL, 144 smplstosa(&sc->sc_smpls), sc->sc_rdomain); 145 } 146 NET_UNLOCK(); 147 148 ifq_barrier(&ifp->if_snd); 149 150 ether_ifdetach(ifp); 151 if_detach(ifp); 152 153 free(sc->sc_neighbor, M_DEVBUF, sizeof(*sc->sc_neighbor)); 154 free(sc, M_DEVBUF, sizeof(*sc)); 155 156 return (0); 157 } 158 159 int 160 mpw_set_route(struct mpw_softc *sc, uint32_t label, unsigned int rdomain) 161 { 162 int error; 163 164 if (sc->sc_dead) 165 return (ENXIO); 166 167 if (sc->sc_smpls.smpls_label) { 168 rt_ifa_del(&sc->sc_ifa, RTF_MPLS|RTF_LOCAL, 169 smplstosa(&sc->sc_smpls), sc->sc_rdomain); 170 } 171 172 sc->sc_smpls.smpls_label = label; 173 sc->sc_rdomain = rdomain; 174 175 /* only install with a label or mpw_clone_destroy() will ignore it */ 176 if (sc->sc_smpls.smpls_label == MPLS_LABEL2SHIM(0)) 177 return 0; 178 179 error = rt_ifa_add(&sc->sc_ifa, RTF_MPLS|RTF_LOCAL, 180 smplstosa(&sc->sc_smpls), sc->sc_rdomain); 181 if (error != 0) 182 sc->sc_smpls.smpls_label = 0; 183 184 return (error); 185 } 186 187 static int 188 mpw_set_neighbor(struct mpw_softc *sc, const struct if_laddrreq *req) 189 { 190 struct mpw_neighbor *n, *o; 191 const struct sockaddr_storage *ss; 192 const struct sockaddr_mpls *smpls; 193 uint32_t label; 194 195 smpls = (const struct sockaddr_mpls *)&req->dstaddr; 196 197 if (smpls->smpls_family != AF_MPLS) 198 return (EINVAL); 199 label = smpls->smpls_label; 200 if (label > MPLS_LABEL_MAX || label <= MPLS_LABEL_RESERVED_MAX) 201 return (EINVAL); 202 203 ss = &req->addr; 204 switch (ss->ss_family) { 205 case AF_INET: { 206 const struct sockaddr_in *sin = 207 (const struct sockaddr_in *)ss; 208 209 if (in_nullhost(sin->sin_addr) || 210 IN_MULTICAST(sin->sin_addr.s_addr)) 211 return (EINVAL); 212 213 break; 214 } 215 #ifdef INET6 216 case AF_INET6: { 217 const struct sockaddr_in6 *sin6 = 218 (const struct sockaddr_in6 *)ss; 219 220 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || 221 IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 222 return (EINVAL); 223 224 /* check scope */ 225 226 break; 227 } 228 #endif 229 default: 230 return (EAFNOSUPPORT); 231 } 232 233 if (sc->sc_dead) 234 return (ENXIO); 235 236 n = malloc(sizeof(*n), M_DEVBUF, M_WAITOK|M_CANFAIL|M_ZERO); 237 if (n == NULL) 238 return (ENOMEM); 239 240 n->n_rshim.shim_label = MPLS_LABEL2SHIM(label); 241 n->n_nexthop = *ss; 242 243 o = sc->sc_neighbor; 244 sc->sc_neighbor = n; 245 246 NET_UNLOCK(); 247 ifq_barrier(&sc->sc_if.if_snd); 248 NET_LOCK(); 249 250 free(o, M_DEVBUF, sizeof(*o)); 251 252 return (0); 253 } 254 255 static int 256 mpw_get_neighbor(struct mpw_softc *sc, struct if_laddrreq *req) 257 { 258 struct sockaddr_mpls *smpls = (struct sockaddr_mpls *)&req->dstaddr; 259 struct mpw_neighbor *n = sc->sc_neighbor; 260 261 if (n == NULL) 262 return (EADDRNOTAVAIL); 263 264 smpls->smpls_len = sizeof(*smpls); 265 smpls->smpls_family = AF_MPLS; 266 smpls->smpls_label = MPLS_SHIM2LABEL(n->n_rshim.shim_label); 267 268 req->addr = n->n_nexthop; 269 270 return (0); 271 } 272 273 static int 274 mpw_del_neighbor(struct mpw_softc *sc) 275 { 276 struct mpw_neighbor *o; 277 278 if (sc->sc_dead) 279 return (ENXIO); 280 281 o = sc->sc_neighbor; 282 sc->sc_neighbor = NULL; 283 284 NET_UNLOCK(); 285 ifq_barrier(&sc->sc_if.if_snd); 286 NET_LOCK(); 287 288 free(o, M_DEVBUF, sizeof(*o)); 289 290 return (0); 291 } 292 293 static int 294 mpw_set_label(struct mpw_softc *sc, const struct shim_hdr *label) 295 { 296 uint32_t shim; 297 298 if (label->shim_label > MPLS_LABEL_MAX || 299 label->shim_label <= MPLS_LABEL_RESERVED_MAX) 300 return (EINVAL); 301 302 shim = MPLS_LABEL2SHIM(label->shim_label); 303 if (sc->sc_smpls.smpls_label == shim) 304 return (0); 305 306 return (mpw_set_route(sc, shim, sc->sc_rdomain)); 307 } 308 309 static int 310 mpw_get_label(struct mpw_softc *sc, struct ifreq *ifr) 311 { 312 struct shim_hdr label; 313 314 label.shim_label = MPLS_SHIM2LABEL(sc->sc_smpls.smpls_label); 315 316 if (label.shim_label == 0) 317 return (EADDRNOTAVAIL); 318 319 return (copyout(&label, ifr->ifr_data, sizeof(label))); 320 } 321 322 static int 323 mpw_del_label(struct mpw_softc *sc) 324 { 325 if (sc->sc_dead) 326 return (ENXIO); 327 328 if (sc->sc_smpls.smpls_label != MPLS_LABEL2SHIM(0)) { 329 rt_ifa_del(&sc->sc_ifa, RTF_MPLS | RTF_LOCAL, 330 smplstosa(&sc->sc_smpls), sc->sc_rdomain); 331 } 332 333 sc->sc_smpls.smpls_label = MPLS_LABEL2SHIM(0); 334 335 return (0); 336 } 337 338 static int 339 mpw_set_config(struct mpw_softc *sc, const struct ifreq *ifr) 340 { 341 struct ifmpwreq imr; 342 struct if_laddrreq req; 343 struct sockaddr_mpls *smpls; 344 struct sockaddr_in *sin; 345 int error; 346 347 error = copyin(ifr->ifr_data, &imr, sizeof(imr)); 348 if (error != 0) 349 return (error); 350 351 /* Teardown all configuration if got no nexthop */ 352 sin = (struct sockaddr_in *)&imr.imr_nexthop; 353 if (sin->sin_addr.s_addr == 0) { 354 mpw_del_label(sc); 355 mpw_del_neighbor(sc); 356 sc->sc_cword = 0; 357 sc->sc_type = 0; 358 return (0); 359 } 360 361 error = mpw_set_label(sc, &imr.imr_lshim); 362 if (error != 0) 363 return (error); 364 365 smpls = (struct sockaddr_mpls *)&req.dstaddr; 366 smpls->smpls_family = AF_MPLS; 367 smpls->smpls_label = imr.imr_rshim.shim_label; 368 req.addr = imr.imr_nexthop; 369 370 error = mpw_set_neighbor(sc, &req); 371 if (error != 0) 372 return (error); 373 374 sc->sc_cword = ISSET(imr.imr_flags, IMR_FLAG_CONTROLWORD); 375 sc->sc_type = imr.imr_type; 376 377 return (0); 378 } 379 380 static int 381 mpw_get_config(struct mpw_softc *sc, const struct ifreq *ifr) 382 { 383 struct ifmpwreq imr; 384 385 memset(&imr, 0, sizeof(imr)); 386 imr.imr_flags = sc->sc_cword ? IMR_FLAG_CONTROLWORD : 0; 387 imr.imr_type = sc->sc_type; 388 389 imr.imr_lshim.shim_label = MPLS_SHIM2LABEL(sc->sc_smpls.smpls_label); 390 if (sc->sc_neighbor) { 391 imr.imr_rshim.shim_label = 392 MPLS_SHIM2LABEL(sc->sc_neighbor->n_rshim.shim_label); 393 imr.imr_nexthop = sc->sc_neighbor->n_nexthop; 394 } 395 396 return (copyout(&imr, ifr->ifr_data, sizeof(imr))); 397 } 398 399 int 400 mpw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 401 { 402 struct ifreq *ifr = (struct ifreq *) data; 403 struct mpw_softc *sc = ifp->if_softc; 404 struct shim_hdr shim; 405 int error = 0; 406 407 switch (cmd) { 408 case SIOCSIFFLAGS: 409 if ((ifp->if_flags & IFF_UP)) 410 ifp->if_flags |= IFF_RUNNING; 411 else 412 ifp->if_flags &= ~IFF_RUNNING; 413 break; 414 415 case SIOCGPWE3: 416 ifr->ifr_pwe3 = IF_PWE3_ETHERNET; 417 break; 418 case SIOCSPWE3CTRLWORD: 419 sc->sc_cword = ifr->ifr_pwe3 ? 1 : 0; 420 break; 421 case SIOCGPWE3CTRLWORD: 422 ifr->ifr_pwe3 = sc->sc_cword; 423 break; 424 case SIOCSPWE3FAT: 425 sc->sc_fword = ifr->ifr_pwe3 ? 1 : 0; 426 break; 427 case SIOCGPWE3FAT: 428 ifr->ifr_pwe3 = sc->sc_fword; 429 break; 430 431 case SIOCSPWE3NEIGHBOR: 432 error = mpw_set_neighbor(sc, (struct if_laddrreq *)data); 433 break; 434 case SIOCGPWE3NEIGHBOR: 435 error = mpw_get_neighbor(sc, (struct if_laddrreq *)data); 436 break; 437 case SIOCDPWE3NEIGHBOR: 438 error = mpw_del_neighbor(sc); 439 break; 440 441 case SIOCGETLABEL: 442 error = mpw_get_label(sc, ifr); 443 break; 444 case SIOCSETLABEL: 445 error = copyin(ifr->ifr_data, &shim, sizeof(shim)); 446 if (error != 0) 447 break; 448 error = mpw_set_label(sc, &shim); 449 break; 450 case SIOCDELLABEL: 451 error = mpw_del_label(sc); 452 break; 453 454 case SIOCSETMPWCFG: 455 error = mpw_set_config(sc, ifr); 456 break; 457 458 case SIOCGETMPWCFG: 459 error = mpw_get_config(sc, ifr); 460 break; 461 462 case SIOCSLIFPHYRTABLE: 463 if (ifr->ifr_rdomainid < 0 || 464 ifr->ifr_rdomainid > RT_TABLEID_MAX || 465 !rtable_exists(ifr->ifr_rdomainid) || 466 ifr->ifr_rdomainid != rtable_l2(ifr->ifr_rdomainid)) { 467 error = EINVAL; 468 break; 469 } 470 if (sc->sc_rdomain != ifr->ifr_rdomainid) { 471 error = mpw_set_route(sc, sc->sc_smpls.smpls_label, 472 ifr->ifr_rdomainid); 473 } 474 break; 475 case SIOCGLIFPHYRTABLE: 476 ifr->ifr_rdomainid = sc->sc_rdomain; 477 break; 478 479 case SIOCSTXHPRIO: 480 error = if_txhprio_l2_check(ifr->ifr_hdrprio); 481 if (error != 0) 482 break; 483 484 sc->sc_txhprio = ifr->ifr_hdrprio; 485 break; 486 case SIOCGTXHPRIO: 487 ifr->ifr_hdrprio = sc->sc_txhprio; 488 break; 489 490 case SIOCSRXHPRIO: 491 error = if_rxhprio_l2_check(ifr->ifr_hdrprio); 492 if (error != 0) 493 break; 494 495 sc->sc_rxhprio = ifr->ifr_hdrprio; 496 break; 497 case SIOCGRXHPRIO: 498 ifr->ifr_hdrprio = sc->sc_rxhprio; 499 break; 500 501 case SIOCADDMULTI: 502 case SIOCDELMULTI: 503 break; 504 505 default: 506 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); 507 break; 508 } 509 510 return (error); 511 } 512 513 static void 514 mpw_input(struct mpw_softc *sc, struct mbuf *m) 515 { 516 struct ifnet *ifp = &sc->sc_if; 517 struct shim_hdr *shim; 518 struct mbuf *n; 519 uint32_t exp; 520 int rxprio; 521 int off; 522 523 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 524 goto drop; 525 526 shim = mtod(m, struct shim_hdr *); 527 exp = ntohl(shim->shim_label & MPLS_EXP_MASK) >> MPLS_EXP_OFFSET; 528 if (sc->sc_fword) { 529 uint32_t flow; 530 531 if (MPLS_BOS_ISSET(shim->shim_label)) 532 goto drop; 533 m_adj(m, sizeof(*shim)); 534 535 if (m->m_len < sizeof(*shim)) { 536 m = m_pullup(m, sizeof(*shim)); 537 if (m == NULL) 538 return; 539 } 540 shim = mtod(m, struct shim_hdr *); 541 542 if (!MPLS_BOS_ISSET(shim->shim_label)) 543 goto drop; 544 545 flow = MPLS_SHIM2LABEL(shim->shim_label); 546 flow ^= sc->sc_flow; 547 SET(m->m_pkthdr.csum_flags, M_FLOWID); 548 m->m_pkthdr.ph_flowid = flow; 549 } else { 550 if (!MPLS_BOS_ISSET(shim->shim_label)) 551 goto drop; 552 } 553 m_adj(m, sizeof(*shim)); 554 555 if (sc->sc_cword) { 556 if (m->m_len < sizeof(*shim)) { 557 m = m_pullup(m, sizeof(*shim)); 558 if (m == NULL) 559 return; 560 } 561 shim = mtod(m, struct shim_hdr *); 562 563 /* 564 * The first 4 bits identifies that this packet is a 565 * control word. If the control word is configured and 566 * we received an IP datagram we shall drop it. 567 */ 568 if (shim->shim_label & CW_ZERO_MASK) { 569 ifp->if_ierrors++; 570 goto drop; 571 } 572 573 /* We don't support fragmentation just yet. */ 574 if (shim->shim_label & CW_FRAG_MASK) { 575 ifp->if_ierrors++; 576 goto drop; 577 } 578 579 m_adj(m, MPLS_HDRLEN); 580 } 581 582 if (m->m_len < sizeof(struct ether_header)) { 583 m = m_pullup(m, sizeof(struct ether_header)); 584 if (m == NULL) 585 return; 586 } 587 588 n = m_getptr(m, sizeof(struct ether_header), &off); 589 if (n == NULL) { 590 ifp->if_ierrors++; 591 goto drop; 592 } 593 if (!ALIGNED_POINTER(mtod(n, caddr_t) + off, uint32_t)) { 594 n = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT); 595 /* Dispose of the original mbuf chain */ 596 m_freem(m); 597 if (n == NULL) 598 return; 599 m = n; 600 } 601 602 rxprio = sc->sc_rxhprio; 603 switch (rxprio) { 604 case IF_HDRPRIO_PACKET: 605 /* nop */ 606 break; 607 case IF_HDRPRIO_OUTER: 608 m->m_pkthdr.pf.prio = exp; 609 break; 610 default: 611 m->m_pkthdr.pf.prio = rxprio; 612 break; 613 } 614 615 m->m_pkthdr.ph_ifidx = ifp->if_index; 616 m->m_pkthdr.ph_rtableid = ifp->if_rdomain; 617 618 /* packet has not been processed by PF yet. */ 619 KASSERT(m->m_pkthdr.pf.statekey == NULL); 620 621 if_vinput(ifp, m); 622 return; 623 drop: 624 m_freem(m); 625 } 626 627 int 628 mpw_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 629 struct rtentry *rt) 630 { 631 struct mpw_softc *sc = ifp->if_softc; 632 633 if (dst->sa_family == AF_LINK && 634 rt != NULL && ISSET(rt->rt_flags, RTF_LOCAL)) { 635 mpw_input(sc, m); 636 return (0); 637 } 638 639 return (ether_output(ifp, m, dst, rt)); 640 } 641 642 void 643 mpw_start(struct ifnet *ifp) 644 { 645 struct mpw_softc *sc = ifp->if_softc; 646 struct rtentry *rt; 647 struct ifnet *ifp0; 648 struct mbuf *m, *m0; 649 struct shim_hdr *shim; 650 struct mpw_neighbor *n; 651 struct sockaddr_mpls smpls = { 652 .smpls_len = sizeof(smpls), 653 .smpls_family = AF_MPLS, 654 }; 655 int txprio = sc->sc_txhprio; 656 uint8_t prio; 657 uint32_t exp, bos; 658 659 n = sc->sc_neighbor; 660 if (!ISSET(ifp->if_flags, IFF_RUNNING) || 661 n == NULL) { 662 ifq_purge(&ifp->if_snd); 663 return; 664 } 665 666 rt = rtalloc(sstosa(&n->n_nexthop), RT_RESOLVE, sc->sc_rdomain); 667 if (!rtisvalid(rt)) { 668 ifq_purge(&ifp->if_snd); 669 goto rtfree; 670 } 671 672 ifp0 = if_get(rt->rt_ifidx); 673 if (ifp0 == NULL) { 674 ifq_purge(&ifp->if_snd); 675 goto rtfree; 676 } 677 678 while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) { 679 #if NBPFILTER > 0 680 if (sc->sc_if.if_bpf) 681 bpf_mtap(sc->sc_if.if_bpf, m, BPF_DIRECTION_OUT); 682 #endif /* NBPFILTER */ 683 684 m0 = m_get(M_DONTWAIT, m->m_type); 685 if (m0 == NULL) { 686 m_freem(m); 687 continue; 688 } 689 690 M_MOVE_PKTHDR(m0, m); 691 m0->m_next = m; 692 m_align(m0, 0); 693 m0->m_len = 0; 694 695 if (sc->sc_cword) { 696 m0 = m_prepend(m0, sizeof(*shim), M_NOWAIT); 697 if (m0 == NULL) 698 continue; 699 700 shim = mtod(m0, struct shim_hdr *); 701 memset(shim, 0, sizeof(*shim)); 702 } 703 704 switch (txprio) { 705 case IF_HDRPRIO_PACKET: 706 prio = m->m_pkthdr.pf.prio; 707 break; 708 default: 709 prio = txprio; 710 break; 711 } 712 exp = htonl(prio << MPLS_EXP_OFFSET); 713 714 bos = MPLS_BOS_MASK; 715 if (sc->sc_fword) { 716 uint32_t flow = sc->sc_flow; 717 718 m0 = m_prepend(m0, sizeof(*shim), M_NOWAIT); 719 if (m0 == NULL) 720 continue; 721 722 if (ISSET(m->m_pkthdr.csum_flags, M_FLOWID)) 723 flow ^= m->m_pkthdr.ph_flowid; 724 725 shim = mtod(m0, struct shim_hdr *); 726 shim->shim_label = htonl(1) & MPLS_TTL_MASK; 727 shim->shim_label |= MPLS_LABEL2SHIM(flow) | exp | bos; 728 729 bos = 0; 730 } 731 732 m0 = m_prepend(m0, sizeof(*shim), M_NOWAIT); 733 if (m0 == NULL) 734 continue; 735 736 shim = mtod(m0, struct shim_hdr *); 737 shim->shim_label = htonl(mpls_defttl) & MPLS_TTL_MASK; 738 shim->shim_label |= n->n_rshim.shim_label | exp | bos; 739 740 m0->m_pkthdr.ph_rtableid = sc->sc_rdomain; 741 CLR(m0->m_flags, M_BCAST|M_MCAST); 742 743 mpls_output(ifp0, m0, (struct sockaddr *)&smpls, rt); 744 } 745 746 if_put(ifp0); 747 rtfree: 748 rtfree(rt); 749 } 750