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/iflib_clone.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) 2014-2018, Matthew Macy <mmacy@mattmacy.io>
    3  * Copyright (C) 2017-2018 Joyent Inc.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions are met:
    8  *
    9  *  1. Redistributions of source code must retain the above copyright notice,
   10  *     this list of conditions and the following disclaimer.
   11  *
   12  *  2. Neither the name of Matthew Macy nor the names of its
   13  *     contributors may be used to endorse or promote products derived from
   14  *     this software without specific prior written permission.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   26  * POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include "opt_inet.h"
   33 #include "opt_inet6.h"
   34 #include "opt_acpi.h"
   35 #include "opt_sched.h"
   36 
   37 #include <sys/param.h>
   38 #include <sys/types.h>
   39 #include <sys/bus.h>
   40 #include <sys/eventhandler.h>
   41 #include <sys/event.h>
   42 #include <sys/sockio.h>
   43 #include <sys/kernel.h>
   44 #include <sys/lock.h>
   45 #include <sys/mutex.h>
   46 #include <sys/module.h>
   47 #include <sys/kobj.h>
   48 #include <sys/rman.h>
   49 #include <sys/sbuf.h>
   50 #include <sys/smp.h>
   51 #include <sys/socket.h>
   52 #include <sys/sysctl.h>
   53 #include <sys/syslog.h>
   54 #include <sys/taskqueue.h>
   55 #include <sys/limits.h>
   56 #include <sys/queue.h>
   57 #include <sys/jail.h>
   58 #include <sys/md5.h>
   59 #include <sys/proc.h>
   60 
   61 #include <net/if.h>
   62 #include <net/if_var.h>
   63 #include <net/if_private.h>
   64 #include <net/if_types.h>
   65 #include <net/if_media.h>
   66 #include <net/if_clone.h>
   67 #include <net/bpf.h>
   68 #include <net/ethernet.h>
   69 #include <net/vnet.h>
   70 
   71 #include <net/iflib.h>
   72 #include <net/iflib_private.h>
   73 #include "ifdi_if.h"
   74 
   75 int
   76 noop_attach(device_t dev)
   77 {
   78         return (0);
   79 }
   80 
   81 int
   82 iflib_pseudo_detach(device_t dev)
   83 {
   84         if_ctx_t ctx;
   85 
   86         ctx = device_get_softc(dev);
   87         if ((iflib_get_flags(ctx) & (IFC_INIT_DONE | IFC_IN_DETACH)) ==
   88             IFC_INIT_DONE)
   89                 return (EBUSY);
   90         return (0);
   91 }
   92 
   93 static device_t iflib_pseudodev;
   94 
   95 static struct mtx pseudoif_mtx;
   96 MTX_SYSINIT(pseudoif_mtx, &pseudoif_mtx, "pseudoif_mtx", MTX_DEF);
   97 
   98 #define PSEUDO_LOCK() mtx_lock(&pseudoif_mtx);
   99 #define PSEUDO_UNLOCK() mtx_unlock(&pseudoif_mtx);
  100 
  101 struct if_pseudo {
  102         eventhandler_tag ip_detach_tag;
  103         eventhandler_tag ip_lladdr_tag;
  104         struct if_clone *ip_ifc;
  105         if_shared_ctx_t ip_sctx;
  106         devclass_t ip_dc;
  107         LIST_ENTRY(if_pseudo) ip_list;
  108         int ip_on_list;
  109 };
  110 
  111 static LIST_HEAD(, if_pseudo) iflib_pseudos = LIST_HEAD_INITIALIZER(iflib_pseudos);
  112 
  113 /*
  114  * XXX this assumes that the rest of the
  115  * code won't hang on to it after it's
  116  * removed / unloaded
  117  */
  118 static if_pseudo_t
  119 iflib_ip_lookup(const char *name)
  120 {
  121         if_pseudo_t ip = NULL;
  122 
  123         PSEUDO_LOCK();
  124         LIST_FOREACH(ip, &iflib_pseudos, ip_list) {
  125                 if (!strcmp(ip->ip_sctx->isc_name, name))
  126                         break;
  127         }
  128         PSEUDO_UNLOCK();
  129         return (ip);
  130 }
  131 
  132 static void
  133 iflib_ip_delete(if_pseudo_t ip)
  134 {
  135         PSEUDO_LOCK();
  136         if (ip->ip_on_list) {
  137                 LIST_REMOVE(ip, ip_list);
  138                 ip->ip_on_list = 0;
  139         }
  140         PSEUDO_UNLOCK();
  141 }
  142 
  143 static void
  144 iflib_ip_insert(if_pseudo_t ip)
  145 {
  146         PSEUDO_LOCK();
  147         if (!ip->ip_on_list) {
  148                 LIST_INSERT_HEAD(&iflib_pseudos, ip, ip_list);
  149                 ip->ip_on_list = 1;
  150         }
  151         PSEUDO_UNLOCK();
  152 }
  153 
  154 static void
  155 iflib_ifdetach(void *arg __unused, if_t ifp)
  156 {
  157 
  158         /* If the ifnet is just being renamed, don't do anything. */
  159         if (ifp->if_flags & IFF_RENAMING)
  160                 return;
  161 }
  162 
  163 static void
  164 iflib_iflladdr(void *arg __unused, if_t ifp __unused)
  165 {
  166 
  167 }
  168 
  169 static int
  170 iflib_clone_create(struct if_clone *ifc, int unit, caddr_t params)
  171 {
  172         const char *name = ifc_name(ifc);
  173         struct iflib_cloneattach_ctx clctx;
  174         if_ctx_t ctx;
  175         if_pseudo_t ip;
  176         device_t dev;
  177         int rc;
  178 
  179         clctx.cc_ifc = ifc;
  180         clctx.cc_len = 0;
  181         clctx.cc_params = params;
  182         clctx.cc_name = name;
  183 
  184         if (__predict_false(iflib_pseudodev == NULL)) {
  185                 /* SYSINIT initialization would panic !?! */
  186                 bus_topo_lock();
  187                 iflib_pseudodev = device_add_child(root_bus, "ifpseudo", 0);
  188                 bus_topo_unlock();
  189                 MPASS(iflib_pseudodev != NULL);
  190         }
  191         ip = iflib_ip_lookup(name);
  192         if (ip == NULL) {
  193                 printf("no ip found for %s\n", name);
  194                 return (ENOENT);
  195         }
  196         if ((dev = devclass_get_device(ip->ip_dc, unit)) != NULL) {
  197                 printf("unit %d allocated\n", unit);
  198                 bus_generic_print_child(iflib_pseudodev, dev);
  199                 return (EBUSY);
  200         }
  201         PSEUDO_LOCK();
  202         dev = device_add_child(iflib_pseudodev, name, unit);
  203         device_set_driver(dev, &iflib_pseudodriver);
  204         PSEUDO_UNLOCK();
  205         device_quiet(dev);
  206         rc = device_attach(dev);
  207         MPASS(rc == 0);
  208         MPASS(dev != NULL);
  209         MPASS(devclass_get_device(ip->ip_dc, unit) == dev);
  210         rc = iflib_pseudo_register(dev, ip->ip_sctx, &ctx, &clctx);
  211         if (rc) {
  212                 bus_topo_lock();
  213                 device_delete_child(iflib_pseudodev, dev);
  214                 bus_topo_unlock();
  215         } else
  216                 device_set_softc(dev, ctx);
  217 
  218         return (rc);
  219 }
  220 
  221 static void
  222 iflib_clone_destroy(if_t ifp)
  223 {
  224         if_ctx_t ctx;
  225         device_t dev;
  226         struct sx *ctx_lock;
  227         int rc;
  228 
  229         /*
  230          * Detach device / free / free unit 
  231          */
  232         ctx = if_getsoftc(ifp);
  233         dev = iflib_get_dev(ctx);
  234         ctx_lock = iflib_ctx_lock_get(ctx);
  235         sx_xlock(ctx_lock);
  236         iflib_set_detach(ctx);
  237         iflib_stop(ctx);
  238         sx_xunlock(ctx_lock);
  239 
  240         bus_topo_lock();
  241         rc = device_delete_child(iflib_pseudodev, dev);
  242         bus_topo_unlock();
  243         if (rc == 0)
  244                 iflib_pseudo_deregister(ctx);
  245 }
  246 
  247 if_pseudo_t
  248 iflib_clone_register(if_shared_ctx_t sctx)
  249 {
  250         if_pseudo_t ip;
  251 
  252         if (sctx->isc_name == NULL) {
  253                 printf("iflib_clone_register failed - shared_ctx needs to have a device name\n");
  254                 return (NULL);
  255         }
  256         if (iflib_ip_lookup(sctx->isc_name) != NULL) {
  257                 printf("iflib_clone_register failed - shared_ctx %s alread registered\n",
  258                            sctx->isc_name);
  259                 return (NULL);
  260         }
  261         ip = malloc(sizeof(*ip), M_IFLIB, M_WAITOK|M_ZERO);
  262         ip->ip_sctx = sctx;
  263         ip->ip_dc = devclass_create(sctx->isc_name);
  264         if (ip->ip_dc == NULL)
  265                 goto fail_clone;
  266         /* XXX --- we can handle clone_advanced later */
  267         ip->ip_ifc  = if_clone_simple(sctx->isc_name, iflib_clone_create, iflib_clone_destroy, 0);
  268         if (ip->ip_ifc == NULL) {
  269                 printf("clone_simple failed -- cloned %s  devices will not be available\n", sctx->isc_name);
  270                 goto fail_clone;
  271         }
  272         ip->ip_lladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event,
  273                                                                                          iflib_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
  274         if (ip->ip_lladdr_tag == NULL)
  275                 goto fail_addr;
  276         ip->ip_detach_tag = EVENTHANDLER_REGISTER(ifnet_departure_event,
  277                                                                                          iflib_ifdetach, NULL, EVENTHANDLER_PRI_ANY);
  278 
  279         if (ip->ip_detach_tag == NULL)
  280                 goto fail_depart;
  281 
  282         iflib_ip_insert(ip);
  283         return (ip);
  284  fail_depart:
  285         EVENTHANDLER_DEREGISTER(iflladdr_event, ip->ip_lladdr_tag);
  286  fail_addr:
  287         if_clone_detach(ip->ip_ifc);
  288  fail_clone:
  289         free(ip, M_IFLIB);
  290         return (NULL);
  291 }
  292 
  293 void
  294 iflib_clone_deregister(if_pseudo_t ip)
  295 {
  296         /* XXX check that is not still in use */
  297         iflib_ip_delete(ip);
  298         EVENTHANDLER_DEREGISTER(ifnet_departure_event, ip->ip_detach_tag);
  299         EVENTHANDLER_DEREGISTER(iflladdr_event, ip->ip_lladdr_tag);
  300         if_clone_detach(ip->ip_ifc);
  301         /* XXX free devclass */
  302         free(ip, M_IFLIB);
  303 }

Cache object: 23a1f543028ada5c3e43ca7fa202c7d3


[ 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.