mirror of
https://github.com/xcat2/xNBA.git
synced 2025-01-18 21:43:14 +00:00
Add support for TCP timestamps
This commit is contained in:
parent
eb530845d4
commit
096fa94f0c
@ -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
|
||||
*/
|
||||
|
@ -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 );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user