Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 9 Apr 2015 21:32:33 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r281334 - head/sys/netinet
Message-ID:  <201504092132.t39LWXmw043855@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Thu Apr  9 21:32:32 2015
New Revision: 281334
URL: https://svnweb.freebsd.org/changeset/base/281334

Log:
  In the ip_reass() do packet examination and adjusting before acquiring
  locks and doing lookups.
  
  Sponsored by:	Nginx, Inc.

Modified:
  head/sys/netinet/ip_input.c

Modified: head/sys/netinet/ip_input.c
==============================================================================
--- head/sys/netinet/ip_input.c	Thu Apr  9 21:30:11 2015	(r281333)
+++ head/sys/netinet/ip_input.c	Thu Apr  9 21:32:32 2015	(r281334)
@@ -938,6 +938,41 @@ ip_reass(struct mbuf *m)
 	ip = mtod(m, struct ip *);
 	hlen = ip->ip_hl << 2;
 
+	/*
+	 * Adjust ip_len to not reflect header,
+	 * convert offset of this to bytes.
+	 */
+	ip->ip_len = htons(ntohs(ip->ip_len) - hlen);
+	if (ip->ip_off & htons(IP_MF)) {
+		/*
+		 * Make sure that fragments have a data length
+		 * that's a non-zero multiple of 8 bytes.
+		 */
+		if (ip->ip_len == htons(0) || (ntohs(ip->ip_len) & 0x7) != 0) {
+			IPSTAT_INC(ips_toosmall); /* XXX */
+			IPSTAT_INC(ips_fragdropped);
+			m_freem(m);
+			return (NULL);
+		}
+		m->m_flags |= M_IP_FRAG;
+	} else
+		m->m_flags &= ~M_IP_FRAG;
+	ip->ip_off = htons(ntohs(ip->ip_off) << 3);
+
+	/*
+	 * Attempt reassembly; if it succeeds, proceed.
+	 * ip_reass() will return a different mbuf.
+	 */
+	IPSTAT_INC(ips_fragments);
+	m->m_pkthdr.PH_loc.ptr = ip;
+
+	/*
+	 * Presence of header sizes in mbufs
+	 * would confuse code below.
+	 */
+	m->m_data += hlen;
+	m->m_len -= hlen;
+
 	hash = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id);
 	head = &V_ipq[hash].head;
 	IPQ_LOCK(hash);
@@ -980,40 +1015,6 @@ ip_reass(struct mbuf *m)
 
 found:
 	/*
-	 * Adjust ip_len to not reflect header,
-	 * convert offset of this to bytes.
-	 */
-	ip->ip_len = htons(ntohs(ip->ip_len) - hlen);
-	if (ip->ip_off & htons(IP_MF)) {
-		/*
-		 * Make sure that fragments have a data length
-		 * that's a non-zero multiple of 8 bytes.
-		 */
-		if (ip->ip_len == htons(0) || (ntohs(ip->ip_len) & 0x7) != 0) {
-			IPSTAT_INC(ips_toosmall); /* XXX */
-			goto dropfrag;
-		}
-		m->m_flags |= M_IP_FRAG;
-	} else
-		m->m_flags &= ~M_IP_FRAG;
-	ip->ip_off = htons(ntohs(ip->ip_off) << 3);
-
-	/*
-	 * Attempt reassembly; if it succeeds, proceed.
-	 * ip_reass() will return a different mbuf.
-	 */
-	IPSTAT_INC(ips_fragments);
-	m->m_pkthdr.PH_loc.ptr = ip;
-
-	/* Previous ip_reass() started here. */
-	/*
-	 * Presence of header sizes in mbufs
-	 * would confuse code below.
-	 */
-	m->m_data += hlen;
-	m->m_len -= hlen;
-
-	/*
 	 * If first fragment to arrive, create a reassembly queue.
 	 */
 	if (fp == NULL) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201504092132.t39LWXmw043855>