summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/flowtable.c9
-rw-r--r--sys/net/if_arcsubr.c6
-rw-r--r--sys/net/if_ethersubr.c47
-rw-r--r--sys/net/if_fddisubr.c4
-rw-r--r--sys/net/if_fwsubr.c5
-rw-r--r--sys/net/if_iso88025subr.c4
-rw-r--r--sys/net/if_llatbl.h1
-rw-r--r--sys/net/route.c2
-rw-r--r--sys/net/route.h15
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)