From 6d7682268826ca15ed86237eb25286740b952f1c Mon Sep 17 00:00:00 2001 From: "George V. Neville-Neil" Date: Thu, 2 Jun 2016 17:51:29 +0000 Subject: This change re-adds L2 caching for TCP and UDP, as originally added in D4306 but removed due to other changes in the system. Restore the llentry pointer to the "struct route", and use it to cache the L2 lookup (ARP or ND6) as appropriate. Submitted by: Mike Karels Differential Revision: https://reviews.freebsd.org/D6262 --- sys/net/if_ethersubr.c | 47 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) (limited to 'sys/net/if_ethersubr.c') diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 6f0e6e3cc177..9346aecb9f82 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -199,7 +199,7 @@ ether_requestencap(struct ifnet *ifp, struct if_encap_req *req) static int ether_resolve_addr(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct route *ro, u_char *phdr, - uint32_t *pflags) + uint32_t *pflags, struct llentry **plle) { struct ether_header *eh; uint32_t lleflags = 0; @@ -208,13 +208,16 @@ ether_resolve_addr(struct ifnet *ifp, struct mbuf *m, uint16_t etype; #endif + if (plle) + *plle = NULL; eh = (struct ether_header *)phdr; switch (dst->sa_family) { #ifdef INET case AF_INET: if ((m->m_flags & (M_BCAST | M_MCAST)) == 0) - error = arpresolve(ifp, 0, m, dst, phdr, &lleflags); + error = arpresolve(ifp, 0, m, dst, phdr, &lleflags, + plle); else { if (m->m_flags & M_BCAST) memcpy(eh->ether_dhost, ifp->if_broadcastaddr, @@ -233,7 +236,8 @@ ether_resolve_addr(struct ifnet *ifp, struct mbuf *m, #ifdef INET6 case AF_INET6: if ((m->m_flags & M_MCAST) == 0) - error = nd6_resolve(ifp, 0, m, dst, phdr, &lleflags); + error = nd6_resolve(ifp, 0, m, dst, phdr, &lleflags, + plle); else { const struct in6_addr *a6; a6 = &(((const struct sockaddr_in6 *)dst)->sin6_addr); @@ -283,14 +287,40 @@ ether_output(struct ifnet *ifp, struct mbuf *m, int loop_copy = 1; int hlen; /* link layer header length */ uint32_t pflags; + struct llentry *lle = NULL; + struct rtentry *rt0 = NULL; + int addref = 0; phdr = NULL; pflags = 0; if (ro != NULL) { - phdr = ro->ro_prepend; - hlen = ro->ro_plen; - pflags = ro->ro_flags; + /* XXX BPF uses ro_prepend */ + if (ro->ro_prepend != NULL) { + phdr = ro->ro_prepend; + hlen = ro->ro_plen; + } else if (!(m->m_flags & (M_BCAST | M_MCAST))) { + if ((ro->ro_flags & RT_LLE_CACHE) != 0) { + lle = ro->ro_lle; + if (lle != NULL && + (lle->la_flags & LLE_VALID) == 0) { + LLE_FREE(lle); + lle = NULL; /* redundant */ + ro->ro_lle = NULL; + } + if (lle == NULL) { + /* if we lookup, keep cache */ + addref = 1; + } + } + if (lle != NULL) { + phdr = lle->r_linkdata; + hlen = lle->r_hdrlen; + pflags = lle->r_flags; + } + } + rt0 = ro->ro_rt; } + #ifdef MAC error = mac_ifnet_check_transmit(ifp, m); if (error) @@ -308,7 +338,10 @@ ether_output(struct ifnet *ifp, struct mbuf *m, /* No prepend data supplied. Try to calculate ourselves. */ phdr = linkhdr; hlen = ETHER_HDR_LEN; - error = ether_resolve_addr(ifp, m, dst, ro, phdr, &pflags); + error = ether_resolve_addr(ifp, m, dst, ro, phdr, &pflags, + addref ? &lle : NULL); + if (addref && lle != NULL) + ro->ro_lle = lle; if (error != 0) return (error == EWOULDBLOCK ? 0 : error); } -- cgit v1.2.3