Use lltable calculated header when sending lle holdchain after successful lle resolution.
Subscribers: imp, ae, bz Differential Revision: https://reviews.freebsd.org/D31391
This commit is contained in:
parent
87322a9075
commit
8482aa7748
@ -1145,6 +1145,44 @@ in_arpinput(struct mbuf *m)
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct mbuf *
|
||||
arp_grab_holdchain(struct llentry *la)
|
||||
{
|
||||
struct mbuf *chain;
|
||||
|
||||
LLE_WLOCK_ASSERT(la);
|
||||
|
||||
chain = la->la_hold;
|
||||
la->la_hold = NULL;
|
||||
la->la_numheld = 0;
|
||||
|
||||
return (chain);
|
||||
}
|
||||
|
||||
static void
|
||||
arp_flush_holdchain(struct ifnet *ifp, struct llentry *la, struct mbuf *chain)
|
||||
{
|
||||
struct mbuf *m_hold, *m_hold_next;
|
||||
struct sockaddr_in sin;
|
||||
|
||||
NET_EPOCH_ASSERT();
|
||||
|
||||
struct route ro = {
|
||||
.ro_prepend = la->r_linkdata,
|
||||
.ro_plen = la->r_hdrlen,
|
||||
};
|
||||
|
||||
lltable_fill_sa_entry(la, (struct sockaddr *)&sin);
|
||||
|
||||
for (m_hold = chain; m_hold != NULL; m_hold = m_hold_next) {
|
||||
m_hold_next = m_hold->m_nextpkt;
|
||||
m_hold->m_nextpkt = NULL;
|
||||
/* Avoid confusing lower layers. */
|
||||
m_clrprotoflags(m_hold);
|
||||
(*ifp->if_output)(ifp, m_hold, (struct sockaddr *)&sin, &ro);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks received arp data against existing @la.
|
||||
* Updates lle state/performs notification if necessary.
|
||||
@ -1153,8 +1191,6 @@ static void
|
||||
arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp,
|
||||
int bridged, struct llentry *la)
|
||||
{
|
||||
struct sockaddr sa;
|
||||
struct mbuf *m_hold, *m_hold_next;
|
||||
uint8_t linkhdr[LLE_MAX_LINKHDR];
|
||||
size_t linkhdrsize;
|
||||
int lladdr_off;
|
||||
@ -1227,18 +1263,11 @@ arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp
|
||||
* output routine.
|
||||
*/
|
||||
if (la->la_hold != NULL) {
|
||||
m_hold = la->la_hold;
|
||||
la->la_hold = NULL;
|
||||
la->la_numheld = 0;
|
||||
lltable_fill_sa_entry(la, &sa);
|
||||
struct mbuf *chain;
|
||||
|
||||
chain = arp_grab_holdchain(la);
|
||||
LLE_WUNLOCK(la);
|
||||
for (; m_hold != NULL; m_hold = m_hold_next) {
|
||||
m_hold_next = m_hold->m_nextpkt;
|
||||
m_hold->m_nextpkt = NULL;
|
||||
/* Avoid confusing lower layers. */
|
||||
m_clrprotoflags(m_hold);
|
||||
(*ifp->if_output)(ifp, m_hold, &sa, NULL);
|
||||
}
|
||||
arp_flush_holdchain(ifp, la, chain);
|
||||
} else
|
||||
LLE_WUNLOCK(la);
|
||||
}
|
||||
|
@ -1923,7 +1923,6 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
||||
int llchange;
|
||||
int flags;
|
||||
uint16_t router = 0;
|
||||
struct sockaddr_in6 sin6;
|
||||
struct mbuf *chain = NULL;
|
||||
u_char linkhdr[LLE_MAX_LINKHDR];
|
||||
size_t linkhdrsize;
|
||||
@ -2044,7 +2043,7 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
||||
EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
|
||||
|
||||
if (ln->la_hold != NULL)
|
||||
nd6_grab_holdchain(ln, &chain, &sin6);
|
||||
chain = nd6_grab_holdchain(ln);
|
||||
}
|
||||
|
||||
/* Calculates new router status */
|
||||
@ -2062,7 +2061,7 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
|
||||
LLE_RUNLOCK(ln);
|
||||
|
||||
if (chain != NULL)
|
||||
nd6_flush_holdchain(ifp, chain, &sin6);
|
||||
nd6_flush_holdchain(ifp, ln, chain);
|
||||
|
||||
/*
|
||||
* When the link-layer address of a router changes, select the
|
||||
@ -2119,16 +2118,15 @@ nd6_slowtimo(void *arg)
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
void
|
||||
nd6_grab_holdchain(struct llentry *ln, struct mbuf **chain,
|
||||
struct sockaddr_in6 *sin6)
|
||||
struct mbuf *
|
||||
nd6_grab_holdchain(struct llentry *ln)
|
||||
{
|
||||
struct mbuf *chain;
|
||||
|
||||
LLE_WLOCK_ASSERT(ln);
|
||||
|
||||
*chain = ln->la_hold;
|
||||
chain = ln->la_hold;
|
||||
ln->la_hold = NULL;
|
||||
lltable_fill_sa_entry(ln, (struct sockaddr *)sin6);
|
||||
|
||||
if (ln->ln_state == ND6_LLINFO_STALE) {
|
||||
/*
|
||||
@ -2142,6 +2140,8 @@ nd6_grab_holdchain(struct llentry *ln, struct mbuf **chain,
|
||||
*/
|
||||
nd6_llinfo_setstate(ln, ND6_LLINFO_DELAY);
|
||||
}
|
||||
|
||||
return (chain);
|
||||
}
|
||||
|
||||
int
|
||||
@ -2435,19 +2435,27 @@ nd6_resolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst,
|
||||
}
|
||||
|
||||
int
|
||||
nd6_flush_holdchain(struct ifnet *ifp, struct mbuf *chain,
|
||||
struct sockaddr_in6 *dst)
|
||||
nd6_flush_holdchain(struct ifnet *ifp, struct llentry *lle, struct mbuf *chain)
|
||||
{
|
||||
struct mbuf *m, *m_head;
|
||||
struct sockaddr_in6 dst6;
|
||||
int error = 0;
|
||||
|
||||
NET_EPOCH_ASSERT();
|
||||
|
||||
struct route_in6 ro = {
|
||||
.ro_prepend = lle->r_linkdata,
|
||||
.ro_plen = lle->r_hdrlen,
|
||||
};
|
||||
|
||||
lltable_fill_sa_entry(lle, (struct sockaddr *)&dst6);
|
||||
m_head = chain;
|
||||
|
||||
while (m_head) {
|
||||
m = m_head;
|
||||
m_head = m_head->m_nextpkt;
|
||||
m->m_nextpkt = NULL;
|
||||
error = nd6_output_ifp(ifp, ifp, m, dst, NULL);
|
||||
error = nd6_output_ifp(ifp, ifp, m, &dst6, (struct route *)&ro);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -376,10 +376,8 @@ int nd6_resolve(struct ifnet *, int, struct mbuf *,
|
||||
int nd6_ioctl(u_long, caddr_t, struct ifnet *);
|
||||
void nd6_cache_lladdr(struct ifnet *, struct in6_addr *,
|
||||
char *, int, int, int);
|
||||
void nd6_grab_holdchain(struct llentry *, struct mbuf **,
|
||||
struct sockaddr_in6 *);
|
||||
int nd6_flush_holdchain(struct ifnet *, struct mbuf *,
|
||||
struct sockaddr_in6 *);
|
||||
struct mbuf *nd6_grab_holdchain(struct llentry *);
|
||||
int nd6_flush_holdchain(struct ifnet *, struct llentry *, struct mbuf *);
|
||||
int nd6_add_ifa_lle(struct in6_ifaddr *);
|
||||
void nd6_rem_ifa_lle(struct in6_ifaddr *, int);
|
||||
int nd6_output_ifp(struct ifnet *, struct ifnet *, struct mbuf *,
|
||||
|
@ -623,7 +623,6 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
|
||||
struct mbuf *chain;
|
||||
struct nd_neighbor_advert *nd_na;
|
||||
struct in6_addr daddr6, taddr6;
|
||||
struct sockaddr_in6 sin6;
|
||||
union nd_opts ndopts;
|
||||
u_char linkhdr[LLE_MAX_LINKHDR];
|
||||
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
|
||||
@ -899,16 +898,14 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
|
||||
* rt->rt_flags &= ~RTF_REJECT;
|
||||
*/
|
||||
ln->la_asked = 0;
|
||||
if (ln->la_hold != NULL) {
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
nd6_grab_holdchain(ln, &chain, &sin6);
|
||||
}
|
||||
if (ln->la_hold != NULL)
|
||||
chain = nd6_grab_holdchain(ln);
|
||||
freeit:
|
||||
if (ln != NULL)
|
||||
LLE_WUNLOCK(ln);
|
||||
|
||||
if (chain != NULL)
|
||||
nd6_flush_holdchain(ifp, chain, &sin6);
|
||||
nd6_flush_holdchain(ifp, ln, chain);
|
||||
|
||||
if (checklink)
|
||||
pfxlist_onlink_check();
|
||||
|
Loading…
Reference in New Issue
Block a user