Browse Source

Add support for TCP timestamps

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
096fa94f0c
2 changed files with 115 additions and 6 deletions
  1. 44
    3
      src/include/gpxe/tcp.h
  2. 71
    3
      src/net/tcp.c

+ 44
- 3
src/include/gpxe/tcp.h View File

@@ -27,18 +27,59 @@ struct tcp_header {
27 27
 	uint16_t urg;		/* Urgent pointer */
28 28
 };
29 29
 
30
-/**
31
- * TCP MSS option
30
+/** @defgroup tcpopts TCP options
31
+ * @{
32 32
  */
33
+
34
+/** End of TCP options list */
35
+#define TCP_OPTION_END 0
36
+
37
+/** TCP option pad */
38
+#define TCP_OPTION_NOP 1
39
+
40
+/** Generic TCP option */
41
+struct tcp_option {
42
+	uint8_t kind;
43
+	uint8_t length;
44
+} __attribute__ (( packed ));
45
+
46
+/** TCP MSS option */
33 47
 struct tcp_mss_option {
34 48
 	uint8_t kind;
35 49
 	uint8_t length;
36 50
 	uint16_t mss;
37
-};
51
+} __attribute__ (( packed ));
38 52
 
39 53
 /** Code for the TCP MSS option */
40 54
 #define TCP_OPTION_MSS 2
41 55
 
56
+/** TCP timestamp option */
57
+struct tcp_timestamp_option {
58
+	uint8_t kind;
59
+	uint8_t length;
60
+	uint32_t tsval;
61
+	uint32_t tsecr;
62
+} __attribute__ (( packed ));
63
+
64
+/** Padded TCP timestamp option (used for sending) */
65
+struct tcp_timestamp_padded_option {
66
+	uint8_t nop[2];
67
+	struct tcp_timestamp_option tsopt;
68
+} __attribute__ (( packed ));
69
+
70
+/** Code for the TCP timestamp option */
71
+#define TCP_OPTION_TS 8
72
+
73
+/** Parsed TCP options */
74
+struct tcp_options {
75
+	/** MSS option, if present */
76
+	const struct tcp_mss_option *mssopt;
77
+	/** Timestampe option, if present */
78
+	const struct tcp_timestamp_option *tsopt;
79
+};
80
+
81
+/** @} */
82
+
42 83
 /*
43 84
  * TCP flags
44 85
  */

+ 71
- 3
src/net/tcp.c View File

@@ -65,6 +65,13 @@ struct tcp_connection {
65 65
 	 * Equivalent to RCV.NXT in RFC 793 terminology.
66 66
 	 */
67 67
 	uint32_t rcv_ack;
68
+	/** Most recent received timestamp
69
+	 *
70
+	 * Equivalent to TS.Recent in RFC 1323 terminology.
71
+	 */
72
+	uint32_t ts_recent;
73
+	/** Timestamps enabled */
74
+	int timestamps;
68 75
 
69 76
 	/** Transmit queue */
70 77
 	struct list_head queue;
@@ -381,6 +388,7 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
381 388
 	struct io_buffer *iobuf;
382 389
 	struct tcp_header *tcphdr;
383 390
 	struct tcp_mss_option *mssopt;
391
+	struct tcp_timestamp_padded_option *tsopt;
384 392
 	void *payload;
385 393
 	unsigned int flags;
386 394
 	size_t len = 0;
@@ -449,6 +457,14 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
449 457
 		mssopt->length = sizeof ( *mssopt );
450 458
 		mssopt->mss = htons ( TCP_MSS );
451 459
 	}
460
+	if ( ( flags & TCP_SYN ) || tcp->timestamps ) {
461
+		tsopt = iob_push ( iobuf, sizeof ( *tsopt ) );
462
+		memset ( tsopt->nop, TCP_OPTION_NOP, sizeof ( tsopt->nop ) );
463
+		tsopt->tsopt.kind = TCP_OPTION_TS;
464
+		tsopt->tsopt.length = sizeof ( tsopt->tsopt );
465
+		tsopt->tsopt.tsval = ntohl ( currticks() );
466
+		tsopt->tsopt.tsecr = ntohl ( tcp->ts_recent );
467
+	}
452 468
 	tcphdr = iob_push ( iobuf, sizeof ( *tcphdr ) );
453 469
 	memset ( tcphdr, 0, sizeof ( *tcphdr ) );
454 470
 	tcphdr->src = tcp->local_port;
@@ -594,18 +610,63 @@ static struct tcp_connection * tcp_demux ( unsigned int local_port ) {
594 610
 	return NULL;
595 611
 }
596 612
 
613
+/**
614
+ * Parse TCP received options
615
+ *
616
+ * @v tcp		TCP connection
617
+ * @v data		Raw options data
618
+ * @v len		Raw options length
619
+ * @v options		Options structure to fill in
620
+ */
621
+static void tcp_rx_opts ( struct tcp_connection *tcp, const void *data,
622
+			  size_t len, struct tcp_options *options ) {
623
+	const void *end = ( data + len );
624
+	const struct tcp_option *option;
625
+	unsigned int kind;
626
+
627
+	memset ( options, 0, sizeof ( *options ) );
628
+	while ( data < end ) {
629
+		option = data;
630
+		kind = option->kind;
631
+		if ( kind == TCP_OPTION_END )
632
+			return;
633
+		if ( kind == TCP_OPTION_NOP ) {
634
+			data++;
635
+			continue;
636
+		}
637
+		switch ( kind ) {
638
+		case TCP_OPTION_MSS:
639
+			options->mssopt = data;
640
+			break;
641
+		case TCP_OPTION_TS:
642
+			options->tsopt = data;
643
+			break;
644
+		default:
645
+			DBGC ( tcp, "TCP %p received unknown option %d\n",
646
+			       tcp, kind );
647
+			break;
648
+		}
649
+		data += option->length;
650
+	}
651
+}
652
+
597 653
 /**
598 654
  * Handle TCP received SYN
599 655
  *
600 656
  * @v tcp		TCP connection
601 657
  * @v seq		SEQ value (in host-endian order)
658
+ * @v options		TCP options
602 659
  * @ret rc		Return status code
603 660
  */
604
-static int tcp_rx_syn ( struct tcp_connection *tcp, uint32_t seq ) {
661
+static int tcp_rx_syn ( struct tcp_connection *tcp, uint32_t seq,
662
+			struct tcp_options *options ) {
605 663
 
606 664
 	/* Synchronise sequence numbers on first SYN */
607
-	if ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) )
665
+	if ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) {
608 666
 		tcp->rcv_ack = seq;
667
+		if ( options->tsopt )
668
+			tcp->timestamps = 1;
669
+	}
609 670
 
610 671
 	/* Ignore duplicate SYN */
611 672
 	if ( ( tcp->rcv_ack - seq ) > 0 )
@@ -776,6 +837,7 @@ static int tcp_rx ( struct io_buffer *iobuf,
776 837
 		    uint16_t pshdr_csum ) {
777 838
 	struct tcp_header *tcphdr = iobuf->data;
778 839
 	struct tcp_connection *tcp;
840
+	struct tcp_options options;
779 841
 	unsigned int hlen;
780 842
 	uint16_t csum;
781 843
 	uint32_t start_seq;
@@ -820,6 +882,8 @@ static int tcp_rx ( struct io_buffer *iobuf,
820 882
 	ack = ntohl ( tcphdr->ack );
821 883
 	win = ntohs ( tcphdr->win );
822 884
 	flags = tcphdr->flags;
885
+	tcp_rx_opts ( tcp, ( ( ( void * ) tcphdr ) + sizeof ( *tcphdr ) ),
886
+		      ( hlen - sizeof ( *tcphdr ) ), &options );
823 887
 	iob_pull ( iobuf, hlen );
824 888
 	len = iob_len ( iobuf );
825 889
 
@@ -849,7 +913,7 @@ static int tcp_rx ( struct io_buffer *iobuf,
849 913
 
850 914
 	/* Handle SYN, if present */
851 915
 	if ( flags & TCP_SYN ) {
852
-		tcp_rx_syn ( tcp, seq );
916
+		tcp_rx_syn ( tcp, seq, &options );
853 917
 		seq++;
854 918
 	}
855 919
 
@@ -869,6 +933,10 @@ static int tcp_rx ( struct io_buffer *iobuf,
869 933
 		seq++;
870 934
 	}
871 935
 
936
+	/* Update timestamp, if present and applicable */
937
+	if ( ( seq == tcp->rcv_ack ) && options.tsopt )
938
+		tcp->ts_recent = ntohl ( options.tsopt->tsval );
939
+
872 940
 	/* Dump out any state change as a result of the received packet */
873 941
 	tcp_dump_state ( tcp );
874 942
 

Loading…
Cancel
Save