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 
   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, if_t ifp)
  157 {
  158 
  159         /* If the ifnet is just being renamed, don't do anything. */
  160         if (ifp->if_flags & IFF_RENAMING)
  161                 return;
  162 }
  163 
  164 static void
  165 iflib_iflladdr(void *arg __unused, if_t ifp __unused)
  166 {
  167 
  168 }
  169 
  170 static int
  171 iflib_clone_create(struct if_clone *ifc, int unit, caddr_t params)
  172 {
  173         const char *name = ifc_name(ifc);
  174         struct iflib_cloneattach_ctx clctx;
  175         if_ctx_t ctx;
  176         if_pseudo_t ip;
  177         device_t dev;
  178         int rc;
  179 
  180         clctx.cc_ifc = ifc;
  181         clctx.cc_len = 0;
  182         clctx.cc_params = params;
  183         clctx.cc_name = name;
  184 
  185         if (__predict_false(iflib_pseudodev == NULL)) {
  186                 /* SYSINIT initialization would panic !?! */
  187                 mtx_lock(&Giant);
  188                 iflib_pseudodev = device_add_child(root_bus, "ifpseudo", 0);
  189                 mtx_unlock(&Giant);
  190                 MPASS(iflib_pseudodev != NULL);
  191         }
  192         ip = iflib_ip_lookup(name);
  193         if (ip == NULL) {
  194                 printf("no ip found for %s\n", name);
  195                 return (ENOENT);
  196         }
  197         if ((dev = devclass_get_device(ip->ip_dc, unit)) != NULL) {
  198                 printf("unit %d allocated\n", unit);
  199                 bus_generic_print_child(iflib_pseudodev, dev);
  200                 return (EBUSY);
  201         }
  202         PSEUDO_LOCK();
  203         dev = device_add_child(iflib_pseudodev, name, unit);
  204         device_set_driver(dev, &iflib_pseudodriver);
  205         PSEUDO_UNLOCK();
  206         device_quiet(dev);
  207         rc = device_attach(dev);
  208         MPASS(rc == 0);
  209         MPASS(dev != NULL);
  210         MPASS(devclass_get_device(ip->ip_dc, unit) == dev);
  211         rc = iflib_pseudo_register(dev, ip->ip_sctx, &ctx, &clctx);
  212         if (rc) {
  213                 mtx_lock(&Giant);
  214                 device_delete_child(iflib_pseudodev, dev);
  215                 mtx_unlock(&Giant);
  216         } else
  217                 device_set_softc(dev, ctx);
  218 
  219         return (rc);
  220 }
  221 
  222 static void
  223 iflib_clone_destroy(if_t ifp)
  224 {
  225         if_ctx_t ctx;
  226         device_t dev;
  227         struct sx *ctx_lock;
  228         int rc;
  229 
  230         /*
  231          * Detach device / free / free unit 
  232          */
  233         ctx = if_getsoftc(ifp);
  234         dev = iflib_get_dev(ctx);
  235         ctx_lock = iflib_ctx_lock_get(ctx);
  236         sx_xlock(ctx_lock);
  237         iflib_set_detach(ctx);
  238         iflib_stop(ctx);
  239         sx_xunlock(ctx_lock);
  240 
  241         mtx_lock(&Giant);
  242         rc = device_delete_child(iflib_pseudodev, dev);
  243         mtx_unlock(&Giant);
  244         if (rc == 0)
  245                 iflib_pseudo_deregister(ctx);
  246 }
  247 
  248 if_pseudo_t
  249 iflib_clone_register(if_shared_ctx_t sctx)
  250 {
  251         if_pseudo_t ip;
  252 
  253         if (sctx->isc_name == NULL) {
  254                 printf("iflib_clone_register failed - shared_ctx needs to have a device name\n");
  255                 return (NULL);
  256         }
  257         if (iflib_ip_lookup(sctx->isc_name) != NULL) {
  258                 printf("iflib_clone_register failed - shared_ctx %s alread registered\n",
  259                            sctx->isc_name);
  260                 return (NULL);
  261         }
  262         ip = malloc(sizeof(*ip), M_IFLIB, M_WAITOK|M_ZERO);
  263         ip->ip_sctx = sctx;
  264         ip->ip_dc = devclass_create(sctx->isc_name);
  265         if (ip->ip_dc == NULL)
  266                 goto fail_clone;
  267         /* XXX --- we can handle clone_advanced later */
  268         ip->ip_ifc  = if_clone_simple(sctx->isc_name, iflib_clone_create, iflib_clone_destroy, 0);
  269         if (ip->ip_ifc == NULL) {
  270                 printf("clone_simple failed -- cloned %s  devices will not be available\n", sctx->isc_name);
  271                 goto fail_clone;
  272         }
  273         ifc_flags_set(ip->ip_ifc, IFC_NOGROUP);
  274         ip->ip_lladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event,
  275                                                                                          iflib_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
  276         if (ip->ip_lladdr_tag == NULL)
  277                 goto fail_addr;
  278         ip->ip_detach_tag = EVENTHANDLER_REGISTER(ifnet_departure_event,
  279                                                                                          iflib_ifdetach, NULL, EVENTHANDLER_PRI_ANY);
  280 
  281         if (ip->ip_detach_tag == NULL)
  282                 goto fail_depart;
  283 
  284         iflib_ip_insert(ip);
  285         return (ip);
  286  fail_depart:
  287         EVENTHANDLER_DEREGISTER(iflladdr_event, ip->ip_lladdr_tag);
  288  fail_addr:
  289         if_clone_detach(ip->ip_ifc);
  290  fail_clone:
  291         free(ip, M_IFLIB);
  292         return (NULL);
  293 }
  294 
  295 void
  296 iflib_clone_deregister(if_pseudo_t ip)
  297 {
  298         /* XXX check that is not still in use */
  299         iflib_ip_delete(ip);
  300         EVENTHANDLER_DEREGISTER(ifnet_departure_event, ip->ip_detach_tag);
  301         EVENTHANDLER_DEREGISTER(iflladdr_event, ip->ip_lladdr_tag);
  302         if_clone_detach(ip->ip_ifc);
  303         /* XXX free devclass */
  304         free(ip, M_IFLIB);
  305 }

Cache object: 7352e29f75c7f5a7d947204bf3d7e8be


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