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
 	uint16_t urg;		/* Urgent pointer */
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
 struct tcp_mss_option {
47
 struct tcp_mss_option {
34
 	uint8_t kind;
48
 	uint8_t kind;
35
 	uint8_t length;
49
 	uint8_t length;
36
 	uint16_t mss;
50
 	uint16_t mss;
37
-};
51
+} __attribute__ (( packed ));
38
 
52
 
39
 /** Code for the TCP MSS option */
53
 /** Code for the TCP MSS option */
40
 #define TCP_OPTION_MSS 2
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
  * TCP flags
84
  * TCP flags
44
  */
85
  */

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

65
 	 * Equivalent to RCV.NXT in RFC 793 terminology.
65
 	 * Equivalent to RCV.NXT in RFC 793 terminology.
66
 	 */
66
 	 */
67
 	uint32_t rcv_ack;
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
 	/** Transmit queue */
76
 	/** Transmit queue */
70
 	struct list_head queue;
77
 	struct list_head queue;
381
 	struct io_buffer *iobuf;
388
 	struct io_buffer *iobuf;
382
 	struct tcp_header *tcphdr;
389
 	struct tcp_header *tcphdr;
383
 	struct tcp_mss_option *mssopt;
390
 	struct tcp_mss_option *mssopt;
391
+	struct tcp_timestamp_padded_option *tsopt;
384
 	void *payload;
392
 	void *payload;
385
 	unsigned int flags;
393
 	unsigned int flags;
386
 	size_t len = 0;
394
 	size_t len = 0;
449
 		mssopt->length = sizeof ( *mssopt );
457
 		mssopt->length = sizeof ( *mssopt );
450
 		mssopt->mss = htons ( TCP_MSS );
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
 	tcphdr = iob_push ( iobuf, sizeof ( *tcphdr ) );
468
 	tcphdr = iob_push ( iobuf, sizeof ( *tcphdr ) );
453
 	memset ( tcphdr, 0, sizeof ( *tcphdr ) );
469
 	memset ( tcphdr, 0, sizeof ( *tcphdr ) );
454
 	tcphdr->src = tcp->local_port;
470
 	tcphdr->src = tcp->local_port;
594
 	return NULL;
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
  * Handle TCP received SYN
654
  * Handle TCP received SYN
599
  *
655
  *
600
  * @v tcp		TCP connection
656
  * @v tcp		TCP connection
601
  * @v seq		SEQ value (in host-endian order)
657
  * @v seq		SEQ value (in host-endian order)
658
+ * @v options		TCP options
602
  * @ret rc		Return status code
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
 	/* Synchronise sequence numbers on first SYN */
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
 		tcp->rcv_ack = seq;
666
 		tcp->rcv_ack = seq;
667
+		if ( options->tsopt )
668
+			tcp->timestamps = 1;
669
+	}
609
 
670
 
610
 	/* Ignore duplicate SYN */
671
 	/* Ignore duplicate SYN */
611
 	if ( ( tcp->rcv_ack - seq ) > 0 )
672
 	if ( ( tcp->rcv_ack - seq ) > 0 )
776
 		    uint16_t pshdr_csum ) {
837
 		    uint16_t pshdr_csum ) {
777
 	struct tcp_header *tcphdr = iobuf->data;
838
 	struct tcp_header *tcphdr = iobuf->data;
778
 	struct tcp_connection *tcp;
839
 	struct tcp_connection *tcp;
840
+	struct tcp_options options;
779
 	unsigned int hlen;
841
 	unsigned int hlen;
780
 	uint16_t csum;
842
 	uint16_t csum;
781
 	uint32_t start_seq;
843
 	uint32_t start_seq;
820
 	ack = ntohl ( tcphdr->ack );
882
 	ack = ntohl ( tcphdr->ack );
821
 	win = ntohs ( tcphdr->win );
883
 	win = ntohs ( tcphdr->win );
822
 	flags = tcphdr->flags;
884
 	flags = tcphdr->flags;
885
+	tcp_rx_opts ( tcp, ( ( ( void * ) tcphdr ) + sizeof ( *tcphdr ) ),
886
+		      ( hlen - sizeof ( *tcphdr ) ), &options );
823
 	iob_pull ( iobuf, hlen );
887
 	iob_pull ( iobuf, hlen );
824
 	len = iob_len ( iobuf );
888
 	len = iob_len ( iobuf );
825
 
889
 
849
 
913
 
850
 	/* Handle SYN, if present */
914
 	/* Handle SYN, if present */
851
 	if ( flags & TCP_SYN ) {
915
 	if ( flags & TCP_SYN ) {
852
-		tcp_rx_syn ( tcp, seq );
916
+		tcp_rx_syn ( tcp, seq, &options );
853
 		seq++;
917
 		seq++;
854
 	}
918
 	}
855
 
919
 
869
 		seq++;
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
 	/* Dump out any state change as a result of the received packet */
940
 	/* Dump out any state change as a result of the received packet */
873
 	tcp_dump_state ( tcp );
941
 	tcp_dump_state ( tcp );
874
 
942
 

Loading…
Cancel
Save