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 "opt_rss.h" 44 #include "opt_inet.h" 45 #include "opt_inet6.h" 46 47 #include <sys/param.h> 48 #include <sys/hash.h> 49 #include <sys/jail.h> 50 #include <sys/kernel.h> 51 #include <sys/libkern.h> 52 #include <sys/malloc.h> 53 #include <sys/mbuf.h> 54 #include <sys/module.h> 55 #include <sys/proc.h> 56 #include <sys/queue.h> 57 #include <sys/sched.h> 58 #include <sys/smp.h> 59 #include <sys/socket.h> 60 #include <sys/sockio.h> 61 #include <sys/taskqueue.h> 62 #include <sys/types.h> 63 #include <sys/buf_ring.h> 64 #include <sys/bus.h> 65 #include <sys/interrupt.h> 66 67 #include <net/bpf.h> 68 #include <net/ethernet.h> 69 #include <net/if.h> 70 #include <net/if_var.h> 71 #include <net/if_clone.h> 72 #include <net/if_media.h> 73 #include <net/if_var.h> 74 #include <net/if_types.h> 75 #include <net/netisr.h> 76 #ifdef RSS 77 #include <net/rss_config.h> 78 #ifdef INET 79 #include <netinet/in_rss.h> 80 #endif 81 #ifdef INET6 82 #include <netinet6/in6_rss.h> 83 #endif 84 #endif 85 #include <net/vnet.h> 86 87 static int epair_clone_match(struct if_clone *, const char *); 88 static int epair_clone_create(struct if_clone *, char *, size_t, caddr_t); 89 static int epair_clone_destroy(struct if_clone *, struct ifnet *); 90 91 static const char epairname[] = "epair"; 92 #define RXRSIZE 4096 /* Probably overkill by 4-8x. */ 93 94 static MALLOC_DEFINE(M_EPAIR, epairname, 95 "Pair of virtual cross-over connected Ethernet-like interfaces"); 96 97 VNET_DEFINE_STATIC(struct if_clone *, epair_cloner); 98 #define V_epair_cloner VNET(epair_cloner) 99 100 static unsigned int next_index = 0; 101 #define EPAIR_LOCK_INIT() mtx_init(&epair_n_index_mtx, "epairidx", \ 102 NULL, MTX_DEF) 103 #define EPAIR_LOCK_DESTROY() mtx_destroy(&epair_n_index_mtx) 104 #define EPAIR_LOCK() mtx_lock(&epair_n_index_mtx) 105 #define EPAIR_UNLOCK() mtx_unlock(&epair_n_index_mtx) 106 107 #define BIT_QUEUE_TASK 0 108 #define BIT_MBUF_QUEUED 1 109 110 struct epair_softc; 111 struct epair_queue { 112 int id; 113 struct buf_ring *rxring[2]; 114 volatile int ridx; /* 0 || 1 */ 115 volatile long state; /* taskqueue coordination */ 116 struct task tx_task; 117 struct epair_softc *sc; 118 }; 119 120 static struct mtx epair_n_index_mtx; 121 struct epair_softc { 122 struct ifnet *ifp; /* This ifp. */ 123 struct ifnet *oifp; /* other ifp of pair. */ 124 int num_queues; 125 struct epair_queue *queues; 126 struct ifmedia media; /* Media config (fake). */ 127 STAILQ_ENTRY(epair_softc) entry; 128 }; 129 130 struct epair_tasks_t { 131 int tasks; 132 struct taskqueue *tq[MAXCPU]; 133 }; 134 135 static struct epair_tasks_t epair_tasks; 136 137 static void 138 epair_clear_mbuf(struct mbuf *m) 139 { 140 /* Remove any CSUM_SND_TAG as ether_input will barf. */ 141 if (m->m_pkthdr.csum_flags & CSUM_SND_TAG) { 142 m_snd_tag_rele(m->m_pkthdr.snd_tag); 143 m->m_pkthdr.snd_tag = NULL; 144 m->m_pkthdr.csum_flags &= ~CSUM_SND_TAG; 145 } 146 147 m_tag_delete_nonpersistent(m); 148 } 149 150 static void 151 epair_if_input(struct epair_softc *sc, struct epair_queue *q, int ridx) 152 { 153 struct ifnet *ifp; 154 struct mbuf *m; 155 156 ifp = sc->ifp; 157 CURVNET_SET(ifp->if_vnet); 158 while (! buf_ring_empty(q->rxring[ridx])) { 159 m = buf_ring_dequeue_mc(q->rxring[ridx]); 160 if (m == NULL) 161 continue; 162 163 MPASS((m->m_pkthdr.csum_flags & CSUM_SND_TAG) == 0); 164 (*ifp->if_input)(ifp, m); 165 166 } 167 CURVNET_RESTORE(); 168 } 169 170 static void 171 epair_tx_start_deferred(void *arg, int pending) 172 { 173 struct epair_queue *q = (struct epair_queue *)arg; 174 struct epair_softc *sc = q->sc; 175 int ridx, nidx; 176 177 if_ref(sc->ifp); 178 ridx = atomic_load_int(&q->ridx); 179 do { 180 nidx = (ridx == 0) ? 1 : 0; 181 } while (!atomic_fcmpset_int(&q->ridx, &ridx, nidx)); 182 epair_if_input(sc, q, ridx); 183 184 atomic_clear_long(&q->state, (1 << BIT_QUEUE_TASK)); 185 if (atomic_testandclear_long(&q->state, BIT_MBUF_QUEUED)) 186 taskqueue_enqueue(epair_tasks.tq[q->id], &q->tx_task); 187 188 if_rele(sc->ifp); 189 } 190 191 static int 192 epair_menq(struct mbuf *m, struct epair_softc *osc) 193 { 194 struct ifnet *ifp, *oifp; 195 int len, ret; 196 int ridx; 197 short mflags; 198 struct epair_queue *q = NULL; 199 uint32_t bucket; 200 #ifdef RSS 201 struct ether_header *eh; 202 #endif 203 204 /* 205 * I know this looks weird. We pass the "other sc" as we need that one 206 * and can get both ifps from it as well. 207 */ 208 oifp = osc->ifp; 209 ifp = osc->oifp; 210 211 M_ASSERTPKTHDR(m); 212 epair_clear_mbuf(m); 213 if_setrcvif(m, oifp); 214 M_SETFIB(m, oifp->if_fib); 215 216 /* Save values as once the mbuf is queued, it's not ours anymore. */ 217 len = m->m_pkthdr.len; 218 mflags = m->m_flags; 219 220 MPASS(m->m_nextpkt == NULL); 221 MPASS((m->m_pkthdr.csum_flags & CSUM_SND_TAG) == 0); 222 223 #ifdef RSS 224 ret = rss_m2bucket(m, &bucket); 225 if (ret) { 226 /* Actually hash the packet. */ 227 eh = mtod(m, struct ether_header *); 228 229 switch (ntohs(eh->ether_type)) { 230 #ifdef INET 231 case ETHERTYPE_IP: 232 rss_soft_m2cpuid_v4(m, 0, &bucket); 233 break; 234 #endif 235 #ifdef INET6 236 case ETHERTYPE_IPV6: 237 rss_soft_m2cpuid_v6(m, 0, &bucket); 238 break; 239 #endif 240 default: 241 bucket = 0; 242 break; 243 } 244 } 245 bucket %= osc->num_queues; 246 #else 247 bucket = 0; 248 #endif 249 q = &osc->queues[bucket]; 250 251 atomic_set_long(&q->state, (1 << BIT_MBUF_QUEUED)); 252 ridx = atomic_load_int(&q->ridx); 253 ret = buf_ring_enqueue(q->rxring[ridx], m); 254 if (ret != 0) { 255 /* Ring is full. */ 256 if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1); 257 m_freem(m); 258 return (0); 259 } 260 261 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 262 /* 263 * IFQ_HANDOFF_ADJ/ip_handoff() update statistics, 264 * but as we bypass all this we have to duplicate 265 * the logic another time. 266 */ 267 if_inc_counter(ifp, IFCOUNTER_OBYTES, len); 268 if (mflags & (M_BCAST|M_MCAST)) 269 if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1); 270 /* Someone else received the packet. */ 271 if_inc_counter(oifp, IFCOUNTER_IPACKETS, 1); 272 273 if (!atomic_testandset_long(&q->state, BIT_QUEUE_TASK)) 274 taskqueue_enqueue(epair_tasks.tq[bucket], &q->tx_task); 275 276 return (0); 277 } 278 279 static void 280 epair_start(struct ifnet *ifp) 281 { 282 struct mbuf *m; 283 struct epair_softc *sc; 284 struct ifnet *oifp; 285 286 /* 287 * We get packets here from ether_output via if_handoff() 288 * and need to put them into the input queue of the oifp 289 * and will put the packet into the receive-queue (rxq) of the 290 * other interface (oifp) of our pair. 291 */ 292 sc = ifp->if_softc; 293 oifp = sc->oifp; 294 sc = oifp->if_softc; 295 for (;;) { 296 IFQ_DEQUEUE(&ifp->if_snd, m); 297 if (m == NULL) 298 break; 299 M_ASSERTPKTHDR(m); 300 BPF_MTAP(ifp, m); 301 302 /* In case either interface is not usable drop the packet. */ 303 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || 304 (ifp->if_flags & IFF_UP) == 0 || 305 (oifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || 306 (oifp->if_flags & IFF_UP) == 0) { 307 m_freem(m); 308 continue; 309 } 310 311 (void) epair_menq(m, sc); 312 } 313 } 314 315 static int 316 epair_transmit(struct ifnet *ifp, struct mbuf *m) 317 { 318 struct epair_softc *sc; 319 struct ifnet *oifp; 320 int error; 321 #ifdef ALTQ 322 int len; 323 short mflags; 324 #endif 325 326 if (m == NULL) 327 return (0); 328 M_ASSERTPKTHDR(m); 329 330 /* 331 * We are not going to use the interface en/dequeue mechanism 332 * on the TX side. We are called from ether_output_frame() 333 * and will put the packet into the receive-queue (rxq) of the 334 * other interface (oifp) of our pair. 335 */ 336 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 337 m_freem(m); 338 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 339 return (ENXIO); 340 } 341 if ((ifp->if_flags & IFF_UP) == 0) { 342 m_freem(m); 343 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 344 return (ENETDOWN); 345 } 346 347 BPF_MTAP(ifp, m); 348 349 /* 350 * In case the outgoing interface is not usable, 351 * drop the packet. 352 */ 353 sc = ifp->if_softc; 354 oifp = sc->oifp; 355 if ((oifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || 356 (oifp->if_flags & IFF_UP) == 0) { 357 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 358 m_freem(m); 359 return (0); 360 } 361 362 #ifdef ALTQ 363 len = m->m_pkthdr.len; 364 mflags = m->m_flags; 365 366 /* Support ALTQ via the classic if_start() path. */ 367 IF_LOCK(&ifp->if_snd); 368 if (ALTQ_IS_ENABLED(&ifp->if_snd)) { 369 ALTQ_ENQUEUE(&ifp->if_snd, m, NULL, error); 370 if (error) 371 if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1); 372 IF_UNLOCK(&ifp->if_snd); 373 if (!error) { 374 if_inc_counter(ifp, IFCOUNTER_OBYTES, len); 375 if (mflags & (M_BCAST|M_MCAST)) 376 if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1); 377 epair_start(ifp); 378 } 379 return (error); 380 } 381 IF_UNLOCK(&ifp->if_snd); 382 #endif 383 384 error = epair_menq(m, oifp->if_softc); 385 return (error); 386 } 387 388 static int 389 epair_media_change(struct ifnet *ifp __unused) 390 { 391 392 /* Do nothing. */ 393 return (0); 394 } 395 396 static void 397 epair_media_status(struct ifnet *ifp __unused, struct ifmediareq *imr) 398 { 399 400 imr->ifm_status = IFM_AVALID | IFM_ACTIVE; 401 imr->ifm_active = IFM_ETHER | IFM_10G_T | IFM_FDX; 402 } 403 404 static int 405 epair_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 406 { 407 struct epair_softc *sc; 408 struct ifreq *ifr; 409 int error; 410 411 ifr = (struct ifreq *)data; 412 switch (cmd) { 413 case SIOCSIFFLAGS: 414 case SIOCADDMULTI: 415 case SIOCDELMULTI: 416 error = 0; 417 break; 418 419 case SIOCSIFMEDIA: 420 case SIOCGIFMEDIA: 421 sc = ifp->if_softc; 422 error = ifmedia_ioctl(ifp, ifr, &sc->media, cmd); 423 break; 424 425 case SIOCSIFMTU: 426 /* We basically allow all kinds of MTUs. */ 427 ifp->if_mtu = ifr->ifr_mtu; 428 error = 0; 429 break; 430 431 default: 432 /* Let the common ethernet handler process this. */ 433 error = ether_ioctl(ifp, cmd, data); 434 break; 435 } 436 437 return (error); 438 } 439 440 static void 441 epair_init(void *dummy __unused) 442 { 443 } 444 445 /* 446 * Interface cloning functions. 447 * We use our private ones so that we can create/destroy our secondary 448 * device along with the primary one. 449 */ 450 static int 451 epair_clone_match(struct if_clone *ifc, const char *name) 452 { 453 const char *cp; 454 455 /* 456 * Our base name is epair. 457 * Our interfaces will be named epair<n>[ab]. 458 * So accept anything of the following list: 459 * - epair 460 * - epair<n> 461 * but not the epair<n>[ab] versions. 462 */ 463 if (strncmp(epairname, name, sizeof(epairname)-1) != 0) 464 return (0); 465 466 for (cp = name + sizeof(epairname) - 1; *cp != '\0'; cp++) { 467 if (*cp < '0' || *cp > '9') 468 return (0); 469 } 470 471 return (1); 472 } 473 474 static void 475 epair_clone_add(struct if_clone *ifc, struct epair_softc *scb) 476 { 477 struct ifnet *ifp; 478 uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ 479 480 ifp = scb->ifp; 481 /* Copy epairNa etheraddr and change the last byte. */ 482 memcpy(eaddr, scb->oifp->if_hw_addr, ETHER_ADDR_LEN); 483 eaddr[5] = 0x0b; 484 ether_ifattach(ifp, eaddr); 485 486 if_clone_addif(ifc, ifp); 487 } 488 489 static int 490 epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) 491 { 492 struct epair_softc *sca, *scb; 493 struct ifnet *ifp; 494 char *dp; 495 int error, unit, wildcard; 496 uint64_t hostid; 497 uint32_t key[3]; 498 uint32_t hash; 499 uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ 500 501 /* Try to see if a special unit was requested. */ 502 error = ifc_name2unit(name, &unit); 503 if (error != 0) 504 return (error); 505 wildcard = (unit < 0); 506 507 error = ifc_alloc_unit(ifc, &unit); 508 if (error != 0) 509 return (error); 510 511 /* 512 * If no unit had been given, we need to adjust the ifName. 513 * Also make sure there is space for our extra [ab] suffix. 514 */ 515 for (dp = name; *dp != '\0'; dp++); 516 if (wildcard) { 517 error = snprintf(dp, len - (dp - name), "%d", unit); 518 if (error > len - (dp - name) - 1) { 519 /* ifName too long. */ 520 ifc_free_unit(ifc, unit); 521 return (ENOSPC); 522 } 523 dp += error; 524 } 525 if (len - (dp - name) - 1 < 1) { 526 /* No space left for our [ab] suffix. */ 527 ifc_free_unit(ifc, unit); 528 return (ENOSPC); 529 } 530 *dp = 'b'; 531 /* Must not change dp so we can replace 'a' by 'b' later. */ 532 *(dp+1) = '\0'; 533 534 /* Check if 'a' and 'b' interfaces already exist. */ 535 if (ifunit(name) != NULL) 536 return (EEXIST); 537 *dp = 'a'; 538 if (ifunit(name) != NULL) 539 return (EEXIST); 540 541 /* Allocate memory for both [ab] interfaces */ 542 sca = malloc(sizeof(struct epair_softc), M_EPAIR, M_WAITOK | M_ZERO); 543 sca->ifp = if_alloc(IFT_ETHER); 544 sca->num_queues = epair_tasks.tasks; 545 if (sca->ifp == NULL) { 546 free(sca, M_EPAIR); 547 ifc_free_unit(ifc, unit); 548 return (ENOSPC); 549 } 550 sca->queues = mallocarray(sca->num_queues, sizeof(struct epair_queue), 551 M_EPAIR, M_WAITOK); 552 for (int i = 0; i < sca->num_queues; i++) { 553 struct epair_queue *q = &sca->queues[i]; 554 q->id = i; 555 q->rxring[0] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); 556 q->rxring[1] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); 557 q->ridx = 0; 558 q->state = 0; 559 q->sc = sca; 560 NET_TASK_INIT(&q->tx_task, 0, epair_tx_start_deferred, q); 561 } 562 563 scb = malloc(sizeof(struct epair_softc), M_EPAIR, M_WAITOK | M_ZERO); 564 scb->ifp = if_alloc(IFT_ETHER); 565 scb->num_queues = epair_tasks.tasks; 566 if (scb->ifp == NULL) { 567 free(scb, M_EPAIR); 568 if_free(sca->ifp); 569 free(sca, M_EPAIR); 570 ifc_free_unit(ifc, unit); 571 return (ENOSPC); 572 } 573 scb->queues = mallocarray(scb->num_queues, sizeof(struct epair_queue), 574 M_EPAIR, M_WAITOK); 575 for (int i = 0; i < scb->num_queues; i++) { 576 struct epair_queue *q = &scb->queues[i]; 577 q->id = i; 578 q->rxring[0] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); 579 q->rxring[1] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); 580 q->ridx = 0; 581 q->state = 0; 582 q->sc = scb; 583 NET_TASK_INIT(&q->tx_task, 0, epair_tx_start_deferred, q); 584 } 585 586 /* 587 * Cross-reference the interfaces so we will be able to free both. 588 */ 589 sca->oifp = scb->ifp; 590 scb->oifp = sca->ifp; 591 592 EPAIR_LOCK(); 593 #ifdef SMP 594 /* Get an approximate distribution. */ 595 hash = next_index % mp_ncpus; 596 #else 597 hash = 0; 598 #endif 599 EPAIR_UNLOCK(); 600 601 /* Initialise pseudo media types. */ 602 ifmedia_init(&sca->media, 0, epair_media_change, epair_media_status); 603 ifmedia_add(&sca->media, IFM_ETHER | IFM_10G_T, 0, NULL); 604 ifmedia_set(&sca->media, IFM_ETHER | IFM_10G_T); 605 ifmedia_init(&scb->media, 0, epair_media_change, epair_media_status); 606 ifmedia_add(&scb->media, IFM_ETHER | IFM_10G_T, 0, NULL); 607 ifmedia_set(&scb->media, IFM_ETHER | IFM_10G_T); 608 609 /* Finish initialization of interface <n>a. */ 610 ifp = sca->ifp; 611 ifp->if_softc = sca; 612 strlcpy(ifp->if_xname, name, IFNAMSIZ); 613 ifp->if_dname = epairname; 614 ifp->if_dunit = unit; 615 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 616 ifp->if_flags |= IFF_KNOWSEPOCH; 617 ifp->if_capabilities = IFCAP_VLAN_MTU; 618 ifp->if_capenable = IFCAP_VLAN_MTU; 619 ifp->if_start = epair_start; 620 ifp->if_ioctl = epair_ioctl; 621 ifp->if_init = epair_init; 622 if_setsendqlen(ifp, ifqmaxlen); 623 if_setsendqready(ifp); 624 625 /* 626 * Calculate the etheraddr hashing the hostid and the 627 * interface index. The result would be hopefully unique. 628 * Note that the "a" component of an epair instance may get moved 629 * to a different VNET after creation. In that case its index 630 * will be freed and the index can get reused by new epair instance. 631 * Make sure we do not create same etheraddr again. 632 */ 633 getcredhostid(curthread->td_ucred, (unsigned long *)&hostid); 634 if (hostid == 0) 635 arc4rand(&hostid, sizeof(hostid), 0); 636 637 EPAIR_LOCK(); 638 if (ifp->if_index > next_index) 639 next_index = ifp->if_index; 640 else 641 next_index++; 642 643 key[0] = (uint32_t)next_index; 644 EPAIR_UNLOCK(); 645 key[1] = (uint32_t)(hostid & 0xffffffff); 646 key[2] = (uint32_t)((hostid >> 32) & 0xfffffffff); 647 hash = jenkins_hash32(key, 3, 0); 648 649 eaddr[0] = 0x02; 650 memcpy(&eaddr[1], &hash, 4); 651 eaddr[5] = 0x0a; 652 ether_ifattach(ifp, eaddr); 653 ifp->if_baudrate = IF_Gbps(10); /* arbitrary maximum */ 654 ifp->if_transmit = epair_transmit; 655 656 /* Swap the name and finish initialization of interface <n>b. */ 657 *dp = 'b'; 658 659 ifp = scb->ifp; 660 ifp->if_softc = scb; 661 strlcpy(ifp->if_xname, name, IFNAMSIZ); 662 ifp->if_dname = epairname; 663 ifp->if_dunit = unit; 664 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 665 ifp->if_flags |= IFF_KNOWSEPOCH; 666 ifp->if_capabilities = IFCAP_VLAN_MTU; 667 ifp->if_capenable = IFCAP_VLAN_MTU; 668 ifp->if_start = epair_start; 669 ifp->if_ioctl = epair_ioctl; 670 ifp->if_init = epair_init; 671 if_setsendqlen(ifp, ifqmaxlen); 672 if_setsendqready(ifp); 673 /* We need to play some tricks here for the second interface. */ 674 strlcpy(name, epairname, len); 675 676 /* Correctly set the name for the cloner list. */ 677 strlcpy(name, scb->ifp->if_xname, len); 678 epair_clone_add(ifc, scb); 679 680 ifp->if_baudrate = IF_Gbps(10); /* arbitrary maximum */ 681 ifp->if_transmit = epair_transmit; 682 683 /* 684 * Restore name to <n>a as the ifp for this will go into the 685 * cloner list for the initial call. 686 */ 687 strlcpy(name, sca->ifp->if_xname, len); 688 689 /* Tell the world, that we are ready to rock. */ 690 sca->ifp->if_drv_flags |= IFF_DRV_RUNNING; 691 if_link_state_change(sca->ifp, LINK_STATE_UP); 692 scb->ifp->if_drv_flags |= IFF_DRV_RUNNING; 693 if_link_state_change(scb->ifp, LINK_STATE_UP); 694 695 return (0); 696 } 697 698 static void 699 epair_drain_rings(struct epair_softc *sc) 700 { 701 int ridx; 702 struct mbuf *m; 703 704 for (ridx = 0; ridx < 2; ridx++) { 705 for (int i = 0; i < sc->num_queues; i++) { 706 struct epair_queue *q = &sc->queues[i]; 707 do { 708 m = buf_ring_dequeue_sc(q->rxring[ridx]); 709 if (m == NULL) 710 break; 711 m_freem(m); 712 } while (1); 713 } 714 } 715 } 716 717 static int 718 epair_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) 719 { 720 struct ifnet *oifp; 721 struct epair_softc *sca, *scb; 722 int unit, error; 723 724 /* 725 * In case we called into if_clone_destroyif() ourselves 726 * again to remove the second interface, the softc will be 727 * NULL. In that case so not do anything but return success. 728 */ 729 if (ifp->if_softc == NULL) 730 return (0); 731 732 unit = ifp->if_dunit; 733 sca = ifp->if_softc; 734 oifp = sca->oifp; 735 scb = oifp->if_softc; 736 737 /* Frist get the interfaces down and detached. */ 738 if_link_state_change(ifp, LINK_STATE_DOWN); 739 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 740 if_link_state_change(oifp, LINK_STATE_DOWN); 741 oifp->if_drv_flags &= ~IFF_DRV_RUNNING; 742 743 ether_ifdetach(ifp); 744 ether_ifdetach(oifp); 745 746 /* Third free any queued packets and all the resources. */ 747 CURVNET_SET_QUIET(oifp->if_vnet); 748 epair_drain_rings(scb); 749 oifp->if_softc = NULL; 750 error = if_clone_destroyif(ifc, oifp); 751 if (error) 752 panic("%s: if_clone_destroyif() for our 2nd iface failed: %d", 753 __func__, error); 754 if_free(oifp); 755 ifmedia_removeall(&scb->media); 756 for (int i = 0; i < scb->num_queues; i++) { 757 struct epair_queue *q = &scb->queues[i]; 758 buf_ring_free(q->rxring[0], M_EPAIR); 759 buf_ring_free(q->rxring[1], M_EPAIR); 760 } 761 free(scb->queues, M_EPAIR); 762 free(scb, M_EPAIR); 763 CURVNET_RESTORE(); 764 765 epair_drain_rings(sca); 766 if_free(ifp); 767 ifmedia_removeall(&sca->media); 768 for (int i = 0; i < sca->num_queues; i++) { 769 struct epair_queue *q = &sca->queues[i]; 770 buf_ring_free(q->rxring[0], M_EPAIR); 771 buf_ring_free(q->rxring[1], M_EPAIR); 772 } 773 free(sca->queues, M_EPAIR); 774 free(sca, M_EPAIR); 775 776 /* Last free the cloner unit. */ 777 ifc_free_unit(ifc, unit); 778 779 return (0); 780 } 781 782 static void 783 vnet_epair_init(const void *unused __unused) 784 { 785 786 V_epair_cloner = if_clone_advanced(epairname, 0, 787 epair_clone_match, epair_clone_create, epair_clone_destroy); 788 } 789 VNET_SYSINIT(vnet_epair_init, SI_SUB_PSEUDO, SI_ORDER_ANY, 790 vnet_epair_init, NULL); 791 792 static void 793 vnet_epair_uninit(const void *unused __unused) 794 { 795 796 if_clone_detach(V_epair_cloner); 797 } 798 VNET_SYSUNINIT(vnet_epair_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY, 799 vnet_epair_uninit, NULL); 800 801 static int 802 epair_mod_init(void) 803 { 804 char name[32]; 805 epair_tasks.tasks = 0; 806 807 #ifdef RSS 808 struct pcpu *pcpu; 809 int cpu; 810 811 CPU_FOREACH(cpu) { 812 cpuset_t cpu_mask; 813 814 /* Pin to this CPU so we get appropriate NUMA allocations. */ 815 pcpu = pcpu_find(cpu); 816 thread_lock(curthread); 817 sched_bind(curthread, cpu); 818 thread_unlock(curthread); 819 820 snprintf(name, sizeof(name), "epair_task_%d", cpu); 821 822 epair_tasks.tq[cpu] = taskqueue_create(name, M_WAITOK, 823 taskqueue_thread_enqueue, 824 &epair_tasks.tq[cpu]); 825 CPU_SETOF(cpu, &cpu_mask); 826 taskqueue_start_threads_cpuset(&epair_tasks.tq[cpu], 1, PI_NET, 827 &cpu_mask, "%s", name); 828 829 epair_tasks.tasks++; 830 } 831 #else 832 snprintf(name, sizeof(name), "epair_task"); 833 834 epair_tasks.tq[0] = taskqueue_create(name, M_WAITOK, 835 taskqueue_thread_enqueue, 836 &epair_tasks.tq[0]); 837 taskqueue_start_threads(&epair_tasks.tq[0], 1, PI_NET, "%s", name); 838 839 epair_tasks.tasks = 1; 840 #endif 841 842 return (0); 843 } 844 845 static void 846 epair_mod_cleanup(void) 847 { 848 849 for (int i = 0; i < epair_tasks.tasks; i++) { 850 taskqueue_drain_all(epair_tasks.tq[i]); 851 taskqueue_free(epair_tasks.tq[i]); 852 } 853 } 854 855 static int 856 epair_modevent(module_t mod, int type, void *data) 857 { 858 int ret; 859 860 switch (type) { 861 case MOD_LOAD: 862 EPAIR_LOCK_INIT(); 863 ret = epair_mod_init(); 864 if (ret != 0) 865 return (ret); 866 if (bootverbose) 867 printf("%s: %s initialized.\n", __func__, epairname); 868 break; 869 case MOD_UNLOAD: 870 epair_mod_cleanup(); 871 EPAIR_LOCK_DESTROY(); 872 if (bootverbose) 873 printf("%s: %s unloaded.\n", __func__, epairname); 874 break; 875 default: 876 return (EOPNOTSUPP); 877 } 878 return (0); 879 } 880 881 static moduledata_t epair_mod = { 882 "if_epair", 883 epair_modevent, 884 0 885 }; 886 887 DECLARE_MODULE(if_epair, epair_mod, SI_SUB_PSEUDO, SI_ORDER_MIDDLE); 888 MODULE_VERSION(if_epair, 3); 889