|
@@ -74,7 +74,13 @@ struct tcp_connection {
|
74
|
74
|
* Equivalent to RCV.WND in RFC 793 terminology.
|
75
|
75
|
*/
|
76
|
76
|
uint32_t rcv_win;
|
77
|
|
- /** Most recent received timestamp
|
|
77
|
+ /** Received timestamp value
|
|
78
|
+ *
|
|
79
|
+ * Updated when a packet is received; copied to ts_recent when
|
|
80
|
+ * the window is advanced.
|
|
81
|
+ */
|
|
82
|
+ uint32_t ts_val;
|
|
83
|
+ /** Most recent received timestamp that advanced the window
|
78
|
84
|
*
|
79
|
85
|
* Equivalent to TS.Recent in RFC 1323 terminology.
|
80
|
86
|
*/
|
|
@@ -740,12 +746,24 @@ static void tcp_rx_opts ( struct tcp_connection *tcp, const void *data,
|
740
|
746
|
* @v seq_len Sequence space length to consume
|
741
|
747
|
*/
|
742
|
748
|
static void tcp_rx_seq ( struct tcp_connection *tcp, uint32_t seq_len ) {
|
|
749
|
+
|
|
750
|
+ /* Sanity check */
|
|
751
|
+ assert ( seq_len > 0 );
|
|
752
|
+
|
|
753
|
+ /* Update acknowledgement number */
|
743
|
754
|
tcp->rcv_ack += seq_len;
|
|
755
|
+
|
|
756
|
+ /* Update window */
|
744
|
757
|
if ( tcp->rcv_win > seq_len ) {
|
745
|
758
|
tcp->rcv_win -= seq_len;
|
746
|
759
|
} else {
|
747
|
760
|
tcp->rcv_win = 0;
|
748
|
761
|
}
|
|
762
|
+
|
|
763
|
+ /* Update timestamp */
|
|
764
|
+ tcp->ts_recent = tcp->ts_val;
|
|
765
|
+
|
|
766
|
+ /* Mark ACK as pending */
|
749
|
767
|
tcp->flags |= TCP_ACK_PENDING;
|
750
|
768
|
}
|
751
|
769
|
|
|
@@ -1060,7 +1078,6 @@ static int tcp_rx ( struct io_buffer *iobuf,
|
1060
|
1078
|
struct tcp_options options;
|
1061
|
1079
|
size_t hlen;
|
1062
|
1080
|
uint16_t csum;
|
1063
|
|
- uint32_t start_seq;
|
1064
|
1081
|
uint32_t seq;
|
1065
|
1082
|
uint32_t ack;
|
1066
|
1083
|
uint32_t win;
|
|
@@ -1100,12 +1117,14 @@ static int tcp_rx ( struct io_buffer *iobuf,
|
1100
|
1117
|
|
1101
|
1118
|
/* Parse parameters from header and strip header */
|
1102
|
1119
|
tcp = tcp_demux ( ntohs ( tcphdr->dest ) );
|
1103
|
|
- seq = start_seq = ntohl ( tcphdr->seq );
|
|
1120
|
+ seq = ntohl ( tcphdr->seq );
|
1104
|
1121
|
ack = ntohl ( tcphdr->ack );
|
1105
|
1122
|
win = ntohs ( tcphdr->win );
|
1106
|
1123
|
flags = tcphdr->flags;
|
1107
|
1124
|
tcp_rx_opts ( tcp, ( ( ( void * ) tcphdr ) + sizeof ( *tcphdr ) ),
|
1108
|
1125
|
( hlen - sizeof ( *tcphdr ) ), &options );
|
|
1126
|
+ if ( options.tsopt )
|
|
1127
|
+ tcp->ts_val = ntohl ( options.tsopt->tsval );
|
1109
|
1128
|
iob_pull ( iobuf, hlen );
|
1110
|
1129
|
len = iob_len ( iobuf );
|
1111
|
1130
|
seq_len = ( len + ( ( flags & TCP_SYN ) ? 1 : 0 ) +
|
|
@@ -1152,12 +1171,6 @@ static int tcp_rx ( struct io_buffer *iobuf,
|
1152
|
1171
|
goto discard;
|
1153
|
1172
|
}
|
1154
|
1173
|
|
1155
|
|
- /* Update timestamp, if applicable */
|
1156
|
|
- if ( options.tsopt &&
|
1157
|
|
- tcp_in_window ( tcp->rcv_ack, start_seq, seq_len ) ) {
|
1158
|
|
- tcp->ts_recent = ntohl ( options.tsopt->tsval );
|
1159
|
|
- }
|
1160
|
|
-
|
1161
|
1174
|
/* Enqueue received data */
|
1162
|
1175
|
tcp_rx_enqueue ( tcp, seq, flags, iob_disown ( iobuf ) );
|
1163
|
1176
|
|