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