So netinet6/nd6_nbr.c references MH_ALIGN() in two comments. Instead of aligning the packet to the back of the mbuf, the functions just shift it by max_linkhdr. In most cases this should be good enough but esp. when packets move over tunnels the additional headers will not fit into the packet (resulting in an extra allocation).
Now using what is set as m_len as the argument for m_align() will not work since it does not include the possible option header that is slapped on the packet further below. This is why maxlen is used instead, which includes the size of the option. I'm not super happy with the function in general. It feels fragile and error prone the way it fills the mbuf but I don't want to rewrite the two functions just right now. -- :wq Claudio Index: netinet6/nd6_nbr.c =================================================================== RCS file: /cvs/src/sys/netinet6/nd6_nbr.c,v retrieving revision 1.124 diff -u -p -r1.124 nd6_nbr.c --- netinet6/nd6_nbr.c 12 Jul 2018 16:07:35 -0000 1.124 +++ netinet6/nd6_nbr.c 4 Dec 2018 12:54:17 -0000 @@ -406,7 +406,7 @@ nd6_ns_output(struct ifnet *ifp, struct icmp6len = sizeof(*nd_ns); m->m_pkthdr.len = m->m_len = sizeof(*ip6) + icmp6len; - m->m_data += max_linkhdr; /* or MH_ALIGN() equivalent? */ + m_align(m, maxlen); /* fill neighbor solicitation packet */ ip6 = mtod(m, struct ip6_hdr *); @@ -913,7 +913,6 @@ nd6_na_output(struct ifnet *ifp, struct } if (m == NULL) return; - m->m_pkthdr.ph_ifidx = 0; m->m_pkthdr.ph_rtableid = ifp->if_rdomain; if (IN6_IS_ADDR_MULTICAST(daddr6)) { @@ -925,7 +924,7 @@ nd6_na_output(struct ifnet *ifp, struct icmp6len = sizeof(*nd_na); m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + icmp6len; - m->m_data += max_linkhdr; /* or MH_ALIGN() equivalent? */ + m_align(m, maxlen); /* fill neighbor advertisement packet */ ip6 = mtod(m, struct ip6_hdr *); @@ -1022,7 +1021,7 @@ nd6_na_output(struct ifnet *ifp, struct m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT; ip6_output(m, NULL, NULL, 0, &im6o, NULL); - icmp6stat_inc(icp6s_outhist+ ND_NEIGHBOR_ADVERT); + icmp6stat_inc(icp6s_outhist + ND_NEIGHBOR_ADVERT); return; bad: