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--