svn commit: r301217 - in head/sys: net netinet netinet6

Alexander V. Chernikov melifaro at freebsd.org
Sat Jun 4 19:05:38 UTC 2016


02.06.2016, 20:51, "George V. Neville-Neil" <gnn at freebsd.org>:
> Author: gnn
> Date: Thu Jun 2 17:51:29 2016
> New Revision: 301217
> URL: https://svnweb.freebsd.org/changeset/base/301217
>
> Log:
>   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.

I have several comments regarding this commit.

1 Architecturally, there was quite a lot of efforts to eliminate layering violation between lltable and other places in network stack.
It ended by committing D4102, which allowed both to cleanup lower level, provide abstract “prepend” framework which could be used to provide cached data to _otuput() functions.
This change brings these violations back in a really invasive way.

Additionally, implementing L2 PCB caching at the other subsystem expense is really a bad idea.
If one wants caching in some subsystem, it should be implemented in that subsystem not polluting other things.
Current implementation permits this by filling in “ro_prepend” / ro_plen fields.

In general, this change looks more like a local hack and not like the code that should be included in the tree.

2 There was no benchmarks proving the effectiveness of this change. (For example, it is not obvious if it could significantly improve TCP since we still have per-session TCP wlock + (typically) per-ring mutex, so removing lltable rock might not help things here). Given that the patch complicates existing code, there should be adequate benefits to consider whether this change is worth implementing.

3 The “network” group was not included to the review despite the fact that most of the changes were related to the L2 layer which is not “transport”, so some people might have missed this review.

4 This change DOES NOT WORK. really.
(which raises questions on both review and benchmarking process).

The reason is that “plle” argument is filled only in “heavy” lltable lookup functions (e.g. when we don’t have neighbour adjacency). 99.9% of the time arpresolve/nd6_resolve() returns the result w/o calling their heavy versions, and the returned “plle” is NULL.

This can be easily verified by calling something like
dtrace -n 'fbt:kernel:ether_output:entry /arg3!=NULL&&((struct route *)arg3)->ro_lle != NULL/ { stack(); }'

Given that, I kindly ask you to backout this change.

>
>   Submitted by: Mike Karels
>   Differential Revision: https://reviews.freebsd.org/D6262
>
> Modified:
>   head/sys/net/flowtable.c
>   head/sys/net/if_arcsubr.c
>   head/sys/net/if_ethersubr.c
>   head/sys/net/if_fddisubr.c
>   head/sys/net/if_fwsubr.c
>   head/sys/net/if_iso88025subr.c
>   head/sys/net/if_llatbl.h
>   head/sys/net/route.c
>   head/sys/net/route.h
>   head/sys/netinet/if_ether.c
>   head/sys/netinet/if_ether.h
>   head/sys/netinet/in_pcb.c
>   head/sys/netinet/ip_output.c
>   head/sys/netinet/toecore.c
>   head/sys/netinet6/in6.h
>   head/sys/netinet6/in6_pcb.c
>   head/sys/netinet6/ip6_output.c
>   head/sys/netinet6/nd6.c
>   head/sys/netinet6/nd6.h
>
> Modified: head/sys/net/flowtable.c
> ==============================================================================
> --- head/sys/net/flowtable.c Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/net/flowtable.c Thu Jun 2 17:51:29 2016 (r301217)
> @@ -696,13 +696,8 @@ flowtable_lookup(sa_family_t sa, struct
>          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);
>  }
>
> Modified: head/sys/net/if_arcsubr.c
> ==============================================================================
> --- head/sys/net/if_arcsubr.c Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/net/if_arcsubr.c Thu Jun 2 17:51:29 2016 (r301217)
> @@ -129,7 +129,8 @@ arc_output(struct ifnet *ifp, struct mbu
>                  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 mbu
>                  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);
>                  }
>
> Modified: head/sys/net/if_ethersubr.c
> ==============================================================================
> --- head/sys/net/if_ethersubr.c Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/net/if_ethersubr.c Thu Jun 2 17:51:29 2016 (r301217)
> @@ -199,7 +199,7 @@ ether_requestencap(struct ifnet *ifp, st
>  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, st
>          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, st
>  #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 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 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);
>          }
>
> Modified: head/sys/net/if_fddisubr.c
> ==============================================================================
> --- head/sys/net/if_fddisubr.c Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/net/if_fddisubr.c Thu Jun 2 17:51:29 2016 (r301217)
> @@ -126,7 +126,7 @@ fddi_output(struct ifnet *ifp, struct mb
>          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 mb
>  #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);
>
> Modified: head/sys/net/if_fwsubr.c
> ==============================================================================
> --- head/sys/net/if_fwsubr.c Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/net/if_fwsubr.c Thu Jun 2 17:51:29 2016 (r301217)
> @@ -144,7 +144,8 @@ firewire_output(struct ifnet *ifp, struc
>                   * 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, struc
>          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);
>                  }
>
> Modified: head/sys/net/if_iso88025subr.c
> ==============================================================================
> --- head/sys/net/if_iso88025subr.c Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/net/if_iso88025subr.c Thu Jun 2 17:51:29 2016 (r301217)
> @@ -254,7 +254,7 @@ iso88025_output(struct ifnet *ifp, struc
>          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, struc
>  #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;
>
> Modified: head/sys/net/if_llatbl.h
> ==============================================================================
> --- head/sys/net/if_llatbl.h Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/net/if_llatbl.h Thu Jun 2 17:51:29 2016 (r301217)
> @@ -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,
>
> Modified: head/sys/net/route.c
> ==============================================================================
> --- head/sys/net/route.c Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/net/route.c Thu Jun 2 17:51:29 2016 (r301217)
> @@ -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);
>  }
>
> Modified: head/sys/net/route.h
> ==============================================================================
> --- head/sys/net/route.h Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/net/route.h Thu Jun 2 17:51:29 2016 (r301217)
> @@ -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)
>
> Modified: head/sys/netinet/if_ether.c
> ==============================================================================
> --- head/sys/netinet/if_ether.c Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/netinet/if_ether.c Thu Jun 2 17:51:29 2016 (r301217)
> @@ -420,7 +420,8 @@ arprequest(struct ifnet *ifp, const stru
>   */
>  static int
>  arpresolve_full(struct ifnet *ifp, int is_gw, int flags, struct mbuf *m,
> - const struct sockaddr *dst, u_char *desten, uint32_t *pflags)
> + const struct sockaddr *dst, u_char *desten, uint32_t *pflags,
> + struct llentry **plle)
>  {
>          struct llentry *la = NULL, *la_tmp;
>          struct mbuf *curr = NULL;
> @@ -431,6 +432,8 @@ arpresolve_full(struct ifnet *ifp, int i
>
>          if (pflags != NULL)
>                  *pflags = 0;
> + if (plle != NULL)
> + *plle = NULL;
>
>          if ((flags & LLE_CREATE) == 0) {
>                  IF_AFDATA_RLOCK(ifp);
> @@ -483,6 +486,10 @@ arpresolve_full(struct ifnet *ifp, int i
>                  }
>                  if (pflags != NULL)
>                          *pflags = la->la_flags & (LLE_VALID|LLE_IFADDR);
> + if (plle) {
> + LLE_ADDREF(la);
> + *plle = la;
> + }
>                  LLE_WUNLOCK(la);
>                  return (0);
>          }
> @@ -548,12 +555,12 @@ arpresolve_full(struct ifnet *ifp, int i
>   */
>  int
>  arpresolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst,
> - char *desten, uint32_t *pflags)
> + char *desten, uint32_t *pflags, struct llentry **plle)
>  {
>          int error;
>
>          flags |= LLE_ADDRONLY;
> - error = arpresolve_full(ifp, 0, flags, NULL, dst, desten, pflags);
> + error = arpresolve_full(ifp, 0, flags, NULL, dst, desten, pflags, plle);
>          return (error);
>  }
>
> @@ -576,12 +583,15 @@ arpresolve_addr(struct ifnet *ifp, int f
>   */
>  int
>  arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
> - const struct sockaddr *dst, u_char *desten, uint32_t *pflags)
> + const struct sockaddr *dst, u_char *desten, uint32_t *pflags,
> + struct llentry **plle)
>  {
>          struct llentry *la = NULL;
>
>          if (pflags != NULL)
>                  *pflags = 0;
> + if (plle != NULL)
> + *plle = NULL;
>
>          if (m != NULL) {
>                  if (m->m_flags & M_BCAST) {
> @@ -616,7 +626,7 @@ arpresolve(struct ifnet *ifp, int is_gw,
>          IF_AFDATA_RUNLOCK(ifp);
>
>          return (arpresolve_full(ifp, is_gw, la == NULL ? LLE_CREATE : 0, m, dst,
> - desten, pflags));
> + desten, pflags, plle));
>  }
>
>  /*
>
> Modified: head/sys/netinet/if_ether.h
> ==============================================================================
> --- head/sys/netinet/if_ether.h Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/netinet/if_ether.h Thu Jun 2 17:51:29 2016 (r301217)
> @@ -113,11 +113,14 @@ extern u_char ether_ipmulticast_min[ETHE
>  extern u_char ether_ipmulticast_max[ETHER_ADDR_LEN];
>
>  struct ifaddr;
> +struct llentry;
>
>  int arpresolve_addr(struct ifnet *ifp, int flags,
> - const struct sockaddr *dst, char *desten, uint32_t *pflags);
> + const struct sockaddr *dst, char *desten, uint32_t *pflags,
> + struct llentry **plle);
>  int arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
> - const struct sockaddr *dst, u_char *desten, uint32_t *pflags);
> + const struct sockaddr *dst, u_char *desten, uint32_t *pflags,
> + struct llentry **plle);
>  void arprequest(struct ifnet *, const struct in_addr *,
>              const struct in_addr *, u_char *);
>  void arp_ifinit(struct ifnet *, struct ifaddr *);
>
> Modified: head/sys/netinet/in_pcb.c
> ==============================================================================
> --- head/sys/netinet/in_pcb.c Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/netinet/in_pcb.c Thu Jun 2 17:51:29 2016 (r301217)
> @@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
>  #include <net/if.h>
>  #include <net/if_var.h>
>  #include <net/if_types.h>
> +#include <net/if_llatbl.h>
>  #include <net/route.h>
>  #include <net/rss_config.h>
>  #include <net/vnet.h>
> @@ -1302,6 +1303,8 @@ in_pcbfree(struct inpcb *inp)
>                  RTFREE(inp->inp_route.ro_rt);
>                  inp->inp_route.ro_rt = (struct rtentry *)NULL;
>          }
> + if (inp->inp_route.ro_lle)
> + LLE_FREE(inp->inp_route.ro_lle); /* zeros ro_lle */
>
>          inp->inp_vflag = 0;
>          inp->inp_flags2 |= INP_FREED;
> @@ -2243,6 +2246,8 @@ in_losing(struct inpcb *inp)
>                  RTFREE(inp->inp_route.ro_rt);
>                  inp->inp_route.ro_rt = (struct rtentry *)NULL;
>          }
> + if (inp->inp_route.ro_lle)
> + LLE_FREE(inp->inp_route.ro_lle); /* zeros ro_lle */
>          return;
>  }
>
> Modified: head/sys/netinet/ip_output.c
> ==============================================================================
> --- head/sys/netinet/ip_output.c Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/netinet/ip_output.c Thu Jun 2 17:51:29 2016 (r301217)
> @@ -245,7 +245,8 @@ ip_output(struct mbuf *m, struct mbuf *o
>          if (ro == NULL) {
>                  ro = &iproute;
>                  bzero(ro, sizeof (*ro));
> - }
> + } else
> + ro->ro_flags |= RT_LLE_CACHE;
>
>  #ifdef FLOWTABLE
>          if (ro->ro_rt == NULL)
> @@ -311,6 +312,9 @@ again:
>                            dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
>                  RTFREE(rte);
>                  rte = ro->ro_rt = (struct rtentry *)NULL;
> + if (ro->ro_lle)
> + LLE_FREE(ro->ro_lle); /* zeros ro_lle */
> + ro->ro_lle = (struct llentry *)NULL;
>          }
>          ia = NULL;
>          have_ia_ref = 0;
>
> Modified: head/sys/netinet/toecore.c
> ==============================================================================
> --- head/sys/netinet/toecore.c Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/netinet/toecore.c Thu Jun 2 17:51:29 2016 (r301217)
> @@ -451,12 +451,12 @@ toe_l2_resolve(struct toedev *tod, struc
>          switch (sa->sa_family) {
>  #ifdef INET
>          case AF_INET:
> - rc = arpresolve(ifp, 0, NULL, sa, lladdr, NULL);
> + rc = arpresolve(ifp, 0, NULL, sa, lladdr, NULL, NULL);
>                  break;
>  #endif
>  #ifdef INET6
>          case AF_INET6:
> - rc = nd6_resolve(ifp, 0, NULL, sa, lladdr, NULL);
> + rc = nd6_resolve(ifp, 0, NULL, sa, lladdr, NULL, NULL);
>                  break;
>  #endif
>          default:
>
> Modified: head/sys/netinet6/in6.h
> ==============================================================================
> --- head/sys/netinet6/in6.h Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/netinet6/in6.h Thu Jun 2 17:51:29 2016 (r301217)
> @@ -375,6 +375,11 @@ extern const struct in6_addr in6addr_lin
>  #if __BSD_VISIBLE
>  struct route_in6 {
>          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;
>
> Modified: head/sys/netinet6/in6_pcb.c
> ==============================================================================
> --- head/sys/netinet6/in6_pcb.c Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/netinet6/in6_pcb.c Thu Jun 2 17:51:29 2016 (r301217)
> @@ -92,6 +92,7 @@ __FBSDID("$FreeBSD$");
>
>  #include <net/if.h>
>  #include <net/if_var.h>
> +#include <net/if_llatbl.h>
>  #include <net/if_types.h>
>  #include <net/route.h>
>
> @@ -831,6 +832,8 @@ in6_losing(struct inpcb *in6p)
>                  RTFREE(in6p->inp_route6.ro_rt);
>                  in6p->inp_route6.ro_rt = (struct rtentry *)NULL;
>          }
> + if (in6p->inp_route.ro_lle)
> + LLE_FREE(in6p->inp_route.ro_lle); /* zeros ro_lle */
>          return;
>  }
>
> @@ -846,6 +849,8 @@ in6_rtchange(struct inpcb *inp, int errn
>                  RTFREE(inp->inp_route6.ro_rt);
>                  inp->inp_route6.ro_rt = (struct rtentry *)NULL;
>          }
> + if (inp->inp_route.ro_lle)
> + LLE_FREE(inp->inp_route.ro_lle); /* zeros ro_lle */
>          return inp;
>  }
>
> Modified: head/sys/netinet6/ip6_output.c
> ==============================================================================
> --- head/sys/netinet6/ip6_output.c Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/netinet6/ip6_output.c Thu Jun 2 17:51:29 2016 (r301217)
> @@ -500,7 +500,8 @@ ip6_output(struct mbuf *m0, struct ip6_p
>          if (ro == NULL) {
>                  ro = &ip6route;
>                  bzero((caddr_t)ro, sizeof(*ro));
> - }
> + } else
> + ro->ro_flags |= RT_LLE_CACHE;
>          ro_pmtu = ro;
>          if (opt && opt->ip6po_rthdr)
>                  ro = &opt->ip6po_route;
>
> Modified: head/sys/netinet6/nd6.c
> ==============================================================================
> --- head/sys/netinet6/nd6.c Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/netinet6/nd6.c Thu Jun 2 17:51:29 2016 (r301217)
> @@ -136,7 +136,7 @@ static void nd6_llinfo_settimer_locked(s
>  static void clear_llinfo_pqueue(struct llentry *);
>  static void nd6_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
>  static int nd6_resolve_slow(struct ifnet *, int, struct mbuf *,
> - const struct sockaddr_in6 *, u_char *, uint32_t *);
> + const struct sockaddr_in6 *, u_char *, uint32_t *, struct llentry **);
>  static int nd6_need_cache(struct ifnet *);
>
> @@ -2175,7 +2175,8 @@ nd6_output_ifp(struct ifnet *ifp, struct
>   */
>  int
>  nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
> - const struct sockaddr *sa_dst, u_char *desten, uint32_t *pflags)
> + const struct sockaddr *sa_dst, u_char *desten, uint32_t *pflags,
> + struct llentry **plle)
>  {
>          struct llentry *ln = NULL;
>          const struct sockaddr_in6 *dst6;
> @@ -2227,7 +2228,7 @@ nd6_resolve(struct ifnet *ifp, int is_gw
>          }
>          IF_AFDATA_RUNLOCK(ifp);
>
> - return (nd6_resolve_slow(ifp, 0, m, dst6, desten, pflags));
> + return (nd6_resolve_slow(ifp, 0, m, dst6, desten, pflags, plle));
>  }
>
> @@ -2244,7 +2245,8 @@ nd6_resolve(struct ifnet *ifp, int is_gw
>   */
>  static __noinline int
>  nd6_resolve_slow(struct ifnet *ifp, int flags, struct mbuf *m,
> - const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags)
> + const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags,
> + struct llentry **plle)
>  {
>          struct llentry *lle = NULL, *lle_tmp;
>          struct in6_addr *psrc, src;
> @@ -2331,6 +2333,10 @@ nd6_resolve_slow(struct ifnet *ifp, int
>                  bcopy(lladdr, desten, ll_len);
>                  if (pflags != NULL)
>                          *pflags = lle->la_flags;
> + if (plle) {
> + LLE_ADDREF(lle);
> + *plle = lle;
> + }
>                  LLE_WUNLOCK(lle);
>                  return (0);
>          }
> @@ -2405,7 +2411,7 @@ nd6_resolve_addr(struct ifnet *ifp, int
>
>          flags |= LLE_ADDRONLY;
>          error = nd6_resolve_slow(ifp, flags, NULL,
> - (const struct sockaddr_in6 *)dst, desten, pflags);
> + (const struct sockaddr_in6 *)dst, desten, pflags, NULL);
>          return (error);
>  }
>
> Modified: head/sys/netinet6/nd6.h
> ==============================================================================
> --- head/sys/netinet6/nd6.h Thu Jun 2 17:31:37 2016 (r301216)
> +++ head/sys/netinet6/nd6.h Thu Jun 2 17:51:29 2016 (r301217)
> @@ -428,7 +428,7 @@ void nd6_purge(struct ifnet *);
>  int nd6_resolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst,
>      char *desten, uint32_t *pflags);
>  int nd6_resolve(struct ifnet *, int, struct mbuf *,
> - const struct sockaddr *, u_char *, uint32_t *);
> + const struct sockaddr *, u_char *, uint32_t *, struct llentry **);
>  int nd6_ioctl(u_long, caddr_t, struct ifnet *);
>  void nd6_cache_lladdr(struct ifnet *, struct in6_addr *,
>          char *, int, int, int);


More information about the svn-src-head mailing list