diff options
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/flowtable.c | 9 | ||||
-rw-r--r-- | sys/net/if_arcsubr.c | 6 | ||||
-rw-r--r-- | sys/net/if_ethersubr.c | 47 | ||||
-rw-r--r-- | sys/net/if_fddisubr.c | 4 | ||||
-rw-r--r-- | sys/net/if_fwsubr.c | 5 | ||||
-rw-r--r-- | sys/net/if_iso88025subr.c | 4 | ||||
-rw-r--r-- | sys/net/if_llatbl.h | 1 | ||||
-rw-r--r-- | sys/net/route.c | 2 | ||||
-rw-r--r-- | sys/net/route.h | 15 |
9 files changed, 67 insertions, 26 deletions
diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c index 895b233ab1a3c..35aff00a5ab39 100644 --- a/sys/net/flowtable.c +++ b/sys/net/flowtable.c @@ -696,13 +696,8 @@ flowtable_lookup(sa_family_t sa, struct mbuf *m, struct route *ro) ro->ro_rt = fle->f_rt; ro->ro_flags |= RT_NORTREF; lle = fle->f_lle; - if (lle != NULL && (lle->la_flags & LLE_VALID)) { - ro->ro_prepend = lle->r_linkdata; - ro->ro_plen = lle->r_hdrlen; - ro->ro_flags |= RT_MAY_LOOP; - if (lle->la_flags & LLE_IFADDR) - ro->ro_flags |= RT_L2_ME; - } + if (lle != NULL && (lle->la_flags & LLE_VALID)) + ro->ro_lle = lle; /* share ref with fle->f_lle */ return (0); } diff --git a/sys/net/if_arcsubr.c b/sys/net/if_arcsubr.c index ff38b68f5dc2a..3bf372baba6c9 100644 --- a/sys/net/if_arcsubr.c +++ b/sys/net/if_arcsubr.c @@ -129,7 +129,8 @@ arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, else if (ifp->if_flags & IFF_NOARP) adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF; else { - error = arpresolve(ifp, is_gw, m, dst, &adst, NULL); + error = arpresolve(ifp, is_gw, m, dst, &adst, NULL, + NULL); if (error) return (error == EWOULDBLOCK ? 0 : error); } @@ -170,7 +171,8 @@ arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, if ((m->m_flags & M_MCAST) != 0) adst = arcbroadcastaddr; /* ARCnet broadcast address */ else { - error = nd6_resolve(ifp, is_gw, m, dst, &adst, NULL); + error = nd6_resolve(ifp, is_gw, m, dst, &adst, NULL, + NULL); if (error != 0) return (error == EWOULDBLOCK ? 0 : error); } diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 6f0e6e3cc1776..9346aecb9f827 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); } diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c index 1ebd4da44d6f2..b02901ffab8e8 100644 --- a/sys/net/if_fddisubr.c +++ b/sys/net/if_fddisubr.c @@ -126,7 +126,7 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, switch (dst->sa_family) { #ifdef INET case AF_INET: { - error = arpresolve(ifp, is_gw, m, dst, edst, NULL); + error = arpresolve(ifp, is_gw, m, dst, edst, NULL, NULL); if (error) return (error == EWOULDBLOCK ? 0 : error); type = htons(ETHERTYPE_IP); @@ -162,7 +162,7 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, #endif /* INET */ #ifdef INET6 case AF_INET6: - error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL); + error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL, NULL); if (error) return (error == EWOULDBLOCK ? 0 : error); type = htons(ETHERTYPE_IPV6); diff --git a/sys/net/if_fwsubr.c b/sys/net/if_fwsubr.c index c2253d4ef0ae9..57f42567128fd 100644 --- a/sys/net/if_fwsubr.c +++ b/sys/net/if_fwsubr.c @@ -144,7 +144,8 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, * doesn't fit into the arp model. */ if (unicast) { - error = arpresolve(ifp, is_gw, m, dst, (u_char *) destfw, NULL); + error = arpresolve(ifp, is_gw, m, dst, + (u_char *) destfw, NULL, NULL); if (error) return (error == EWOULDBLOCK ? 0 : error); } @@ -174,7 +175,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, case AF_INET6: if (unicast) { error = nd6_resolve(fc->fc_ifp, is_gw, m, dst, - (u_char *) destfw, NULL); + (u_char *) destfw, NULL, NULL); if (error) return (error == EWOULDBLOCK ? 0 : error); } diff --git a/sys/net/if_iso88025subr.c b/sys/net/if_iso88025subr.c index a96e2b9c69463..8306154e56756 100644 --- a/sys/net/if_iso88025subr.c +++ b/sys/net/if_iso88025subr.c @@ -254,7 +254,7 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, switch (dst->sa_family) { #ifdef INET case AF_INET: - error = arpresolve(ifp, is_gw, m, dst, edst, NULL); + error = arpresolve(ifp, is_gw, m, dst, edst, NULL, NULL); if (error) return (error == EWOULDBLOCK ? 0 : error); snap_type = ETHERTYPE_IP; @@ -289,7 +289,7 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, #endif /* INET */ #ifdef INET6 case AF_INET6: - error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL); + error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL, NULL); if (error) return (error == EWOULDBLOCK ? 0 : error); snap_type = ETHERTYPE_IPV6; diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h index b6111c65cc9f8..51de726a621ec 100644 --- a/sys/net/if_llatbl.h +++ b/sys/net/if_llatbl.h @@ -138,7 +138,6 @@ struct llentry { LLE_FREE_LOCKED(lle); \ } while (0) - typedef struct llentry *(llt_lookup_t)(struct lltable *, u_int flags, const struct sockaddr *l3addr); typedef struct llentry *(llt_alloc_t)(struct lltable *, u_int flags, diff --git a/sys/net/route.c b/sys/net/route.c index 4b191d00d4e04..26e3b851c15a3 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -207,6 +207,8 @@ rt_tables_get_gen(int table, int fam) struct rib_head *rnh; rnh = *rt_tables_get_rnh_ptr(table, fam); + KASSERT(rnh != NULL, ("%s: NULL rib_head pointer table %d fam %d", + __func__, table, fam)); return (rnh->rnh_gen); } diff --git a/sys/net/route.h b/sys/net/route.h index e0ff6b4081a6e..46e2ace15f903 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -50,6 +50,11 @@ */ struct route { struct rtentry *ro_rt; + struct llentry *ro_lle; + /* + * ro_prepend and ro_plen are only used for bpf to pass in a + * preformed header. They are not cacheable. + */ char *ro_prepend; uint16_t ro_plen; uint16_t ro_flags; @@ -71,6 +76,7 @@ struct route { #define RT_REJECT 0x0020 /* Destination is reject */ #define RT_BLACKHOLE 0x0040 /* Destination is blackhole */ #define RT_HAS_GW 0x0080 /* Destination has GW */ +#define RT_LLE_CACHE 0x0100 /* Cache link layer */ struct rt_metrics { u_long rmx_locks; /* Kernel must leave these values alone */ @@ -399,6 +405,7 @@ struct rt_addrinfo { if ((_ro)->ro_flags & RT_NORTREF) { \ (_ro)->ro_flags &= ~RT_NORTREF; \ (_ro)->ro_rt = NULL; \ + (_ro)->ro_lle = NULL; \ } else { \ RT_LOCK((_ro)->ro_rt); \ RTFREE_LOCKED((_ro)->ro_rt); \ @@ -413,9 +420,11 @@ struct rt_addrinfo { */ #define RT_VALIDATE(ro, cookiep, fibnum) do { \ rt_gen_t cookie = RT_GEN(fibnum, (ro)->ro_dst.sa_family); \ - if (*(cookiep) != cookie && (ro)->ro_rt != NULL) { \ - RTFREE((ro)->ro_rt); \ - (ro)->ro_rt = NULL; \ + if (*(cookiep) != cookie) { \ + if ((ro)->ro_rt != NULL) { \ + RTFREE((ro)->ro_rt); \ + (ro)->ro_rt = NULL; \ + } \ *(cookiep) = cookie; \ } \ } while (0) |