From owner-svn-src-all@FreeBSD.ORG Thu Jun 18 20:32:54 2015 Return-Path: Delivered-To: svn-src-all@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id EA91D558; Thu, 18 Jun 2015 20:32:54 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id CBEFC981; Thu, 18 Jun 2015 20:32:54 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t5IKWsse027036; Thu, 18 Jun 2015 20:32:54 GMT (envelope-from kp@FreeBSD.org) Received: (from kp@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t5IKWsug027034; Thu, 18 Jun 2015 20:32:54 GMT (envelope-from kp@FreeBSD.org) Message-Id: <201506182032.t5IKWsug027034@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: kp set sender to kp@FreeBSD.org using -f From: Kristof Provost Date: Thu, 18 Jun 2015 20:32:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r284570 - stable/10/sys/netinet6 X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 18 Jun 2015 20:32:55 -0000 Author: kp Date: Thu Jun 18 20:32:53 2015 New Revision: 284570 URL: https://svnweb.freebsd.org/changeset/base/284570 Log: Merge r278842 Factor out ip6_fragment() function, to be used in IPv6 stack and pf(4). Differential Revision: https://reviews.freebsd.org/D2815 Reviewed by: gnn Modified: stable/10/sys/netinet6/ip6_output.c stable/10/sys/netinet6/ip6_var.h Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/netinet6/ip6_output.c ============================================================================== --- stable/10/sys/netinet6/ip6_output.c Thu Jun 18 20:28:52 2015 (r284569) +++ stable/10/sys/netinet6/ip6_output.c Thu Jun 18 20:32:53 2015 (r284570) @@ -208,6 +208,65 @@ in6_delayed_cksum(struct mbuf *m, uint32 *(u_short *)(m->m_data + offset) = csum; } +int +ip6_fragment(struct ifnet *ifp, struct mbuf *m0, int hlen, u_char nextproto, + int mtu) +{ + struct mbuf *m, **mnext, *m_frgpart; + struct ip6_hdr *ip6, *mhip6; + struct ip6_frag *ip6f; + int off; + int error; + int tlen = m0->m_pkthdr.len; + uint32_t id = htonl(ip6_randomid()); + + m = m0; + ip6 = mtod(m, struct ip6_hdr *); + mnext = &m->m_nextpkt; + + for (off = hlen; off < tlen; off += mtu) { + m = m_gethdr(M_NOWAIT, MT_DATA); + if (!m) { + IP6STAT_INC(ip6s_odropped); + return (ENOBUFS); + } + m->m_flags = m0->m_flags & M_COPYFLAGS; + *mnext = m; + mnext = &m->m_nextpkt; + m->m_data += max_linkhdr; + mhip6 = mtod(m, struct ip6_hdr *); + *mhip6 = *ip6; + m->m_len = sizeof(*mhip6); + error = ip6_insertfraghdr(m0, m, hlen, &ip6f); + if (error) { + IP6STAT_INC(ip6s_odropped); + return (error); + } + ip6f->ip6f_offlg = htons((u_short)((off - hlen) & ~7)); + if (off + mtu >= tlen) + mtu = tlen - off; + else + ip6f->ip6f_offlg |= IP6F_MORE_FRAG; + mhip6->ip6_plen = htons((u_short)(mtu + hlen + + sizeof(*ip6f) - sizeof(struct ip6_hdr))); + if ((m_frgpart = m_copy(m0, off, mtu)) == 0) { + IP6STAT_INC(ip6s_odropped); + return (ENOBUFS); + } + m_cat(m, m_frgpart); + m->m_pkthdr.len = mtu + hlen + sizeof(*ip6f); + m->m_pkthdr.fibnum = m0->m_pkthdr.fibnum; + m->m_pkthdr.rcvif = NULL; + ip6f->ip6f_reserved = 0; + ip6f->ip6f_ident = id; + ip6f->ip6f_nxt = nextproto; + IP6STAT_INC(ip6s_ofragments); + in6_ifstat_inc(ifp, ifs6_out_fragcreat); + } + + return (0); +} + /* * IP6 output. The packet in mbuf chain m contains a skeletal IP6 * header (with pri, len, nxt, hlim, src, dst). @@ -229,11 +288,11 @@ ip6_output(struct mbuf *m0, struct ip6_p struct route_in6 *ro, int flags, struct ip6_moptions *im6o, struct ifnet **ifpp, struct inpcb *inp) { - struct ip6_hdr *ip6, *mhip6; + struct ip6_hdr *ip6; struct ifnet *ifp, *origifp; struct mbuf *m = m0; struct mbuf *mprev = NULL; - int hlen, tlen, len, off; + int hlen, tlen, len; struct route_in6 ip6route; struct rtentry *rt = NULL; struct sockaddr_in6 *dst, src_sa, dst_sa; @@ -866,9 +925,6 @@ passout: in6_ifstat_inc(ifp, ifs6_out_fragfail); goto bad; } else { - struct mbuf **mnext, *m_frgpart; - struct ip6_frag *ip6f; - u_int32_t id = htonl(ip6_randomid()); u_char nextproto; int qslots = ifp->if_snd.ifq_maxlen - ifp->if_snd.ifq_len; @@ -916,8 +972,6 @@ passout: m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6; } #endif - mnext = &m->m_nextpkt; - /* * Change the next header field of the last header in the * unfragmentable part. @@ -942,47 +996,8 @@ passout: * chain. */ m0 = m; - for (off = hlen; off < tlen; off += len) { - m = m_gethdr(M_NOWAIT, MT_DATA); - if (!m) { - error = ENOBUFS; - IP6STAT_INC(ip6s_odropped); - goto sendorfree; - } - m->m_flags = m0->m_flags & M_COPYFLAGS; - *mnext = m; - mnext = &m->m_nextpkt; - m->m_data += max_linkhdr; - mhip6 = mtod(m, struct ip6_hdr *); - *mhip6 = *ip6; - m->m_len = sizeof(*mhip6); - error = ip6_insertfraghdr(m0, m, hlen, &ip6f); - if (error) { - IP6STAT_INC(ip6s_odropped); - goto sendorfree; - } - ip6f->ip6f_offlg = htons((u_short)((off - hlen) & ~7)); - if (off + len >= tlen) - len = tlen - off; - else - ip6f->ip6f_offlg |= IP6F_MORE_FRAG; - mhip6->ip6_plen = htons((u_short)(len + hlen + - sizeof(*ip6f) - sizeof(struct ip6_hdr))); - if ((m_frgpart = m_copy(m0, off, len)) == 0) { - error = ENOBUFS; - IP6STAT_INC(ip6s_odropped); - goto sendorfree; - } - m_cat(m, m_frgpart); - m->m_pkthdr.len = len + hlen + sizeof(*ip6f); - m->m_pkthdr.fibnum = m0->m_pkthdr.fibnum; - m->m_pkthdr.rcvif = NULL; - ip6f->ip6f_reserved = 0; - ip6f->ip6f_ident = id; - ip6f->ip6f_nxt = nextproto; - IP6STAT_INC(ip6s_ofragments); - in6_ifstat_inc(ifp, ifs6_out_fragcreat); - } + if ((error = ip6_fragment(ifp, m, hlen, nextproto, len))) + goto sendorfree; in6_ifstat_inc(ifp, ifs6_out_fragok); } Modified: stable/10/sys/netinet6/ip6_var.h ============================================================================== --- stable/10/sys/netinet6/ip6_var.h Thu Jun 18 20:28:52 2015 (r284569) +++ stable/10/sys/netinet6/ip6_var.h Thu Jun 18 20:32:53 2015 (r284570) @@ -426,6 +426,7 @@ void ip6_clearpktopts(struct ip6_pktopts struct ip6_pktopts *ip6_copypktopts(struct ip6_pktopts *, int); int ip6_optlen(struct inpcb *); int ip6_deletefraghdr(struct mbuf *, int, int); +int ip6_fragment(struct ifnet *, struct mbuf *, int, u_char, int); int route6_input(struct mbuf **, int *, int);