Index: sys/netinet6/ip6_output.c =================================================================== --- sys/netinet6/ip6_output.c +++ sys/netinet6/ip6_output.c @@ -209,6 +209,41 @@ *(u_short *)mtodo(m, offset) = csum; } +static int +ip6_output_delayed_csum(struct mbuf *m, struct ifnet *ifp, int csum_flags, + int plen, int optlen, bool frag) +{ + + if ((csum_flags & CSUM_DELAY_DATA_IPV6) || +#ifdef SCTP + (csum_flags & CSUM_SCTP_IPV6) || +#endif + (!frag && (ifp->if_capenable & IFCAP_NOMAP) == 0)) { + m = mb_unmapped_to_ext(m); + if (m == NULL) { + if (frag) + in6_ifstat_inc(ifp, ifs6_out_fragfail); + else + IP6STAT_INC(ip6s_odropped); + return (ENOBUFS); + } + if (csum_flags & CSUM_DELAY_DATA_IPV6) { + in6_delayed_cksum(m, plen - optlen, + sizeof(struct ip6_hdr) + optlen); + m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6; + } +#ifdef SCTP + if (csum_flags & CSUM_SCTP_IPV6) { + sctp_delayed_cksum(m, sizeof(struct ip6_hdr) + optlen); + m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6; + } +#endif + } + + return (0); +} + + int ip6_fragment(struct ifnet *ifp, struct mbuf *m0, int hlen, u_char nextproto, int fraglen , uint32_t id) @@ -994,36 +1029,9 @@ * XXX-BZ Need a framework to know when the NIC can handle it, even * with ext. hdrs. */ - if (sw_csum & CSUM_DELAY_DATA_IPV6) { - sw_csum &= ~CSUM_DELAY_DATA_IPV6; - m = mb_unmapped_to_ext(m); - if (m == NULL) { - error = ENOBUFS; - IP6STAT_INC(ip6s_odropped); - goto bad; - } - in6_delayed_cksum(m, plen, sizeof(struct ip6_hdr)); - } else if ((ifp->if_capenable & IFCAP_NOMAP) == 0) { - m = mb_unmapped_to_ext(m); - if (m == NULL) { - error = ENOBUFS; - IP6STAT_INC(ip6s_odropped); - goto bad; - } - } -#ifdef SCTP - if (sw_csum & CSUM_SCTP_IPV6) { - sw_csum &= ~CSUM_SCTP_IPV6; - m = mb_unmapped_to_ext(m); - if (m == NULL) { - error = ENOBUFS; - IP6STAT_INC(ip6s_odropped); - goto bad; - } - sctp_delayed_cksum(m, sizeof(struct ip6_hdr)); - } -#endif - m->m_pkthdr.csum_flags &= ifp->if_hwassist; + error = ip6_output_delayed_csum(m, ifp, sw_csum, plen, optlen, false); + if (error != 0) + goto bad; tlen = m->m_pkthdr.len; if ((opt && (opt->ip6po_flags & IP6PO_DONTFRAG)) || tso) @@ -1102,28 +1110,11 @@ * fragmented packets, then do it here. * XXX-BZ handle the hw offloading case. Need flags. */ - if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) { - m = mb_unmapped_to_ext(m); - if (m == NULL) { - in6_ifstat_inc(ifp, ifs6_out_fragfail); - error = ENOBUFS; - goto bad; - } - in6_delayed_cksum(m, plen, hlen); - m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6; - } -#ifdef SCTP - if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) { - m = mb_unmapped_to_ext(m); - if (m == NULL) { - in6_ifstat_inc(ifp, ifs6_out_fragfail); - error = ENOBUFS; - goto bad; - } - sctp_delayed_cksum(m, hlen); - m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6; - } -#endif + error = ip6_output_delayed_csum(m, ifp, sw_csum, plen, optlen, + true); + if (error != 0) + goto bad; + /* * Change the next header field of the last header in the * unfragmentable part.