Skip to content

Commit b457937

Browse files
committed
new tcp design notes
1 parent 210c0e2 commit b457937

File tree

3 files changed

+141
-4
lines changed

3 files changed

+141
-4
lines changed

littletoe/tcp.v

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,64 @@
33

44
////////////////////////////////////////////////////////////////////////////////
55
// Company:
6-
// Engineer: Chris Shucksmith
7-
// Description:
8-
// Pull out TCP payload bytes from packet-orientated TCP/IP frames.
9-
// Follows a single TCP session/stream
6+
// Engineer: Chris Shucksmith
7+
// Description: Read-only TCP/IP decoder stack, 4x socket streams.
8+
//
9+
// Identify and classify TCP payload bytes from packet-orientated TCP/IP frames.
10+
// Follow up to four extenally configured TCP session/streams for sequence correctness
11+
//
12+
// Four sockets can be independantly followed, ABCD, documented here genericaly as N.
13+
//
14+
// If TCP packet with SYN flag set is seen matching the src/dest ip/port an initial sequence
15+
// number is loaded. TCP Payload bytes in-sequence from this are emitted guarded by
16+
// outDataMatchN flag. Out of sequence packets are emitted with the lower guard tcp_matchN
17+
// set, which indicates payload for the right TCP socket, but not in sequenece. A yet-lower
18+
// priority flag, outDataPayload indicates payload bytes belong *some* unclassified TCP session.
19+
//
20+
// Eg. For in-sequence payload bytes of TCPA, outDataMatchA and outDataPayload
21+
// are all asserted for every byte in the payload, while tcp_matchA is asserted from the
22+
// bytes that identidy the stream until the next stream is selected. Guard it by outDataPayload
23+
// if that is required.
24+
//
25+
// If the tcpN_{src/dest}_{port/ip} registers are modified to follow an established session
26+
// it is likely a SYN will not be seen. If the next packet should be used to seed the sequence
27+
// number, assert tcpN_resync for one cycle. This will be latched internally until such a
28+
// matching packet arrives. If the context of the packet should be used to determine if the
29+
// join is appropriate, based on the context within some higher level protocol, drive
30+
// tcp_rejoin within the payload to indicate the rejoin is permitted. Otherwise drive rejoin
31+
// with 1 to join at any packet boundary, or zero to join only at SYN packets.
32+
//
33+
// TCP sequence number is a modulo 32-bit counter increasing from the 'initial sequence number'
34+
// seeded from a random value. For a packet of payload length L and sequence number S, the next
35+
// packet will contain sequence number S+L.
36+
//
37+
// As mentioned previously, for packets in-sequence, outDataMatchN is asserted.
38+
// if the sequence number is below that expected, 'tcp_retran' is asserted, and the
39+
// stream sequence number unchanged. If the sequence number is above that expected,
40+
// 'tcp_gap' is asserted.
41+
//
42+
// TCP retransmission can be benign: packets with 'tcp_retran' can be ignored in the
43+
// hope that the retransmission will conclude with the expected packet. Such a scenario can
44+
// be caused by a lost-ACK on the reutrn path. A gap however requires active handling. If the
45+
// active host also experiances the gap and causes retransmission in the usual way (ack'ing a prev
46+
// sequence number) it is possible the sequence will be resumed autonoumously by that host's actions.
47+
// In an imperfect local network however it should be considered that the packet could be lost before
48+
// this decoder yet reached the active host. In this case, the gap will never be filled, ie. outDataMatchN
49+
// never resserted.
50+
//
51+
// Knowledge of the upper-level payload protocol is required to rejoin the stream at a
52+
// safe point, or to trigger the active host to reconnect, causing a SYN and reset of the sequence
53+
// number. By setting tcp_rejoin at a safe-point the logic is asserting to the stack that payload was
54+
// rejoined and that packets after that should be considered in sequence.
55+
//
56+
// There is a third classification for packets arriveing more than 1M bytes behind or 1M ahead of the
57+
// expected stream position, 'tcp_sequnknown' which is often found when looping a packet capture and
58+
// may require careful handling. It is not clear when this is asserted, if a retransmission or gap has
59+
// occured. Most likely ignoring the packet is the correct action to take, reusming from the next
60+
// safe-point.
61+
//
62+
//
63+
//
1064
//
1165
////////////////////////////////////////////////////////////////////////////////
1266

@@ -21,6 +75,8 @@ module Tcp
2175
input dataValid,
2276
input [7:0] data,
2377

78+
input rejoin, // assert during a payload, whilst tcp_matchN is asserted but not outDataMatchN to rejoin stream
79+
2480
// per session
2581
input [15:0] tcpA_src_port, tcpB_src_port, tcpC_src_port, tcpD_src_port,
2682
input [31:0] tcpA_src_ip, tcpB_src_ip, tcpC_src_ip, tcpD_src_ip,

littletoe/tcp_test.v

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ module Tcp_test;
5050
.tcpB_src_ip( { 8'd0, 8'd0, 8'd0, 8'd0 } ),
5151
.tcpB_dst_port(16'd0),
5252
.tcpB_dst_ip( { 8'd0, 8'd0, 8'd0, 8'd0 } ),
53+
.tcpC_src_port(16'd0),
54+
.tcpC_src_ip( { 8'd0, 8'd0, 8'd0, 8'd0 } ),
55+
.tcpC_dst_port(16'd0),
56+
.tcpC_dst_ip( { 8'd0, 8'd0, 8'd0, 8'd0 } ),
57+
.tcpD_src_port(16'd0),
58+
.tcpD_src_ip( { 8'd0, 8'd0, 8'd0, 8'd0 } ),
59+
.tcpD_dst_port(16'd0),
60+
.tcpD_dst_ip( { 8'd0, 8'd0, 8'd0, 8'd0 } ),
5361
.dataValid( streamvalid ),
5462
.data( stream ),
5563
.newpkt( newpkt ),
@@ -72,6 +80,14 @@ module Tcp_test;
7280
.tcpB_src_ip( { 8'd10, 8'd210, 8'd50, 8'd28 } ),
7381
.tcpB_dst_port(16'd4846),
7482
.tcpB_dst_ip( { 8'd10, 8'd210, 8'd144, 8'd11 } ),
83+
.tcpC_src_port(16'd0),
84+
.tcpC_src_ip( { 8'd0, 8'd0, 8'd0, 8'd0 } ),
85+
.tcpC_dst_port(16'd0),
86+
.tcpC_dst_ip( { 8'd0, 8'd0, 8'd0, 8'd0 } ),
87+
.tcpD_src_port(16'd0),
88+
.tcpD_src_ip( { 8'd0, 8'd0, 8'd0, 8'd0 } ),
89+
.tcpD_dst_port(16'd0),
90+
.tcpD_dst_ip( { 8'd0, 8'd0, 8'd0, 8'd0 } ),
7591
.dataValid( streamvalid ),
7692
.data( stream ),
7793
.newpkt( newpkt ),

littletoe/timing.wavedrom.html

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
2+
<!DOCTYPE HTML>
3+
<html>
4+
<head>
5+
<script src="http://wavedrom.googlecode.com/svn/trunk/skins/default.js" type="text/javascript"></script>
6+
<script src="http://wavedrom.googlecode.com/svn/trunk/WaveDrom.js" type="text/javascript"></script>
7+
<style type="text/css">
8+
<!--
9+
body {font-family: Arial, Helvetica, sans-serif}
10+
-->
11+
</style>
12+
</head>
13+
<body>
14+
Timing Diagram
15+
16+
<script type="WaveDrom">
17+
{ "signal" : [
18+
{ "name": "clk", "wave": "p..........|...........|.." },
19+
["config bus" ,
20+
{ "name": "tcpA_resync", "wave": "010........|...........|..", "data": ["src IP"] },
21+
{ "name": "tcpA_src_ip (32)", "wave": "x4.........|...........|..", "data": ["src IP"] },
22+
{ "name": "tcpA_dst_ip (32)", "wave": "x4.........|...........|..", "data": ["dst IP"] },
23+
{ "name": "tcpA_src_port (16)", "wave": "x5.........|...........|..", "data": ["src Port"] },
24+
{ "name": "tcpA_dst_port (16)", "wave": "x5.........|...........|..", "data": ["dst Port"] },
25+
],
26+
{},
27+
[ "ethernet-in",
28+
{ "name": "data (8)", "wave": "x.3.4.5.=..|x.3.4.5.=..|x.",
29+
"data": ["Eth", "IP", "TCP", "Payload", "Eth", "IP", "TCP", "Payload"] },
30+
{ "name": "dataValid", "wave": "0.1........|0.1........|0." },
31+
],
32+
{},
33+
[ "ethernet-out",
34+
{ "name": "outData (8)", "wave": "x..3.4.5.=..|x.3.4.5.=..|x",
35+
"data": ["Eth", "IP", "TCP", "Payload", "Eth", "IP", "TCP", "Payload"] },
36+
{ "name": "outDataValid", "wave": "0..1........|0.1........|0" },
37+
{ "name": "outDataPayload", "wave": "0........1..|0.......1..|0" },
38+
39+
{ "name": "tcp_src_ip (32)", "wave": "x....4......|x...4......|x", "data": ["src IP"] },
40+
{ "name": "tcp_dst_ip (32)", "wave": "x.....4.....|x....4.....|x", "data": ["dst IP"] },
41+
{ "name": "tcp_src_port (16)", "wave": "x......5....|x.....5....|x", "data": ["src Port"] },
42+
{ "name": "tcp_dst_port (16)", "wave": "x.......5...|x......5...|x", "data": ["dst Port"] },
43+
],
44+
{},
45+
[ "socket",
46+
{ "name": "tcp_matchA", "wave": "0.......1...|x......1...|x" },
47+
{ "name": "outDataMatchA", "wave": "0........1..|0..........|." },
48+
{ "name": "tcp_retran", "wave": "0...........|...........|." },
49+
{ "name": "tcp_gap", "wave": "0...........|.......1...|0" },
50+
{ "name": "tcp_sequnknown", "wave": "0...........|...........|." },
51+
],
52+
{},
53+
[ "rejoin",
54+
{ "name": "rejoin", "wave": "0...........|........10.|0" },
55+
],
56+
{},
57+
58+
],
59+
"config" : { "hscale" : 1.0 }
60+
}
61+
</script>
62+
63+
64+
</body>
65+
</html>

0 commit comments

Comments
 (0)