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/route/route_subscription.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2021-2022 Alexander V. Chernikov
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 #include "opt_route.h"
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/malloc.h>
   35 #include <sys/socket.h>
   36 #include <sys/kernel.h>
   37 #include <sys/lock.h>
   38 #include <sys/rmlock.h>
   39 
   40 #include <net/route.h>
   41 #include <net/route/route_ctl.h>
   42 #include <net/route/route_var.h>
   43 #include <net/route/nhop.h>
   44 
   45 struct rib_subscription {
   46         CK_STAILQ_ENTRY(rib_subscription)       next;
   47         rib_subscription_cb_t                   *func;
   48         void                                    *arg;
   49         struct rib_head                         *rnh;
   50         enum rib_subscription_type              type;
   51         struct epoch_context                    epoch_ctx;
   52 };
   53 
   54 static void destroy_subscription_epoch(epoch_context_t ctx);
   55 
   56 void
   57 rib_notify(struct rib_head *rnh, enum rib_subscription_type type,
   58     struct rib_cmd_info *rc)
   59 {
   60         struct rib_subscription *rs;
   61 
   62         CK_STAILQ_FOREACH(rs, &rnh->rnh_subscribers, next) {
   63                 if (rs->type == type)
   64                         rs->func(rnh, rc, rs->arg);
   65         }
   66 }
   67 
   68 static struct rib_subscription *
   69 allocate_subscription(rib_subscription_cb_t *f, void *arg,
   70     enum rib_subscription_type type, bool waitok)
   71 {
   72         struct rib_subscription *rs;
   73         int flags = M_ZERO | (waitok ? M_WAITOK : M_NOWAIT);
   74 
   75         rs = malloc(sizeof(struct rib_subscription), M_RTABLE, flags);
   76         if (rs == NULL)
   77                 return (NULL);
   78 
   79         rs->func = f;
   80         rs->arg = arg;
   81         rs->type = type;
   82 
   83         return (rs);
   84 }
   85 
   86 /*
   87  * Subscribe for the changes in the routing table specified by @fibnum and
   88  *  @family.
   89  *
   90  * Returns pointer to the subscription structure on success.
   91  */
   92 struct rib_subscription *
   93 rib_subscribe(uint32_t fibnum, int family, rib_subscription_cb_t *f, void *arg,
   94     enum rib_subscription_type type, bool waitok)
   95 {
   96         struct rib_head *rnh;
   97         struct epoch_tracker et;
   98 
   99         NET_EPOCH_ENTER(et);
  100         KASSERT((fibnum < rt_numfibs), ("%s: bad fibnum", __func__));
  101         rnh = rt_tables_get_rnh(fibnum, family);
  102         NET_EPOCH_EXIT(et);
  103 
  104         return (rib_subscribe_internal(rnh, f, arg, type, waitok));
  105 }
  106 
  107 struct rib_subscription *
  108 rib_subscribe_internal(struct rib_head *rnh, rib_subscription_cb_t *f, void *arg,
  109     enum rib_subscription_type type, bool waitok)
  110 {
  111         struct rib_subscription *rs;
  112         struct epoch_tracker et;
  113 
  114         if ((rs = allocate_subscription(f, arg, type, waitok)) == NULL)
  115                 return (NULL);
  116         rs->rnh = rnh;
  117 
  118         NET_EPOCH_ENTER(et);
  119         RIB_WLOCK(rnh);
  120         CK_STAILQ_INSERT_HEAD(&rnh->rnh_subscribers, rs, next);
  121         RIB_WUNLOCK(rnh);
  122         NET_EPOCH_EXIT(et);
  123 
  124         return (rs);
  125 }
  126 
  127 struct rib_subscription *
  128 rib_subscribe_locked(struct rib_head *rnh, rib_subscription_cb_t *f, void *arg,
  129     enum rib_subscription_type type)
  130 {
  131         struct rib_subscription *rs;
  132 
  133         NET_EPOCH_ASSERT();
  134         RIB_WLOCK_ASSERT(rnh);
  135 
  136         if ((rs = allocate_subscription(f, arg, type, false)) == NULL)
  137                 return (NULL);
  138         rs->rnh = rnh;
  139 
  140         CK_STAILQ_INSERT_HEAD(&rnh->rnh_subscribers, rs, next);
  141 
  142         return (rs);
  143 }
  144 
  145 /*
  146  * Remove rtable subscription @rs from the routing table.
  147  * Needs to be run in network epoch.
  148  */
  149 void
  150 rib_unsubscribe(struct rib_subscription *rs)
  151 {
  152         struct rib_head *rnh = rs->rnh;
  153 
  154         NET_EPOCH_ASSERT();
  155 
  156         RIB_WLOCK(rnh);
  157         CK_STAILQ_REMOVE(&rnh->rnh_subscribers, rs, rib_subscription, next);
  158         RIB_WUNLOCK(rnh);
  159 
  160         NET_EPOCH_CALL(destroy_subscription_epoch, &rs->epoch_ctx);
  161 }
  162 
  163 void
  164 rib_unsubscribe_locked(struct rib_subscription *rs)
  165 {
  166         struct rib_head *rnh = rs->rnh;
  167 
  168         NET_EPOCH_ASSERT();
  169         RIB_WLOCK_ASSERT(rnh);
  170 
  171         CK_STAILQ_REMOVE(&rnh->rnh_subscribers, rs, rib_subscription, next);
  172 
  173         NET_EPOCH_CALL(destroy_subscription_epoch, &rs->epoch_ctx);
  174 }
  175 
  176 /*
  177  * Epoch callback indicating subscription is safe to destroy
  178  */
  179 static void
  180 destroy_subscription_epoch(epoch_context_t ctx)
  181 {
  182         struct rib_subscription *rs;
  183 
  184         rs = __containerof(ctx, struct rib_subscription, epoch_ctx);
  185 
  186         free(rs, M_RTABLE);
  187 }
  188 
  189 void
  190 rib_init_subscriptions(struct rib_head *rnh)
  191 {
  192 
  193         CK_STAILQ_INIT(&rnh->rnh_subscribers);
  194 }
  195 
  196 void
  197 rib_destroy_subscriptions(struct rib_head *rnh)
  198 {
  199         struct rib_subscription *rs;
  200         struct epoch_tracker et;
  201 
  202         NET_EPOCH_ENTER(et);
  203         RIB_WLOCK(rnh);
  204         while ((rs = CK_STAILQ_FIRST(&rnh->rnh_subscribers)) != NULL) {
  205                 CK_STAILQ_REMOVE_HEAD(&rnh->rnh_subscribers, next);
  206                 NET_EPOCH_CALL(destroy_subscription_epoch, &rs->epoch_ctx);
  207         }
  208         RIB_WUNLOCK(rnh);
  209         NET_EPOCH_EXIT(et);
  210 }

Cache object: 221479b3cad865fd36287a4ec79a4dba


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