From bffcec436c2450faab70947943156027b8c98c2c Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 22 Mar 2014 12:04:26 +0800 Subject: [PATCH] Tools/NetTest - Add TCP Window test (not passing) --- Tools/NetTest/cmdline_backend.c | 15 +++++- Tools/NetTest/tcpserver.c | 2 +- Tools/NetTest_Runner/include/tcp.h | 4 +- Tools/NetTest_Runner/include/tests.h | 1 + Tools/NetTest_Runner/main.c | 1 + Tools/NetTest_Runner/tcp.c | 6 +-- Tools/NetTest_Runner/test_tcp.c | 74 +++++++++++++++++++++++++--- 7 files changed, 88 insertions(+), 15 deletions(-) diff --git a/Tools/NetTest/cmdline_backend.c b/Tools/NetTest/cmdline_backend.c index ea6fa63e..5e106729 100644 --- a/Tools/NetTest/cmdline_backend.c +++ b/Tools/NetTest/cmdline_backend.c @@ -1,6 +1,11 @@ /* + * Acess2 Network Tester + * - By John Hodge (thePowersGang) + * + * cmdline_backend.c + * - Backend Thread for 'cmdline' suite */ -#define DEBUG 1 +#define DEBUG 0 #include "cmdline.h" #include "tcpserver.h" #include @@ -43,6 +48,14 @@ void Cmdline_Backend_Thread(void *unused) int rv = VFS_Select(max+1, &rfd, &wfd, &efd, NULL, THREAD_EVENT_USER1, false); LOG("rv = %i", rv); + if( rv < 0 ) { + // Oh, shite + } + + // Woken with no file changes, skip checking + if( rv == 0 ) + continue ; + if(gpCmdline_TCPEchoServer) NetTest_TCPServer_HandleSelect(gpCmdline_TCPEchoServer, &rfd, &wfd, &efd); } diff --git a/Tools/NetTest/tcpserver.c b/Tools/NetTest/tcpserver.c index e5ebdc9b..5e4aa727 100644 --- a/Tools/NetTest/tcpserver.c +++ b/Tools/NetTest/tcpserver.c @@ -86,7 +86,7 @@ void NetTest_TCPServer_HandleSelect(tNetTest_TCPServer *Srv, const fd_set *rfds, if( FD_ISSET(client->FD, rfds) ) { // RX'd data on client - // TODO: Do something other than echo back + // TODO: Cache until '.' is seen, and send all data before+incl that character char buf[1024]; size_t len = VFS_Read(client->FD, sizeof(buf), buf); Debug_HexDump("TCP Srv Rx", buf, len); diff --git a/Tools/NetTest_Runner/include/tcp.h b/Tools/NetTest_Runner/include/tcp.h index eb7edf55..aff8917b 100644 --- a/Tools/NetTest_Runner/include/tcp.h +++ b/Tools/NetTest_Runner/include/tcp.h @@ -30,13 +30,13 @@ typedef struct { extern void TCP_SendC(const tTCPConn *Conn, uint8_t flags, size_t data_len, const void *data); -extern void TCP_Send(int IF, int AF, const void *IP, short sport, short dport, uint32_t seq, uint32_t ack, uint8_t flags, uint16_t window, size_t data_len, const void *data); +extern void TCP_Send(int IF, int AF, const void *IP, uint16_t sport, uint16_t dport, uint32_t seq, uint32_t ack, uint8_t flags, uint16_t window, size_t data_len, const void *data); // The following skip the next check of each field extern void TCP_SkipCheck_Seq(bool Skip); extern bool TCP_Pkt_CheckC(size_t len, const void *data, size_t *ofs, size_t *out_len, const tTCPConn *Conn, uint8_t flags); -extern bool TCP_Pkt_Check(size_t len, const void *data, size_t *ofs, size_t *out_len, int AF, const void *IP, short sport, short dport, uint32_t seq, uint32_t ack, uint8_t flags); +extern bool TCP_Pkt_Check(size_t len, const void *data, size_t *ofs, size_t *out_len, int AF, const void *IP, uint16_t sport, uint16_t dport, uint32_t seq, uint32_t ack, uint8_t flags); // - Get a field from a previously validated packet extern uint32_t TCP_Pkt_GetSeq(size_t len, const void *data, int AF); diff --git a/Tools/NetTest_Runner/include/tests.h b/Tools/NetTest_Runner/include/tests.h index bb167228..a96f3881 100644 --- a/Tools/NetTest_Runner/include/tests.h +++ b/Tools/NetTest_Runner/include/tests.h @@ -10,6 +10,7 @@ extern bool Test_ARP_Basic(void); extern bool Test_TCP_Basic(void); +extern bool Test_TCP_WindowSizes(void); #endif diff --git a/Tools/NetTest_Runner/main.c b/Tools/NetTest_Runner/main.c index 0c2b6c06..b1d95c13 100644 --- a/Tools/NetTest_Runner/main.c +++ b/Tools/NetTest_Runner/main.c @@ -26,6 +26,7 @@ int main(int argc, char *argv[]) t_test *tests[] = { Test_ARP_Basic, Test_TCP_Basic, + Test_TCP_WindowSizes, NULL }; diff --git a/Tools/NetTest_Runner/tcp.c b/Tools/NetTest_Runner/tcp.c index d5c76372..db2519d5 100644 --- a/Tools/NetTest_Runner/tcp.c +++ b/Tools/NetTest_Runner/tcp.c @@ -44,7 +44,7 @@ void TCP_SendC(const tTCPConn *Conn, uint8_t flags, size_t data_len, const void TCP_Send(Conn->IFNum, Conn->AF, Conn->RAddr, Conn->LPort, Conn->RPort, Conn->LSeq, Conn->RSeq, flags, Conn->Window, data_len, data); } -void TCP_Send(int IF, int AF, const void *IP, short sport, short dport, +void TCP_Send(int IF, int AF, const void *IP, uint16_t sport, uint16_t dport, uint32_t seq, uint32_t ack, uint8_t flags, uint16_t window, size_t data_len, const void *data ) @@ -91,7 +91,7 @@ bool TCP_Pkt_CheckC(size_t len, const void *data, size_t *out_ofs, size_t *len_o } bool TCP_Pkt_Check(size_t len, const void *data, size_t *out_ofs, size_t *len_out, - int AF, const void *IP, short sport, short dport, + int AF, const void *IP, uint16_t sport, uint16_t dport, uint32_t seq, uint32_t ack, uint8_t flags) { size_t ofs, rlen; @@ -105,9 +105,9 @@ bool TCP_Pkt_Check(size_t len, const void *data, size_t *out_ofs, size_t *len_ou TEST_ASSERT_REL( hdr.DataOfs >> 4, >=, sizeof(hdr)/4 ); if( !gTCP_Skips.SPort ) TEST_ASSERT_REL( ntohs(hdr.SPort), ==, sport ); TEST_ASSERT_REL( ntohs(hdr.DPort), ==, dport ); + TEST_ASSERT_REL( hdr.Flags, ==, flags); if( !gTCP_Skips.Seq ) TEST_ASSERT_REL( ntohl(hdr.Seq), ==, seq ); if( flags & TCP_ACK ) TEST_ASSERT_REL( ntohl(hdr.Ack), ==, ack ); - TEST_ASSERT_REL( hdr.Flags, ==, flags); uint16_t real_cksum = htons(hdr.Checksum); hdr.Checksum = 0; diff --git a/Tools/NetTest_Runner/test_tcp.c b/Tools/NetTest_Runner/test_tcp.c index 9c4e2e4d..36942a5a 100644 --- a/Tools/NetTest_Runner/test_tcp.c +++ b/Tools/NetTest_Runner/test_tcp.c @@ -15,18 +15,18 @@ #define TEST_ASSERT_rx() TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, ERX_TIMEOUT) ) #define TEST_ASSERT_no_rx() TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, NRX_TIMEOUT) == 0 ) +const int ERX_TIMEOUT = 1000; // Expect RX timeout (timeout=failure) +const int NRX_TIMEOUT = 250; // Not expect RX timeout (timeout=success) +const int RETX_TIMEOUT = 1000; // OS PARAM - Retransmit timeout +const int LOST_TIMEOUT = 1000; // OS PARAM - Time before sending an ACK +const int DACK_TIMEOUT = 500; // OS PARAM - Timeout for delayed ACKs +const size_t DACK_BYTES = 4096; // OS PARAM - Threshold for delayed ACKs bool Test_TCP_Basic(void) { TEST_SETNAME(__func__); size_t rxlen, ofs, len; char rxbuf[MTU]; - const int ERX_TIMEOUT = 1000; // Expect RX timeout (timeout=failure) - const int NRX_TIMEOUT = 250; // Not expect RX timeout (timeout=success) - const int RETX_TIMEOUT = 1000; // OS PARAM - Retransmit timeout - const int LOST_TIMEOUT = 1000; // OS PARAM - Time before sending an ACK - const int DACK_TIMEOUT = 500; // OS PARAM - Timeout for delayed ACKs - const size_t DACK_BYTES = 4096; // OS PARAM - Threshold for delayed ACKs tTCPConn testconn = { .IFNum = 0, .AF = 4, @@ -39,9 +39,11 @@ bool Test_TCP_Basic(void) .RSeq = 0, }; - const char testblob[] = "HelloWorld, this is some random testing data for TCP\xFF\x00\x66\x12\x12"; + const char testblob[] = "HelloWorld, this is some random testing data for TCP\xFF\x00\x66\x12\x12."; const size_t testblob_len = sizeof(testblob); - + + // TODO: Check checksum failures + // 1. Test packets to closed port // > RFC793 Pg.65 @@ -206,8 +208,64 @@ bool Test_TCP_Basic(void) bool Test_TCP_SYN_RECEIVED(void) { + TEST_SETNAME(__func__); // 1. Get into SYN-RECEIVED // 2. Send various non-ACK packets return false; } + +bool Test_TCP_WindowSizes(void) +{ + TEST_SETNAME(__func__); + size_t rxlen, ofs, len; + char rxbuf[MTU]; + tTCPConn testconn = { + .IFNum = 0, + .AF = 4, + .LAddr = BLOB(HOST_IP), + .RAddr = BLOB(TEST_IP), + .LPort = 44359, + .RPort = 9, + .LSeq = 0x600, + .RSeq = 0x600, + .Window = 128 + }; + char testdata[152]; + memset(testdata, 0xAB, sizeof(testdata)); + + Stack_SendCommand("tcp_echo_server %i", testconn.RPort); + // > Open Connection + TCP_SendC(&testconn, TCP_SYN, 0, NULL); + testconn.LSeq ++; + TEST_ASSERT_rx(); + TCP_SkipCheck_Seq(true); + TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_SYN|TCP_ACK) ); + TEST_ASSERT_REL(len, ==, 0); + testconn.RSeq = TCP_Pkt_GetSeq(rxlen, rxbuf, testconn.AF) + 1; + TCP_SendC(&testconn, TCP_ACK, 0, NULL); + TEST_ASSERT_no_rx(); + + // 1. Test remote respecting our transmission window (>=1 byte) + // > Send more data than our RX window + TCP_SendC(&testconn, TCP_PSH, sizeof(testdata), testdata); + testconn.LSeq += sizeof(testdata); + // Expect our RX window back + TEST_ASSERT_rx(); + TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_ACK|TCP_PSH) ); + TEST_ASSERT_REL(len, ==, testconn.Window); + testconn.RSeq += len; + // > Send ACK and reduce window to 1 byte + testconn.Window = 1; + TCP_SendC(&testconn, TCP_ACK, 0, NULL); + testconn.LSeq += sizeof(testdata); + // > Expect 1 byte back + TEST_ASSERT_rx(); + TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_ACK|TCP_PSH) ); + TEST_ASSERT_REL(len, ==, 1); + testconn.RSeq += len; + // 2. Test remote handling our window being 0 (should only send ACKs) + // 3. Test that remote drops data outside of its RX window + // 3.1. Ensure that data that wraps the end of the RX window is handled correctly + return false; +} -- 2.20.1