Subject: some sack fixes
To: None <tech-net@netbsd.org>
From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
List: tech-net
Date: 03/14/2005 21:04:56
--NextPart-20050314205750-0058400
Content-Type: Text/Plain; charset=us-ascii

hi,

can anyone review the attached patch?  thanks.

- use full sized segments unless we actually have SACKs to send.
- avoid TSO duplicate D-SACK.
- send SACKs regardless of TF_ACKNOW.
- don't clear rcv_sack_num when transmitting.

YAMAMOTO Takashi

--NextPart-20050314205750-0058400
Content-Type: Text/Plain; charset=us-ascii
Content-Disposition: attachment; filename="sack2.diff"

Index: tcp_subr.c
===================================================================
--- tcp_subr.c	(revision 1082)
+++ tcp_subr.c	(working copy)
@@ -2195,8 +2195,5 @@ tcp_optlen(struct tcpcb *tp)
 		optlen += TCPOLEN_SIGNATURE + 2;
 #endif /* TCP_SIGNATURE */
 
-	if (tp->t_flags & TF_WILL_SACK)
-		optlen += 8 * TCP_SACK_MAX + 4;
-
 	return optlen;
 }
Index: tcp_sack.c
===================================================================
--- tcp_sack.c	(revision 1082)
+++ tcp_sack.c	(working copy)
@@ -191,7 +191,6 @@ tcp_update_sack_list(struct tcpcb *tp)
 	if (tp->rcv_sack_flags & TCPSACK_HAVED) {
 		tp->rcv_sack_block[0].left = tp->rcv_dsack_block.left;
 		tp->rcv_sack_block[0].right = tp->rcv_dsack_block.right;
-		tp->rcv_sack_flags &= ~TCPSACK_HAVED;
 		i++;
 	}
 
@@ -552,4 +551,15 @@ tcp_sack_adjust(struct tcpcb *tp)
 	tp->snd_nxt = tp->rcv_lastsack;
 
 	return;
+}
+
+int
+tcp_sack_optlen(struct tcpcb *tp)
+{
+
+	if (!TCP_SACK_ENABLED(tp) || tp->rcv_sack_num == 0) {
+		return 0;
+	}
+
+	return tp->rcv_sack_num * 8 + 2 + 2;
 }
Index: tcp_var.h
===================================================================
--- tcp_var.h	(revision 1082)
+++ tcp_var.h	(working copy)
@@ -852,6 +852,7 @@ void	 tcp_free_sackholes(struct tcpcb *)
 void	 tcp_sack_adjust(struct tcpcb *tp);
 struct sackhole *tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt);
 void	 tcp_sack_newack(struct tcpcb *, struct tcphdr *);
+int	 tcp_sack_optlen(struct tcpcb *);
 
 
 int	 syn_cache_add(struct sockaddr *, struct sockaddr *,
Index: tcp_output.c
===================================================================
--- tcp_output.c	(revision 1083)
+++ tcp_output.c	(working copy)
@@ -550,11 +550,13 @@ tcp_output(struct tcpcb *tp)
 	struct tcphdr *th;
 	u_char opt[MAX_TCPOPTLEN];
 	unsigned optlen, hdrlen;
+	unsigned int sack_optlen;
 	int idle, sendalot, txsegsize, rxsegsize;
+	int txsegsize_nosack;
 	int maxburst = TCP_MAXBURST;
 	int af;		/* address family on the wire */
 	int iphdrlen;
-	int use_tso;
+	int has_tso, use_tso;
 	int sack_rxmit;
 	int sack_bytes_rxmt;
 	struct sackhole *p;
@@ -612,7 +614,7 @@ tcp_output(struct tcpcb *tp)
 	 * - If there is not an IPsec policy that prevents it
 	 * - If the interface can do it
 	 */
-	use_tso = tp->t_inpcb != NULL &&
+	has_tso = tp->t_inpcb != NULL &&
 #if defined(IPSEC) || defined(FAST_IPSEC)
 		  IPSEC_PCB_SKIP_IPSEC(tp->t_inpcb->inp_sp,
 		  		       IPSEC_DIR_OUTBOUND) &&
@@ -667,7 +669,17 @@ tcp_output(struct tcpcb *tp)
 		}
 	}
 
+	txsegsize_nosack = txsegsize;
 again:
+	sack_optlen = tcp_sack_optlen(tp);
+	if (sack_optlen && (tp->rcv_sack_flags & TCPSACK_HAVED) != 0) {
+		/* don't duplicate D-SACK. */
+		use_tso = 0;
+	} else {
+		use_tso = has_tso;
+	}
+	txsegsize = txsegsize_nosack - sack_optlen;
+
 	/*
 	 * Determine length of data that should be transmitted, and
 	 * flags that should be used.  If there is some data or critical
@@ -1064,8 +1076,7 @@ send:
 	/*
 	 * Tack on the SACK block if it is necessary.
 	 */
-	if (TCP_SACK_ENABLED(tp) && (tp->t_flags & TF_ACKNOW)
-			&& (tp->rcv_sack_num > 0)) {
+	if (sack_optlen) {
 		int sack_len, i;
 		u_char *bp = (u_char *)(opt + optlen);
 		u_int32_t *lp = (u_int32_t *)(bp + 4);
@@ -1079,7 +1090,11 @@ send:
 			*lp++ = htonl(tp->rcv_sack_block[i].left);
 			*lp++ = htonl(tp->rcv_sack_block[i].right);
 		}
-		tp->rcv_sack_num = 0;
+		if ((tp->rcv_sack_flags & TCPSACK_HAVED) != 0) {
+			tp->rcv_sack_flags &= ~TCPSACK_HAVED;
+			tcp_update_sack_list(tp);
+		}
+		KASSERT(sack_len + 2 == sack_optlen);
 		optlen += sack_len + 2;
 	}
 

--NextPart-20050314205750-0058400--