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_llatbl.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) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
    5  * Copyright (c) 2004-2008 Qing Li. All rights reserved.
    6  * Copyright (c) 2008 Kip Macy. All rights reserved.
    7  * 
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 
   17  * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 DISCLAIMED.  IN NO EVENT SHALL AUTHOR 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 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include "opt_ddb.h"
   33 #include "opt_inet.h"
   34 #include "opt_inet6.h"
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/eventhandler.h>
   39 #include <sys/malloc.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/syslog.h>
   42 #include <sys/sysctl.h>
   43 #include <sys/socket.h>
   44 #include <sys/kernel.h>
   45 #include <sys/lock.h>
   46 #include <sys/mutex.h>
   47 #include <sys/rwlock.h>
   48 
   49 #ifdef DDB
   50 #include <ddb/ddb.h>
   51 #endif
   52 
   53 #include <vm/uma.h>
   54 
   55 #include <netinet/in.h>
   56 #include <net/if_llatbl.h>
   57 #include <net/if.h>
   58 #include <net/if_dl.h>
   59 #include <net/if_var.h>
   60 #include <net/if_private.h>
   61 #include <net/route.h>
   62 #include <net/route/route_ctl.h>
   63 #include <net/route/route_debug.h>
   64 #include <net/vnet.h>
   65 #include <netinet/if_ether.h>
   66 #include <netinet6/in6_var.h>
   67 #include <netinet6/nd6.h>
   68 
   69 MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables");
   70 
   71 VNET_DEFINE_STATIC(SLIST_HEAD(, lltable), lltables) =
   72     SLIST_HEAD_INITIALIZER(lltables);
   73 #define V_lltables      VNET(lltables)
   74 
   75 static struct rwlock lltable_list_lock;
   76 RW_SYSINIT(lltable_list_lock, &lltable_list_lock, "lltable_list_lock");
   77 #define LLTABLE_LIST_RLOCK()            rw_rlock(&lltable_list_lock)
   78 #define LLTABLE_LIST_RUNLOCK()          rw_runlock(&lltable_list_lock)
   79 #define LLTABLE_LIST_WLOCK()            rw_wlock(&lltable_list_lock)
   80 #define LLTABLE_LIST_WUNLOCK()          rw_wunlock(&lltable_list_lock)
   81 #define LLTABLE_LIST_LOCK_ASSERT()      rw_assert(&lltable_list_lock, RA_LOCKED)
   82 
   83 static void lltable_unlink(struct lltable *llt);
   84 static void llentries_unlink(struct lltable *llt, struct llentries *head);
   85 
   86 /*
   87  * Dump lle state for a specific address family.
   88  */
   89 static int
   90 lltable_dump_af(struct lltable *llt, struct sysctl_req *wr)
   91 {
   92         struct epoch_tracker et;
   93         int error;
   94 
   95         LLTABLE_LIST_LOCK_ASSERT();
   96 
   97         if (llt->llt_ifp->if_flags & IFF_LOOPBACK)
   98                 return (0);
   99         error = 0;
  100 
  101         NET_EPOCH_ENTER(et);
  102         error = lltable_foreach_lle(llt,
  103             (llt_foreach_cb_t *)llt->llt_dump_entry, wr);
  104         NET_EPOCH_EXIT(et);
  105 
  106         return (error);
  107 }
  108 
  109 /*
  110  * Dump arp state for a specific address family.
  111  */
  112 int
  113 lltable_sysctl_dumparp(int af, struct sysctl_req *wr)
  114 {
  115         struct lltable *llt;
  116         int error = 0;
  117 
  118         LLTABLE_LIST_RLOCK();
  119         SLIST_FOREACH(llt, &V_lltables, llt_link) {
  120                 if (llt->llt_af == af) {
  121                         error = lltable_dump_af(llt, wr);
  122                         if (error != 0)
  123                                 goto done;
  124                 }
  125         }
  126 done:
  127         LLTABLE_LIST_RUNLOCK();
  128         return (error);
  129 }
  130 
  131 /*
  132  * Adds a mbuf to hold queue. Drops old packets if the queue is full.
  133  *
  134  * Returns the number of held packets that were dropped.
  135  */
  136 size_t
  137 lltable_append_entry_queue(struct llentry *lle, struct mbuf *m,
  138     size_t maxheld)
  139 {
  140         size_t pkts_dropped = 0;
  141 
  142         LLE_WLOCK_ASSERT(lle);
  143 
  144         while (lle->la_numheld >= maxheld && lle->la_hold != NULL) {
  145                 struct mbuf *next = lle->la_hold->m_nextpkt;
  146                 m_freem(lle->la_hold);
  147                 lle->la_hold = next;
  148                 lle->la_numheld--;
  149                 pkts_dropped++;
  150         }
  151 
  152         if (lle->la_hold != NULL) {
  153                 struct mbuf *curr = lle->la_hold;
  154                 while (curr->m_nextpkt != NULL)
  155                         curr = curr->m_nextpkt;
  156                 curr->m_nextpkt = m;
  157         } else
  158                 lle->la_hold = m;
  159 
  160         lle->la_numheld++;
  161 
  162         return pkts_dropped;
  163 }
  164 
  165 
  166 /*
  167  * Common function helpers for chained hash table.
  168  */
  169 
  170 /*
  171  * Runs specified callback for each entry in @llt.
  172  * Caller does the locking.
  173  *
  174  */
  175 static int
  176 htable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f, void *farg)
  177 {
  178         struct llentry *lle, *next;
  179         int i, error;
  180 
  181         error = 0;
  182 
  183         for (i = 0; i < llt->llt_hsize; i++) {
  184                 CK_LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
  185                         error = f(llt, lle, farg);
  186                         if (error != 0)
  187                                 break;
  188                 }
  189         }
  190 
  191         return (error);
  192 }
  193 
  194 /*
  195  * The htable_[un]link_entry() functions return:
  196  * 0 if the entry was (un)linked already and nothing changed,
  197  * 1 if the entry was added/removed to/from the table, and
  198  * -1 on error (e.g., not being able to add the entry due to limits reached).
  199  * While the "unlink" operation should never error, callers of
  200  * lltable_link_entry() need to check for errors and handle them.
  201  */
  202 static int
  203 htable_link_entry(struct lltable *llt, struct llentry *lle)
  204 {
  205         struct llentries *lleh;
  206         uint32_t hashidx;
  207 
  208         if ((lle->la_flags & LLE_LINKED) != 0)
  209                 return (0);
  210 
  211         IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp);
  212 
  213         if (llt->llt_maxentries > 0 &&
  214             llt->llt_entries >= llt->llt_maxentries)
  215                 return (-1);
  216 
  217         hashidx = llt->llt_hash(lle, llt->llt_hsize);
  218         lleh = &llt->lle_head[hashidx];
  219 
  220         lle->lle_tbl  = llt;
  221         lle->lle_head = lleh;
  222         lle->la_flags |= LLE_LINKED;
  223         CK_LIST_INSERT_HEAD(lleh, lle, lle_next);
  224         llt->llt_entries++;
  225 
  226         return (1);
  227 }
  228 
  229 static int
  230 htable_unlink_entry(struct llentry *lle)
  231 {
  232         struct lltable *llt;
  233 
  234         if ((lle->la_flags & LLE_LINKED) == 0)
  235                 return (0);
  236 
  237         llt = lle->lle_tbl;
  238         IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp);
  239         KASSERT(llt->llt_entries > 0, ("%s: lltable %p (%s) entries %d <= 0",
  240             __func__, llt, if_name(llt->llt_ifp), llt->llt_entries));
  241 
  242         CK_LIST_REMOVE(lle, lle_next);
  243         lle->la_flags &= ~(LLE_VALID | LLE_LINKED);
  244 #if 0
  245         lle->lle_tbl = NULL;
  246         lle->lle_head = NULL;
  247 #endif
  248         llt->llt_entries--;
  249 
  250         return (1);
  251 }
  252 
  253 struct prefix_match_data {
  254         const struct sockaddr *addr;
  255         const struct sockaddr *mask;
  256         struct llentries dchain;
  257         u_int flags;
  258 };
  259 
  260 static int
  261 htable_prefix_free_cb(struct lltable *llt, struct llentry *lle, void *farg)
  262 {
  263         struct prefix_match_data *pmd;
  264 
  265         pmd = (struct prefix_match_data *)farg;
  266 
  267         if (llt->llt_match_prefix(pmd->addr, pmd->mask, pmd->flags, lle)) {
  268                 LLE_WLOCK(lle);
  269                 CK_LIST_INSERT_HEAD(&pmd->dchain, lle, lle_chain);
  270         }
  271 
  272         return (0);
  273 }
  274 
  275 static void
  276 htable_prefix_free(struct lltable *llt, const struct sockaddr *addr,
  277     const struct sockaddr *mask, u_int flags)
  278 {
  279         struct llentry *lle, *next;
  280         struct prefix_match_data pmd;
  281 
  282         bzero(&pmd, sizeof(pmd));
  283         pmd.addr = addr;
  284         pmd.mask = mask;
  285         pmd.flags = flags;
  286         CK_LIST_INIT(&pmd.dchain);
  287 
  288         IF_AFDATA_WLOCK(llt->llt_ifp);
  289         /* Push matching lles to chain */
  290         lltable_foreach_lle(llt, htable_prefix_free_cb, &pmd);
  291 
  292         llentries_unlink(llt, &pmd.dchain);
  293         IF_AFDATA_WUNLOCK(llt->llt_ifp);
  294 
  295         CK_LIST_FOREACH_SAFE(lle, &pmd.dchain, lle_chain, next)
  296                 lltable_free_entry(llt, lle);
  297 }
  298 
  299 static void
  300 htable_free_tbl(struct lltable *llt)
  301 {
  302 
  303         free(llt->lle_head, M_LLTABLE);
  304         free(llt, M_LLTABLE);
  305 }
  306 
  307 static void
  308 llentries_unlink(struct lltable *llt, struct llentries *head)
  309 {
  310         struct llentry *lle, *next;
  311 
  312         CK_LIST_FOREACH_SAFE(lle, head, lle_chain, next)
  313                 llt->llt_unlink_entry(lle);
  314 }
  315 
  316 /*
  317  * Helper function used to drop all mbufs in hold queue.
  318  *
  319  * Returns the number of held packets, if any, that were dropped.
  320  */
  321 size_t
  322 lltable_drop_entry_queue(struct llentry *lle)
  323 {
  324         size_t pkts_dropped = 0;
  325 
  326         LLE_WLOCK_ASSERT(lle);
  327 
  328         while (lle->la_hold != NULL) {
  329                 struct mbuf *next = lle->la_hold->m_nextpkt;
  330                 m_freem(lle->la_hold);
  331                 lle->la_hold = next;
  332                 lle->la_numheld--;
  333                 pkts_dropped++;
  334         }
  335 
  336         KASSERT(lle->la_numheld == 0,
  337                 ("%s: la_numheld %d > 0, pkts_dropped %zd", __func__,
  338                  lle->la_numheld, pkts_dropped));
  339 
  340         return (pkts_dropped);
  341 }
  342 
  343 void
  344 lltable_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
  345     const char *linkhdr, size_t linkhdrsize, int lladdr_off)
  346 {
  347 
  348         memcpy(lle->r_linkdata, linkhdr, linkhdrsize);
  349         lle->r_hdrlen = linkhdrsize;
  350         lle->ll_addr = &lle->r_linkdata[lladdr_off];
  351         lle->la_flags |= LLE_VALID;
  352         lle->r_flags |= RLLE_VALID;
  353 }
  354 
  355 /*
  356  * Acquires lltable write lock.
  357  *
  358  * Returns true on success, with both lltable and lle lock held.
  359  * On failure, false is returned and lle wlock is still held.
  360  */
  361 bool
  362 lltable_acquire_wlock(struct ifnet *ifp, struct llentry *lle)
  363 {
  364         NET_EPOCH_ASSERT();
  365 
  366         /* Perform real LLE update */
  367         /* use afdata WLOCK to update fields */
  368         LLE_WUNLOCK(lle);
  369         IF_AFDATA_WLOCK(ifp);
  370         LLE_WLOCK(lle);
  371 
  372         /*
  373          * Since we droppped LLE lock, other thread might have deleted
  374          * this lle. Check and return
  375          */
  376         if ((lle->la_flags & LLE_DELETED) != 0) {
  377                 IF_AFDATA_WUNLOCK(ifp);
  378                 return (false);
  379         }
  380 
  381         return (true);
  382 }
  383 
  384 /*
  385  * Tries to update @lle link-level address.
  386  * Since update requires AFDATA WLOCK, function
  387  * drops @lle lock, acquires AFDATA lock and then acquires
  388  * @lle lock to maintain lock order.
  389  *
  390  * Returns 1 on success.
  391  */
  392 int
  393 lltable_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
  394     const char *linkhdr, size_t linkhdrsize, int lladdr_off)
  395 {
  396 
  397         if (!lltable_acquire_wlock(ifp, lle))
  398                 return (0);
  399 
  400         /* Update data */
  401         lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize, lladdr_off);
  402 
  403         IF_AFDATA_WUNLOCK(ifp);
  404 
  405         return (1);
  406 }
  407 
  408  /*
  409  * Helper function used to pre-compute full/partial link-layer
  410  * header data suitable for feeding into if_output().
  411  */
  412 int
  413 lltable_calc_llheader(struct ifnet *ifp, int family, char *lladdr,
  414     char *buf, size_t *bufsize, int *lladdr_off)
  415 {
  416         struct if_encap_req ereq;
  417         int error;
  418 
  419         bzero(buf, *bufsize);
  420         bzero(&ereq, sizeof(ereq));
  421         ereq.buf = buf;
  422         ereq.bufsize = *bufsize;
  423         ereq.rtype = IFENCAP_LL;
  424         ereq.family = family;
  425         ereq.lladdr = lladdr;
  426         ereq.lladdr_len = ifp->if_addrlen;
  427         error = ifp->if_requestencap(ifp, &ereq);
  428         if (error == 0) {
  429                 *bufsize = ereq.bufsize;
  430                 *lladdr_off = ereq.lladdr_off;
  431         }
  432 
  433         return (error);
  434 }
  435 
  436 /*
  437  * Searches for the child entry matching @family inside @lle.
  438  * Returns the entry or NULL.
  439  */
  440 struct llentry *
  441 llentry_lookup_family(struct llentry *lle, int family)
  442 {
  443         struct llentry *child_lle;
  444 
  445         if (lle == NULL)
  446                 return (NULL);
  447 
  448         CK_SLIST_FOREACH(child_lle, &lle->lle_children, lle_child_next) {
  449                 if (child_lle->r_family == family)
  450                         return (child_lle);
  451         }
  452 
  453         return (NULL);
  454 }
  455 
  456 /*
  457  * Retrieves upper protocol family for the llentry.
  458  * By default, all "normal" (e.g. upper_family == transport_family)
  459  * llentries have r_family set to 0.
  460  * Thus, use @default_family in that regard, otherwise use r_family.
  461  *
  462  * Returns upper protocol family
  463  */
  464 int
  465 llentry_get_upper_family(const struct llentry *lle, int default_family)
  466 {
  467         return (lle->r_family == 0 ? default_family : lle->r_family);
  468 }
  469 
  470 /*
  471  * Prints llentry @lle data into provided buffer.
  472  * Example: lle/inet/valid/em0/1.2.3.4
  473  *
  474  * Returns @buf.
  475  */
  476 char *
  477 llentry_print_buf(const struct llentry *lle, struct ifnet *ifp, int family,
  478     char *buf, size_t bufsize)
  479 {
  480 #if defined(INET) || defined(INET6)
  481         char abuf[INET6_ADDRSTRLEN];
  482 #endif
  483 
  484         const char *valid = (lle->r_flags & RLLE_VALID) ? "valid" : "no_l2";
  485         const char *upper_str = rib_print_family(llentry_get_upper_family(lle, family));
  486 
  487         switch (family) {
  488 #ifdef INET
  489         case AF_INET:
  490                 inet_ntop(AF_INET, &lle->r_l3addr.addr4, abuf, sizeof(abuf));
  491                 snprintf(buf, bufsize, "lle/%s/%s/%s/%s", upper_str,
  492                     valid, if_name(ifp), abuf);
  493                 break;
  494 #endif
  495 #ifdef INET6
  496         case AF_INET6:
  497                 inet_ntop(AF_INET6, &lle->r_l3addr.addr6, abuf, sizeof(abuf));
  498                 snprintf(buf, bufsize, "lle/%s/%s/%s/%s", upper_str,
  499                     valid, if_name(ifp), abuf);
  500                 break;
  501 #endif
  502         default:
  503                 snprintf(buf, bufsize, "lle/%s/%s/%s/????", upper_str,
  504                     valid, if_name(ifp));
  505                 break;
  506         }
  507 
  508         return (buf);
  509 }
  510 
  511 char *
  512 llentry_print_buf_lltable(const struct llentry *lle, char *buf, size_t bufsize)
  513 {
  514         struct lltable *tbl = lle->lle_tbl;
  515 
  516         return (llentry_print_buf(lle, lltable_get_ifp(tbl), lltable_get_af(tbl), buf, bufsize));
  517 }
  518 
  519 /*
  520  * Requests feedback from the datapath.
  521  * First packet using @lle should result in
  522  * setting r_skip_req back to 0 and updating
  523  * lle_hittime to the current time_uptime.
  524  */
  525 void
  526 llentry_request_feedback(struct llentry *lle)
  527 {
  528         struct llentry *child_lle;
  529 
  530         LLE_REQ_LOCK(lle);
  531         lle->r_skip_req = 1;
  532         LLE_REQ_UNLOCK(lle);
  533 
  534         CK_SLIST_FOREACH(child_lle, &lle->lle_children, lle_child_next) {
  535                 LLE_REQ_LOCK(child_lle);
  536                 child_lle->r_skip_req = 1;
  537                 LLE_REQ_UNLOCK(child_lle);
  538         }
  539 }
  540 
  541 /*
  542  * Updates the lle state to mark it has been used
  543  * and record the time.
  544  * Used by the llentry_provide_feedback() wrapper.
  545  */
  546 void
  547 llentry_mark_used(struct llentry *lle)
  548 {
  549         LLE_REQ_LOCK(lle);
  550         lle->r_skip_req = 0;
  551         lle->lle_hittime = time_uptime;
  552         LLE_REQ_UNLOCK(lle);
  553 }
  554 
  555 /*
  556  * Fetches the time when lle was used.
  557  * Return 0 if the entry was not used, relevant time_uptime
  558  *  otherwise.
  559  */
  560 static time_t
  561 llentry_get_hittime_raw(struct llentry *lle)
  562 {
  563         time_t lle_hittime = 0;
  564 
  565         LLE_REQ_LOCK(lle);
  566         if ((lle->r_skip_req == 0) && (lle_hittime < lle->lle_hittime))
  567                 lle_hittime = lle->lle_hittime;
  568         LLE_REQ_UNLOCK(lle);
  569 
  570         return (lle_hittime);
  571 }
  572 
  573 time_t
  574 llentry_get_hittime(struct llentry *lle)
  575 {
  576         time_t lle_hittime = 0;
  577         struct llentry *child_lle;
  578 
  579         lle_hittime = llentry_get_hittime_raw(lle);
  580 
  581         CK_SLIST_FOREACH(child_lle, &lle->lle_children, lle_child_next) {
  582                 time_t hittime = llentry_get_hittime_raw(child_lle);
  583                 if (hittime > lle_hittime)
  584                         lle_hittime = hittime;
  585         }
  586 
  587         return (lle_hittime);
  588 }
  589 
  590 /*
  591  * Update link-layer header for given @lle after
  592  * interface lladdr was changed.
  593  */
  594 static int
  595 llentry_update_ifaddr(struct lltable *llt, struct llentry *lle, void *farg)
  596 {
  597         struct ifnet *ifp;
  598         u_char linkhdr[LLE_MAX_LINKHDR];
  599         size_t linkhdrsize;
  600         u_char *lladdr;
  601         int lladdr_off;
  602 
  603         ifp = (struct ifnet *)farg;
  604 
  605         lladdr = lle->ll_addr;
  606 
  607         LLE_WLOCK(lle);
  608         if ((lle->la_flags & LLE_VALID) == 0) {
  609                 LLE_WUNLOCK(lle);
  610                 return (0);
  611         }
  612 
  613         if ((lle->la_flags & LLE_IFADDR) != 0)
  614                 lladdr = IF_LLADDR(ifp);
  615 
  616         linkhdrsize = sizeof(linkhdr);
  617         lltable_calc_llheader(ifp, llt->llt_af, lladdr, linkhdr, &linkhdrsize,
  618             &lladdr_off);
  619         memcpy(lle->r_linkdata, linkhdr, linkhdrsize);
  620         LLE_WUNLOCK(lle);
  621 
  622         return (0);
  623 }
  624 
  625 /*
  626  * Update all calculated headers for given @llt
  627  */
  628 void
  629 lltable_update_ifaddr(struct lltable *llt)
  630 {
  631 
  632         if (llt->llt_ifp->if_flags & IFF_LOOPBACK)
  633                 return;
  634 
  635         IF_AFDATA_WLOCK(llt->llt_ifp);
  636         lltable_foreach_lle(llt, llentry_update_ifaddr, llt->llt_ifp);
  637         IF_AFDATA_WUNLOCK(llt->llt_ifp);
  638 }
  639 
  640 /*
  641  *
  642  * Performs generic cleanup routines and frees lle.
  643  *
  644  * Called for non-linked entries, with callouts and
  645  * other AF-specific cleanups performed.
  646  *
  647  * @lle must be passed WLOCK'ed
  648  *
  649  * Returns the number of held packets, if any, that were dropped.
  650  */
  651 size_t
  652 llentry_free(struct llentry *lle)
  653 {
  654         size_t pkts_dropped;
  655 
  656         LLE_WLOCK_ASSERT(lle);
  657 
  658         KASSERT((lle->la_flags & LLE_LINKED) == 0, ("freeing linked lle"));
  659 
  660         pkts_dropped = lltable_drop_entry_queue(lle);
  661 
  662         /* cancel timer */
  663         if (callout_stop(&lle->lle_timer) > 0)
  664                 LLE_REMREF(lle);
  665         LLE_FREE_LOCKED(lle);
  666 
  667         return (pkts_dropped);
  668 }
  669 
  670 /*
  671  * Free all entries from given table and free itself.
  672  */
  673 
  674 static int
  675 lltable_free_cb(struct lltable *llt, struct llentry *lle, void *farg)
  676 {
  677         struct llentries *dchain;
  678 
  679         dchain = (struct llentries *)farg;
  680 
  681         LLE_WLOCK(lle);
  682         CK_LIST_INSERT_HEAD(dchain, lle, lle_chain);
  683 
  684         return (0);
  685 }
  686 
  687 /*
  688  * Free all entries from given table and free itself.
  689  */
  690 void
  691 lltable_free(struct lltable *llt)
  692 {
  693         struct llentry *lle, *next;
  694         struct llentries dchain;
  695 
  696         KASSERT(llt != NULL, ("%s: llt is NULL", __func__));
  697 
  698         lltable_unlink(llt);
  699 
  700         CK_LIST_INIT(&dchain);
  701         IF_AFDATA_WLOCK(llt->llt_ifp);
  702         /* Push all lles to @dchain */
  703         lltable_foreach_lle(llt, lltable_free_cb, &dchain);
  704         llentries_unlink(llt, &dchain);
  705         IF_AFDATA_WUNLOCK(llt->llt_ifp);
  706 
  707         CK_LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) {
  708                 llentry_free(lle);
  709         }
  710 
  711         KASSERT(llt->llt_entries == 0, ("%s: lltable %p (%s) entires not 0: %d",
  712             __func__, llt, llt->llt_ifp->if_xname, llt->llt_entries));
  713 
  714         llt->llt_free_tbl(llt);
  715 }
  716 
  717 /*
  718  * Deletes an address from given lltable.
  719  * Used for userland interaction to remove
  720  * individual entries. Skips entries added by OS.
  721  */
  722 int
  723 lltable_delete_addr(struct lltable *llt, u_int flags,
  724     const struct sockaddr *l3addr)
  725 {
  726         struct llentry *lle;
  727         struct ifnet *ifp;
  728 
  729         ifp = llt->llt_ifp;
  730         IF_AFDATA_WLOCK(ifp);
  731         lle = lla_lookup(llt, LLE_SF(l3addr->sa_family, LLE_EXCLUSIVE), l3addr);
  732 
  733         if (lle == NULL) {
  734                 IF_AFDATA_WUNLOCK(ifp);
  735                 return (ENOENT);
  736         }
  737         if ((lle->la_flags & LLE_IFADDR) != 0 && (flags & LLE_IFADDR) == 0) {
  738                 IF_AFDATA_WUNLOCK(ifp);
  739                 LLE_WUNLOCK(lle);
  740                 return (EPERM);
  741         }
  742 
  743         lltable_unlink_entry(llt, lle);
  744         IF_AFDATA_WUNLOCK(ifp);
  745 
  746         llt->llt_delete_entry(llt, lle);
  747 
  748         return (0);
  749 }
  750 
  751 void
  752 lltable_prefix_free(int af, struct sockaddr *addr, struct sockaddr *mask,
  753     u_int flags)
  754 {
  755         struct lltable *llt;
  756 
  757         LLTABLE_LIST_RLOCK();
  758         SLIST_FOREACH(llt, &V_lltables, llt_link) {
  759                 if (llt->llt_af != af)
  760                         continue;
  761 
  762                 llt->llt_prefix_free(llt, addr, mask, flags);
  763         }
  764         LLTABLE_LIST_RUNLOCK();
  765 }
  766 
  767 /*
  768  * Delete llentries that func() returns true.
  769  */
  770 struct lle_match_data {
  771         struct llentries dchain;
  772         llt_match_cb_t *func;
  773         void *farg;
  774 };
  775 
  776 static int
  777 lltable_delete_conditional_cb(struct lltable *llt, struct llentry *lle,
  778     void *farg)
  779 {
  780         struct lle_match_data *lmd;
  781 
  782         lmd = (struct lle_match_data *)farg;
  783         if (lmd->func(llt, lle, lmd->farg)) {
  784                 LLE_WLOCK(lle);
  785                 CK_LIST_INSERT_HEAD(&lmd->dchain, lle, lle_chain);
  786         }
  787 
  788         return (0);
  789 }
  790 
  791 void
  792 lltable_delete_conditional(struct lltable *llt, llt_match_cb_t *func,
  793     void *farg)
  794 {
  795         struct llentry *lle, *next;
  796         struct lle_match_data lmd;
  797 
  798         bzero(&lmd, sizeof(lmd));
  799         CK_LIST_INIT(&lmd.dchain);
  800         lmd.func = func;
  801         lmd.farg = farg;
  802 
  803         IF_AFDATA_WLOCK(llt->llt_ifp);
  804         lltable_foreach_lle(llt, lltable_delete_conditional_cb, &lmd);
  805         llentries_unlink(llt, &lmd.dchain);
  806         IF_AFDATA_WUNLOCK(llt->llt_ifp);
  807 
  808         CK_LIST_FOREACH_SAFE(lle, &lmd.dchain, lle_chain, next)
  809                 llt->llt_delete_entry(llt, lle);
  810 }
  811 
  812 struct lltable *
  813 lltable_allocate_htbl(uint32_t hsize)
  814 {
  815         struct lltable *llt;
  816         int i;
  817 
  818         llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK | M_ZERO);
  819         llt->llt_hsize = hsize;
  820         llt->lle_head = malloc(sizeof(struct llentries) * hsize,
  821             M_LLTABLE, M_WAITOK | M_ZERO);
  822 
  823         for (i = 0; i < llt->llt_hsize; i++)
  824                 CK_LIST_INIT(&llt->lle_head[i]);
  825 
  826         /* Set some default callbacks */
  827         llt->llt_link_entry = htable_link_entry;
  828         llt->llt_unlink_entry = htable_unlink_entry;
  829         llt->llt_prefix_free = htable_prefix_free;
  830         llt->llt_foreach_entry = htable_foreach_lle;
  831         llt->llt_free_tbl = htable_free_tbl;
  832 
  833         return (llt);
  834 }
  835 
  836 /*
  837  * Links lltable to global llt list.
  838  */
  839 void
  840 lltable_link(struct lltable *llt)
  841 {
  842 
  843         LLTABLE_LIST_WLOCK();
  844         SLIST_INSERT_HEAD(&V_lltables, llt, llt_link);
  845         LLTABLE_LIST_WUNLOCK();
  846 }
  847 
  848 static void
  849 lltable_unlink(struct lltable *llt)
  850 {
  851 
  852         LLTABLE_LIST_WLOCK();
  853         SLIST_REMOVE(&V_lltables, llt, lltable, llt_link);
  854         LLTABLE_LIST_WUNLOCK();
  855 
  856 }
  857 
  858 /*
  859  * Gets interface @ifp lltable for the specified @family
  860  */
  861 struct lltable *
  862 lltable_get(struct ifnet *ifp, int family)
  863 {
  864         switch (family) {
  865 #ifdef INET
  866         case AF_INET:
  867                 return (in_lltable_get(ifp));
  868 #endif
  869 #ifdef INET6
  870         case AF_INET6:
  871                 return (in6_lltable_get(ifp));
  872 #endif
  873         }
  874 
  875         return (NULL);
  876 }
  877 
  878 /*
  879  * External methods used by lltable consumers
  880  */
  881 
  882 int
  883 lltable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f, void *farg)
  884 {
  885 
  886         return (llt->llt_foreach_entry(llt, f, farg));
  887 }
  888 
  889 struct llentry *
  890 lltable_alloc_entry(struct lltable *llt, u_int flags,
  891     const struct sockaddr *l3addr)
  892 {
  893 
  894         return (llt->llt_alloc_entry(llt, flags, l3addr));
  895 }
  896 
  897 void
  898 lltable_free_entry(struct lltable *llt, struct llentry *lle)
  899 {
  900 
  901         llt->llt_free_entry(llt, lle);
  902 }
  903 
  904 int
  905 lltable_link_entry(struct lltable *llt, struct llentry *lle)
  906 {
  907 
  908         return (llt->llt_link_entry(llt, lle));
  909 }
  910 
  911 void
  912 lltable_link_child_entry(struct llentry *lle, struct llentry *child_lle)
  913 {
  914         child_lle->lle_parent = lle;
  915         child_lle->lle_tbl = lle->lle_tbl;
  916         child_lle->la_flags |= LLE_LINKED;
  917         CK_SLIST_INSERT_HEAD(&lle->lle_children, child_lle, lle_child_next);
  918 }
  919 
  920 void
  921 lltable_unlink_child_entry(struct llentry *child_lle)
  922 {
  923         struct llentry *lle = child_lle->lle_parent;
  924 
  925         child_lle->la_flags &= ~LLE_LINKED;
  926         child_lle->lle_parent = NULL;
  927         CK_SLIST_REMOVE(&lle->lle_children, child_lle, llentry, lle_child_next);
  928 }
  929 
  930 int
  931 lltable_unlink_entry(struct lltable *llt, struct llentry *lle)
  932 {
  933 
  934         return (llt->llt_unlink_entry(lle));
  935 }
  936 
  937 void
  938 lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa)
  939 {
  940         struct lltable *llt;
  941 
  942         llt = lle->lle_tbl;
  943         llt->llt_fill_sa_entry(lle, sa);
  944 }
  945 
  946 struct ifnet *
  947 lltable_get_ifp(const struct lltable *llt)
  948 {
  949 
  950         return (llt->llt_ifp);
  951 }
  952 
  953 int
  954 lltable_get_af(const struct lltable *llt)
  955 {
  956 
  957         return (llt->llt_af);
  958 }
  959 
  960 /*
  961  * Called in route_output when rtm_flags contains RTF_LLDATA.
  962  */
  963 int
  964 lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
  965 {
  966         struct sockaddr_dl *dl =
  967             (struct sockaddr_dl *)info->rti_info[RTAX_GATEWAY];
  968         struct sockaddr *dst = (struct sockaddr *)info->rti_info[RTAX_DST];
  969         struct ifnet *ifp;
  970         struct lltable *llt;
  971         struct llentry *lle, *lle_tmp;
  972         uint8_t linkhdr[LLE_MAX_LINKHDR];
  973         size_t linkhdrsize;
  974         int lladdr_off;
  975         u_int laflags = 0;
  976         int error;
  977 
  978         if (dl == NULL || dl->sdl_family != AF_LINK)
  979                 return (EINVAL);
  980 
  981         /* XXX: should be ntohs() */
  982         ifp = ifnet_byindex(dl->sdl_index);
  983         if (ifp == NULL) {
  984                 log(LOG_INFO, "%s: invalid ifp (sdl_index %d)\n",
  985                     __func__, dl->sdl_index);
  986                 return EINVAL;
  987         }
  988 
  989         llt = lltable_get(ifp, dst->sa_family);
  990 
  991         if (llt == NULL)
  992                 return (ESRCH);
  993 
  994         error = 0;
  995 
  996         switch (rtm->rtm_type) {
  997         case RTM_ADD:
  998                 /* Add static LLE */
  999                 laflags = 0;
 1000                 if (rtm->rtm_rmx.rmx_expire == 0)
 1001                         laflags = LLE_STATIC;
 1002                 lle = lltable_alloc_entry(llt, laflags, dst);
 1003                 if (lle == NULL)
 1004                         return (ENOMEM);
 1005 
 1006                 linkhdrsize = sizeof(linkhdr);
 1007                 if (lltable_calc_llheader(ifp, dst->sa_family, LLADDR(dl),
 1008                     linkhdr, &linkhdrsize, &lladdr_off) != 0) {
 1009                         lltable_free_entry(llt, lle);
 1010                         return (EINVAL);
 1011                 }
 1012                 lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize,
 1013                     lladdr_off);
 1014                 if ((rtm->rtm_flags & RTF_ANNOUNCE))
 1015                         lle->la_flags |= LLE_PUB;
 1016                 lle->la_expire = rtm->rtm_rmx.rmx_expire;
 1017 
 1018                 laflags = lle->la_flags;
 1019 
 1020                 /* Try to link new entry */
 1021                 lle_tmp = NULL;
 1022                 IF_AFDATA_WLOCK(ifp);
 1023                 LLE_WLOCK(lle);
 1024                 lle_tmp = lla_lookup(llt, LLE_EXCLUSIVE, dst);
 1025                 if (lle_tmp != NULL) {
 1026                         /* Check if we are trying to replace immutable entry */
 1027                         if ((lle_tmp->la_flags & LLE_IFADDR) != 0) {
 1028                                 IF_AFDATA_WUNLOCK(ifp);
 1029                                 LLE_WUNLOCK(lle_tmp);
 1030                                 lltable_free_entry(llt, lle);
 1031                                 return (EPERM);
 1032                         }
 1033                         /* Unlink existing entry from table */
 1034                         lltable_unlink_entry(llt, lle_tmp);
 1035                 }
 1036                 lltable_link_entry(llt, lle);
 1037                 if ((lle->la_flags & LLE_PUB) != 0 &&
 1038                     (llt->llt_flags & LLT_ADDEDPROXY) == 0)
 1039                         llt->llt_flags |= LLT_ADDEDPROXY;
 1040                 IF_AFDATA_WUNLOCK(ifp);
 1041 
 1042                 if (lle_tmp != NULL) {
 1043                         EVENTHANDLER_INVOKE(lle_event, lle_tmp,LLENTRY_EXPIRED);
 1044                         lltable_free_entry(llt, lle_tmp);
 1045                 }
 1046 
 1047                 /*
 1048                  * By invoking LLE handler here we might get
 1049                  * two events on static LLE entry insertion
 1050                  * in routing socket. However, since we might have
 1051                  * other subscribers we need to generate this event.
 1052                  */
 1053                 EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_RESOLVED);
 1054                 LLE_WUNLOCK(lle);
 1055                 llt->llt_post_resolved(llt, lle);
 1056                 break;
 1057 
 1058         case RTM_DELETE:
 1059                 return (lltable_delete_addr(llt, 0, dst));
 1060 
 1061         default:
 1062                 error = EINVAL;
 1063         }
 1064 
 1065         return (error);
 1066 }
 1067 
 1068 #ifdef DDB
 1069 struct llentry_sa {
 1070         struct llentry          base;
 1071         struct sockaddr         l3_addr;
 1072 };
 1073 
 1074 static void
 1075 llatbl_lle_show(struct llentry_sa *la)
 1076 {
 1077         struct llentry *lle;
 1078         uint8_t octet[6];
 1079 
 1080         lle = &la->base;
 1081         db_printf("lle=%p\n", lle);
 1082         db_printf(" lle_next=%p\n", lle->lle_next.cle_next);
 1083         db_printf(" lle_lock=%p\n", &lle->lle_lock);
 1084         db_printf(" lle_tbl=%p\n", lle->lle_tbl);
 1085         db_printf(" lle_head=%p\n", lle->lle_head);
 1086         db_printf(" la_hold=%p\n", lle->la_hold);
 1087         db_printf(" la_numheld=%d\n", lle->la_numheld);
 1088         db_printf(" la_expire=%ju\n", (uintmax_t)lle->la_expire);
 1089         db_printf(" la_flags=0x%04x\n", lle->la_flags);
 1090         db_printf(" la_asked=%u\n", lle->la_asked);
 1091         db_printf(" la_preempt=%u\n", lle->la_preempt);
 1092         db_printf(" ln_state=%d\n", lle->ln_state);
 1093         db_printf(" ln_router=%u\n", lle->ln_router);
 1094         db_printf(" ln_ntick=%ju\n", (uintmax_t)lle->ln_ntick);
 1095         db_printf(" lle_refcnt=%d\n", lle->lle_refcnt);
 1096         bcopy(lle->ll_addr, octet, sizeof(octet));
 1097         db_printf(" ll_addr=%02x:%02x:%02x:%02x:%02x:%02x\n",
 1098             octet[0], octet[1], octet[2], octet[3], octet[4], octet[5]);
 1099         db_printf(" lle_timer=%p\n", &lle->lle_timer);
 1100 
 1101         switch (la->l3_addr.sa_family) {
 1102 #ifdef INET
 1103         case AF_INET:
 1104         {
 1105                 struct sockaddr_in *sin;
 1106                 char l3s[INET_ADDRSTRLEN];
 1107 
 1108                 sin = (struct sockaddr_in *)&la->l3_addr;
 1109                 inet_ntoa_r(sin->sin_addr, l3s);
 1110                 db_printf(" l3_addr=%s\n", l3s);
 1111                 break;
 1112         }
 1113 #endif
 1114 #ifdef INET6
 1115         case AF_INET6:
 1116         {
 1117                 struct sockaddr_in6 *sin6;
 1118                 char l3s[INET6_ADDRSTRLEN];
 1119 
 1120                 sin6 = (struct sockaddr_in6 *)&la->l3_addr;
 1121                 ip6_sprintf(l3s, &sin6->sin6_addr);
 1122                 db_printf(" l3_addr=%s\n", l3s);
 1123                 break;
 1124         }
 1125 #endif
 1126         default:
 1127                 db_printf(" l3_addr=N/A (af=%d)\n", la->l3_addr.sa_family);
 1128                 break;
 1129         }
 1130 }
 1131 
 1132 DB_SHOW_COMMAND(llentry, db_show_llentry)
 1133 {
 1134 
 1135         if (!have_addr) {
 1136                 db_printf("usage: show llentry <struct llentry *>\n");
 1137                 return;
 1138         }
 1139 
 1140         llatbl_lle_show((struct llentry_sa *)addr);
 1141 }
 1142 
 1143 static void
 1144 llatbl_llt_show(struct lltable *llt)
 1145 {
 1146         int i;
 1147         struct llentry *lle;
 1148 
 1149         db_printf("llt=%p llt_af=%d llt_ifp=%p\n",
 1150             llt, llt->llt_af, llt->llt_ifp);
 1151 
 1152         for (i = 0; i < llt->llt_hsize; i++) {
 1153                 CK_LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
 1154                         llatbl_lle_show((struct llentry_sa *)lle);
 1155                         if (db_pager_quit)
 1156                                 return;
 1157                 }
 1158         }
 1159 }
 1160 
 1161 DB_SHOW_COMMAND(lltable, db_show_lltable)
 1162 {
 1163 
 1164         if (!have_addr) {
 1165                 db_printf("usage: show lltable <struct lltable *>\n");
 1166                 return;
 1167         }
 1168 
 1169         llatbl_llt_show((struct lltable *)addr);
 1170 }
 1171 
 1172 DB_SHOW_ALL_COMMAND(lltables, db_show_all_lltables)
 1173 {
 1174         VNET_ITERATOR_DECL(vnet_iter);
 1175         struct lltable *llt;
 1176 
 1177         VNET_FOREACH(vnet_iter) {
 1178                 CURVNET_SET_QUIET(vnet_iter);
 1179 #ifdef VIMAGE
 1180                 db_printf("vnet=%p\n", curvnet);
 1181 #endif
 1182                 SLIST_FOREACH(llt, &V_lltables, llt_link) {
 1183                         db_printf("llt=%p llt_af=%d llt_ifp=%p(%s)\n",
 1184                             llt, llt->llt_af, llt->llt_ifp,
 1185                             (llt->llt_ifp != NULL) ?
 1186                                 llt->llt_ifp->if_xname : "?");
 1187                         if (have_addr && addr != 0) /* verbose */
 1188                                 llatbl_llt_show(llt);
 1189                         if (db_pager_quit) {
 1190                                 CURVNET_RESTORE();
 1191                                 return;
 1192                         }
 1193                 }
 1194                 CURVNET_RESTORE();
 1195         }
 1196 }
 1197 #endif

Cache object: 273dbf333459ea1ef70e9330c0b3c791


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