diff options
| author | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2021-08-02 23:16:48 +0000 |
|---|---|---|
| committer | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2021-08-05 20:44:36 +0000 |
| commit | 8482aa77481a1576df7a19dbeaccb91243fbb2a3 (patch) | |
| tree | 5df88d2a0b3f0b8025cca4a0448fb22716ab4664 /sys/netinet/if_ether.c | |
| parent | 87322a907545fa76fbaf7949f80e85b1377a53ad (diff) | |
Diffstat (limited to 'sys/netinet/if_ether.c')
| -rw-r--r-- | sys/netinet/if_ether.c | 55 |
1 files changed, 42 insertions, 13 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 3eb9d7210afb..2f92d623feeb 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -1145,6 +1145,44 @@ drop: } #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); } |
