* Do not assume lle has sockaddr key after struct lle:

use llt_fill_sa_entry() llt method to store lle address in sa.
* Eliminate L3_ADDR macro and either reference IPv4/IPv6 address
   directly from lle or use newly-created llt_fill_sa_entry().
* Do not store sockaddr inside arp/ndp lle anymore.
This commit is contained in:
Alexander V. Chernikov 2014-12-09 00:48:08 +00:00
parent d82ed5051c
commit ee7e9a4e17
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/routing/; revision=275628
7 changed files with 78 additions and 59 deletions

View File

@ -135,10 +135,6 @@ struct llentry {
#define ln_timer_ch lle_timer.ln_timer_ch
#define la_timer lle_timer.la_timer
/* XXX bad name */
#define L3_ADDR(lle) ((struct sockaddr *)(&lle[1]))
#define L3_ADDR_LEN(lle) (((struct sockaddr *)(&lle[1]))->sa_len)
#ifndef LLTBL_HASHTBL_SIZE
#define LLTBL_HASHTBL_SIZE 32 /* default 32 ? */
#endif
@ -165,6 +161,7 @@ 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 void (llt_fill_sa_entry_t)(const struct llentry *, struct sockaddr *);
typedef int (llt_foreach_cb_t)(struct lltable *, struct llentry *, void *);
typedef int (llt_foreach_entry_t)(struct lltable *, llt_foreach_cb_t *, void *);
@ -188,6 +185,7 @@ struct lltable {
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_fill_sa_entry_t *llt_fill_sa_entry;
llt_free_tbl_t *llt_free_tbl;
};
@ -271,6 +269,16 @@ lltable_unlink_entry(struct lltable *llt, struct llentry *lle)
llt->llt_unlink_entry(lle);
}
static __inline void
lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa)
{
struct lltable *llt;
llt = lle->lle_tbl;
llt->llt_fill_sa_entry(lle, sa);
}
int lla_rt_output(struct rt_msghdr *, struct rt_addrinfo *);
#include <sys/eventhandler.h>

View File

@ -232,9 +232,7 @@ arptimer(void *arg)
case ARP_LLINFO_VERIFY:
if (lle->r_kick == 0 && lle->la_preempt > 0) {
/* Entry was used, issue refresh request */
struct sockaddr_in *dst;
dst = (struct sockaddr_in *)L3_ADDR(lle);
arprequest(ifp, NULL, &dst->sin_addr, NULL);
arprequest(ifp, NULL, &lle->r_l3addr.addr4, NULL);
lle->la_preempt--;
lle->r_kick = 1;
callout_schedule(&lle->la_timer, hz * V_arpt_rexmit);
@ -1193,7 +1191,7 @@ arp_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp,
m_hold = la->la_hold;
la->la_hold = NULL;
la->la_numheld = 0;
memcpy(&sin, L3_ADDR(la), sizeof(sin));
lltable_fill_sa_entry(la, (struct sockaddr *)&sin);
LLE_WUNLOCK(la);
for (; m_hold != NULL; m_hold = m_hold_next) {
m_hold_next = m_hold->m_nextpkt;

View File

@ -988,11 +988,6 @@ in_purgemaddrs(struct ifnet *ifp)
IN_MULTI_UNLOCK();
}
struct in_llentry {
struct llentry base;
struct sockaddr_in l3_addr4;
};
/*
* Frees unlinked record.
* This function is called by the timer functions
@ -1011,17 +1006,13 @@ in_lltable_free(struct llentry *lle)
static struct llentry *
in_lltable_new(struct in_addr addr4, u_int flags)
{
struct in_llentry *lle;
struct llentry *lle;
lle = malloc(sizeof(struct in_llentry), M_LLTABLE, M_NOWAIT | M_ZERO);
lle = malloc(sizeof(struct llentry), M_LLTABLE, M_NOWAIT | M_ZERO);
if (lle == NULL) /* NB: caller generates msg */
return NULL;
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
@ -1038,7 +1029,7 @@ in_lltable_new(struct in_addr addr4, u_int flags)
}
#define IN_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \
(((ntohl((d)->sin_addr.s_addr) ^ (a)->sin_addr.s_addr) & (m)->sin_addr.s_addr)) == 0 )
(((ntohl((d).s_addr) ^ (a)->sin_addr.s_addr) & (m)->sin_addr.s_addr)) == 0 )
static int
in_lltable_match_prefix(const struct sockaddr *prefix,
@ -1051,7 +1042,7 @@ in_lltable_match_prefix(const struct sockaddr *prefix,
* (flags & LLE_STATIC) means deleting all entries
* including static ARP entries.
*/
if (IN_ARE_MASKED_ADDR_EQUAL(satosin(L3_ADDR(lle)), pfx, msk) &&
if (IN_ARE_MASKED_ADDR_EQUAL(lle->r_l3addr.addr4, pfx, msk) &&
((flags & LLE_STATIC) || !(lle->la_flags & LLE_STATIC)))
return (1);
@ -1118,6 +1109,18 @@ in_lltable_get_sa_addr(const struct sockaddr *l3addr)
return ((const void *)&sin->sin_addr);
}
static void
in_lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa)
{
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)sa;
bzero(sin, sizeof(*sin));
sin->sin_family = AF_INET;
sin->sin_len = sizeof(*sin);
sin->sin_addr = lle->r_l3addr.addr4;
}
static inline struct llentry *
in_lltable_find_dst(struct lltable *llt, struct in_addr dst)
{
@ -1251,8 +1254,11 @@ in_lltable_dump_entry(struct lltable *llt, struct llentry *lle,
struct sockaddr_dl *sdl;
int error;
bzero(&arpc, sizeof(arpc));
/* Skip if jailed and not a valid IP of the prison. */
if (prison_if(wr->td->td_ucred, L3_ADDR(lle)) != 0)
lltable_fill_sa_entry(lle,(struct sockaddr *)&arpc.sin);
if (prison_if(wr->td->td_ucred,
(struct sockaddr *)&arpc.sin) != 0)
return (0);
/*
* produce a msg made of:
@ -1260,15 +1266,11 @@ in_lltable_dump_entry(struct lltable *llt, struct llentry *lle,
* struct sockaddr_in; (IPv4)
* struct sockaddr_dl;
*/
bzero(&arpc, sizeof(arpc));
arpc.rtm.rtm_msglen = sizeof(arpc);
arpc.rtm.rtm_version = RTM_VERSION;
arpc.rtm.rtm_type = RTM_GET;
arpc.rtm.rtm_flags = RTF_UP;
arpc.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
arpc.sin.sin_family = AF_INET;
arpc.sin.sin_len = sizeof(arpc.sin);
arpc.sin.sin_addr.s_addr = lle->r_l3addr.addr4.s_addr;
/* publish */
if (lle->la_flags & LLE_PUB)
@ -1317,6 +1319,7 @@ in_domifattach(struct ifnet *ifp)
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_fill_sa_entry = in_lltable_fill_sa_entry;
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

@ -392,21 +392,26 @@ toe_lle_event(void *arg __unused, struct llentry *lle, int evt)
struct sockaddr *sa;
uint8_t *lladdr;
uint16_t vtag;
int sa_family;
struct sockaddr_storage ss;
LLE_WLOCK_ASSERT(lle);
ifp = lle->lle_tbl->llt_ifp;
sa = L3_ADDR(lle);
sa_family = lle->lle_tbl->llt_af;
#if 0
/* XXX: Do not panic, ignore event instead */
KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6,
("%s: lle_event %d for lle %p but sa %p !INET && !INET6",
__func__, evt, lle, sa));
#endif
/*
* Not interested if the interface's TOE capability is not enabled.
*/
if ((sa->sa_family == AF_INET && !(ifp->if_capenable & IFCAP_TOE4)) ||
(sa->sa_family == AF_INET6 && !(ifp->if_capenable & IFCAP_TOE6)))
if ((sa_family == AF_INET && !(ifp->if_capenable & IFCAP_TOE4)) ||
(sa_family == AF_INET6 && !(ifp->if_capenable & IFCAP_TOE6)))
return;
tod = TOEDEV(ifp);
@ -433,6 +438,8 @@ toe_lle_event(void *arg __unused, struct llentry *lle, int evt)
#endif
}
sa = (struct sockaddr *)&ss;
lltable_fill_sa_entry(lle, sa);
tod->tod_l2_update(tod, ifp, sa, lladdr, vtag);
}

View File

@ -2046,11 +2046,6 @@ in6_if2idlen(struct ifnet *ifp)
#include <sys/sysctl.h>
struct in6_llentry {
struct llentry base;
struct sockaddr_in6 l3_addr6;
};
/*
* Frees already unlinked @lle.
*/
@ -2066,17 +2061,13 @@ in6_lltable_free(struct llentry *lle)
static struct llentry *
in6_lltable_new(const struct in6_addr *addr6, u_int flags)
{
struct in6_llentry *lle;
struct llentry *lle;
lle = malloc(sizeof(struct in6_llentry), M_LLTABLE, M_NOWAIT | M_ZERO);
lle = malloc(sizeof(struct llentry), M_LLTABLE, M_NOWAIT | M_ZERO);
if (lle == NULL) /* NB: caller generates msg */
return NULL;
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);
@ -2093,7 +2084,7 @@ in6_lltable_match_prefix(const struct sockaddr *prefix,
const struct sockaddr_in6 *pfx = (const struct sockaddr_in6 *)prefix;
const struct sockaddr_in6 *msk = (const struct sockaddr_in6 *)mask;
if (IN6_ARE_MASKED_ADDR_EQUAL(&satosin6(L3_ADDR(lle))->sin6_addr,
if (IN6_ARE_MASKED_ADDR_EQUAL(&lle->r_l3addr.addr6,
&pfx->sin6_addr, &msk->sin6_addr) &&
((flags & LLE_STATIC) || !(lle->la_flags & LLE_STATIC)))
return (1);
@ -2164,6 +2155,18 @@ in6_lltable_get_sa_addr(const struct sockaddr *l3addr)
return ((const void *)&sin6->sin6_addr);
}
static void
in6_lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa)
{
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)sa;
bzero(sin6, sizeof(*sin6));
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(*sin6);
sin6->sin6_addr = lle->r_l3addr.addr6;
}
static inline struct llentry *
in6_lltable_find_dst(struct lltable *llt, const struct in6_addr *dst)
{
@ -2300,11 +2303,15 @@ in6_lltable_dump_entry(struct lltable *llt, struct llentry *lle,
struct sockaddr_dl *sdl;
int error;
bzero(&ndpc, sizeof(ndpc));
/* skip invalid entries */
if ((lle->la_flags & LLE_VALID) == 0)
return (0);
/* Skip if jailed and not a valid IP of the prison. */
if (prison_if(wr->td->td_ucred, L3_ADDR(lle)) != 0)
lltable_fill_sa_entry(lle,
(struct sockaddr *)&ndpc.sin6);
if (prison_if(wr->td->td_ucred,
(struct sockaddr *)&ndpc.sin6) != 0)
return (0);
/*
* produce a msg made of:
@ -2312,15 +2319,11 @@ in6_lltable_dump_entry(struct lltable *llt, struct llentry *lle,
* struct sockaddr_in6 (IPv6)
* struct sockaddr_dl;
*/
bzero(&ndpc, sizeof(ndpc));
ndpc.rtm.rtm_msglen = sizeof(ndpc);
ndpc.rtm.rtm_version = RTM_VERSION;
ndpc.rtm.rtm_type = RTM_GET;
ndpc.rtm.rtm_flags = RTF_UP;
ndpc.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
ndpc.sin6.sin6_family = AF_INET6;
ndpc.sin6.sin6_len = sizeof(ndpc.sin6);
bcopy(L3_ADDR(lle), &ndpc.sin6, L3_ADDR_LEN(lle));
if (V_deembed_scopeid)
sa6_recoverscope(&ndpc.sin6);
@ -2389,6 +2392,7 @@ in6_domifattach(struct ifnet *ifp)
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_fill_sa_entry = in6_lltable_fill_sa_entry;
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

@ -68,7 +68,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_kdtrace.h>
#include <net/if_llatbl.h>
#define L3_ADDR_SIN6(le) ((struct sockaddr_in6 *) L3_ADDR(le))
#include <netinet/if_ether.h>
#include <netinet6/in6_var.h>
#include <netinet/ip6.h>
@ -543,7 +542,7 @@ nd6_llinfo_timer(void *arg)
CURVNET_SET(ifp->if_vnet);
ndi = ND_IFINFO(ifp);
dst = &L3_ADDR_SIN6(ln)->sin6_addr;
dst = &ln->r_l3addr.addr6;
/*
* Each case statement needs to unlock @ln before break/return.
@ -1122,7 +1121,7 @@ nd6_check_del_defrtr(struct lltable *llt, struct llentry *ln)
struct in6_addr dst;
ifp = llt->llt_ifp;
dst = L3_ADDR_SIN6(ln)->sin6_addr;
dst = ln->r_l3addr.addr6;
LLE_WLOCK_ASSERT(ln);
@ -1165,7 +1164,7 @@ nd6_check_recalc_defrtr(struct lltable *llt, struct llentry *ln)
struct in6_addr dst;
ifp = llt->llt_ifp;
dst = L3_ADDR_SIN6(ln)->sin6_addr;
dst = ln->r_l3addr.addr6;
LLE_WLOCK_ASSERT(ln);
@ -1909,6 +1908,8 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
if (ln->la_hold) {
struct mbuf *m_hold, *m_hold_next;
lltable_fill_sa_entry(ln, (struct sockaddr *)&sin6);
/*
* reset the la_hold in advance, to explicitly
* prevent a la_hold lookup in nd6_output()
@ -1924,15 +1925,12 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
* just set the 2nd argument as the
* 1st one.
*/
nd6_output_lle(ifp, ifp, m_hold, L3_ADDR_SIN6(ln), NULL, ln, &chain);
nd6_output_lle(ifp, ifp, m_hold, &sin6, NULL, ln, &chain);
}
/*
* If we have mbufs in the chain we need to do
* deferred transmit. Copy the address from the
* llentry before dropping the lock down below.
* deferred transmit.
*/
if (chain != NULL)
memcpy(&sin6, L3_ADDR_SIN6(ln), sizeof(sin6));
}
} else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
/* probe right away */

View File

@ -65,7 +65,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <net/if_llatbl.h>
#define L3_ADDR_SIN6(le) ((struct sockaddr_in6 *) L3_ADDR(le))
#include <netinet6/in6_var.h>
#include <netinet6/in6_ifattach.h>
#include <netinet/ip6.h>
@ -824,7 +823,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
struct nd_defrouter *dr;
struct in6_addr *in6;
in6 = &L3_ADDR_SIN6(ln)->sin6_addr;
in6 = &ln->r_l3addr.addr6;
/*
* Lock to protect the default router list.
@ -879,13 +878,15 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
m_tag_prepend(m, mtag);
}
nd6_output_lle(ifp, ifp, m_hold, L3_ADDR_SIN6(ln), NULL, ln, &chain);
lltable_fill_sa_entry(ln, (struct sockaddr *)&sin6);
nd6_output_lle(ifp, ifp, m_hold, &sin6, NULL, ln,
&chain);
}
}
freeit:
if (ln != NULL) {
if (chain)
memcpy(&sin6, L3_ADDR_SIN6(ln), sizeof(sin6));
lltable_fill_sa_entry(ln, (struct sockaddr *)&sin6);
LLE_WUNLOCK(ln);
if (chain)