Simplify lle lookup/create api by using addresses instead of sockaddrs.

This commit is contained in:
Alexander V. Chernikov 2014-12-08 23:23:53 +00:00
parent 73b52ad896
commit d82ed5051c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/routing/; revision=275625
12 changed files with 152 additions and 175 deletions

View File

@ -229,9 +229,12 @@ llentry_alloc(struct ifnet *ifp, struct lltable *lt,
struct sockaddr_storage *dst)
{
struct llentry *la;
const void *l3addr;
l3addr = lt->llt_get_sa_addr((struct sockaddr *)dst);
IF_AFDATA_RLOCK(ifp);
la = lt->llt_lookup(lt, LLE_EXCLUSIVE, (struct sockaddr *)dst);
la = lt->llt_lookup(lt, LLE_EXCLUSIVE, l3addr);
IF_AFDATA_RUNLOCK(ifp);
if ((la == NULL) &&
(ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) {
@ -441,6 +444,7 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
struct ifnet *ifp;
struct lltable *llt;
struct llentry *lle, *lle_tmp;
const void *l3addr;
u_int laflags = 0;
int error;
@ -469,6 +473,7 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
switch (rtm->rtm_type) {
case RTM_ADD:
/* Add static LLE */
l3addr = llt->llt_get_sa_addr(dst);
lle = llt->llt_create(llt, 0, dst);
if (lle == NULL)
return (ENOMEM);
@ -491,7 +496,7 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
LLE_WLOCK(lle);
/* Check if we already have this lle */
/* XXX: Use LLE_UNLOCKED */
lle_tmp = llt->llt_lookup(llt, LLE_EXCLUSIVE, dst);
lle_tmp = llt->llt_lookup(llt, LLE_EXCLUSIVE, l3addr);
if (lle_tmp != NULL) {
IF_AFDATA_CFG_WUNLOCK(ifp);
LLE_WUNLOCK(lle_tmp);

View File

@ -148,9 +148,9 @@ struct llentry {
#endif
typedef struct llentry *(llt_lookup_t)(struct lltable *, u_int flags,
const struct sockaddr *l3addr);
const void *paddr);
typedef struct llentry *(llt_create_t)(struct lltable *, u_int flags,
const struct sockaddr *l3addr);
const void *paddr);
typedef int (llt_delete_addr_t)(struct lltable *, u_int flags,
const struct sockaddr *l3addr);
typedef int (llt_dump_entry_t)(struct lltable *, struct llentry *,
@ -164,6 +164,7 @@ typedef void (llt_link_entry_t)(struct lltable *, struct llentry *);
typedef void (llt_unlink_entry_t)(struct llentry *);
typedef int (llt_prepare_sentry_t)(struct lltable *, struct llentry *,
struct rt_addrinfo *);
typedef const void *(llt_get_sa_addr_t)(const struct sockaddr *l3addr);
typedef int (llt_foreach_cb_t)(struct lltable *, struct llentry *, void *);
typedef int (llt_foreach_entry_t)(struct lltable *, llt_foreach_cb_t *, void *);
@ -186,6 +187,7 @@ struct lltable {
llt_link_entry_t *llt_link_entry;
llt_unlink_entry_t *llt_unlink_entry;
llt_prepare_sentry_t *llt_prepare_static_entry;
llt_get_sa_addr_t *llt_get_sa_addr;
llt_free_tbl_t *llt_free_tbl;
};
@ -233,18 +235,18 @@ size_t lltable_drop_entry_queue(struct llentry *);
*/
static __inline struct llentry *
lltable_lookup_lle(struct lltable *llt, u_int flags,
const struct sockaddr *l3addr)
const void *paddr)
{
return llt->llt_lookup(llt, flags, l3addr);
return (llt->llt_lookup(llt, flags, paddr));
}
static __inline struct llentry *
lltable_create_lle(struct lltable *llt, u_int flags,
const struct sockaddr *l3addr)
const void *paddr)
{
return llt->llt_create(llt, flags, l3addr);
return (llt->llt_create(llt, flags, paddr));
}
static __inline int

View File

@ -680,7 +680,6 @@ fib6_storelladdr(struct ifnet *ifp, struct in6_addr *dst, int mm_flags,
u_char *desten)
{
struct llentry *ln;
struct sockaddr_in6 dst_sa;
IF_AFDATA_RUN_TRACKER;
if (mm_flags & M_MCAST) {
@ -688,19 +687,11 @@ fib6_storelladdr(struct ifnet *ifp, struct in6_addr *dst, int mm_flags,
return (0);
}
memset(&dst_sa, 0, sizeof(dst_sa));
dst_sa.sin6_family = AF_INET6;
dst_sa.sin6_len = sizeof(dst_sa);
dst_sa.sin6_addr = *dst;
dst_sa.sin6_scope_id = ifp->if_index;
/*
* the entry should have been created in nd6_store_lladdr
*/
IF_AFDATA_RUN_RLOCK(ifp);
ln = lltable_lookup_lle(LLTABLE6(ifp), LLE_UNLOCKED,
(struct sockaddr *)&dst_sa);
ln = lltable_lookup_lle6(ifp, LLE_UNLOCKED, dst);
/*
* Perform fast path for the following cases:

View File

@ -417,8 +417,6 @@ arpresolve_fast(struct ifnet *ifp, struct in_addr dst, u_int mflags,
u_char *dst_addr)
{
struct llentry *la;
struct sockaddr_in sin;
const struct sockaddr *sa_dst;
IF_AFDATA_RUN_TRACKER;
if (mflags & M_BCAST) {
@ -430,14 +428,8 @@ arpresolve_fast(struct ifnet *ifp, struct in_addr dst, u_int mflags,
return (0);
}
memset(&sin, 0, sizeof(sin));
sin.sin_addr = dst;
sin.sin_family = AF_INET;
sin.sin_len = sizeof(sin);
sa_dst = (const struct sockaddr *)&sin;
IF_AFDATA_RUN_RLOCK(ifp);
la = lltable_lookup_lle(LLTABLE(ifp), LLE_UNLOCKED, sa_dst);
la = lltable_lookup_lle4(ifp, LLE_UNLOCKED, &dst);
if (la != NULL && (la->r_flags & RLLE_VALID) != 0) {
/* Entry found, let's copy lle info */
bcopy(&la->ll_addr, dst_addr, ifp->if_addrlen);
@ -503,9 +495,12 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
const struct sockaddr *dst, u_char *desten, struct llentry **lle)
{
struct llentry *la = NULL;
struct in_addr dst4;
int is_gw;
IF_AFDATA_RUN_TRACKER;
dst4 = SIN(dst)->sin_addr;
*lle = NULL;
if (m != NULL) {
if (m->m_flags & M_BCAST) {
@ -516,13 +511,13 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
}
if (m->m_flags & M_MCAST && ifp->if_type != IFT_ARCNET) {
/* multicast */
ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
ETHER_MAP_IP_MULTICAST(&dst4, desten);
return (0);
}
}
IF_AFDATA_RUN_RLOCK(ifp);
la = lltable_lookup_lle(LLTABLE(ifp), LLE_UNLOCKED, dst);
la = lltable_lookup_lle4(ifp, LLE_UNLOCKED, &dst4);
if (la != NULL && (la->r_flags & RLLE_VALID) != 0) {
/* Entry found, let's copy lle info */
bcopy(&la->ll_addr, desten, ifp->if_addrlen);
@ -545,22 +540,23 @@ arpresolve_slow(struct ifnet *ifp, int is_gw, struct mbuf *m,
struct llentry *la, *la_tmp;
struct mbuf *curr = NULL;
struct mbuf *next = NULL;
struct in_addr dst4;
int create, error;
create = 0;
*lle = NULL;
dst4 = SIN(dst)->sin_addr;
IF_AFDATA_RLOCK(ifp);
la = lltable_lookup_lle(LLTABLE(ifp), LLE_EXCLUSIVE, dst);
la = lltable_lookup_lle4(ifp, LLE_EXCLUSIVE, &dst4);
IF_AFDATA_RUNLOCK(ifp);
if (la == NULL && (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) {
create = 1;
la = lltable_create_lle(LLTABLE(ifp), 0, dst);
la = lltable_create_lle4(ifp, 0, &dst4);
if (la != NULL) {
IF_AFDATA_CFG_WLOCK(ifp);
LLE_WLOCK(la);
la_tmp = lltable_lookup_lle(LLTABLE(ifp), LLE_EXCLUSIVE,
dst);
la_tmp = lltable_lookup_lle4(ifp, LLE_EXCLUSIVE, &dst4);
if (la_tmp == NULL) {
/*
* No entry has been found. Link new one.
@ -582,7 +578,7 @@ arpresolve_slow(struct ifnet *ifp, int is_gw, struct mbuf *m,
if (create != 0)
log(LOG_DEBUG,
"arpresolve: can't allocate llinfo for %s on %s\n",
inet_ntoa(SIN(dst)->sin_addr), ifp->if_xname);
inet_ntoa(dst4), ifp->if_xname);
m_freem(m);
return (EINVAL);
}
@ -781,13 +777,8 @@ in_arpinput(struct mbuf *m)
int bridged = 0, is_bridge = 0;
int carped;
struct nhop4_extended nh_ext;
struct sockaddr_in sin;
struct llentry *la_tmp;
sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
if (ifp->if_bridge)
bridged = 1;
if (ifp->if_type == IFT_BRIDGE)
@ -938,14 +929,8 @@ in_arpinput(struct mbuf *m)
if (ifp->if_flags & IFF_STATICARP)
goto reply;
bzero(&sin, sizeof(sin));
sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_family = AF_INET;
sin.sin_addr = isaddr;
IF_AFDATA_CFG_RLOCK(ifp);
la = lltable_lookup_lle(LLTABLE(ifp), LLE_EXCLUSIVE,
(struct sockaddr *)&sin);
la = lltable_lookup_lle4(ifp, LLE_EXCLUSIVE, &isaddr);
IF_AFDATA_CFG_RUNLOCK(ifp);
if (la != NULL)
arp_update_lle(ah, isaddr, ifp, bridged, la);
@ -955,14 +940,12 @@ in_arpinput(struct mbuf *m)
* Reply to our address, but no lle exists yet.
* do we really have to create an entry?
*/
la = lltable_create_lle(LLTABLE(ifp), 0,
(struct sockaddr *)&sin);
la = lltable_create_lle4(ifp, 0, &isaddr);
if (la != NULL) {
IF_AFDATA_CFG_WLOCK(ifp);
LLE_WLOCK(la);
/* Let's try to search another time */
la_tmp = lltable_lookup_lle(LLTABLE(ifp), LLE_EXCLUSIVE,
(struct sockaddr *)&sin);
la_tmp = lltable_lookup_lle4(ifp, LLE_EXCLUSIVE, &isaddr);
if (la_tmp != NULL) {
/*
* Someone has already inserted another entry.
@ -995,10 +978,8 @@ in_arpinput(struct mbuf *m)
} else {
struct llentry *lle = NULL;
sin.sin_addr = itaddr;
IF_AFDATA_RLOCK(ifp);
lle = lltable_lookup_lle(LLTABLE(ifp), 0,
(struct sockaddr *)&sin);
lle = lltable_lookup_lle4(ifp, 0, &itaddr);
IF_AFDATA_RUNLOCK(ifp);
if ((lle != NULL) && (lle->la_flags & LLE_PUB)) {
@ -1013,7 +994,6 @@ in_arpinput(struct mbuf *m)
if (!V_arp_proxyall)
goto drop;
sin.sin_addr = itaddr;
/* XXX MRT use table 0 for arp reply */
if (fib4_lookup_nh_ext(0, itaddr, 0, 0, &nh_ext) != 0)
goto drop;
@ -1035,7 +1015,6 @@ in_arpinput(struct mbuf *m)
* avoids ARP chaos if an interface is connected to the
* wrong network.
*/
sin.sin_addr = isaddr;
/* XXX MRT use table 0 for arp checks */
if (fib4_lookup_nh_ext(0, isaddr, 0, 0, &nh_ext) != 0)
@ -1252,8 +1231,7 @@ arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa)
* because the output of the arp utility shows
* that L2 entry as permanent
*/
lle = lltable_create_lle(LLTABLE(ifp), LLE_IFADDR | LLE_STATIC,
(struct sockaddr *)IA_SIN(ifa));
lle = lltable_create_lle4(ifp, LLE_IFADDR | LLE_STATIC, &addr);
if (lle == NULL) {
log(LOG_INFO, "arp_ifinit: cannot create arp "
"entry for interface address\n");
@ -1271,8 +1249,7 @@ arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa)
* Instead of dealing with callouts/flags/etc we simply
* delete it and add new one.
*/
lle_tmp = lltable_lookup_lle(llt, LLE_EXCLUSIVE,
(struct sockaddr *)IA_SIN(ifa));
lle_tmp = lltable_lookup_lle4(ifp, LLE_EXCLUSIVE, &addr);
IF_AFDATA_RUN_WLOCK(ifp);
if (lle_tmp != NULL)

View File

@ -117,6 +117,21 @@ struct llentry;
struct ifaddr;
struct rt_addrinfo;
#define LLTABLE(ifp) \
((struct in_ifinfo *)(ifp)->if_afdata[AF_INET])->ii_llt
static __inline const void *
_check_in_addr_typecast(const struct in_addr *paddr)
{
return ((const void *)paddr);
}
#define lltable_lookup_lle4(i, f, a) \
lltable_lookup_lle(LLTABLE(i), (f), _check_in_addr_typecast(a))
#define lltable_create_lle4(i, f, a) \
lltable_create_lle(LLTABLE(i), (f), _check_in_addr_typecast(a))
int arpresolve(struct ifnet *ifp, struct rtentry *rt, struct mbuf *m,
const struct sockaddr *dst, u_char *desten, struct llentry **lle);
int arpresolve_fast(struct ifnet *ifp, struct in_addr dst, u_int mflags,

View File

@ -1009,18 +1009,19 @@ in_lltable_free(struct llentry *lle)
}
static struct llentry *
in_lltable_new(const struct sockaddr *l3addr, u_int flags)
in_lltable_new(struct in_addr addr4, u_int flags)
{
struct in_llentry *lle;
const struct sockaddr_in *l3addr_sin;
lle = malloc(sizeof(struct in_llentry), M_LLTABLE, M_NOWAIT | M_ZERO);
if (lle == NULL) /* NB: caller generates msg */
return NULL;
l3addr_sin = (const struct sockaddr_in *)l3addr;
lle->base.r_l3addr.addr4 = l3addr_sin->sin_addr;
lle->l3_addr4 = *l3addr_sin;
lle->base.r_l3addr.addr4 = addr4;
/* XXX: Legacy */
lle->l3_addr4.sin_len = sizeof(lle->l3_addr4);
lle->l3_addr4.sin_family = AF_INET;
lle->l3_addr4.sin_addr = addr4;
/*
* For IPv4 this will trigger "arpresolve" to generate
@ -1058,15 +1059,10 @@ in_lltable_match_prefix(const struct sockaddr *prefix,
}
static int
in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr)
in_lltable_rtcheck(struct ifnet *ifp, u_int flags, struct in_addr dst)
{
struct nhop4_basic nh4;
struct in_addr dst;
KASSERT(l3addr->sa_family == AF_INET,
("sin_family %d", l3addr->sa_family));
dst = ((struct sockaddr_in *)l3addr)->sin_addr;
if (fib4_lookup_nh(ifp->if_fib, dst, 0, 0, &nh4) != 0)
return (EINVAL);
@ -1112,6 +1108,16 @@ in_lltable_hash(const struct llentry *lle)
return (in_lltable_hash_dst(lle->r_l3addr.addr4));
}
static const void *
in_lltable_get_sa_addr(const struct sockaddr *l3addr)
{
const struct sockaddr_in *sin;
sin = (const struct sockaddr_in *)l3addr;
return ((const void *)&sin->sin_addr);
}
static inline struct llentry *
in_lltable_find_dst(struct lltable *llt, struct in_addr dst)
{
@ -1174,13 +1180,13 @@ in_lltable_delete(struct lltable *llt, u_int flags,
}
static struct llentry *
in_lltable_create(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
in_lltable_create(struct lltable *llt, u_int flags, const void *paddr)
{
struct ifnet *ifp = llt->llt_ifp;
struct llentry *lle;
struct in_addr addr4;
KASSERT(l3addr->sa_family == AF_INET,
("sin_family %d", l3addr->sa_family));
addr4 = *((const struct in_addr *)paddr);
/*
* A route that covers the given address must have
@ -1188,10 +1194,10 @@ in_lltable_create(struct lltable *llt, u_int flags, const struct sockaddr *l3add
* verify this.
*/
if (!(flags & LLE_IFADDR) &&
in_lltable_rtcheck(ifp, flags, l3addr) != 0)
in_lltable_rtcheck(ifp, flags, addr4) != 0)
return (NULL);
lle = in_lltable_new(l3addr, flags);
lle = in_lltable_new(addr4, flags);
if (lle == NULL) {
log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
return (NULL);
@ -1206,7 +1212,7 @@ in_lltable_create(struct lltable *llt, u_int flags, const struct sockaddr *l3add
* If found return lle read locked.
*/
static struct llentry *
in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
in_lltable_lookup(struct lltable *llt, u_int flags, const void *paddr)
{
struct llentry *lle;
struct in_addr dst;
@ -1216,10 +1222,8 @@ in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3add
* by different locks.
* IF_AFDATA_LOCK_ASSERT(llt->llt_ifp);
*/
KASSERT(l3addr->sa_family == AF_INET,
("sin_family %d", l3addr->sa_family));
dst = ((const struct sockaddr_in *)l3addr)->sin_addr;
dst = *((const struct in_addr *)paddr);
lle = in_lltable_find_dst(llt, dst);
if (lle == NULL)
@ -1312,6 +1316,7 @@ in_domifattach(struct ifnet *ifp)
llt->llt_delete_addr = in_lltable_delete;
llt->llt_dump_entry = in_lltable_dump_entry;
llt->llt_hash = in_lltable_hash;
llt->llt_get_sa_addr = in_lltable_get_sa_addr;
llt->llt_clear_entry = arp_lltable_clear_entry;
llt->llt_match_prefix = in_lltable_match_prefix;
llt->llt_prepare_static_entry = arp_lltable_prepare_static_entry;

View File

@ -96,8 +96,6 @@ struct in_aliasreq {
#ifdef _KERNEL
extern u_char inetctlerrmap[];
#define LLTABLE(ifp) \
((struct in_ifinfo *)(ifp)->if_afdata[AF_INET])->ii_llt
/*
* Hash table for IP addresses.
*/

View File

@ -456,22 +456,24 @@ static int
toe_nd6_resolve(struct ifnet *ifp, struct sockaddr *sa, uint8_t *lladdr)
{
struct llentry *lle, *lle_tmp;
struct sockaddr_in6 *sin6 = (void *)sa;
struct in6_addr *dst;
int rc, flags = 0;
dst = &((struct sockaddr_in6 *)sa)->sin6_addr;
restart:
IF_AFDATA_RLOCK(ifp);
lle = lltable_lookup_lle(LLTABLE6(ifp), flags, sa);
lle = lltable_lookup_lle6(ifp, flags, dst);
IF_AFDATA_RUNLOCK(ifp);
if (lle == NULL) {
lle = nd6_create(&sin6->sin6_addr, 0, ifp);
lle = lltable_create_lle6(ifp, 0, dst);
if (lle == NULL)
return (ENOMEM); /* Couldn't create entry in cache. */
lle->ln_state = ND6_LLINFO_INCOMPLETE;
IF_AFDATA_CFG_WLOCK(ifp);
LLE_WLOCK(lle);
/* Check if the same record was addded */
lle_tmp = lltable_lookup_lle(LLTABLE6(ifp), LLE_EXCLUSIVE, sa);
lle_tmp = lltable_lookup_lle6(ifp, LLE_EXCLUSIVE, dst);
if (lle_tmp == NULL) {
/*
* No entry has been found. Link new one.
@ -487,7 +489,7 @@ toe_nd6_resolve(struct ifnet *ifp, struct sockaddr *sa, uint8_t *lladdr)
(long)ND_IFINFO(ifp)->retrans * hz / 1000);
LLE_WUNLOCK(lle);
nd6_ns_output(ifp, NULL, &sin6->sin6_addr, NULL, 0);
nd6_ns_output(ifp, NULL, dst, NULL, 0);
return (EWOULDBLOCK);
}

View File

@ -2064,18 +2064,19 @@ in6_lltable_free(struct llentry *lle)
}
static struct llentry *
in6_lltable_new(const struct sockaddr *l3addr, u_int flags)
in6_lltable_new(const struct in6_addr *addr6, u_int flags)
{
struct in6_llentry *lle;
const struct sockaddr_in6 *l3addr_sin6;
lle = malloc(sizeof(struct in6_llentry), M_LLTABLE, M_NOWAIT | M_ZERO);
if (lle == NULL) /* NB: caller generates msg */
return NULL;
l3addr_sin6 = (const struct sockaddr_in6 *)l3addr;
lle->l3_addr6 = *l3addr_sin6;
lle->base.r_l3addr.addr6 = l3addr_sin6->sin6_addr;
lle->base.r_l3addr.addr6 = *addr6;
/* XXX: legacy */
lle->l3_addr6.sin6_family = AF_INET6;
lle->l3_addr6.sin6_len = sizeof(lle->l3_addr6);
lle->l3_addr6.sin6_addr = *addr6;
lle->base.lle_refcnt = 1;
lle->base.lle_free = in6_lltable_free;
LLE_LOCK_INIT(&lle->base);
@ -2103,20 +2104,18 @@ in6_lltable_match_prefix(const struct sockaddr *prefix,
static int
in6_lltable_rtcheck(struct ifnet *ifp,
u_int flags,
const struct sockaddr *l3addr)
const struct in6_addr *addr6)
{
struct nhop6_basic nh6;
struct sockaddr_in6 sin6;
struct in6_addr dst;
uint32_t scopeid;
int error;
char ip6buf[INET6_ADDRSTRLEN];
KASSERT(l3addr->sa_family == AF_INET6,
("sin_family %d", l3addr->sa_family));
/* Our local addresses are always only installed on the default FIB. */
in6_splitscope(&((struct sockaddr_in6 *)l3addr)->sin6_addr, &dst, &scopeid);
in6_splitscope(addr6, &dst, &scopeid);
error = fib6_lookup_nh(RT_DEFAULT_FIB, &dst, scopeid, 0, 0, &nh6);
if (error != 0 || ((nh6.nh_flags & NHF_GATEWAY) != 0) || nh6.nh_ifp != ifp) {
struct ifaddr *ifa;
@ -2125,13 +2124,17 @@ in6_lltable_rtcheck(struct ifnet *ifp,
* that is not covered by our own prefix.
*/
/* XXX ifaof_ifpforaddr should take a const param */
ifa = ifaof_ifpforaddr(__DECONST(struct sockaddr *, l3addr), ifp);
bzero(&sin6, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(sin6);
sin6.sin6_addr = *addr6;
ifa = ifaof_ifpforaddr(__DECONST(struct sockaddr *, &sin6), ifp);
if (ifa != NULL) {
ifa_free(ifa);
return 0;
}
log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n",
ip6_sprintf(ip6buf, &((const struct sockaddr_in6 *)l3addr)->sin6_addr));
ip6_sprintf(ip6buf, addr6));
return EINVAL;
}
return 0;
@ -2151,6 +2154,16 @@ in6_lltable_hash(const struct llentry *lle)
return (in6_lltable_hash_dst(&lle->r_l3addr.addr6));
}
static const void *
in6_lltable_get_sa_addr(const struct sockaddr *l3addr)
{
const struct sockaddr_in6 *sin6;
sin6 = (const struct sockaddr_in6 *)l3addr;
return ((const void *)&sin6->sin6_addr);
}
static inline struct llentry *
in6_lltable_find_dst(struct lltable *llt, const struct in6_addr *dst)
{
@ -2213,26 +2226,25 @@ in6_lltable_delete(struct lltable *llt, u_int flags,
static struct llentry *
in6_lltable_create(struct lltable *llt, u_int flags,
const struct sockaddr *l3addr)
const void *paddr)
{
struct ifnet *ifp = llt->llt_ifp;
struct llentry *lle;
KASSERT(l3addr->sa_family == AF_INET6,
("sin_family %d", l3addr->sa_family));
const struct in6_addr *addr6;
IF_AFDATA_CFG_UNLOCK_ASSERT(ifp);
addr6 = (const struct in6_addr *)paddr;
/*
* A route that covers the given address must have
* been installed 1st because we are doing a resolution,
* verify this.
*/
if (!(flags & LLE_IFADDR) &&
in6_lltable_rtcheck(ifp, flags, l3addr) != 0)
in6_lltable_rtcheck(ifp, flags, addr6) != 0)
return NULL;
lle = in6_lltable_new(l3addr, flags);
lle = in6_lltable_new(addr6, flags);
if (lle == NULL) {
log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
return NULL;
@ -2244,9 +2256,9 @@ in6_lltable_create(struct lltable *llt, u_int flags,
static struct llentry *
in6_lltable_lookup(struct lltable *llt, u_int flags,
const struct sockaddr *l3addr)
const void *l3addr)
{
const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr;
const struct in6_addr *dst6;
struct llentry *lle;
/*
@ -2254,10 +2266,9 @@ in6_lltable_lookup(struct lltable *llt, u_int flags,
* by different locks.
* IF_AFDATA_LOCK_ASSERT(llt->llt_ifp);
*/
KASSERT(l3addr->sa_family == AF_INET6,
("sin_family %d", l3addr->sa_family));
dst6 = (const struct in6_addr *)l3addr;
lle = in6_lltable_find_dst(llt, &sin6->sin6_addr);
lle = in6_lltable_find_dst(llt, dst6);
if (lle == NULL)
return (NULL);
@ -2377,6 +2388,7 @@ in6_domifattach(struct ifnet *ifp)
llt->llt_delete_addr = in6_lltable_delete;
llt->llt_dump_entry = in6_lltable_dump_entry;
llt->llt_hash = in6_lltable_hash;
llt->llt_get_sa_addr = in6_lltable_get_sa_addr;
llt->llt_clear_entry = nd6_lltable_clear_entry;
llt->llt_match_prefix = in6_lltable_match_prefix;
llt->llt_prepare_static_entry = nd6_lltable_prepare_static_entry;

View File

@ -108,8 +108,6 @@ struct in6_ifextra {
struct mld_ifinfo *mld_ifinfo;
};
#define LLTABLE6(ifp) (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable)
#if defined(_KERNEL) || defined(_WANT_IFADDR)
struct in6_ifaddr {
struct ifaddr ia_ifa; /* protocol-independent info */

View File

@ -889,55 +889,6 @@ nd6_purge(struct ifnet *ifp)
*/
}
/*
* the caller acquires and releases the lock on the lltbls
* Returns the llentry locked
*/
struct llentry *
nd6_lookup(struct in6_addr *addr6, int flags, struct ifnet *ifp)
{
struct sockaddr_in6 sin6;
struct llentry *ln;
int llflags;
bzero(&sin6, sizeof(sin6));
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = *addr6;
/*
* IF_AFDATA_LOCK_ASSERT(ifp);
*/
llflags = (flags & ND6_EXCLUSIVE) ? LLE_EXCLUSIVE : 0;
ln = lltable_lookup_lle(LLTABLE6(ifp), llflags,
(struct sockaddr *)&sin6);
return (ln);
}
/*
* Creates and returns new, unlinked and unlocked lle.
*/
struct llentry *
nd6_create(struct in6_addr *addr6, int flags, struct ifnet *ifp)
{
struct sockaddr_in6 sin6;
struct llentry *ln;
bzero(&sin6, sizeof(sin6));
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = *addr6;
IF_AFDATA_CFG_UNLOCK_ASSERT(ifp);
ln = lltable_create_lle(LLTABLE6(ifp), 0, (struct sockaddr *)&sin6);
ln->ln_state = ND6_LLINFO_NOSTATE;
return (ln);
}
/*
* Test whether a given IPv6 address is a neighbor or not, ignoring
* the actual neighbor cache. The neighbor cache is ignored in order
@ -1295,7 +1246,7 @@ nd6_nud_hint(struct rtentry *rt, struct in6_addr *dst6, int force)
ifp = rt->rt_ifp;
IF_AFDATA_RLOCK(ifp);
ln = nd6_lookup(dst6, ND6_EXCLUSIVE, NULL);
ln = nd6_lookup(dst6, ND6_EXCLUSIVE, ifp);
IF_AFDATA_RUNLOCK(ifp);
if (ln == NULL)
return;
@ -1798,9 +1749,11 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
ln = nd6_lookup(from, ND6_EXCLUSIVE, ifp);
IF_AFDATA_CFG_RUNLOCK(ifp);
if (ln == NULL) {
ln = nd6_create(from, 0, ifp);
if (ln != NULL)
ln = lltable_create_lle6(ifp, 0, from);
if (ln != NULL) {
LLE_WLOCK(ln);
ln->ln_state = ND6_LLINFO_NOSTATE;
}
is_newentry = 1;
} else {
/* do nothing if record is static */
@ -2204,8 +2157,9 @@ nd6_output_lle(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
* the condition below is not very efficient. But we believe
* it is tolerable, because this should be a rare case.
*/
lle = nd6_create(&dst->sin6_addr, 0, ifp);
lle = lltable_create_lle6(ifp, 0, &dst->sin6_addr);
if (lle != NULL) {
lle->ln_state = ND6_LLINFO_NOSTATE;
IF_AFDATA_CFG_WLOCK(ifp);
LLE_WLOCK(lle);
/* Check if the same record was addded */
@ -2483,12 +2437,13 @@ nd6_add_ifa_lle(struct in6_ifaddr *ia)
struct ifnet *ifp;
struct llentry *ln, *ln_tmp;
struct lltable *llt;
struct in6_addr *addr6;
ifp = ia->ia_ifa.ifa_ifp;
addr6 = &ia->ia_addr.sin6_addr;
ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
ln = lltable_create_lle(LLTABLE6(ifp), LLE_IFADDR,
(struct sockaddr *)&ia->ia_addr);
ln = lltable_create_lle6(ifp, LLE_IFADDR, addr6);
if (ln == NULL)
return (ENOBUFS);
@ -2507,8 +2462,7 @@ nd6_add_ifa_lle(struct in6_ifaddr *ia)
* Instead of dealing with callouts/flags/etc we simply
* delete it and add new one.
*/
ln_tmp = lltable_lookup_lle(llt, LLE_EXCLUSIVE,
(struct sockaddr *)&ia->ia_addr);
ln_tmp = lltable_lookup_lle6(ifp, LLE_EXCLUSIVE, addr6);
bcopy(IF_LLADDR(ifp), &ln->ll_addr, ifp->if_addrlen);
/* Finally, link our lle to the list */
@ -2563,8 +2517,10 @@ nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
const struct sockaddr *dst, u_char *desten, struct llentry **lle)
{
struct llentry *ln;
const struct in6_addr *addr6;
*lle = NULL;
addr6 = &SIN6(dst)->sin6_addr;
IF_AFDATA_CFG_UNLOCK_ASSERT(ifp);
if (m != NULL && m->m_flags & M_MCAST) {
int i;
@ -2580,8 +2536,7 @@ nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
#endif
case IFT_BRIDGE:
case IFT_ISO88025:
ETHER_MAP_IPV6_MULTICAST(&SIN6(dst)->sin6_addr,
desten);
ETHER_MAP_IPV6_MULTICAST(addr6, desten);
return (0);
case IFT_IEEE1394:
/*
@ -2605,7 +2560,7 @@ nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
* the entry should have been created in nd6_store_lladdr
*/
IF_AFDATA_RLOCK(ifp);
ln = lltable_lookup_lle(LLTABLE6(ifp), 0, dst);
ln = lltable_lookup_lle6(ifp, 0, addr6);
IF_AFDATA_RUNLOCK(ifp);
if ((ln == NULL) || !(ln->la_flags & LLE_VALID)) {
if (ln != NULL)

View File

@ -89,8 +89,6 @@ struct nd_ifinfo {
#define ND6_IFF_NO_RADR 0x40
#define ND6_IFF_NO_PREFER_IFACE 0x80 /* XXX: not related to ND. */
#define ND6_EXCLUSIVE LLE_EXCLUSIVE
#ifdef _KERNEL
#define ND_IFINFO(ifp) \
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->nd_ifinfo)
@ -389,14 +387,33 @@ void nd6_init(void);
#ifdef VIMAGE
void nd6_destroy(void);
#endif
#define LLTABLE6(ifp) \
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable)
static __inline const void *
_check_in6_addr_typecast(const struct in6_addr *paddr)
{
return ((const void *)paddr);
}
#define lltable_lookup_lle6(i, f, a) \
lltable_lookup_lle(LLTABLE6(i), (f), _check_in6_addr_typecast(a))
#define lltable_create_lle6(i, f, a) \
lltable_create_lle(LLTABLE6(i), (f), _check_in6_addr_typecast(a))
#define nd6_lookup(a, f, i) lltable_lookup_lle6((i), (f), (a))
#define ND6_EXCLUSIVE LLE_EXCLUSIVE
struct nd_ifinfo *nd6_ifattach(struct ifnet *);
void nd6_ifdetach(struct nd_ifinfo *);
int nd6_is_addr_neighbor(struct sockaddr_in6 *, struct ifnet *);
void nd6_option_init(void *, int, union nd_opts *);
struct nd_opt_hdr *nd6_option(union nd_opts *);
int nd6_options(union nd_opts *);
struct llentry *nd6_lookup(struct in6_addr *, int, struct ifnet *);
struct llentry *nd6_create(struct in6_addr *, int, struct ifnet *);
void nd6_setmtu(struct ifnet *);
void nd6_llinfo_settimer(struct llentry *, long);
void nd6_llinfo_settimer_locked(struct llentry *, long);