From e6b7fab5aac546bcd2be3c37ea14a3ab46cf92d5 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 16 Mar 2014 23:10:09 +0800 Subject: [PATCH] Tools/NetTest - TCP test passing with connection opened/used/closed --- Tools/NetTest/cmdline_backend.c | 5 +-- Tools/NetTest/tcpserver.c | 18 ++++++++-- Tools/NetTest_Runner/include/ip.h | 2 +- Tools/NetTest_Runner/include/tcp.h | 2 +- Tools/NetTest_Runner/ip.c | 6 ++-- Tools/NetTest_Runner/tcp.c | 17 ++++----- Tools/NetTest_Runner/test_tcp.c | 56 ++++++++++++++++++++++++++---- 7 files changed, 84 insertions(+), 22 deletions(-) diff --git a/Tools/NetTest/cmdline_backend.c b/Tools/NetTest/cmdline_backend.c index f95895aa..ea6fa63e 100644 --- a/Tools/NetTest/cmdline_backend.c +++ b/Tools/NetTest/cmdline_backend.c @@ -30,16 +30,17 @@ void Cmdline_Backend_Thread(void *unused) int max = -1; FD_ZERO(&rfd); + FD_ZERO(&wfd); LOG("gpCmdline_TCPEchoServer = %p", gpCmdline_TCPEchoServer); if(gpCmdline_TCPEchoServer) max = MAX(max, NetTest_TCPServer_FillSelect(gpCmdline_TCPEchoServer, &rfd)); - memcpy(&wfd, &rfd, sizeof(rfd)); + //memcpy(&wfd, &rfd, sizeof(rfd)); memcpy(&efd, &rfd, sizeof(rfd)); LOG("max = %i", max); - int rv = VFS_Select(max+1, &rfd, &wfd, &efd, NULL, THREAD_EVENT_USER1, true); + int rv = VFS_Select(max+1, &rfd, &wfd, &efd, NULL, THREAD_EVENT_USER1, false); LOG("rv = %i", rv); if(gpCmdline_TCPEchoServer) diff --git a/Tools/NetTest/tcpserver.c b/Tools/NetTest/tcpserver.c index d38b442f..e5ebdc9b 100644 --- a/Tools/NetTest/tcpserver.c +++ b/Tools/NetTest/tcpserver.c @@ -5,6 +5,7 @@ * tcpserver.c * - TCP Client tester */ +#define DEBUG 1 #include #include #include @@ -45,10 +46,9 @@ void NetTest_TCPServer_Close(tNetTest_TCPServer *Srv) int NetTest_TCPServer_FillSelect(tNetTest_TCPServer *Srv, fd_set *fds) { - ASSERT(Srv->ServerFD >= 0); int max = -1; - if( Srv->nClients == MAX_CLIENTS ) { + if( Srv->nClients < MAX_CLIENTS ) { max = Srv->ServerFD; FD_SET(Srv->ServerFD, fds); } @@ -63,12 +63,21 @@ int NetTest_TCPServer_FillSelect(tNetTest_TCPServer *Srv, fd_set *fds) void NetTest_TCPServer_HandleSelect(tNetTest_TCPServer *Srv, const fd_set *rfds, const fd_set *wfds, const fd_set *efds) { + LOG("Srv=%p", Srv); if( FD_ISSET(Srv->ServerFD, rfds) ) { // New connection! ASSERT(Srv->nClients != MAX_CLIENTS); struct sClient *client = &Srv->Clients[Srv->nClients++]; + LOG("Child?"); client->FD = VFS_OpenChild(Srv->ServerFD, "", VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE); + LOG("client->FD = %i", client->FD); + } + if( FD_ISSET(Srv->ServerFD, efds) ) + { + LOG("Oops, error on server"); + VFS_Close(Srv->ServerFD); + Srv->ServerFD = -1; } for( int i = 0; i < Srv->nClients; i ++ ) @@ -77,6 +86,11 @@ 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 + char buf[1024]; + size_t len = VFS_Read(client->FD, sizeof(buf), buf); + Debug_HexDump("TCP Srv Rx", buf, len); + VFS_Write(client->FD, len, buf); } if( FD_ISSET(client->FD, efds) ) diff --git a/Tools/NetTest_Runner/include/ip.h b/Tools/NetTest_Runner/include/ip.h index 6f0eb152..b04169a2 100644 --- a/Tools/NetTest_Runner/include/ip.h +++ b/Tools/NetTest_Runner/include/ip.h @@ -18,7 +18,7 @@ extern uint16_t IP_Checksum(uint16_t Prev, size_t Length, const void *Data); extern void IP_Send(int IfNum, int AF, const void *Src, const void *Dst, uint8_t proto, int BufCount, size_t BufLens[], const void *Bufs[]); -extern bool IP_Pkt_Check(size_t len, const void *data, size_t *ofs, int AF, const void *Src, const void *Dst, uint8_t proto); +extern bool IP_Pkt_Check(size_t len, const void *data, size_t *out_ofs, size_t *out_len, int AF, const void *Src, const void *Dst, uint8_t proto); #endif diff --git a/Tools/NetTest_Runner/include/tcp.h b/Tools/NetTest_Runner/include/tcp.h index effc3adb..9446b3c9 100644 --- a/Tools/NetTest_Runner/include/tcp.h +++ b/Tools/NetTest_Runner/include/tcp.h @@ -22,7 +22,7 @@ extern void TCP_Send(int IF, int AF, const void *IP, short sport, short dport, u // The following skip the next check of each field extern void TCP_SkipCheck_Seq(bool Skip); -extern bool TCP_Pkt_Check(size_t len, const void *data, size_t *ofs, 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, short sport, short 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/ip.c b/Tools/NetTest_Runner/ip.c index eb53f7ed..13de5bc7 100644 --- a/Tools/NetTest_Runner/ip.c +++ b/Tools/NetTest_Runner/ip.c @@ -92,7 +92,7 @@ void IP_Send(int IfNum, int AF, const void *Src, const void *Dst, uint8_t proto, } } -bool IP_Pkt_Check(size_t len, const void *data, size_t *ofs_out, int AF, const void *Src, const void *Dst, uint8_t proto) +bool IP_Pkt_Check(size_t len, const void *data, size_t *ofs_out, size_t *len_out, int AF, const void *Src, const void *Dst, uint8_t proto) { size_t ofs; if( AF == 4 ) { @@ -105,6 +105,7 @@ bool IP_Pkt_Check(size_t len, const void *data, size_t *ofs_out, int AF, const v TEST_ASSERT_REL(IP_Checksum(IP_CHECKSUM_START, sizeof(hdr), &hdr), ==, 0); TEST_ASSERT_REL(ntohs(hdr.TotalLength), <=, len - ofs); + TEST_ASSERT_REL(ntohs(hdr.TotalLength), >, (hdr.VerLen & 0xF) * 4); TEST_ASSERT_REL(ntohs(hdr.FragmentInfo), ==, 0); TEST_ASSERT_REL(hdr.TTL, >, 1); // >1 because there's no intervening hops @@ -112,7 +113,8 @@ bool IP_Pkt_Check(size_t len, const void *data, size_t *ofs_out, int AF, const v if(Src) TEST_ASSERT( memcmp(hdr.SrcAddr, Src, 4) == 0 ); if(Dst) TEST_ASSERT( memcmp(hdr.DstAddr, Dst, 4) == 0 ); - + + *len_out = ntohs(hdr.TotalLength) - sizeof(hdr); *ofs_out = ofs + (hdr.VerLen & 0xF) * 4; return true; } diff --git a/Tools/NetTest_Runner/tcp.c b/Tools/NetTest_Runner/tcp.c index 22a21a16..2bdc3af1 100644 --- a/Tools/NetTest_Runner/tcp.c +++ b/Tools/NetTest_Runner/tcp.c @@ -76,17 +76,17 @@ void TCP_SkipCheck_Seq(bool Skip) { gTCP_Skips.Seq = Skip; } -bool TCP_Pkt_Check(size_t len, const void *data, size_t *out_ofs, +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, uint32_t seq, uint32_t ack, uint8_t flags) { - size_t ofs; - if( !IP_Pkt_Check(len, data, &ofs, AF, IP, BLOB(HOST_IP), IPPROTO_TCP) ) + size_t ofs, rlen; + if( !IP_Pkt_Check(len, data, &ofs, &rlen, AF, IP, BLOB(HOST_IP), IPPROTO_TCP) ) return false; // TODO: IP has its own length field, use that? tTCPHeader hdr; - TEST_ASSERT_REL(len - ofs, >=, sizeof(hdr)); + TEST_ASSERT_REL(rlen, >=, sizeof(hdr)); memcpy(&hdr, (char*)data + ofs, sizeof(hdr)); TEST_ASSERT_REL( hdr.DataOfs >> 4, >=, sizeof(hdr)/4 ); @@ -99,20 +99,21 @@ bool TCP_Pkt_Check(size_t len, const void *data, size_t *out_ofs, uint16_t real_cksum = htons(hdr.Checksum); hdr.Checksum = 0; uint16_t calc_cksum; - calc_cksum = TCP_int_GetPseudoHeader(AF, IP, BLOB(HOST_IP), IPPROTO_TCP, len-ofs); + calc_cksum = TCP_int_GetPseudoHeader(AF, IP, BLOB(HOST_IP), IPPROTO_TCP, rlen); calc_cksum = IP_Checksum(calc_cksum, sizeof(hdr), &hdr); - calc_cksum = IP_Checksum(calc_cksum, len - ofs - sizeof(hdr), (char*)data+ofs+sizeof(hdr)); + calc_cksum = IP_Checksum(calc_cksum, rlen - sizeof(hdr), (char*)data+ofs+sizeof(hdr)); TEST_ASSERT_REL( real_cksum, ==, calc_cksum ); memset(&gTCP_Skips, 0, sizeof(gTCP_Skips)); *out_ofs = ofs + sizeof(hdr); + *len_out = rlen - sizeof(hdr); return true; } uint32_t TCP_Pkt_GetSeq(size_t len, const void *data, int AF) { - size_t ofs; - IP_Pkt_Check(len, data, &ofs, AF, NULL, NULL, IPPROTO_TCP); + size_t ofs, rlen; + IP_Pkt_Check(len, data, &ofs, &rlen, AF, NULL, NULL, IPPROTO_TCP); tTCPHeader hdr; memcpy(&hdr, (char*)data + ofs, sizeof(hdr)); diff --git a/Tools/NetTest_Runner/test_tcp.c b/Tools/NetTest_Runner/test_tcp.c index 1d7e8280..e57398f5 100644 --- a/Tools/NetTest_Runner/test_tcp.c +++ b/Tools/NetTest_Runner/test_tcp.c @@ -11,6 +11,7 @@ #include "stack.h" #include "arp.h" #include "tcp.h" +#include #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 ) @@ -18,7 +19,7 @@ bool Test_TCP_Basic(void) { TEST_SETNAME(__func__); - size_t rxlen, ofs; + 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) @@ -36,7 +37,7 @@ bool Test_TCP_Basic(void) TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_SYN, 0x1000, testblob_len, testblob); // Expect a TCP_RST|TCP_ACK with SEQ=0,ACK=SEQ+LEN TEST_ASSERT_rx(); - TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), 80, 1234, + TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, &len, 4, BLOB(TEST_IP), 80, 1234, 0, seq_tx+testblob_len, TCP_RST|TCP_ACK) ); TEST_ASSERT_REL(ofs, ==, rxlen); @@ -44,7 +45,7 @@ bool Test_TCP_Basic(void) TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_SYN|TCP_ACK, 0x1000, 0, NULL); // Expect a TCP_RST with SEQ=ACK TEST_ASSERT_rx(); - TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), 80, 1234, seq_exp, seq_tx+0, TCP_RST) ); + TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, &len, 4, BLOB(TEST_IP), 80, 1234, seq_exp, seq_tx+0, TCP_RST) ); TEST_ASSERT_REL(ofs, ==, rxlen); // 1.3. Send a RST packet @@ -59,7 +60,7 @@ bool Test_TCP_Basic(void) // 2. Establishing connection with a server - const int server_port = 1024; + const int server_port = 7; const int local_port = 11234; Stack_SendCommand("tcp_echo_server %i", server_port); @@ -73,7 +74,7 @@ bool Test_TCP_Basic(void) TCP_Send(0, 4, BLOB(TEST_IP), local_port, server_port, seq_tx, seq_exp, TCP_ACK, our_window, 0, NULL); // - Expect RST TEST_ASSERT_rx(); - TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), + TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, &len, 4, BLOB(TEST_IP), server_port, local_port, seq_exp, seq_tx+0, TCP_RST) ); // 2.3. Begin hanshake (SYN) @@ -82,7 +83,7 @@ bool Test_TCP_Basic(void) // - Expect SYN,ACK with ACK == SEQ+1 TEST_ASSERT_rx(); TCP_SkipCheck_Seq(true); - TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), + TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, &len, 4, BLOB(TEST_IP), server_port, local_port, 0, seq_tx+1, TCP_SYN|TCP_ACK) ); seq_exp = TCP_Pkt_GetSeq(rxlen, rxbuf, 4); @@ -99,6 +100,49 @@ bool Test_TCP_Basic(void) // >>> STATE: ESTABLISHED // 2.5. Send data + TCP_Send(0,4,BLOB(TEST_IP), local_port, server_port, seq_tx, seq_exp, + TCP_ACK|TCP_PSH, our_window, testblob_len, testblob); + seq_tx += testblob_len; + // Expect burst delayed ACK + TEST_ASSERT_rx(); + TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, &len, 4, BLOB(TEST_IP), + server_port, local_port, seq_exp, seq_tx, TCP_ACK) ); + TEST_ASSERT_REL( len, ==, 0 ); + + // Expect echoed reponse with ACK + TEST_ASSERT_rx(); + TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, &len, 4, BLOB(TEST_IP), + server_port, local_port, seq_exp, seq_tx, TCP_ACK|TCP_PSH) ); + TEST_ASSERT_REL( len, ==, testblob_len ); + TEST_ASSERT( memcmp(rxbuf + ofs, testblob, testblob_len) == 0 ); + seq_exp += testblob_len; + + // 2.6. Close connection (TCP FIN) + TCP_Send(0,4,BLOB(TEST_IP), local_port, server_port, seq_tx, seq_exp, + TCP_ACK|TCP_FIN, our_window, 0, NULL); + seq_tx ++; // Empty = 1 byte + // Expect ACK? (Does acess do delayed ACKs here?) + TEST_ASSERT_rx(); + TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, &len, 4, BLOB(TEST_IP), + server_port, local_port, seq_exp, seq_tx, TCP_ACK) ); + TEST_ASSERT_REL( len, ==, 0 ); + // >>> STATE: CLOSE WAIT + + // Expect FIN + TEST_ASSERT_rx(); + TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, &len, 4, BLOB(TEST_IP), + server_port, local_port, seq_exp, 0, TCP_FIN) ); + TEST_ASSERT_REL( len, ==, 0 ); + + // >>> STATE: LAST-ACK + + // 2.7 Send ACK of FIN + TCP_Send(0,4,BLOB(TEST_IP), local_port, server_port, seq_tx, seq_exp, + TCP_ACK, our_window, 0, NULL); + // Expect no response + TEST_ASSERT_no_rx(); + + // >>> STATE: CLOSED return true; } -- 2.20.1