if_llatbl.h revision 191154
12786Ssos/* 22786Ssos * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved. 32786Ssos * Copyright (c) 2004-2008 Qing Li. All rights reserved. 42786Ssos * Copyright (c) 2008 Kip Macy. All rights reserved. 52786Ssos * 62786Ssos * Redistribution and use in source and binary forms, with or without 72786Ssos * modification, are permitted provided that the following conditions 86851Ssos * are met: 92786Ssos * 1. Redistributions of source code must retain the above copyright 1029826Sache * notice, this list of conditions and the following disclaimer. 112786Ssos * 2. Redistributions in binary form must reproduce the above copyright 122786Ssos * notice, this list of conditions and the following disclaimer in the 132786Ssos * documentation and/or other materials provided with the distribution. 142786Ssos * 1528375Ssos * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 162786Ssos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 172786Ssos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 182786Ssos * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 197420Ssos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 202786Ssos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 212786Ssos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 222786Ssos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 232786Ssos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 242786Ssos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 252786Ssos * SUCH DAMAGE. 262786Ssos */ 272786Ssos#include <sys/cdefs.h> 282786Ssos__FBSDID("$FreeBSD: head/sys/net/if_llatbl.h 191154 2009-04-16 22:04:07Z kmacy $"); 292786Ssos 302786Ssos#ifndef _NET_IF_LLATBL_H_ 312786Ssos#define _NET_IF_LLATBL_H_ 322786Ssos 332786Ssos#include <sys/_rwlock.h> 342786Ssos#include <netinet/in.h> 352786Ssos 362786Ssosstruct ifnet; 372786Ssosstruct sysctl_req; 382786Ssosstruct rt_msghdr; 392786Ssosstruct rt_addrinfo; 402786Ssos 412786Ssosstruct llentry; 422786SsosLIST_HEAD(llentries, llentry); 432786Ssos 442786Ssos/* 452786Ssos * Code referencing llentry must at least hold 462786Ssos * a shared lock 472786Ssos */ 482786Ssosstruct llentry { 492786Ssos LIST_ENTRY(llentry) lle_next; 502786Ssos struct rwlock lle_lock; 512786Ssos struct lltable *lle_tbl; 522786Ssos struct llentries *lle_head; 532786Ssos struct mbuf *la_hold; 542786Ssos time_t la_expire; 552786Ssos uint16_t la_flags; 562786Ssos uint16_t la_asked; 572786Ssos uint16_t la_preempt; 582786Ssos uint16_t ln_byhint; 592786Ssos int16_t ln_state; /* IPv6 has ND6_LLINFO_NOSTATE == -2 */ 602786Ssos uint16_t ln_router; 612786Ssos time_t ln_ntick; 6232822Syokota int lle_refcnt; 632786Ssos 642786Ssos union { 652786Ssos uint64_t mac_aligned; 662786Ssos uint16_t mac16[3]; 672786Ssos } ll_addr; 682786Ssos 692786Ssos /* XXX af-private? */ 702786Ssos union { 712786Ssos struct callout ln_timer_ch; 722786Ssos struct callout la_timer; 732786Ssos } lle_timer; 742786Ssos /* NB: struct sockaddr must immediately follow */ 752786Ssos}; 762786Ssos 772786Ssos#define LLE_WLOCK(lle) rw_wlock(&(lle)->lle_lock) 782786Ssos#define LLE_RLOCK(lle) rw_rlock(&(lle)->lle_lock) 792786Ssos#define LLE_WUNLOCK(lle) rw_wunlock(&(lle)->lle_lock) 802786Ssos#define LLE_RUNLOCK(lle) rw_runlock(&(lle)->lle_lock) 815994Ssos#define LLE_DOWNGRADE(lle) rw_downgrade(&(lle)->lle_lock) 822786Ssos#define LLE_TRY_UPGRADE(lle) rw_try_upgrade(&(lle)->lle_lock) 832786Ssos#define LLE_LOCK_INIT(lle) rw_init_flags(&(lle)->lle_lock, "lle", RW_DUPOK) 842786Ssos#define LLE_LOCK_DESTROY(lle) rw_destroy(&(lle)->lle_lock) 852786Ssos#define LLE_WLOCK_ASSERT(lle) rw_assert(&(lle)->lle_lock, RA_WLOCKED) 862786Ssos 872786Ssos#define LLE_IS_VALID(lle) (((lle) != NULL) && ((lle) != (void *)-1)) 886045Ssos 892786Ssos#define LLE_ADDREF(lle) do { \ 902786Ssos LLE_WLOCK_ASSERT(lle); \ 912786Ssos KASSERT((lle)->lle_refcnt >= 0, \ 922786Ssos ("negative refcnt %d", (lle)->lle_refcnt)); \ 932786Ssos (lle)->lle_refcnt++; \ 9418194Ssos} while (0) 952786Ssos 962786Ssos#define LLE_REMREF(lle) do { \ 972786Ssos LLE_WLOCK_ASSERT(lle); \ 982786Ssos KASSERT((lle)->lle_refcnt > 1, \ 992786Ssos ("bogus refcnt %d", (lle)->lle_refcnt)); \ 1002786Ssos (lle)->lle_refcnt--; \ 1012786Ssos} while (0) 1022786Ssos 1032786Ssos#define LLE_FREE_LOCKED(lle) do { \ 1042786Ssos if ((lle)->lle_refcnt <= 1) \ 1052786Ssos (lle)->lle_tbl->llt_free((lle)->lle_tbl, (lle));\ 1062786Ssos else { \ 1072786Ssos (lle)->lle_refcnt--; \ 1086851Ssos LLE_WUNLOCK(lle); \ 1092786Ssos } \ 1106851Ssos /* guard against invalid refs */ \ 1116851Ssos lle = 0; \ 1126851Ssos} while (0) 113 114#define LLE_FREE(lle) do { \ 115 LLE_WLOCK(lle); \ 116 if ((lle)->lle_refcnt <= 1) \ 117 (lle)->lle_tbl->llt_free((lle)->lle_tbl, (lle));\ 118 else { \ 119 (lle)->lle_refcnt--; \ 120 LLE_WUNLOCK(lle); \ 121 } \ 122 /* guard against invalid refs */ \ 123 lle = NULL; \ 124} while (0) 125 126 127#define ln_timer_ch lle_timer.ln_timer_ch 128#define la_timer lle_timer.la_timer 129 130/* XXX bad name */ 131#define L3_ADDR(lle) ((struct sockaddr *)(&lle[1])) 132#define L3_ADDR_LEN(lle) (((struct sockaddr *)(&lle[1]))->sa_len) 133 134#ifndef LLTBL_HASHTBL_SIZE 135#define LLTBL_HASHTBL_SIZE 32 /* default 32 ? */ 136#endif 137 138#ifndef LLTBL_HASHMASK 139#define LLTBL_HASHMASK (LLTBL_HASHTBL_SIZE - 1) 140#endif 141 142struct lltable { 143 SLIST_ENTRY(lltable) llt_link; 144 struct llentries lle_head[LLTBL_HASHTBL_SIZE]; 145 int llt_af; 146 struct ifnet *llt_ifp; 147 148 struct llentry * (*llt_new)(const struct sockaddr *, u_int); 149 void (*llt_free)(struct lltable *, struct llentry *); 150 struct llentry * (*llt_lookup)(struct lltable *, u_int flags, 151 const struct sockaddr *l3addr); 152 int (*llt_rtcheck)(struct ifnet *, 153 const struct sockaddr *); 154 int (*llt_dump)(struct lltable *, 155 struct sysctl_req *); 156}; 157MALLOC_DECLARE(M_LLTABLE); 158 159/* 160 * flags to be passed to arplookup. 161 */ 162#define LLE_DELETED 0x0001 /* entry must be deleted */ 163#define LLE_STATIC 0x0002 /* entry is static */ 164#define LLE_IFADDR 0x0004 /* entry is interface addr */ 165#define LLE_VALID 0x0008 /* ll_addr is valid */ 166#define LLE_PROXY 0x0010 /* proxy entry ??? */ 167#define LLE_PUB 0x0020 /* publish entry ??? */ 168#define LLE_DELETE 0x4000 /* delete on a lookup - match LLE_IFADDR */ 169#define LLE_CREATE 0x8000 /* create on a lookup miss */ 170#define LLE_EXCLUSIVE 0x2000 /* return lle xlocked */ 171 172#define LLATBL_HASH(key, mask) \ 173 (((((((key >> 8) ^ key) >> 8) ^ key) >> 8) ^ key) & mask) 174 175struct lltable *lltable_init(struct ifnet *, int); 176void lltable_free(struct lltable *); 177void lltable_drain(int); 178int lltable_sysctl_dumparp(int, struct sysctl_req *); 179 180void llentry_free(struct llentry *); 181int llentry_update(struct llentry **, struct lltable *, 182 struct sockaddr *, struct ifnet *); 183 184/* 185 * Generic link layer address lookup function. 186 */ 187static __inline struct llentry * 188lla_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr) 189{ 190 return llt->llt_lookup(llt, flags, l3addr); 191} 192 193int lla_rt_output(struct rt_msghdr *, struct rt_addrinfo *); 194#endif /* _NET_IF_LLATBL_H_ */ 195