Page MenuHomeFreeBSD

D506.id1666.diff
No OneTemporary

D506.id1666.diff

Index: sys/netinet/tcp_output.c
===================================================================
--- sys/netinet/tcp_output.c
+++ sys/netinet/tcp_output.c
@@ -675,6 +675,12 @@
send:
SOCKBUF_LOCK_ASSERT(&so->so_snd);
+ if (len > 0) {
+ if (len >= tp->t_maxseg)
+ tp->t_pmtud_flags |= PLPMTU_MAXSEGSNT;
+ else
+ tp->t_pmtud_flags &= ~PLPMTU_MAXSEGSNT;
+ }
/*
* Before ESTABLISHED, force sending of initial options
* unless TCP set not to do any options.
@@ -1219,8 +1225,12 @@
*
* NB: Don't set DF on small MTU/MSS to have a safe fallback.
*/
- if (V_path_mtu_discovery && tp->t_maxopd > V_tcp_minmss)
+ if (V_path_mtu_discovery && tp->t_maxopd > V_tcp_minmss) {
ip->ip_off |= htons(IP_DF);
+ tp->t_pmtud_flags |= PLPMTU_PMTUD;
+ } else {
+ tp->t_pmtud_flags &= ~PLPMTU_PMTUD;
+ }
if (tp->t_state == TCPS_SYN_SENT)
TCP_PROBE5(connect__request, NULL, tp, ip, tp, th);
Index: sys/netinet/tcp_timer.c
===================================================================
--- sys/netinet/tcp_timer.c
+++ sys/netinet/tcp_timer.c
@@ -66,6 +66,9 @@
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
+#ifdef INET6
+#include <netinet6/tcp6_var.h>
+#endif
#include <netinet/tcpip.h>
#ifdef TCPDEBUG
#include <netinet/tcp_debug.h>
@@ -127,6 +130,35 @@
&tcp_rexmit_drop_options, 0,
"Drop TCP options from 3rd and later retransmitted SYN");
+
+VNET_DECLARE(int, tcp_pmtud_black_hole_detect);
+#define V_tcp_pmtud_black_hole_detect VNET(tcp_pmtud_black_hole_detect)
+
+VNET_DEFINE(int, tcp_pmtud_black_hole_detect) = 0;
+SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_detection,
+ CTLTYPE_INT|CTLFLAG_RW, &VNET_NAME(tcp_pmtud_black_hole_detect), 0,
+ "Path MTU Discovery Black Hole Detection");
+
+#ifdef INET
+VNET_DECLARE(int, tcp_pmtud_black_hole_mss);
+#define V_tcp_pmtud_black_hole_mss VNET(tcp_pmtud_black_hole_mss)
+
+VNET_DEFINE(int, tcp_pmtud_black_hole_mss) = 536;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_mss,
+ CTLTYPE_INT|CTLFLAG_RW, &VNET_NAME(tcp_pmtud_black_hole_mss), 0,
+ "Path MTU Discovery Black Hole Detection lowered MSS");
+#endif
+
+#ifdef INET6
+VNET_DECLARE(int, tcp_v6pmtud_black_hole_mss);
+#define V_tcp_v6pmtud_black_hole_mss VNET(tcp_v6pmtud_black_hole_mss)
+
+VNET_DEFINE(int, tcp_v6pmtud_black_hole_mss) = 1220;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, v6pmtud_blackhole_mss,
+ CTLTYPE_INT|CTLFLAG_RW, &VNET_NAME(tcp_v6pmtud_black_hole_mss), 0,
+ "Path MTU Discovery IPv6 Black Hole Detection lowered MSS");
+#endif
+
#ifdef RSS
static int per_cpu_timers = 1;
#else
@@ -539,6 +571,10 @@
ostate = tp->t_state;
#endif
+#if defined(INET6) && defined(INET)
+ int isipv6;
+#endif
+
INP_INFO_RLOCK(&V_tcbinfo);
inp = tp->t_inpcb;
/*
@@ -640,6 +676,89 @@
rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
TCPT_RANGESET(tp->t_rxtcur, rexmt,
tp->t_rttmin, TCPTV_REXMTMAX);
+
+ if (V_tcp_pmtud_black_hole_detect && (tp->t_state == TCPS_ESTABLISHED)) {
+ int optlen = 0;
+ if (((tp->t_pmtud_flags & (PLPMTU_PMTUD|PLPMTU_MAXSEGSNT)) ==
+ (PLPMTU_PMTUD|PLPMTU_MAXSEGSNT)) &&
+ (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.
+ */
+ /* Disable Path MTU Discovery for now */
+ tp->t_pmtud_flags &= ~PLPMTU_PMTUD;
+ /* Record that we may have found a black hole */
+ tp->t_pmtud_flags |= PLPMTU_BLACKHOLE;
+ optlen = tp->t_maxopd - tp->t_maxseg;
+ /* Keep track of previous MSS */
+ tp->t_pmtud_saved_maxopd = tp->t_maxopd;
+
+#if defined(INET6) && defined(INET)
+ isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) ? 1 : 0;
+
+ /* Reduce the MSS to intermediary value */
+ if (ispiv6)
+#endif
+#if defined(INET6)
+ if (tp->t_maxopd > V_tcp_pmtud_black_hole_mss) {
+#elif defined (INET)
+ if (tp->t_maxopd > V_tcp_pmtud_black_hole_mss) {
+#endif
+ /* use the sysctl tuneable blackhole MSS */
+ tp->t_maxopd =
+#if defined(INET6) && defined(INET)
+ isipv6 ? V_tcp_v6pmtud_black_hole_mss :
+ V_tcp_pmtud_black_hole_mss;
+#elif defined (INET6)
+ V_tcp_v6pmtud_black_hole_mss;
+#elif defined (INET)
+ V_tcp_pmtud_black_hole_mss;
+#endif /* INET6 vs INET checks */
+ } else {
+ /* use the default MSS */
+ tp->t_maxopd =
+#if defined(INET6) && defined(INET)
+ isipv6 ? V_tcp_v6mssdflt :
+ V_tcp_mssdflt;
+#elif defined (INET6)
+ V_tcp_v6mssdflt;
+#elif defined (INET)
+ V_tcp_mssdflt;
+#endif /* INET6 */
+ }
+ tp->t_maxseg = tp->t_maxopd - optlen;
+ /*
+ * Reset the slow-start flight size
+ * as it may depend on the new MSS
+ */
+ if (CC_ALGO(tp)->conn_init != NULL)
+ CC_ALGO(tp)->conn_init(tp->ccv);
+ } else {
+ /*
+ * 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.
+ */
+ if ((tp->t_pmtud_flags & PLPMTU_BLACKHOLE) &&
+ (tp->t_rxtshift > 4)) {
+ tp->t_pmtud_flags |= PLPMTU_PMTUD;
+ tp->t_pmtud_flags &= ~PLPMTU_BLACKHOLE;
+ optlen = tp->t_maxopd - tp->t_maxseg;
+ tp->t_maxopd = tp->t_pmtud_saved_maxopd;
+ tp->t_maxseg = tp->t_maxopd - optlen;
+ /*
+ * Reset the slow-start flight size as it
+ * may depend on the new MSS.
+ */
+ if (CC_ALGO(tp)->conn_init != NULL)
+ CC_ALGO(tp)->conn_init(tp->ccv);
+ }
+ }
+ }
+
/*
* Disable RFC1323 and SACK if we haven't got any response to
* our third SYN to work-around some broken terminal servers
Index: sys/netinet/tcp_var.h
===================================================================
--- sys/netinet/tcp_var.h
+++ sys/netinet/tcp_var.h
@@ -200,6 +200,8 @@
u_int t_keepcnt; /* number of keepalives before close */
u_int t_tsomax; /* tso burst length limit */
+ u_int t_pmtud_saved_maxopd; /* pre-blackhole MSS */
+ u_int t_pmtud_flags; /* PLPMTU flags */
uint32_t t_ispare[8]; /* 5 UTO, 3 TBD */
void *t_pspare2[4]; /* 1 TCP_SIGNATURE, 3 TBD */
@@ -275,6 +277,13 @@
#endif /* TCP_SIGNATURE */
/*
+ * Flags for PLPMTU handling, t_pmtu_flags
+ */
+#define PLPMTU_BLACKHOLE 0x00000001 /* possible PLPMTUD Black Hole */
+#define PLPMTU_PMTUD 0x00000002 /* allowed to attempt PLPMTUD */
+#define PLPMTU_MAXSEGSNT 0x00000004 /* last segment sent was full seg */
+
+/*
* Structure to hold TCP options that are only used during segment
* processing (in tcp_input), but not held in the tcpcb.
* It's basically used to reduce the number of parameters

File Metadata

Mime Type
text/plain
Expires
Sun, Apr 13, 3:40 PM (6 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17500528
Default Alt Text
D506.id1666.diff (6 KB)

Event Timeline