svn commit: r354040 - head/sys/netinet6

Bjoern A. Zeeb bz at FreeBSD.org
Thu Oct 24 19:57:19 UTC 2019


Author: bz
Date: Thu Oct 24 19:57:18 2019
New Revision: 354040
URL: https://svnweb.freebsd.org/changeset/base/354040

Log:
  frag6: fix counter leak in error case and optimise code
  
  In case the first fragmented part (off=0) arrives we check for the
  maximum packet size for each fragmented part we already queued with the
  addition of the unfragmentable part from the first one.
  
  For one we do not have to enter the loop at all if this is the first
  fragmented part to arrive, and we can skip the check.
  
  Should we encounter an error case we send an ICMPv6 message for any
  fragment exceeding the maximum length limit.  While dequeueing the
  original packet and freeing it, statistics were not updated and leaked
  both the reassembly queue count for the fragment and the global
  fragment count.  Found by code inspection and confirmed by tightening
  test cases checking more statistical and system counters.
  
  While here properly wrap a line.
  
  MFC after:	3 weeks
  Sponsored by:	Netflix

Modified:
  head/sys/netinet6/frag6.c

Modified: head/sys/netinet6/frag6.c
==============================================================================
--- head/sys/netinet6/frag6.c	Thu Oct 24 19:52:41 2019	(r354039)
+++ head/sys/netinet6/frag6.c	Thu Oct 24 19:57:18 2019	(r354040)
@@ -608,11 +608,11 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
 	 * If it is the first fragment, do the above check for each
 	 * fragment already stored in the reassembly queue.
 	 */
-	if (fragoff == 0) {
+	if (fragoff == 0 && !only_frag) {
 		TAILQ_FOREACH_SAFE(af6, &q6->ip6q_frags, ip6af_tq, af6tmp) {
 
-			if (q6->ip6q_unfrglen + af6->ip6af_off + af6->ip6af_frglen >
-			    IPV6_MAXPACKET) {
+			if (q6->ip6q_unfrglen + af6->ip6af_off +
+			    af6->ip6af_frglen > IPV6_MAXPACKET) {
 				struct ip6_hdr *ip6err;
 				struct mbuf *merr;
 				int erroff;
@@ -622,6 +622,8 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
 
 				/* Dequeue the fragment. */
 				TAILQ_REMOVE(&q6->ip6q_frags, af6, ip6af_tq);
+				q6->ip6q_nfrag--;
+				atomic_subtract_int(&frag6_nfrags, 1);
 				free(af6, M_FRAG6);
 
 				/* Set a valid receive interface pointer. */


More information about the svn-src-head mailing list