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: releng/12.0/sys/net/iflib_clone.c 333502 2018-05-11 20:08:28Z mmacy $");
   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 
   62 #include <net/if.h>
   63 #include <net/if_var.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         uint32_t ifc_flags;
   86 
   87         ctx = device_get_softc(dev);
   88         ifc_flags = iflib_get_flags(ctx);
   89         if ((ifc_flags & IFC_INIT_DONE) == 0)
   90                 return (0);
   91         return (IFDI_DETACH(ctx));
   92 }
   93 
   94 static device_t iflib_pseudodev;
   95 
   96 static struct mtx pseudoif_mtx;
   97 MTX_SYSINIT(pseudoif_mtx, &pseudoif_mtx, "pseudoif_mtx", MTX_DEF);
   98 
   99 #define PSEUDO_LOCK() mtx_lock(&pseudoif_mtx);
  100 #define PSEUDO_UNLOCK() mtx_unlock(&pseudoif_mtx);
  101 
  102 struct if_pseudo {
  103         eventhandler_tag ip_detach_tag;
  104         eventhandler_tag ip_lladdr_tag;
  105         struct if_clone *ip_ifc;
  106         if_shared_ctx_t ip_sctx;
  107         devclass_t ip_dc;
  108         LIST_ENTRY(if_pseudo) ip_list;
  109         int ip_on_list;
  110 };
  111 
  112 static LIST_HEAD(, if_pseudo) iflib_pseudos = LIST_HEAD_INITIALIZER(iflib_pseudos);
  113 
  114 /*
  115  * XXX this assumes that the rest of the
  116  * code won't hang on to it after it's
  117  * removed / unloaded
  118  */
  119 static if_pseudo_t
  120 iflib_ip_lookup(const char *name)
  121 {
  122         if_pseudo_t ip = NULL;
  123 
  124         PSEUDO_LOCK();
  125         LIST_FOREACH(ip, &iflib_pseudos, ip_list) {
  126                 if (!strcmp(ip->ip_sctx->isc_name, name))
  127                         break;
  128         }
  129         PSEUDO_UNLOCK();
  130         return (ip);
  131 }
  132 
  133 static void
  134 iflib_ip_delete(if_pseudo_t ip)
  135 {
  136         PSEUDO_LOCK();
  137         if (ip->ip_on_list) {
  138                 LIST_REMOVE(ip, ip_list);
  139                 ip->ip_on_list = 0;
  140         }
  141         PSEUDO_UNLOCK();
  142 }
  143 
  144 static void
  145 iflib_ip_insert(if_pseudo_t ip)
  146 {
  147         PSEUDO_LOCK();
  148         if (!ip->ip_on_list) {
  149                 LIST_INSERT_HEAD(&iflib_pseudos, ip, ip_list);
  150                 ip->ip_on_list = 1;
  151         }
  152         PSEUDO_UNLOCK();
  153 }
  154 
  155 static void
  156 iflib_ifdetach(void *arg __unused, struct ifnet *ifp)
  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, struct ifnet *ifp)
  165 {
  166 }
  167 
  168 static int
  169 iflib_clone_create(struct if_clone *ifc, int unit, caddr_t params)
  170 {
  171         const char *name = ifc_name(ifc);
  172         struct iflib_cloneattach_ctx clctx;
  173         if_ctx_t ctx;
  174         if_pseudo_t ip;
  175         device_t dev;
  176         int rc;
  177 
  178         clctx.cc_ifc = ifc;
  179         clctx.cc_len = 0;
  180         clctx.cc_params = params;
  181         clctx.cc_name = name;
  182 
  183         if (__predict_false(iflib_pseudodev == NULL)) {
  184                 /* SYSINIT initialization would panic !?! */
  185                 mtx_lock(&Giant);
  186                 iflib_pseudodev = device_add_child(root_bus, "ifpseudo", 0);
  187                 mtx_unlock(&Giant);
  188                 MPASS(iflib_pseudodev != NULL);
  189         }
  190         ip = iflib_ip_lookup(name);
  191         if (ip == NULL) {
  192                 printf("no ip found for %s\n", name);
  193                 return (ENOENT);
  194         }
  195         if ((dev = devclass_get_device(ip->ip_dc, unit)) != NULL) {
  196                 printf("unit %d allocated\n", unit);
  197                 bus_generic_print_child(iflib_pseudodev, dev);
  198                 return (EBUSY);
  199         }
  200         PSEUDO_LOCK();
  201         dev = device_add_child(iflib_pseudodev, name, unit);
  202         device_set_driver(dev, &iflib_pseudodriver);
  203         PSEUDO_UNLOCK();
  204         device_quiet(dev);
  205         rc = device_attach(dev);
  206         MPASS(rc == 0);
  207         MPASS(dev != NULL);
  208         MPASS(devclass_get_device(ip->ip_dc, unit) == dev);
  209         rc = iflib_pseudo_register(dev, ip->ip_sctx, &ctx, &clctx);
  210         if (rc) {
  211                 mtx_lock(&Giant);
  212                 device_delete_child(iflib_pseudodev, dev);
  213                 mtx_unlock(&Giant);
  214         } else
  215                 device_set_softc(dev, ctx);
  216 
  217         return (rc);
  218 }
  219 
  220 static void
  221 iflib_clone_destroy(struct ifnet *ifp)
  222 {
  223         if_ctx_t ctx;
  224         device_t dev;
  225         struct sx *ctx_lock;
  226         int rc;
  227         /*
  228          * Detach device / free / free unit 
  229          *
  230          */
  231         ctx = if_getsoftc(ifp);
  232         dev = iflib_get_dev(ctx);
  233         ctx_lock = iflib_ctx_lock_get(ctx);
  234         sx_xlock(ctx_lock);
  235         iflib_set_detach(ctx);
  236         iflib_stop(ctx);
  237         sx_xunlock(ctx_lock);
  238 
  239         mtx_lock(&Giant);
  240         rc = device_delete_child(iflib_pseudodev, dev);
  241         mtx_unlock(&Giant);
  242         if (rc == 0)
  243                 iflib_pseudo_deregister(ctx);
  244 }
  245 
  246 if_pseudo_t
  247 iflib_clone_register(if_shared_ctx_t sctx)
  248 {
  249         if_pseudo_t ip;
  250 
  251         if (sctx->isc_name == NULL) {
  252                 printf("iflib_clone_register failed - shared_ctx needs to have a device name\n");
  253                 return (NULL);
  254         }
  255         if (iflib_ip_lookup(sctx->isc_name) != NULL) {
  256                 printf("iflib_clone_register failed - shared_ctx %s alread registered\n",
  257                            sctx->isc_name);
  258                 return (NULL);
  259         }
  260         ip = malloc(sizeof(*ip), M_IFLIB, M_WAITOK|M_ZERO);
  261         ip->ip_sctx = sctx;
  262         ip->ip_dc = devclass_create(sctx->isc_name);
  263         if (ip->ip_dc == NULL)
  264                 goto fail_clone;
  265         /* XXX --- we can handle clone_advanced later */
  266         ip->ip_ifc  = if_clone_simple(sctx->isc_name, iflib_clone_create, iflib_clone_destroy, 0);
  267         if (ip->ip_ifc == NULL) {
  268                 printf("clone_simple failed -- cloned %s  devices will not be available\n", sctx->isc_name);
  269                 goto fail_clone;
  270         }
  271         ifc_flags_set(ip->ip_ifc, IFC_NOGROUP);
  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: 4c6718aa4b3dcefe9536c4fcdd4a0e86


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