Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 14 Jun 2010 09:32:11 +0900
From:      Arifumi Matsumoto <a@arifumi.net>
To:        bug-followup@FreeBSD.org, freebsd-net@freebsd.org
Subject:   Re: kern/143666: [ip6] [request] PMTU black hole detection not  implemented
Message-ID:  <AANLkTikRI9hzTIn80qAEoKiHOjo0aeCZz5TJsgXUe-6-@mail.gmail.com>

index | next in thread | raw e-mail

[-- Attachment #1 --]
Hi,

I made a patch for 8.0 release to fix this issue of path-mtu blackhole
detection.
This was mostly derived from macosx, which is APSL and BSD
dual-licensed code base,
and slightly modified so that it should not affect ipv4 path mtu detection.

I tested it on 8.0 release only.
I'm guessing this can be applied for CURRENT also, as the related code does not
seem to be changed that much.

Best regards,

[-- Attachment #2 --]
diff -c netinet.org/tcp_timer.c netinet/tcp_timer.c
*** netinet.org/tcp_timer.c	Sun Oct 25 01:10:29 2009
--- netinet/tcp_timer.c	Mon Jun 14 03:17:33 2010
***************
*** 61,66 ****
--- 61,67 ----
  #include <netinet/tcp_fsm.h>
  #include <netinet/tcp_timer.h>
  #include <netinet/tcp_var.h>
+ #include <netinet6/tcp6_var.h>
  #include <netinet/tcpip.h>
  #ifdef TCPDEBUG
  #include <netinet/tcp_debug.h>
***************
*** 110,115 ****
--- 111,123 ----
  SYSCTL_PROC(_net_inet_tcp, OID_AUTO, finwait2_timeout, CTLTYPE_INT|CTLFLAG_RW,
      &tcp_finwait2_timeout, 0, sysctl_msec_to_ticks, "I", "FIN-WAIT2 timeout");
  
+ int     tcp_pmtud_black_hole_detect = 1 ;
+ SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_detection, CTLFLAG_RW,
+     &tcp_pmtud_black_hole_detect, 0, "Path MTU Discovery Black Hole Detection");
+ 
+ int     tcp_pmtud_black_hole_mss = 1200 ;
+ SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_mss, CTLFLAG_RW,
+     &tcp_pmtud_black_hole_mss, 0, "Path MTU Discovery Black Hole Detection lowered MSS");
  
  static int	tcp_keepcnt = TCPTV_KEEPCNT;
  	/* max idle probes */
***************
*** 442,447 ****
--- 450,458 ----
  	int rexmt;
  	int headlocked;
  	struct inpcb *inp;
+ #ifdef INET6
+ 	int optlen = 0;
+ #endif
  #ifdef TCPDEBUG
  	int ostate;
  
***************
*** 513,518 ****
--- 524,570 ----
  		rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
  	TCPT_RANGESET(tp->t_rxtcur, rexmt,
  		      tp->t_rttmin, TCPTV_REXMTMAX);
+ 
+         /*
+          * Check for potential Path MTU Discovery Black Hole 
+          */
+ 
+ #if INET6
+         if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0 && tcp_pmtud_black_hole_detect && (tp->t_state == TCPS_ESTABLISHED)) {
+                 if (tp->t_rxtshift == 2) {
+                         /* 
+                          * Enter Path MTU Black-hole Detection mechanism:
+                          * - Disable Path MTU Discovery (IP "DF" bit).
+                          * - Reduce MTU to lower value than what we negociated with peer.
+                          */
+ 
+                         tp->t_flags |= TF_BLACKHOLE; /* Record that we may have found a black hole */
+                         optlen = tp->t_maxopd - tp->t_maxseg;
+                         tp->t_pmtud_saved_maxopd = tp->t_maxopd; /* Keep track of previous MSS */
+                         if (tp->t_maxopd > tcp_pmtud_black_hole_mss)
+                                 tp->t_maxopd = tcp_pmtud_black_hole_mss; /* Reduce the MSS to intermediary value */
+                         else {
+                                 tp->t_maxopd = V_tcp_v6mssdflt;
+                         }
+                         tp->t_maxseg = tp->t_maxopd - optlen;
+                 }
+                 /*
+                  * If further retransmissions are still unsuccessful with a lowered MTU,
+                  * maybe this isn't a Black Hole and we restore the previous MSS and
+                  * blackhole detection flags.
+                  */
+                 else {
+ 
+                         if ((tp->t_flags & TF_BLACKHOLE) && (tp->t_rxtshift > 4)) {
+                                 tp->t_flags &= ~TF_BLACKHOLE; 
+                                 optlen = tp->t_maxopd - tp->t_maxseg;
+                                 tp->t_maxopd = tp->t_pmtud_saved_maxopd;
+                                 tp->t_maxseg = tp->t_maxopd - optlen;
+                         }
+                 }
+         }
+ #endif
+ 
  	/*
  	 * Disable rfc1323 if we havn't got any response to
  	 * our third SYN to work-around some broken terminal servers
diff -c netinet.org/tcp_var.h netinet/tcp_var.h
*** netinet.org/tcp_var.h	Sun Oct 25 01:10:29 2009
--- netinet/tcp_var.h	Mon Jun 14 09:21:25 2010
***************
*** 203,208 ****
--- 203,209 ----
  	int	t_ispare;		/* explicit pad for 64bit alignment */
  	void	*t_pspare2[6];		/* 2 CC / 4 TBD */
  	uint64_t _pad[12];		/* 7 UTO, 5 TBD (1-2 CC/RTT?) */
+         u_int   t_pmtud_saved_maxopd;   /* MSS saved before performing PMTU-D BlackHole detection */
  };
  
  /*
***************
*** 234,239 ****
--- 235,241 ----
  #define	TF_ECN_PERMIT	0x4000000	/* connection ECN-ready */
  #define	TF_ECN_SND_CWR	0x8000000	/* ECN CWR in queue */
  #define	TF_ECN_SND_ECE	0x10000000	/* ECN ECE in queue */
+ #define TF_BLACKHOLE    0x20000000      /* Path MTU Discovery Black Hole detection */
  
  #define IN_FASTRECOVERY(tp)	(tp->t_flags & TF_FASTRECOVERY)
  #define ENTER_FASTRECOVERY(tp)	tp->t_flags |= TF_FASTRECOVERY
help

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