1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2008 The FreeBSD Foundation 5 * Copyright (c) 2009-2021 Bjoern A. Zeeb <bz@FreeBSD.org> 6 * 7 * This software was developed by CK Software GmbH under sponsorship 8 * from the FreeBSD Foundation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * A pair of virtual back-to-back connected ethernet like interfaces 34 * (``two interfaces with a virtual cross-over cable''). 35 * 36 * This is mostly intended to be used to provide connectivity between 37 * different virtual network stack instances. 38 */ 39 40 #include <sys/cdefs.h> 41 __FBSDID("$FreeBSD$"); 42 43 #include <sys/param.h> 44 #include <sys/hash.h> 45 #include <sys/jail.h> 46 #include <sys/kernel.h> 47 #include <sys/libkern.h> 48 #include <sys/malloc.h> 49 #include <sys/mbuf.h> 50 #include <sys/module.h> 51 #include <sys/proc.h> 52 #include <sys/queue.h> 53 #include <sys/smp.h> 54 #include <sys/socket.h> 55 #include <sys/sockio.h> 56 #include <sys/sysctl.h> 57 #include <sys/types.h> 58 #include <sys/buf_ring.h> 59 #include <sys/bus.h> 60 #include <sys/interrupt.h> 61 62 #include <net/bpf.h> 63 #include <net/ethernet.h> 64 #include <net/if.h> 65 #include <net/if_var.h> 66 #include <net/if_clone.h> 67 #include <net/if_media.h> 68 #include <net/if_var.h> 69 #include <net/if_types.h> 70 #include <net/netisr.h> 71 #include <net/vnet.h> 72 73 static int epair_clone_match(struct if_clone *, const char *); 74 static int epair_clone_create(struct if_clone *, char *, size_t, caddr_t); 75 static int epair_clone_destroy(struct if_clone *, struct ifnet *); 76 77 static const char epairname[] = "epair"; 78 #define RXRSIZE 4096 /* Probably overkill by 4-8x. */ 79 80 static MALLOC_DEFINE(M_EPAIR, epairname, 81 "Pair of virtual cross-over connected Ethernet-like interfaces"); 82 83 VNET_DEFINE_STATIC(struct if_clone *, epair_cloner); 84 #define V_epair_cloner VNET(epair_cloner) 85 86 static unsigned int next_index = 0; 87 #define EPAIR_LOCK_INIT() mtx_init(&epair_n_index_mtx, "epairidx", \ 88 NULL, MTX_DEF) 89 #define EPAIR_LOCK_DESTROY() mtx_destroy(&epair_n_index_mtx) 90 #define EPAIR_LOCK() mtx_lock(&epair_n_index_mtx) 91 #define EPAIR_UNLOCK() mtx_unlock(&epair_n_index_mtx) 92 93 static void *swi_cookie[MAXCPU]; /* swi(9). */ 94 static STAILQ_HEAD(, epair_softc) swi_sc[MAXCPU]; 95 96 static struct mtx epair_n_index_mtx; 97 struct epair_softc { 98 struct ifnet *ifp; /* This ifp. */ 99 struct ifnet *oifp; /* other ifp of pair. */ 100 void *swi_cookie; /* swi(9). */ 101 struct buf_ring *rxring[2]; 102 volatile int ridx; /* 0 || 1 */ 103 struct ifmedia media; /* Media config (fake). */ 104 uint32_t cpuidx; 105 STAILQ_ENTRY(epair_softc) entry; 106 }; 107 108 static void 109 epair_clear_mbuf(struct mbuf *m) 110 { 111 /* Remove any CSUM_SND_TAG as ether_input will barf. */ 112 if (m->m_pkthdr.csum_flags & CSUM_SND_TAG) { 113 m_snd_tag_rele(m->m_pkthdr.snd_tag); 114 m->m_pkthdr.snd_tag = NULL; 115 m->m_pkthdr.csum_flags &= ~CSUM_SND_TAG; 116 } 117 118 m_tag_delete_nonpersistent(m); 119 } 120 121 static void 122 epair_if_input(struct epair_softc *sc, int ridx) 123 { 124 struct epoch_tracker et; 125 struct ifnet *ifp; 126 struct mbuf *m; 127 128 ifp = sc->ifp; 129 NET_EPOCH_ENTER(et); 130 do { 131 m = buf_ring_dequeue_sc(sc->rxring[ridx]); 132 if (m == NULL) 133 break; 134 135 MPASS((m->m_pkthdr.csum_flags & CSUM_SND_TAG) == 0); 136 (*ifp->if_input)(ifp, m); 137 138 } while (1); 139 NET_EPOCH_EXIT(et); 140 } 141 142 static void 143 epair_sintr(struct epair_softc *sc) 144 { 145 int ridx, nidx; 146 147 if_ref(sc->ifp); 148 do { 149 ridx = sc->ridx; 150 nidx = (ridx == 0) ? 1 : 0; 151 } while (!atomic_cmpset_int(&sc->ridx, ridx, nidx)); 152 epair_if_input(sc, ridx); 153 154 if_rele(sc->ifp); 155 } 156 157 static void 158 epair_intr(void *arg) 159 { 160 struct epair_softc *sc; 161 uint32_t cpuidx; 162 163 cpuidx = (uintptr_t)arg; 164 /* If this is a problem, this is a read-mostly situation. */ 165 EPAIR_LOCK(); 166 STAILQ_FOREACH(sc, &swi_sc[cpuidx], entry) { 167 /* Do this lockless. */ 168 if (buf_ring_empty(sc->rxring[sc->ridx])) 169 continue; 170 epair_sintr(sc); 171 } 172 EPAIR_UNLOCK(); 173 174 return; 175 } 176 177 static int 178 epair_menq(struct mbuf *m, struct epair_softc *osc) 179 { 180 struct ifnet *ifp, *oifp; 181 int len, ret; 182 int ridx; 183 short mflags; 184 bool was_empty; 185 186 /* 187 * I know this looks weird. We pass the "other sc" as we need that one 188 * and can get both ifps from it as well. 189 */ 190 oifp = osc->ifp; 191 ifp = osc->oifp; 192 193 M_ASSERTPKTHDR(m); 194 epair_clear_mbuf(m); 195 if_setrcvif(m, oifp); 196 M_SETFIB(m, oifp->if_fib); 197 198 /* Save values as once the mbuf is queued, it's not ours anymore. */ 199 len = m->m_pkthdr.len; 200 mflags = m->m_flags; 201 202 MPASS(m->m_nextpkt == NULL); 203 MPASS((m->m_pkthdr.csum_flags & CSUM_SND_TAG) == 0); 204 205 ridx = atomic_load_int(&osc->ridx); 206 was_empty = buf_ring_empty(osc->rxring[ridx]); 207 ret = buf_ring_enqueue(osc->rxring[ridx], m); 208 if (ret != 0) { 209 /* Ring is full. */ 210 m_freem(m); 211 return (0); 212 } 213 214 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 215 /* 216 * IFQ_HANDOFF_ADJ/ip_handoff() update statistics, 217 * but as we bypass all this we have to duplicate 218 * the logic another time. 219 */ 220 if_inc_counter(ifp, IFCOUNTER_OBYTES, len); 221 if (mflags & (M_BCAST|M_MCAST)) 222 if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1); 223 /* Someone else received the packet. */ 224 if_inc_counter(oifp, IFCOUNTER_IPACKETS, 1); 225 226 /* Kick the interrupt handler for the first packet. */ 227 if (was_empty && osc->swi_cookie != NULL) 228 swi_sched(osc->swi_cookie, 0); 229 230 return (0); 231 } 232 233 static void 234 epair_start(struct ifnet *ifp) 235 { 236 struct mbuf *m; 237 struct epair_softc *sc; 238 struct ifnet *oifp; 239 240 /* 241 * We get packets here from ether_output via if_handoff() 242 * and need to put them into the input queue of the oifp 243 * and will put the packet into the receive-queue (rxq) of the 244 * other interface (oifp) of our pair. 245 */ 246 sc = ifp->if_softc; 247 oifp = sc->oifp; 248 sc = oifp->if_softc; 249 for (;;) { 250 IFQ_DEQUEUE(&ifp->if_snd, m); 251 if (m == NULL) 252 break; 253 M_ASSERTPKTHDR(m); 254 BPF_MTAP(ifp, m); 255 256 /* In case either interface is not usable drop the packet. */ 257 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || 258 (ifp->if_flags & IFF_UP) == 0 || 259 (oifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || 260 (oifp->if_flags & IFF_UP) == 0) { 261 m_freem(m); 262 continue; 263 } 264 265 (void) epair_menq(m, sc); 266 } 267 } 268 269 static int 270 epair_transmit(struct ifnet *ifp, struct mbuf *m) 271 { 272 struct epair_softc *sc; 273 struct ifnet *oifp; 274 int error; 275 #ifdef ALTQ 276 int len; 277 short mflags; 278 #endif 279 280 if (m == NULL) 281 return (0); 282 M_ASSERTPKTHDR(m); 283 284 /* 285 * We are not going to use the interface en/dequeue mechanism 286 * on the TX side. We are called from ether_output_frame() 287 * and will put the packet into the receive-queue (rxq) of the 288 * other interface (oifp) of our pair. 289 */ 290 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 291 m_freem(m); 292 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 293 return (ENXIO); 294 } 295 if ((ifp->if_flags & IFF_UP) == 0) { 296 m_freem(m); 297 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 298 return (ENETDOWN); 299 } 300 301 BPF_MTAP(ifp, m); 302 303 /* 304 * In case the outgoing interface is not usable, 305 * drop the packet. 306 */ 307 sc = ifp->if_softc; 308 oifp = sc->oifp; 309 if ((oifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || 310 (oifp->if_flags & IFF_UP) == 0) { 311 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 312 m_freem(m); 313 return (0); 314 } 315 316 #ifdef ALTQ 317 len = m->m_pkthdr.len; 318 mflags = m->m_flags; 319 320 /* Support ALTQ via the classic if_start() path. */ 321 IF_LOCK(&ifp->if_snd); 322 if (ALTQ_IS_ENABLED(&ifp->if_snd)) { 323 ALTQ_ENQUEUE(&ifp->if_snd, m, NULL, error); 324 if (error) 325 if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1); 326 IF_UNLOCK(&ifp->if_snd); 327 if (!error) { 328 if_inc_counter(ifp, IFCOUNTER_OBYTES, len); 329 if (mflags & (M_BCAST|M_MCAST)) 330 if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1); 331 epair_start(ifp); 332 } 333 return (error); 334 } 335 IF_UNLOCK(&ifp->if_snd); 336 #endif 337 338 error = epair_menq(m, oifp->if_softc); 339 return (error); 340 } 341 342 static int 343 epair_media_change(struct ifnet *ifp __unused) 344 { 345 346 /* Do nothing. */ 347 return (0); 348 } 349 350 static void 351 epair_media_status(struct ifnet *ifp __unused, struct ifmediareq *imr) 352 { 353 354 imr->ifm_status = IFM_AVALID | IFM_ACTIVE; 355 imr->ifm_active = IFM_ETHER | IFM_10G_T | IFM_FDX; 356 } 357 358 static int 359 epair_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 360 { 361 struct epair_softc *sc; 362 struct ifreq *ifr; 363 int error; 364 365 ifr = (struct ifreq *)data; 366 switch (cmd) { 367 case SIOCSIFFLAGS: 368 case SIOCADDMULTI: 369 case SIOCDELMULTI: 370 error = 0; 371 break; 372 373 case SIOCSIFMEDIA: 374 case SIOCGIFMEDIA: 375 sc = ifp->if_softc; 376 error = ifmedia_ioctl(ifp, ifr, &sc->media, cmd); 377 break; 378 379 case SIOCSIFMTU: 380 /* We basically allow all kinds of MTUs. */ 381 ifp->if_mtu = ifr->ifr_mtu; 382 error = 0; 383 break; 384 385 default: 386 /* Let the common ethernet handler process this. */ 387 error = ether_ioctl(ifp, cmd, data); 388 break; 389 } 390 391 return (error); 392 } 393 394 static void 395 epair_init(void *dummy __unused) 396 { 397 } 398 399 /* 400 * Interface cloning functions. 401 * We use our private ones so that we can create/destroy our secondary 402 * device along with the primary one. 403 */ 404 static int 405 epair_clone_match(struct if_clone *ifc, const char *name) 406 { 407 const char *cp; 408 409 /* 410 * Our base name is epair. 411 * Our interfaces will be named epair<n>[ab]. 412 * So accept anything of the following list: 413 * - epair 414 * - epair<n> 415 * but not the epair<n>[ab] versions. 416 */ 417 if (strncmp(epairname, name, sizeof(epairname)-1) != 0) 418 return (0); 419 420 for (cp = name + sizeof(epairname) - 1; *cp != '\0'; cp++) { 421 if (*cp < '0' || *cp > '9') 422 return (0); 423 } 424 425 return (1); 426 } 427 428 static void 429 epair_clone_add(struct if_clone *ifc, struct epair_softc *scb) 430 { 431 struct ifnet *ifp; 432 uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ 433 434 ifp = scb->ifp; 435 /* Copy epairNa etheraddr and change the last byte. */ 436 memcpy(eaddr, scb->oifp->if_hw_addr, ETHER_ADDR_LEN); 437 eaddr[5] = 0x0b; 438 ether_ifattach(ifp, eaddr); 439 440 if_clone_addif(ifc, ifp); 441 } 442 443 static int 444 epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) 445 { 446 struct epair_softc *sca, *scb; 447 struct ifnet *ifp; 448 char *dp; 449 int error, unit, wildcard; 450 uint64_t hostid; 451 uint32_t key[3]; 452 uint32_t hash; 453 uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ 454 455 /* Try to see if a special unit was requested. */ 456 error = ifc_name2unit(name, &unit); 457 if (error != 0) 458 return (error); 459 wildcard = (unit < 0); 460 461 error = ifc_alloc_unit(ifc, &unit); 462 if (error != 0) 463 return (error); 464 465 /* 466 * If no unit had been given, we need to adjust the ifName. 467 * Also make sure there is space for our extra [ab] suffix. 468 */ 469 for (dp = name; *dp != '\0'; dp++); 470 if (wildcard) { 471 error = snprintf(dp, len - (dp - name), "%d", unit); 472 if (error > len - (dp - name) - 1) { 473 /* ifName too long. */ 474 ifc_free_unit(ifc, unit); 475 return (ENOSPC); 476 } 477 dp += error; 478 } 479 if (len - (dp - name) - 1 < 1) { 480 /* No space left for our [ab] suffix. */ 481 ifc_free_unit(ifc, unit); 482 return (ENOSPC); 483 } 484 *dp = 'b'; 485 /* Must not change dp so we can replace 'a' by 'b' later. */ 486 *(dp+1) = '\0'; 487 488 /* Check if 'a' and 'b' interfaces already exist. */ 489 if (ifunit(name) != NULL) 490 return (EEXIST); 491 *dp = 'a'; 492 if (ifunit(name) != NULL) 493 return (EEXIST); 494 495 /* Allocate memory for both [ab] interfaces */ 496 sca = malloc(sizeof(struct epair_softc), M_EPAIR, M_WAITOK | M_ZERO); 497 sca->ifp = if_alloc(IFT_ETHER); 498 if (sca->ifp == NULL) { 499 free(sca, M_EPAIR); 500 ifc_free_unit(ifc, unit); 501 return (ENOSPC); 502 } 503 sca->rxring[0] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK,NULL); 504 sca->rxring[1] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); 505 506 scb = malloc(sizeof(struct epair_softc), M_EPAIR, M_WAITOK | M_ZERO); 507 scb->ifp = if_alloc(IFT_ETHER); 508 if (scb->ifp == NULL) { 509 free(scb, M_EPAIR); 510 if_free(sca->ifp); 511 free(sca, M_EPAIR); 512 ifc_free_unit(ifc, unit); 513 return (ENOSPC); 514 } 515 scb->rxring[0] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); 516 scb->rxring[1] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); 517 518 /* 519 * Cross-reference the interfaces so we will be able to free both. 520 */ 521 sca->oifp = scb->ifp; 522 scb->oifp = sca->ifp; 523 524 EPAIR_LOCK(); 525 #ifdef SMP 526 /* Get an approximate distribution. */ 527 hash = next_index % mp_ncpus; 528 #else 529 hash = 0; 530 #endif 531 if (swi_cookie[hash] == NULL) { 532 void *cookie; 533 534 EPAIR_UNLOCK(); 535 error = swi_add(NULL, epairname, 536 epair_intr, (void *)(uintptr_t)hash, 537 SWI_NET, INTR_MPSAFE, &cookie); 538 if (error) { 539 buf_ring_free(scb->rxring[0], M_EPAIR); 540 buf_ring_free(scb->rxring[1], M_EPAIR); 541 if_free(scb->ifp); 542 free(scb, M_EPAIR); 543 buf_ring_free(sca->rxring[0], M_EPAIR); 544 buf_ring_free(sca->rxring[1], M_EPAIR); 545 if_free(sca->ifp); 546 free(sca, M_EPAIR); 547 ifc_free_unit(ifc, unit); 548 return (ENOSPC); 549 } 550 EPAIR_LOCK(); 551 /* Recheck under lock even though a race is very unlikely. */ 552 if (swi_cookie[hash] == NULL) { 553 swi_cookie[hash] = cookie; 554 } else { 555 EPAIR_UNLOCK(); 556 (void) swi_remove(cookie); 557 EPAIR_LOCK(); 558 } 559 } 560 sca->cpuidx = hash; 561 STAILQ_INSERT_TAIL(&swi_sc[hash], sca, entry); 562 sca->swi_cookie = swi_cookie[hash]; 563 scb->cpuidx = hash; 564 STAILQ_INSERT_TAIL(&swi_sc[hash], scb, entry); 565 scb->swi_cookie = swi_cookie[hash]; 566 EPAIR_UNLOCK(); 567 568 /* Initialise pseudo media types. */ 569 ifmedia_init(&sca->media, 0, epair_media_change, epair_media_status); 570 ifmedia_add(&sca->media, IFM_ETHER | IFM_10G_T, 0, NULL); 571 ifmedia_set(&sca->media, IFM_ETHER | IFM_10G_T); 572 ifmedia_init(&scb->media, 0, epair_media_change, epair_media_status); 573 ifmedia_add(&scb->media, IFM_ETHER | IFM_10G_T, 0, NULL); 574 ifmedia_set(&scb->media, IFM_ETHER | IFM_10G_T); 575 576 /* Finish initialization of interface <n>a. */ 577 ifp = sca->ifp; 578 ifp->if_softc = sca; 579 strlcpy(ifp->if_xname, name, IFNAMSIZ); 580 ifp->if_dname = epairname; 581 ifp->if_dunit = unit; 582 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 583 ifp->if_flags |= IFF_KNOWSEPOCH; 584 ifp->if_capabilities = IFCAP_VLAN_MTU; 585 ifp->if_capenable = IFCAP_VLAN_MTU; 586 ifp->if_start = epair_start; 587 ifp->if_ioctl = epair_ioctl; 588 ifp->if_init = epair_init; 589 if_setsendqlen(ifp, ifqmaxlen); 590 if_setsendqready(ifp); 591 592 /* 593 * Calculate the etheraddr hashing the hostid and the 594 * interface index. The result would be hopefully unique. 595 * Note that the "a" component of an epair instance may get moved 596 * to a different VNET after creation. In that case its index 597 * will be freed and the index can get reused by new epair instance. 598 * Make sure we do not create same etheraddr again. 599 */ 600 getcredhostid(curthread->td_ucred, (unsigned long *)&hostid); 601 if (hostid == 0) 602 arc4rand(&hostid, sizeof(hostid), 0); 603 604 EPAIR_LOCK(); 605 if (ifp->if_index > next_index) 606 next_index = ifp->if_index; 607 else 608 next_index++; 609 610 key[0] = (uint32_t)next_index; 611 EPAIR_UNLOCK(); 612 key[1] = (uint32_t)(hostid & 0xffffffff); 613 key[2] = (uint32_t)((hostid >> 32) & 0xfffffffff); 614 hash = jenkins_hash32(key, 3, 0); 615 616 eaddr[0] = 0x02; 617 memcpy(&eaddr[1], &hash, 4); 618 eaddr[5] = 0x0a; 619 ether_ifattach(ifp, eaddr); 620 ifp->if_baudrate = IF_Gbps(10); /* arbitrary maximum */ 621 ifp->if_transmit = epair_transmit; 622 623 /* Swap the name and finish initialization of interface <n>b. */ 624 *dp = 'b'; 625 626 ifp = scb->ifp; 627 ifp->if_softc = scb; 628 strlcpy(ifp->if_xname, name, IFNAMSIZ); 629 ifp->if_dname = epairname; 630 ifp->if_dunit = unit; 631 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 632 ifp->if_flags |= IFF_KNOWSEPOCH; 633 ifp->if_capabilities = IFCAP_VLAN_MTU; 634 ifp->if_capenable = IFCAP_VLAN_MTU; 635 ifp->if_start = epair_start; 636 ifp->if_ioctl = epair_ioctl; 637 ifp->if_init = epair_init; 638 if_setsendqlen(ifp, ifqmaxlen); 639 if_setsendqready(ifp); 640 /* We need to play some tricks here for the second interface. */ 641 strlcpy(name, epairname, len); 642 643 /* Correctly set the name for the cloner list. */ 644 strlcpy(name, scb->ifp->if_xname, len); 645 epair_clone_add(ifc, scb); 646 647 ifp->if_baudrate = IF_Gbps(10); /* arbitrary maximum */ 648 ifp->if_transmit = epair_transmit; 649 650 /* 651 * Restore name to <n>a as the ifp for this will go into the 652 * cloner list for the initial call. 653 */ 654 strlcpy(name, sca->ifp->if_xname, len); 655 656 /* Tell the world, that we are ready to rock. */ 657 sca->ifp->if_drv_flags |= IFF_DRV_RUNNING; 658 if_link_state_change(sca->ifp, LINK_STATE_UP); 659 scb->ifp->if_drv_flags |= IFF_DRV_RUNNING; 660 if_link_state_change(scb->ifp, LINK_STATE_UP); 661 662 return (0); 663 } 664 665 static void 666 epair_drain_rings(struct epair_softc *sc) 667 { 668 int ridx; 669 struct mbuf *m; 670 671 for (ridx = 0; ridx < 2; ridx++) { 672 do { 673 m = buf_ring_dequeue_sc(sc->rxring[ridx]); 674 if (m == NULL) 675 break; 676 m_freem(m); 677 } while (1); 678 } 679 } 680 681 static int 682 epair_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) 683 { 684 struct ifnet *oifp; 685 struct epair_softc *sca, *scb; 686 int unit, error; 687 688 /* 689 * In case we called into if_clone_destroyif() ourselves 690 * again to remove the second interface, the softc will be 691 * NULL. In that case so not do anything but return success. 692 */ 693 if (ifp->if_softc == NULL) 694 return (0); 695 696 unit = ifp->if_dunit; 697 sca = ifp->if_softc; 698 oifp = sca->oifp; 699 scb = oifp->if_softc; 700 701 /* Frist get the interfaces down and detached. */ 702 if_link_state_change(ifp, LINK_STATE_DOWN); 703 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 704 if_link_state_change(oifp, LINK_STATE_DOWN); 705 oifp->if_drv_flags &= ~IFF_DRV_RUNNING; 706 707 ether_ifdetach(ifp); 708 ether_ifdetach(oifp); 709 710 /* Second stop interrupt handler. */ 711 EPAIR_LOCK(); 712 STAILQ_REMOVE(&swi_sc[sca->cpuidx], sca, epair_softc, entry); 713 STAILQ_REMOVE(&swi_sc[scb->cpuidx], scb, epair_softc, entry); 714 EPAIR_UNLOCK(); 715 sca->swi_cookie = NULL; 716 scb->swi_cookie = NULL; 717 718 /* Third free any queued packets and all the resources. */ 719 CURVNET_SET_QUIET(oifp->if_vnet); 720 epair_drain_rings(scb); 721 oifp->if_softc = NULL; 722 error = if_clone_destroyif(ifc, oifp); 723 if (error) 724 panic("%s: if_clone_destroyif() for our 2nd iface failed: %d", 725 __func__, error); 726 if_free(oifp); 727 ifmedia_removeall(&scb->media); 728 buf_ring_free(scb->rxring[0], M_EPAIR); 729 buf_ring_free(scb->rxring[1], M_EPAIR); 730 free(scb, M_EPAIR); 731 CURVNET_RESTORE(); 732 733 epair_drain_rings(sca); 734 if_free(ifp); 735 ifmedia_removeall(&sca->media); 736 buf_ring_free(sca->rxring[0], M_EPAIR); 737 buf_ring_free(sca->rxring[1], M_EPAIR); 738 free(sca, M_EPAIR); 739 740 /* Last free the cloner unit. */ 741 ifc_free_unit(ifc, unit); 742 743 return (0); 744 } 745 746 static void 747 vnet_epair_init(const void *unused __unused) 748 { 749 750 V_epair_cloner = if_clone_advanced(epairname, 0, 751 epair_clone_match, epair_clone_create, epair_clone_destroy); 752 } 753 VNET_SYSINIT(vnet_epair_init, SI_SUB_PSEUDO, SI_ORDER_ANY, 754 vnet_epair_init, NULL); 755 756 static void 757 vnet_epair_uninit(const void *unused __unused) 758 { 759 760 if_clone_detach(V_epair_cloner); 761 } 762 VNET_SYSUNINIT(vnet_epair_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY, 763 vnet_epair_uninit, NULL); 764 765 static int 766 epair_modevent(module_t mod, int type, void *data) 767 { 768 int i; 769 770 switch (type) { 771 case MOD_LOAD: 772 for (i = 0; i < MAXCPU; i++) { 773 swi_cookie[i] = NULL; 774 STAILQ_INIT(&swi_sc[i]); 775 } 776 EPAIR_LOCK_INIT(); 777 if (bootverbose) 778 printf("%s: %s initialized.\n", __func__, epairname); 779 break; 780 case MOD_UNLOAD: 781 EPAIR_LOCK(); 782 for (i = 0; i < MAXCPU; i++) { 783 if (!STAILQ_EMPTY(&swi_sc[i])) { 784 printf("%s: swi_sc[%d] active\n", __func__, i); 785 EPAIR_UNLOCK(); 786 return (EBUSY); 787 } 788 } 789 EPAIR_UNLOCK(); 790 for (i = 0; i < MAXCPU; i++) 791 if (swi_cookie[i] != NULL) 792 (void) swi_remove(swi_cookie[i]); 793 EPAIR_LOCK_DESTROY(); 794 if (bootverbose) 795 printf("%s: %s unloaded.\n", __func__, epairname); 796 break; 797 default: 798 return (EOPNOTSUPP); 799 } 800 return (0); 801 } 802 803 static moduledata_t epair_mod = { 804 "if_epair", 805 epair_modevent, 806 0 807 }; 808 809 DECLARE_MODULE(if_epair, epair_mod, SI_SUB_PSEUDO, SI_ORDER_MIDDLE); 810 MODULE_VERSION(if_epair, 3); 811