david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

Add support for TCP timestamps

This commit is contained in:
Michael Brown 2007-07-13 11:32:53 +01:00
parent eb530845d4
commit 096fa94f0c
2 changed files with 115 additions and 6 deletions

View File

@ -27,18 +27,59 @@ struct tcp_header {
uint16_t urg; /* Urgent pointer */
};
/**
* TCP MSS option
/** @defgroup tcpopts TCP options
* @{
*/
/** End of TCP options list */
#define TCP_OPTION_END 0
/** TCP option pad */
#define TCP_OPTION_NOP 1
/** Generic TCP option */
struct tcp_option {
uint8_t kind;
uint8_t length;
} __attribute__ (( packed ));
/** TCP MSS option */
struct tcp_mss_option {
uint8_t kind;
uint8_t length;
uint16_t mss;
};
} __attribute__ (( packed ));
/** Code for the TCP MSS option */
#define TCP_OPTION_MSS 2
/** TCP timestamp option */
struct tcp_timestamp_option {
uint8_t kind;
uint8_t length;
uint32_t tsval;
uint32_t tsecr;
} __attribute__ (( packed ));
/** Padded TCP timestamp option (used for sending) */
struct tcp_timestamp_padded_option {
uint8_t nop[2];
struct tcp_timestamp_option tsopt;
} __attribute__ (( packed ));
/** Code for the TCP timestamp option */
#define TCP_OPTION_TS 8
/** Parsed TCP options */
struct tcp_options {
/** MSS option, if present */
const struct tcp_mss_option *mssopt;
/** Timestampe option, if present */
const struct tcp_timestamp_option *tsopt;
};
/** @} */
/*
* TCP flags
*/

View File

@ -65,6 +65,13 @@ struct tcp_connection {
* Equivalent to RCV.NXT in RFC 793 terminology.
*/
uint32_t rcv_ack;
/** Most recent received timestamp
*
* Equivalent to TS.Recent in RFC 1323 terminology.
*/
uint32_t ts_recent;
/** Timestamps enabled */
int timestamps;
/** Transmit queue */
struct list_head queue;
@ -381,6 +388,7 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
struct io_buffer *iobuf;
struct tcp_header *tcphdr;
struct tcp_mss_option *mssopt;
struct tcp_timestamp_padded_option *tsopt;
void *payload;
unsigned int flags;
size_t len = 0;
@ -449,6 +457,14 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
mssopt->length = sizeof ( *mssopt );
mssopt->mss = htons ( TCP_MSS );
}
if ( ( flags & TCP_SYN ) || tcp->timestamps ) {
tsopt = iob_push ( iobuf, sizeof ( *tsopt ) );
memset ( tsopt->nop, TCP_OPTION_NOP, sizeof ( tsopt->nop ) );
tsopt->tsopt.kind = TCP_OPTION_TS;
tsopt->tsopt.length = sizeof ( tsopt->tsopt );
tsopt->tsopt.tsval = ntohl ( currticks() );
tsopt->tsopt.tsecr = ntohl ( tcp->ts_recent );
}
tcphdr = iob_push ( iobuf, sizeof ( *tcphdr ) );
memset ( tcphdr, 0, sizeof ( *tcphdr ) );
tcphdr->src = tcp->local_port;
@ -594,18 +610,63 @@ static struct tcp_connection * tcp_demux ( unsigned int local_port ) {
return NULL;
}
/**
* Parse TCP received options
*
* @v tcp TCP connection
* @v data Raw options data
* @v len Raw options length
* @v options Options structure to fill in
*/
static void tcp_rx_opts ( struct tcp_connection *tcp, const void *data,
size_t len, struct tcp_options *options ) {
const void *end = ( data + len );
const struct tcp_option *option;
unsigned int kind;
memset ( options, 0, sizeof ( *options ) );
while ( data < end ) {
option = data;
kind = option->kind;
if ( kind == TCP_OPTION_END )
return;
if ( kind == TCP_OPTION_NOP ) {
data++;
continue;
}
switch ( kind ) {
case TCP_OPTION_MSS:
options->mssopt = data;
break;
case TCP_OPTION_TS:
options->tsopt = data;
break;
default:
DBGC ( tcp, "TCP %p received unknown option %d\n",
tcp, kind );
break;
}
data += option->length;
}
}
/**
* Handle TCP received SYN
*
* @v tcp TCP connection
* @v seq SEQ value (in host-endian order)
* @v options TCP options
* @ret rc Return status code
*/
static int tcp_rx_syn ( struct tcp_connection *tcp, uint32_t seq ) {
static int tcp_rx_syn ( struct tcp_connection *tcp, uint32_t seq,
struct tcp_options *options ) {
/* Synchronise sequence numbers on first SYN */
if ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) )
if ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) {
tcp->rcv_ack = seq;
if ( options->tsopt )
tcp->timestamps = 1;
}
/* Ignore duplicate SYN */
if ( ( tcp->rcv_ack - seq ) > 0 )
@ -776,6 +837,7 @@ static int tcp_rx ( struct io_buffer *iobuf,
uint16_t pshdr_csum ) {
struct tcp_header *tcphdr = iobuf->data;
struct tcp_connection *tcp;
struct tcp_options options;
unsigned int hlen;
uint16_t csum;
uint32_t start_seq;
@ -820,6 +882,8 @@ static int tcp_rx ( struct io_buffer *iobuf,
ack = ntohl ( tcphdr->ack );
win = ntohs ( tcphdr->win );
flags = tcphdr->flags;
tcp_rx_opts ( tcp, ( ( ( void * ) tcphdr ) + sizeof ( *tcphdr ) ),
( hlen - sizeof ( *tcphdr ) ), &options );
iob_pull ( iobuf, hlen );
len = iob_len ( iobuf );
@ -849,7 +913,7 @@ static int tcp_rx ( struct io_buffer *iobuf,
/* Handle SYN, if present */
if ( flags & TCP_SYN ) {
tcp_rx_syn ( tcp, seq );
tcp_rx_syn ( tcp, seq, &options );
seq++;
}
@ -869,6 +933,10 @@ static int tcp_rx ( struct io_buffer *iobuf,
seq++;
}
/* Update timestamp, if present and applicable */
if ( ( seq == tcp->rcv_ack ) && options.tsopt )
tcp->ts_recent = ntohl ( options.tsopt->tsval );
/* Dump out any state change as a result of the received packet */
tcp_dump_state ( tcp );