1 /*- 2 * Copyright (c) 2008 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by CK Software GmbH under sponsorship 6 * from the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /* 31 * A pair of virtual ethernet interfaces directly connected with 32 * a virtual cross-over cable. 33 * This is mostly intended to be used to provide connectivity between 34 * different virtual network stack instances. 35 */ 36 /* 37 * Things to re-think once we have more experience: 38 * - ifp->if_reassign function once we can test with vimage. 39 * - Real random etheraddrs that are checked to be uniquish; 40 * in case we bridge we may need this or let the user handle that case? 41 * - netisr and callback logic. 42 * - netisr queue lengths. 43 */ 44 45 #include <sys/cdefs.h> 46 __FBSDID("$FreeBSD$"); 47 48 #include <sys/param.h> 49 #include <sys/kernel.h> 50 #include <sys/mbuf.h> 51 #include <sys/module.h> 52 #include <sys/refcount.h> 53 #include <sys/queue.h> 54 #include <sys/socket.h> 55 #include <sys/sockio.h> 56 #include <sys/sysctl.h> 57 #include <sys/types.h> 58 #include <sys/vimage.h> 59 60 #include <net/bpf.h> 61 #include <net/ethernet.h> 62 #include <net/if.h> 63 #include <net/if_clone.h> 64 #include <net/if_var.h> 65 #include <net/if_types.h> 66 #include <net/netisr.h> 67 68 #define EPAIRNAME "epair" 69 70 #ifdef DEBUG_EPAIR 71 static int epair_debug = 0; 72 SYSCTL_DECL(_net_link); 73 SYSCTL_NODE(_net_link, OID_AUTO, epair, CTLFLAG_RW, 0, "epair sysctl"); 74 SYSCTL_XINT(_net_link_epair, OID_AUTO, epair_debug, CTLFLAG_RW, 75 &epair_debug, 0, "if_epair(4) debugging."); 76 #define DPRINTF(fmt, arg...) if (epair_debug) \ 77 printf("[%s:%d] " fmt, __func__, __LINE__, ##arg) 78 #else 79 #define DPRINTF(fmt, arg...) 80 #endif 81 82 struct epair_softc { 83 struct ifnet *ifp; 84 struct ifnet *oifp; 85 u_int refcount; 86 void (*if_qflush)(struct ifnet *); 87 }; 88 89 struct epair_ifp_drain { 90 STAILQ_ENTRY(epair_ifp_drain) ifp_next; 91 struct ifnet *ifp; 92 }; 93 94 static STAILQ_HEAD(, epair_ifp_drain) epair_ifp_drain_list = 95 STAILQ_HEAD_INITIALIZER(epair_ifp_drain_list); 96 97 #define ADD_IFQ_FOR_DRAINING(ifp) \ 98 do { \ 99 struct epair_ifp_drain *elm = NULL; \ 100 \ 101 STAILQ_FOREACH(elm, &epair_ifp_drain_list, ifp_next) { \ 102 if (elm->ifp == (ifp)) \ 103 break; \ 104 } \ 105 if (elm == NULL) { \ 106 elm = malloc(sizeof(struct epair_ifp_drain), \ 107 M_EPAIR, M_ZERO); \ 108 if (elm != NULL) { \ 109 elm->ifp = (ifp); \ 110 STAILQ_INSERT_TAIL( \ 111 &epair_ifp_drain_list, \ 112 elm, ifp_next); \ 113 } \ 114 } \ 115 } while(0) 116 117 /* Our "hw" tx queue. */ 118 static struct ifqueue epairinq; 119 static int epair_drv_flags; 120 121 static struct mtx if_epair_mtx; 122 #define EPAIR_LOCK_INIT() mtx_init(&if_epair_mtx, "if_epair", \ 123 NULL, MTX_DEF) 124 #define EPAIR_LOCK_DESTROY() mtx_destroy(&if_epair_mtx) 125 #define EPAIR_LOCK_ASSERT() mtx_assert(&if_epair_mtx, MA_OWNED) 126 #define EPAIR_LOCK() mtx_lock(&if_epair_mtx) 127 #define EPAIR_UNLOCK() mtx_unlock(&if_epair_mtx) 128 129 static MALLOC_DEFINE(M_EPAIR, EPAIRNAME, 130 "Pair of virtual cross-over connected Ethernet-like interfaces"); 131 132 static int epair_clone_match(struct if_clone *, const char *); 133 static int epair_clone_create(struct if_clone *, char *, size_t, caddr_t); 134 static int epair_clone_destroy(struct if_clone *, struct ifnet *); 135 136 static void epair_start_locked(struct ifnet *); 137 138 static struct if_clone epair_cloner = IFC_CLONE_INITIALIZER( 139 EPAIRNAME, NULL, IF_MAXUNIT, 140 NULL, epair_clone_match, epair_clone_create, epair_clone_destroy); 141 142 143 /* 144 * Netisr handler functions. 145 */ 146 static void 147 epair_sintr(struct mbuf *m) 148 { 149 struct ifnet *ifp; 150 struct epair_softc *sc; 151 152 ifp = m->m_pkthdr.rcvif; 153 (*ifp->if_input)(ifp, m); 154 sc = ifp->if_softc; 155 refcount_release(&sc->refcount); 156 DPRINTF("ifp=%p refcount=%u\n", ifp, sc->refcount); 157 } 158 159 static void 160 epair_sintr_drained(void) 161 { 162 struct epair_ifp_drain *elm, *tvar; 163 struct ifnet *ifp; 164 165 EPAIR_LOCK(); 166 /* 167 * Assume our "hw" queue and possibly ifq will be emptied 168 * again. In case we will overflow the "hw" queue while 169 * draining, epair_start_locked will set IFF_DRV_OACTIVE 170 * again and we will stop and return. 171 */ 172 STAILQ_FOREACH_SAFE(elm, &epair_ifp_drain_list, ifp_next, tvar) { 173 ifp = elm->ifp; 174 epair_drv_flags &= ~IFF_DRV_OACTIVE; 175 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 176 epair_start_locked(ifp); 177 178 IFQ_LOCK(&ifp->if_snd); 179 if (IFQ_IS_EMPTY(&ifp->if_snd)) { 180 STAILQ_REMOVE(&epair_ifp_drain_list, elm, 181 epair_ifp_drain, ifp_next); 182 free(elm, M_EPAIR); 183 } 184 IFQ_UNLOCK(&ifp->if_snd); 185 186 if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) != 0) { 187 /* Our "hw"q overflew again. */ 188 epair_drv_flags |= IFF_DRV_OACTIVE 189 DPRINTF("hw queue length overflow at %u\n", 190 epairinq.ifq_maxlen); 191 #if 0 192 /* ``Auto-tuning.'' */ 193 epairinq.ifq_maxlen += ifqmaxlen; 194 #endif 195 break; 196 } 197 } 198 EPAIR_UNLOCK(); 199 } 200 201 /* 202 * Network interface (`if') related functions. 203 */ 204 static void 205 epair_start_locked(struct ifnet *ifp) 206 { 207 struct mbuf *m; 208 struct epair_softc *sc; 209 struct ifnet *oifp; 210 int error; 211 212 EPAIR_LOCK_ASSERT(); 213 DPRINTF("ifp=%p\n", ifp); 214 215 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 216 return; 217 if ((ifp->if_flags & IFF_UP) == 0) 218 return; 219 220 /* 221 * We get patckets here from ether_output via if_handoff() 222 * and ned to put them into the input queue of the oifp 223 * and call oifp->if_input() via netisr/epair_sintr(). 224 */ 225 sc = ifp->if_softc; 226 oifp = sc->oifp; 227 sc = oifp->if_softc; 228 for (;;) { 229 IFQ_DEQUEUE(&ifp->if_snd, m); 230 if (m == NULL) 231 break; 232 BPF_MTAP(ifp, m); 233 234 /* 235 * In case the outgoing interface is not usable, 236 * drop the packet. 237 */ 238 if ((oifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || 239 (oifp->if_flags & IFF_UP) ==0) { 240 ifp->if_oerrors++; 241 m_freem(m); 242 continue; 243 } 244 DPRINTF("packet %s -> %s\n", ifp->if_xname, oifp->if_xname); 245 246 /* 247 * Add a reference so the interface cannot go while the 248 * packet is in transit as we rely on rcvif to stay valid. 249 */ 250 refcount_acquire(&sc->refcount); 251 m->m_pkthdr.rcvif = oifp; 252 CURVNET_SET_QUIET(oifp->if_vnet); 253 error = netisr_queue(NETISR_EPAIR, m); 254 CURVNET_RESTORE(); 255 if (!error) { 256 ifp->if_opackets++; 257 /* Someone else received the packet. */ 258 oifp->if_ipackets++; 259 } else { 260 epair_drv_flags |= IFF_DRV_OACTIVE; 261 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 262 ADD_IFQ_FOR_DRAINING(ifp); 263 refcount_release(&sc->refcount); 264 } 265 } 266 } 267 268 static void 269 epair_start(struct ifnet *ifp) 270 { 271 272 EPAIR_LOCK(); 273 epair_start_locked(ifp); 274 EPAIR_UNLOCK(); 275 } 276 277 static int 278 epair_transmit_locked(struct ifnet *ifp, struct mbuf *m) 279 { 280 struct epair_softc *sc; 281 struct ifnet *oifp; 282 int error, len; 283 short mflags; 284 285 EPAIR_LOCK_ASSERT(); 286 DPRINTF("ifp=%p m=%p\n", ifp, m); 287 288 if (m == NULL) 289 return (0); 290 291 /* 292 * We are not going to use the interface en/dequeue mechanism 293 * on the TX side. We are called from ether_output_frame() 294 * and will put the packet into the incoming queue of the 295 * other interface of our pair via the netsir. 296 */ 297 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 298 m_freem(m); 299 return (ENXIO); 300 } 301 if ((ifp->if_flags & IFF_UP) == 0) { 302 m_freem(m); 303 return (ENETDOWN); 304 } 305 306 BPF_MTAP(ifp, m); 307 308 /* 309 * In case the outgoing interface is not usable, 310 * drop the packet. 311 */ 312 sc = ifp->if_softc; 313 oifp = sc->oifp; 314 if ((oifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || 315 (oifp->if_flags & IFF_UP) ==0) { 316 ifp->if_oerrors++; 317 m_freem(m); 318 return (0); 319 } 320 len = m->m_pkthdr.len; 321 mflags = m->m_flags; 322 DPRINTF("packet %s -> %s\n", ifp->if_xname, oifp->if_xname); 323 324 #ifdef ALTQ 325 /* Support ALTQ via the clasic if_start() path. */ 326 IF_LOCK(&ifp->if_snd); 327 if (ALTQ_IS_ENABLED(&ifp->if_snd)) { 328 ALTQ_ENQUEUE(&ifp->if_snd, m, NULL, error); 329 if (error) 330 ifp->if_snd.ifq_drops++; 331 IF_UNLOCK(&ifp->if_snd); 332 if (!error) { 333 ifp->if_obytes += len; 334 if (mflags & (M_BCAST|M_MCAST)) 335 ifp->if_omcasts++; 336 337 if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) 338 epair_start_locked(ifp); 339 else 340 ADD_IFQ_FOR_DRAINING(ifp); 341 } 342 return (error); 343 } 344 IF_UNLOCK(&ifp->if_snd); 345 #endif 346 347 if ((epair_drv_flags & IFF_DRV_OACTIVE) != 0) { 348 /* 349 * Our hardware queue is full, try to fall back 350 * queuing to the ifq but do not call ifp->if_start. 351 * Either we are lucky or the packet is gone. 352 */ 353 IFQ_ENQUEUE(&ifp->if_snd, m, error); 354 if (!error) 355 ADD_IFQ_FOR_DRAINING(ifp); 356 return (error); 357 } 358 sc = oifp->if_softc; 359 /* 360 * Add a reference so the interface cannot go while the 361 * packet is in transit as we rely on rcvif to stay valid. 362 */ 363 refcount_acquire(&sc->refcount); 364 m->m_pkthdr.rcvif = oifp; 365 CURVNET_SET_QUIET(oifp->if_vnet); 366 error = netisr_queue(NETISR_EPAIR, m); 367 CURVNET_RESTORE(); 368 if (!error) { 369 ifp->if_opackets++; 370 /* 371 * IFQ_HANDOFF_ADJ/ip_handoff() update statistics, 372 * but as we bypass all this we have to duplicate 373 * the logic another time. 374 */ 375 ifp->if_obytes += len; 376 if (mflags & (M_BCAST|M_MCAST)) 377 ifp->if_omcasts++; 378 /* Someone else received the packet. */ 379 oifp->if_ipackets++; 380 } else { 381 /* The packet was freed already. */ 382 refcount_release(&sc->refcount); 383 epair_drv_flags |= IFF_DRV_OACTIVE; 384 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 385 } 386 387 return (error); 388 } 389 390 static int 391 epair_transmit(struct ifnet *ifp, struct mbuf *m) 392 { 393 int error; 394 395 EPAIR_LOCK(); 396 error = epair_transmit_locked(ifp, m); 397 EPAIR_UNLOCK(); 398 return (error); 399 } 400 401 static void 402 epair_qflush(struct ifnet *ifp) 403 { 404 struct epair_softc *sc; 405 struct ifaltq *ifq; 406 407 EPAIR_LOCK(); 408 sc = ifp->if_softc; 409 ifq = &ifp->if_snd; 410 DPRINTF("ifp=%p sc refcnt=%u ifq_len=%u\n", 411 ifp, sc->refcount, ifq->ifq_len); 412 /* 413 * Instead of calling refcount_release(&sc->refcount); 414 * n times, just subtract for the cleanup. 415 */ 416 sc->refcount -= ifq->ifq_len; 417 EPAIR_UNLOCK(); 418 if (sc->if_qflush) 419 sc->if_qflush(ifp); 420 } 421 422 static int 423 epair_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 424 { 425 struct ifreq *ifr; 426 int error; 427 428 ifr = (struct ifreq *)data; 429 switch (cmd) { 430 case SIOCSIFFLAGS: 431 case SIOCADDMULTI: 432 case SIOCDELMULTI: 433 error = 0; 434 break; 435 436 default: 437 /* Let the common ethernet handler process this. */ 438 error = ether_ioctl(ifp, cmd, data); 439 break; 440 } 441 442 return (error); 443 } 444 445 static void 446 epair_init(void *dummy __unused) 447 { 448 } 449 450 451 /* 452 * Interface cloning functions. 453 * We use our private ones so that we can create/destroy our secondary 454 * device along with the primary one. 455 */ 456 static int 457 epair_clone_match(struct if_clone *ifc, const char *name) 458 { 459 const char *cp; 460 461 DPRINTF("name='%s'\n", name); 462 463 /* 464 * Our base name is epair. 465 * Our interfaces will be named epair<n>[ab]. 466 * So accept anything of the following list: 467 * - epair 468 * - epair<n> 469 * but not the epair<n>[ab] versions. 470 */ 471 if (strncmp(EPAIRNAME, name, sizeof(EPAIRNAME)-1) != 0) 472 return (0); 473 474 for (cp = name + sizeof(EPAIRNAME) - 1; *cp != '\0'; cp++) { 475 if (*cp < '0' || *cp > '9') 476 return (0); 477 } 478 479 return (1); 480 } 481 482 static int 483 epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) 484 { 485 struct epair_softc *sca, *scb; 486 struct ifnet *ifp; 487 char *dp; 488 int error, unit, wildcard; 489 uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ 490 491 /* 492 * We are abusing params to create our second interface. 493 * Actually we already created it and called if_clone_createif() 494 * for it to do the official insertion procedure the moment we knew 495 * it cannot fail anymore. So just do attach it here. 496 */ 497 if (params) { 498 scb = (struct epair_softc *)params; 499 ifp = scb->ifp; 500 /* Assign a hopefully unique, locally administered etheraddr. */ 501 eaddr[0] = 0x02; 502 eaddr[3] = (ifp->if_index >> 8) & 0xff; 503 eaddr[4] = ifp->if_index & 0xff; 504 eaddr[5] = 0x0b; 505 ether_ifattach(ifp, eaddr); 506 /* Correctly set the name for the cloner list. */ 507 strlcpy(name, scb->ifp->if_xname, len); 508 return (0); 509 } 510 511 /* Try to see if a special unit was requested. */ 512 error = ifc_name2unit(name, &unit); 513 if (error != 0) 514 return (error); 515 wildcard = (unit < 0); 516 517 error = ifc_alloc_unit(ifc, &unit); 518 if (error != 0) 519 return (error); 520 521 /* 522 * If no unit had been given, we need to adjust the ifName. 523 * Also make sure there is space for our extra [ab] suffix. 524 */ 525 for (dp = name; *dp != '\0'; dp++); 526 if (wildcard) { 527 error = snprintf(dp, len - (dp - name), "%d", unit); 528 if (error > len - (dp - name) - 1) { 529 /* ifName too long. */ 530 ifc_free_unit(ifc, unit); 531 return (ENOSPC); 532 } 533 dp += error; 534 } 535 if (len - (dp - name) - 1 < 1) { 536 /* No space left for our [ab] suffix. */ 537 ifc_free_unit(ifc, unit); 538 return (ENOSPC); 539 } 540 *dp = 'a'; 541 /* Must not change dp so we can replace 'a' by 'b' later. */ 542 *(dp+1) = '\0'; 543 544 /* Allocate memory for both [ab] interfaces */ 545 sca = malloc(sizeof(struct epair_softc), M_EPAIR, M_WAITOK | M_ZERO); 546 refcount_init(&sca->refcount, 1); 547 sca->ifp = if_alloc(IFT_ETHER); 548 if (sca->ifp == NULL) { 549 free(sca, M_EPAIR); 550 ifc_free_unit(ifc, unit); 551 return (ENOSPC); 552 } 553 554 scb = malloc(sizeof(struct epair_softc), M_EPAIR, M_WAITOK | M_ZERO); 555 refcount_init(&scb->refcount, 1); 556 scb->ifp = if_alloc(IFT_ETHER); 557 if (scb->ifp == NULL) { 558 free(scb, M_EPAIR); 559 if_free(sca->ifp); 560 free(sca, M_EPAIR); 561 ifc_free_unit(ifc, unit); 562 return (ENOSPC); 563 } 564 565 /* 566 * Cross-reference the interfaces so we will be able to free both. 567 */ 568 sca->oifp = scb->ifp; 569 scb->oifp = sca->ifp; 570 571 /* Finish initialization of interface <n>a. */ 572 ifp = sca->ifp; 573 ifp->if_softc = sca; 574 strlcpy(ifp->if_xname, name, IFNAMSIZ); 575 ifp->if_dname = ifc->ifc_name; 576 ifp->if_dunit = unit; 577 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 578 ifp->if_start = epair_start; 579 ifp->if_ioctl = epair_ioctl; 580 ifp->if_init = epair_init; 581 ifp->if_snd.ifq_maxlen = ifqmaxlen; 582 /* Assign a hopefully unique, locally administered etheraddr. */ 583 eaddr[0] = 0x02; 584 eaddr[3] = (ifp->if_index >> 8) & 0xff; 585 eaddr[4] = ifp->if_index & 0xff; 586 eaddr[5] = 0x0a; 587 ether_ifattach(ifp, eaddr); 588 sca->if_qflush = ifp->if_qflush; 589 ifp->if_qflush = epair_qflush; 590 ifp->if_transmit = epair_transmit; 591 ifp->if_baudrate = IF_Gbps(10UL); /* arbitrary maximum */ 592 593 /* Swap the name and finish initialization of interface <n>b. */ 594 *dp = 'b'; 595 596 ifp = scb->ifp; 597 ifp->if_softc = scb; 598 strlcpy(ifp->if_xname, name, IFNAMSIZ); 599 ifp->if_dname = ifc->ifc_name; 600 ifp->if_dunit = unit; 601 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 602 ifp->if_start = epair_start; 603 ifp->if_ioctl = epair_ioctl; 604 ifp->if_init = epair_init; 605 ifp->if_snd.ifq_maxlen = ifqmaxlen; 606 /* We need to play some tricks here for the second interface. */ 607 strlcpy(name, EPAIRNAME, len); 608 error = if_clone_create(name, len, (caddr_t)scb); 609 if (error) 610 panic("%s: if_clone_createif() for our 2nd iface failed: %d", 611 __func__, error); 612 scb->if_qflush = ifp->if_qflush; 613 ifp->if_qflush = epair_qflush; 614 ifp->if_transmit = epair_transmit; 615 ifp->if_baudrate = IF_Gbps(10UL); /* arbitrary maximum */ 616 617 /* 618 * Restore name to <n>a as the ifp for this will go into the 619 * cloner list for the initial call. 620 */ 621 strlcpy(name, sca->ifp->if_xname, len); 622 DPRINTF("name='%s/%db' created sca=%p scb=%p\n", name, unit, sca, scb); 623 624 /* Tell the world, that we are ready to rock. */ 625 sca->ifp->if_drv_flags |= IFF_DRV_RUNNING; 626 scb->ifp->if_drv_flags |= IFF_DRV_RUNNING; 627 628 return (0); 629 } 630 631 static int 632 epair_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) 633 { 634 struct ifnet *oifp; 635 struct epair_softc *sca, *scb; 636 int unit, error; 637 638 DPRINTF("ifp=%p\n", ifp); 639 640 /* 641 * In case we called into if_clone_destroyif() ourselves 642 * again to remove the second interface, the softc will be 643 * NULL. In that case so not do anything but return success. 644 */ 645 if (ifp->if_softc == NULL) 646 return (0); 647 648 unit = ifp->if_dunit; 649 sca = ifp->if_softc; 650 oifp = sca->oifp; 651 scb = oifp->if_softc; 652 653 DPRINTF("ifp=%p oifp=%p\n", ifp, oifp); 654 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 655 oifp->if_drv_flags &= ~IFF_DRV_RUNNING; 656 ether_ifdetach(oifp); 657 ether_ifdetach(ifp); 658 /* 659 * Wait for all packets to be dispatched to if_input. 660 * The numbers can only go down as the interfaces are 661 * detached so there is no need to use atomics. 662 */ 663 DPRINTF("sca refcnt=%u scb refcnt=%u\n", sca->refcount, scb->refcount); 664 KASSERT(sca->refcount == 1 && scb->refcount == 1, 665 ("%s: sca->refcount!=1: %d || scb->refcount!=1: %d", 666 __func__, sca->refcount, scb->refcount)); 667 668 /* 669 * Get rid of our second half. 670 */ 671 oifp->if_softc = NULL; 672 error = if_clone_destroyif(ifc, oifp); 673 if (error) 674 panic("%s: if_clone_destroyif() for our 2nd iface failed: %d", 675 __func__, error); 676 677 /* Finish cleaning up. Free them and release the unit. */ 678 if_free_type(oifp, IFT_ETHER); 679 if_free_type(ifp, IFT_ETHER); 680 free(scb, M_EPAIR); 681 free(sca, M_EPAIR); 682 ifc_free_unit(ifc, unit); 683 684 return (0); 685 } 686 687 static int 688 epair_modevent(module_t mod, int type, void *data) 689 { 690 int tmp; 691 692 switch (type) { 693 case MOD_LOAD: 694 /* For now limit us to one global mutex and one inq. */ 695 EPAIR_LOCK_INIT(); 696 epair_drv_flags = 0; 697 epairinq.ifq_maxlen = 16 * ifqmaxlen; /* What is a good 16? */ 698 if (TUNABLE_INT_FETCH("net.link.epair.netisr_maxqlen", &tmp)) 699 epairinq.ifq_maxlen = tmp; 700 mtx_init(&epairinq.ifq_mtx, "epair_inq", NULL, MTX_DEF); 701 netisr_register2(NETISR_EPAIR, (netisr_t *)epair_sintr, 702 epair_sintr_drained, &epairinq, 0); 703 if_clone_attach(&epair_cloner); 704 if (bootverbose) 705 printf("%s initialized.\n", EPAIRNAME); 706 break; 707 case MOD_UNLOAD: 708 if_clone_detach(&epair_cloner); 709 netisr_unregister(NETISR_EPAIR); 710 mtx_destroy(&epairinq.ifq_mtx); 711 EPAIR_LOCK_DESTROY(); 712 if (bootverbose) 713 printf("%s unloaded.\n", EPAIRNAME); 714 break; 715 default: 716 return (EOPNOTSUPP); 717 } 718 return (0); 719 } 720 721 static moduledata_t epair_mod = { 722 "if_epair", 723 epair_modevent, 724 0 725 }; 726 727 DECLARE_MODULE(if_epair, epair_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 728 MODULE_VERSION(if_epair, 1); 729