]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/if_epair.c
This delta fixes two bugs:
[FreeBSD/FreeBSD.git] / sys / net / if_epair.c
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);