The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/if_edsc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1982, 1986, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following edsclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following edsclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 4. Neither the name of the University nor the names of its contributors
   14  *    may be used to endorse or promote products derived from this software
   15  *    without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 EDSCLAIMED.  IN NO EVENT SHALL THE REGENTS 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  *      From: @(#)if_loop.c     8.1 (Berkeley) 6/10/93
   30  * $FreeBSD$
   31  */
   32 
   33 /*
   34  * Discard interface driver for protocol testing and timing.
   35  * Mimics an Ethernet device so that VLANs can be attached to it etc.
   36  */
   37 
   38 #include <sys/param.h>          /* types, important constants */
   39 #include <sys/kernel.h>         /* SYSINIT for load-time initializations */
   40 #include <sys/lock.h>           /* needed by <sys/mutex.h> */
   41 #include <sys/malloc.h>         /* malloc(9) */
   42 #include <sys/module.h>         /* module(9) */
   43 #include <sys/mbuf.h>           /* mbuf(9) */
   44 #include <sys/mutex.h>          /* mutex(9) */
   45 #include <sys/queue.h>          /* queue(3) to keep the list of interfaces */
   46 #include <sys/socket.h>         /* struct ifreq */
   47 #include <sys/sockio.h>         /* socket ioctl's */
   48 /* #include <sys/systm.h> if you need printf(9) or other all-purpose globals */
   49 
   50 #include <net/bpf.h>            /* bpf(9) */
   51 #include <net/ethernet.h>       /* Ethernet related constants and types */
   52 #include <net/if.h>             /* basic part of ifnet(9) */
   53 #include <net/if_clone.h>       /* network interface cloning */
   54 #include <net/if_types.h>       /* IFT_ETHER and friends */
   55 #include <net/if_var.h>         /* kernel-only part of ifnet(9) */
   56 
   57 /*
   58  * Software configuration of an interface specific to this device type.
   59  */
   60 struct edsc_softc {
   61         struct ifnet    *sc_ifp; /* ptr to generic interface configuration */
   62 
   63         /*
   64          * A non-null driver can keep various things here, for instance,
   65          * the hardware revision, cached values of write-only registers, etc.
   66          */
   67 
   68         LIST_ENTRY(edsc_softc)   sc_list;       /* for MOD_UNLOAD handler */
   69 };
   70 
   71 /*
   72  * Simple cloning methods.
   73  * IFC_SIMPLE_DECLARE() expects precisely these names.
   74  */
   75 static int      edsc_clone_create(struct if_clone *, int);
   76 static void     edsc_clone_destroy(struct ifnet *);
   77 
   78 /*
   79  * Interface driver methods.
   80  */
   81 static void     edsc_init(void *dummy);
   82 /* static void edsc_input(struct ifnet *ifp, struct mbuf *m); would be here */
   83 static int      edsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
   84 static void     edsc_start(struct ifnet *ifp);
   85 
   86 /*
   87  * We'll allocate softc instances from this.
   88  */
   89 static          MALLOC_DEFINE(M_EDSC, "edsc", "Ethernet discard interface");
   90 
   91 /*
   92  * We have to keep the list of interface instances
   93  * so that we can destroy all of them upon unloading this driver.
   94  * The list is protected by the mutex so that different threads
   95  * won't try to modify it at the same time.
   96  */
   97 static LIST_HEAD(, edsc_softc)  edsc_softc_list;
   98 static struct mtx               edsc_mtx;
   99 
  100 /*
  101  * Attach to the interface cloning framework under the name of "edsc".
  102  * The second argument is the number of units to be created from
  103  * the outset.  It's also the minimum number of units allowed.
  104  * We don't want any units created as soon as the driver is loaded.
  105  */
  106 IFC_SIMPLE_DECLARE(edsc, 0);
  107 
  108 /*
  109  * Create an interface instance.
  110  */
  111 static int
  112 edsc_clone_create(struct if_clone *ifc, int unit)
  113 {
  114         struct edsc_softc       *sc;
  115         struct ifnet            *ifp;
  116         static u_char            eaddr[ETHER_ADDR_LEN]; /* 0:0:0:0:0:0 */
  117 
  118         /*
  119          * Allocate soft and ifnet structures.  Link each to the other.
  120          */
  121         sc = malloc(sizeof(struct edsc_softc), M_EDSC, M_WAITOK | M_ZERO);
  122         ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
  123         if (ifp == NULL) {
  124                 free(sc, M_EDSC);
  125                 return (ENOSPC);
  126         }
  127 
  128         ifp->if_softc = sc;
  129 
  130         /*
  131          * Get a name for this particular interface in its ifnet structure.
  132          */
  133         if_initname(ifp, ifc->ifc_name, unit);
  134 
  135         /*
  136          * Typical Ethernet interface flags: we can do broadcast and
  137          * multicast but can't hear our own broadcasts or multicasts.
  138          */
  139         ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX;
  140 
  141         /*
  142          * We can pretent we have the whole set of hardware features
  143          * because we just discard all packets we get from the upper layer.
  144          * However, the features are disabled initially.  They can be
  145          * enabled via edsc_ioctl() when needed.
  146          */
  147         ifp->if_capabilities =
  148             IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING |
  149             IFCAP_HWCSUM |
  150             IFCAP_JUMBO_MTU;
  151         ifp->if_capenable = 0;
  152 
  153         /*
  154          * Set the interface driver methods.
  155          */
  156         ifp->if_init = edsc_init;
  157         /* ifp->if_input = edsc_input; */
  158         ifp->if_ioctl = edsc_ioctl;
  159         ifp->if_start = edsc_start;
  160 
  161         /*
  162          * Set the maximum output queue length from the global parameter.
  163          */
  164         ifp->if_snd.ifq_maxlen = ifqmaxlen;
  165 
  166         /*
  167          * Do ifnet initializations common to all Ethernet drivers
  168          * and attach to the network interface framework.
  169          * TODO: Pick a non-zero link level address.
  170          */
  171         ether_ifattach(ifp, eaddr);
  172 
  173         /*
  174          * Insert this interface in the list we have to keep.
  175          */
  176         mtx_lock(&edsc_mtx);
  177         LIST_INSERT_HEAD(&edsc_softc_list, sc, sc_list);
  178         mtx_unlock(&edsc_mtx);
  179 
  180         /*
  181          * Now we can mark the interface as running, i.e., ready
  182          * for operation.
  183          */
  184         ifp->if_drv_flags |= IFF_DRV_RUNNING;
  185 
  186         return (0);
  187 }
  188 
  189 /*
  190  * Code shared by the handlers for clone destruction and MOD_UNLOAD.
  191  */
  192 static void
  193 edsc_destroy(struct edsc_softc *sc)
  194 {
  195 
  196         /*
  197          * Detach from the network interface framework.
  198          */
  199         ether_ifdetach(sc->sc_ifp);
  200 
  201         /*
  202          * Free memory occupied by ifnet and softc.
  203          */
  204         if_free(sc->sc_ifp);
  205         free(sc, M_EDSC);
  206 }
  207 
  208 /*
  209  * Destroy an interface instance.
  210  */
  211 static void
  212 edsc_clone_destroy(struct ifnet *ifp)
  213 {
  214         struct edsc_softc       *sc = ifp->if_softc;
  215 
  216         mtx_lock(&edsc_mtx);
  217         LIST_REMOVE(sc, sc_list);
  218         mtx_unlock(&edsc_mtx);
  219 
  220         edsc_destroy(sc);
  221 }
  222 
  223 /*
  224  * This method is invoked from ether_ioctl() when it's time
  225  * to bring up the hardware.
  226  */
  227 static void
  228 edsc_init(void *dummy)
  229 {
  230 #if 0   /* what a hardware driver would do here... */
  231         struct edsc_soft        *sc = (struct edsc_softc *)dummy;
  232         struct ifnet            *ifp = sc->sc_ifp;
  233 
  234         /* blah-blah-blah */
  235 #endif
  236 }
  237 
  238 /*
  239  * Network interfaces are controlled via the ioctl(2) syscall.
  240  */
  241 static int
  242 edsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  243 {
  244         struct ifreq            *ifr = (struct ifreq *)data;
  245 
  246         switch (cmd) {
  247         case SIOCSIFCAP:
  248 #if 1
  249                 /*
  250                  * Just turn on any capabilities requested.
  251                  * The generic ifioctl() function has already made sure
  252                  * that they are supported, i.e., set in if_capabilities.
  253                  */
  254                 ifp->if_capenable = ifr->ifr_reqcap;
  255 #else
  256                 /*
  257                  * A h/w driver would need to analyze the requested
  258                  * bits and program the hardware, e.g.:
  259                  */
  260                 mask = ifp->if_capenable ^ ifr->ifr_reqcap;
  261 
  262                 if (mask & IFCAP_VLAN_HWTAGGING) {
  263                         ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
  264 
  265                         if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
  266                                 /* blah-blah-blah */
  267                         else
  268                                 /* etc-etc-etc */
  269                 }
  270 #endif
  271                 break;
  272 
  273         default:
  274                 /*
  275                  * Offload the rest onto the common Ethernet handler.
  276                  */
  277                 return (ether_ioctl(ifp, cmd, data));
  278         }
  279 
  280         return (0);
  281 }
  282 
  283 /*
  284  * Process the output queue.
  285  */
  286 static void
  287 edsc_start(struct ifnet *ifp)
  288 {
  289         struct mbuf             *m;
  290 
  291         /*
  292          * A hardware interface driver can set IFF_DRV_OACTIVE
  293          * in ifp->if_drv_flags:
  294          *
  295          * ifp->if_drv_flags |= IFF_DRV_OACTIVE;
  296          *
  297          * to prevent if_start from being invoked again while the
  298          * transmission is under way.  The flag is to protect the
  299          * device's transmitter, not the method itself.  The output
  300          * queue is locked and several threads can process it in
  301          * parallel safely, so the driver can use other means to
  302          * serialize access to the transmitter.
  303          *
  304          * If using IFF_DRV_OACTIVE, the driver should clear the flag
  305          * not earlier than the current transmission is complete, e.g.,
  306          * upon an interrupt from the device, not just before returning
  307          * from if_start.  This method merely starts the transmission,
  308          * which may proceed asynchronously.
  309          */
  310 
  311         /*
  312          * We loop getting packets from the queue until it's empty.
  313          * A h/w driver would loop until the device can accept more
  314          * data into its buffer, or while there are free transmit
  315          * descriptors, or whatever.
  316          */
  317         for (;;) {
  318                 /*
  319                  * Try to dequeue one packet.  Stop if the queue is empty.
  320                  * Use IF_DEQUEUE() here if ALTQ(9) support is unneeded.
  321                  */
  322                 IFQ_DEQUEUE(&ifp->if_snd, m);
  323                 if (m == NULL)
  324                         break;
  325 
  326                 /*
  327                  * Let bpf(9) at the packet.
  328                  */
  329                 BPF_MTAP(ifp, m);
  330 
  331                 /*
  332                  * Update the interface counters.
  333                  */
  334                 ifp->if_obytes += m->m_pkthdr.len;
  335                 ifp->if_opackets++;
  336 
  337                 /*
  338                  * Finally, just drop the packet.
  339                  * TODO: Reply to ARP requests unless IFF_NOARP is set.
  340                  */
  341                 m_freem(m);
  342         }
  343 
  344         /*
  345          * ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  346          * would be here only if the transmission were synchronous.
  347          */
  348 }
  349 
  350 /*
  351  * This function provides handlers for module events, namely load and unload.
  352  */
  353 static int
  354 edsc_modevent(module_t mod, int type, void *data)
  355 {
  356         struct edsc_softc       *sc;
  357 
  358         switch (type) {
  359         case MOD_LOAD:
  360                 mtx_init(&edsc_mtx, "edsc_mtx", NULL, MTX_DEF);
  361                 LIST_INIT(&edsc_softc_list);
  362                 /*
  363                  * Connect to the network interface cloning framework.
  364                  */
  365                 if_clone_attach(&edsc_cloner);
  366                 break;
  367 
  368         case MOD_UNLOAD:
  369                 /*
  370                  * First of all, disconnect from the cloning framework
  371                  * so that no new interfaces can appear.
  372                  */
  373                 if_clone_detach(&edsc_cloner);
  374 
  375                 /*
  376                  * Now we have to destroy the interfaces by ourselves.
  377                  */
  378                 mtx_lock(&edsc_mtx);
  379                 while ((sc = LIST_FIRST(&edsc_softc_list)) != NULL) {
  380                         LIST_REMOVE(sc, sc_list);
  381                         mtx_unlock(&edsc_mtx);
  382                         edsc_destroy(sc);
  383                         mtx_lock(&edsc_mtx);
  384                 }
  385                 mtx_unlock(&edsc_mtx);
  386 
  387                 /*
  388                  * Don't forget to destroy our mutex.
  389                  */
  390                 mtx_destroy(&edsc_mtx);
  391                 break;
  392 
  393         default:
  394                 /*
  395                  * There are other event types, but we don't handle them.
  396                  * See module(9).
  397                  */
  398                 return (EOPNOTSUPP);
  399         }
  400         return (0);
  401 }
  402 
  403 static moduledata_t edsc_mod = {
  404         "if_edsc",                      /* name */
  405         edsc_modevent,                  /* event handler */
  406         NULL                            /* additional data */
  407 };
  408 
  409 DECLARE_MODULE(if_edsc, edsc_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);

Cache object: dc4f4cbc0a2e414f8c0643483c1e1474


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.