Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
test_tcp.c
00001 #include "test_tcp.h" 00002 00003 #include "lwip/priv/tcp_priv.h" 00004 #include "lwip/stats.h" 00005 #include "tcp_helper.h" 00006 #include "lwip/inet_chksum.h" 00007 00008 #ifdef _MSC_VER 00009 #pragma warning(disable: 4307) /* we explicitly wrap around TCP seqnos */ 00010 #endif 00011 00012 #if !LWIP_STATS || !TCP_STATS || !MEMP_STATS 00013 #error "This tests needs TCP- and MEMP-statistics enabled" 00014 #endif 00015 #if TCP_SND_BUF <= TCP_WND 00016 #error "This tests needs TCP_SND_BUF to be > TCP_WND" 00017 #endif 00018 00019 static u8_t test_tcp_timer; 00020 00021 /* our own version of tcp_tmr so we can reset fast/slow timer state */ 00022 static void 00023 test_tcp_tmr(void) 00024 { 00025 tcp_fasttmr(); 00026 if (++test_tcp_timer & 1) { 00027 tcp_slowtmr(); 00028 } 00029 } 00030 00031 /* Setups/teardown functions */ 00032 00033 static void 00034 tcp_setup(void) 00035 { 00036 /* reset iss to default (6510) */ 00037 tcp_ticks = 0; 00038 tcp_ticks = 0 - (tcp_next_iss(NULL) - 6510); 00039 tcp_next_iss(NULL); 00040 tcp_ticks = 0; 00041 00042 test_tcp_timer = 0; 00043 tcp_remove_all(); 00044 } 00045 00046 static void 00047 tcp_teardown(void) 00048 { 00049 netif_list = NULL; 00050 netif_default = NULL; 00051 tcp_remove_all(); 00052 } 00053 00054 00055 /* Test functions */ 00056 00057 /** Call tcp_new() and tcp_abort() and test memp stats */ 00058 START_TEST(test_tcp_new_abort) 00059 { 00060 struct tcp_pcb* pcb; 00061 LWIP_UNUSED_ARG(_i); 00062 00063 fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); 00064 00065 pcb = tcp_new(); 00066 fail_unless(pcb != NULL); 00067 if (pcb != NULL) { 00068 fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); 00069 tcp_abort(pcb); 00070 fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); 00071 } 00072 } 00073 END_TEST 00074 00075 /** Create an ESTABLISHED pcb and check if receive callback is called */ 00076 START_TEST(test_tcp_recv_inseq) 00077 { 00078 struct test_tcp_counters counters; 00079 struct tcp_pcb* pcb; 00080 struct pbuf* p; 00081 char data[] = {1, 2, 3, 4}; 00082 ip_addr_t remote_ip, local_ip, netmask; 00083 u16_t data_len; 00084 u16_t remote_port = 0x100, local_port = 0x101; 00085 struct netif netif; 00086 struct test_tcp_txcounters txcounters; 00087 LWIP_UNUSED_ARG(_i); 00088 00089 /* initialize local vars */ 00090 memset(&netif, 0, sizeof(netif)); 00091 IP_ADDR4(&local_ip, 192, 168, 1, 1); 00092 IP_ADDR4(&remote_ip, 192, 168, 1, 2); 00093 IP_ADDR4(&netmask, 255, 255, 255, 0); 00094 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); 00095 data_len = sizeof(data); 00096 /* initialize counter struct */ 00097 memset(&counters, 0, sizeof(counters)); 00098 counters.expected_data_len = data_len; 00099 counters.expected_data = data; 00100 00101 /* create and initialize the pcb */ 00102 pcb = test_tcp_new_counters_pcb(&counters); 00103 EXPECT_RET(pcb != NULL); 00104 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); 00105 00106 /* create a segment */ 00107 p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0); 00108 EXPECT(p != NULL); 00109 if (p != NULL) { 00110 /* pass the segment to tcp_input */ 00111 test_tcp_input(p, &netif); 00112 /* check if counters are as expected */ 00113 EXPECT(counters.close_calls == 0); 00114 EXPECT(counters.recv_calls == 1); 00115 EXPECT(counters.recved_bytes == data_len); 00116 EXPECT(counters.err_calls == 0); 00117 } 00118 00119 /* make sure the pcb is freed */ 00120 EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); 00121 tcp_abort(pcb); 00122 EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); 00123 } 00124 END_TEST 00125 00126 /** Check that we handle malformed tcp headers, and discard the pbuf(s) */ 00127 START_TEST(test_tcp_malformed_header) 00128 { 00129 struct test_tcp_counters counters; 00130 struct tcp_pcb* pcb; 00131 struct pbuf* p; 00132 char data[] = {1, 2, 3, 4}; 00133 ip_addr_t remote_ip, local_ip, netmask; 00134 u16_t data_len, chksum; 00135 u16_t remote_port = 0x100, local_port = 0x101; 00136 struct netif netif; 00137 struct test_tcp_txcounters txcounters; 00138 struct tcp_hdr *hdr; 00139 LWIP_UNUSED_ARG(_i); 00140 00141 /* initialize local vars */ 00142 memset(&netif, 0, sizeof(netif)); 00143 IP_ADDR4(&local_ip, 192, 168, 1, 1); 00144 IP_ADDR4(&remote_ip, 192, 168, 1, 2); 00145 IP_ADDR4(&netmask, 255, 255, 255, 0); 00146 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); 00147 data_len = sizeof(data); 00148 /* initialize counter struct */ 00149 memset(&counters, 0, sizeof(counters)); 00150 counters.expected_data_len = data_len; 00151 counters.expected_data = data; 00152 00153 /* create and initialize the pcb */ 00154 pcb = test_tcp_new_counters_pcb(&counters); 00155 EXPECT_RET(pcb != NULL); 00156 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); 00157 00158 /* create a segment */ 00159 p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0); 00160 00161 pbuf_header(p, -(s16_t)sizeof(struct ip_hdr)); 00162 00163 hdr = (struct tcp_hdr *)p->payload; 00164 TCPH_HDRLEN_FLAGS_SET(hdr, 15, 0x3d1); 00165 00166 hdr->chksum = 0; 00167 00168 chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, 00169 &remote_ip, &local_ip); 00170 00171 hdr->chksum = chksum; 00172 00173 pbuf_header(p, sizeof(struct ip_hdr)); 00174 00175 EXPECT(p != NULL); 00176 EXPECT(p->next == NULL); 00177 if (p != NULL) { 00178 /* pass the segment to tcp_input */ 00179 test_tcp_input(p, &netif); 00180 /* check if counters are as expected */ 00181 EXPECT(counters.close_calls == 0); 00182 EXPECT(counters.recv_calls == 0); 00183 EXPECT(counters.recved_bytes == 0); 00184 EXPECT(counters.err_calls == 0); 00185 } 00186 00187 /* make sure the pcb is freed */ 00188 EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); 00189 tcp_abort(pcb); 00190 EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); 00191 } 00192 END_TEST 00193 00194 00195 /** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data. 00196 * At the end, send more data. */ 00197 START_TEST(test_tcp_fast_retx_recover) 00198 { 00199 struct netif netif; 00200 struct test_tcp_txcounters txcounters; 00201 struct test_tcp_counters counters; 00202 struct tcp_pcb* pcb; 00203 struct pbuf* p; 00204 char data1[] = { 1, 2, 3, 4}; 00205 char data2[] = { 5, 6, 7, 8}; 00206 char data3[] = { 9, 10, 11, 12}; 00207 char data4[] = {13, 14, 15, 16}; 00208 char data5[] = {17, 18, 19, 20}; 00209 char data6[TCP_MSS] = {21, 22, 23, 24}; 00210 ip_addr_t remote_ip, local_ip, netmask; 00211 u16_t remote_port = 0x100, local_port = 0x101; 00212 err_t err; 00213 LWIP_UNUSED_ARG(_i); 00214 00215 /* initialize local vars */ 00216 IP_ADDR4(&local_ip, 192, 168, 1, 1); 00217 IP_ADDR4(&remote_ip, 192, 168, 1, 2); 00218 IP_ADDR4(&netmask, 255, 255, 255, 0); 00219 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); 00220 memset(&counters, 0, sizeof(counters)); 00221 00222 /* create and initialize the pcb */ 00223 pcb = test_tcp_new_counters_pcb(&counters); 00224 EXPECT_RET(pcb != NULL); 00225 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); 00226 pcb->mss = TCP_MSS; 00227 /* disable initial congestion window (we don't send a SYN here...) */ 00228 pcb->cwnd = pcb->snd_wnd; 00229 00230 /* send data1 */ 00231 err = tcp_write(pcb, data1, sizeof(data1), TCP_WRITE_FLAG_COPY); 00232 EXPECT_RET(err == ERR_OK); 00233 err = tcp_output(pcb); 00234 EXPECT_RET(err == ERR_OK); 00235 EXPECT_RET(txcounters.num_tx_calls == 1); 00236 EXPECT_RET(txcounters.num_tx_bytes == sizeof(data1) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr)); 00237 memset(&txcounters, 0, sizeof(txcounters)); 00238 /* "recv" ACK for data1 */ 00239 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 4, TCP_ACK); 00240 EXPECT_RET(p != NULL); 00241 test_tcp_input(p, &netif); 00242 EXPECT_RET(txcounters.num_tx_calls == 0); 00243 EXPECT_RET(pcb->unacked == NULL); 00244 /* send data2 */ 00245 err = tcp_write(pcb, data2, sizeof(data2), TCP_WRITE_FLAG_COPY); 00246 EXPECT_RET(err == ERR_OK); 00247 err = tcp_output(pcb); 00248 EXPECT_RET(err == ERR_OK); 00249 EXPECT_RET(txcounters.num_tx_calls == 1); 00250 EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr)); 00251 memset(&txcounters, 0, sizeof(txcounters)); 00252 /* duplicate ACK for data1 (data2 is lost) */ 00253 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); 00254 EXPECT_RET(p != NULL); 00255 test_tcp_input(p, &netif); 00256 EXPECT_RET(txcounters.num_tx_calls == 0); 00257 EXPECT_RET(pcb->dupacks == 1); 00258 /* send data3 */ 00259 err = tcp_write(pcb, data3, sizeof(data3), TCP_WRITE_FLAG_COPY); 00260 EXPECT_RET(err == ERR_OK); 00261 err = tcp_output(pcb); 00262 EXPECT_RET(err == ERR_OK); 00263 /* nagle enabled, no tx calls */ 00264 EXPECT_RET(txcounters.num_tx_calls == 0); 00265 EXPECT_RET(txcounters.num_tx_bytes == 0); 00266 memset(&txcounters, 0, sizeof(txcounters)); 00267 /* 2nd duplicate ACK for data1 (data2 and data3 are lost) */ 00268 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); 00269 EXPECT_RET(p != NULL); 00270 test_tcp_input(p, &netif); 00271 EXPECT_RET(txcounters.num_tx_calls == 0); 00272 EXPECT_RET(pcb->dupacks == 2); 00273 /* queue data4, don't send it (unsent-oversize is != 0) */ 00274 err = tcp_write(pcb, data4, sizeof(data4), TCP_WRITE_FLAG_COPY); 00275 EXPECT_RET(err == ERR_OK); 00276 /* 3nd duplicate ACK for data1 (data2 and data3 are lost) -> fast retransmission */ 00277 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); 00278 EXPECT_RET(p != NULL); 00279 test_tcp_input(p, &netif); 00280 /*EXPECT_RET(txcounters.num_tx_calls == 1);*/ 00281 EXPECT_RET(pcb->dupacks == 3); 00282 memset(&txcounters, 0, sizeof(txcounters)); 00283 /* @todo: check expected data?*/ 00284 00285 /* send data5, not output yet */ 00286 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); 00287 EXPECT_RET(err == ERR_OK); 00288 /*err = tcp_output(pcb); 00289 EXPECT_RET(err == ERR_OK);*/ 00290 EXPECT_RET(txcounters.num_tx_calls == 0); 00291 EXPECT_RET(txcounters.num_tx_bytes == 0); 00292 memset(&txcounters, 0, sizeof(txcounters)); 00293 { 00294 int i = 0; 00295 do 00296 { 00297 err = tcp_write(pcb, data6, TCP_MSS, TCP_WRITE_FLAG_COPY); 00298 i++; 00299 }while(err == ERR_OK); 00300 EXPECT_RET(err != ERR_OK); 00301 } 00302 err = tcp_output(pcb); 00303 EXPECT_RET(err == ERR_OK); 00304 /*EXPECT_RET(txcounters.num_tx_calls == 0); 00305 EXPECT_RET(txcounters.num_tx_bytes == 0);*/ 00306 memset(&txcounters, 0, sizeof(txcounters)); 00307 00308 /* send even more data */ 00309 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); 00310 EXPECT_RET(err == ERR_OK); 00311 err = tcp_output(pcb); 00312 EXPECT_RET(err == ERR_OK); 00313 /* ...and even more data */ 00314 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); 00315 EXPECT_RET(err == ERR_OK); 00316 err = tcp_output(pcb); 00317 EXPECT_RET(err == ERR_OK); 00318 /* ...and even more data */ 00319 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); 00320 EXPECT_RET(err == ERR_OK); 00321 err = tcp_output(pcb); 00322 EXPECT_RET(err == ERR_OK); 00323 /* ...and even more data */ 00324 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); 00325 EXPECT_RET(err == ERR_OK); 00326 err = tcp_output(pcb); 00327 EXPECT_RET(err == ERR_OK); 00328 00329 /* send ACKs for data2 and data3 */ 00330 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 12, TCP_ACK); 00331 EXPECT_RET(p != NULL); 00332 test_tcp_input(p, &netif); 00333 /*EXPECT_RET(txcounters.num_tx_calls == 0);*/ 00334 00335 /* ...and even more data */ 00336 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); 00337 EXPECT_RET(err == ERR_OK); 00338 err = tcp_output(pcb); 00339 EXPECT_RET(err == ERR_OK); 00340 /* ...and even more data */ 00341 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); 00342 EXPECT_RET(err == ERR_OK); 00343 err = tcp_output(pcb); 00344 EXPECT_RET(err == ERR_OK); 00345 00346 #if 0 00347 /* create expected segment */ 00348 p1 = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0); 00349 EXPECT_RET(p != NULL); 00350 if (p != NULL) { 00351 /* pass the segment to tcp_input */ 00352 test_tcp_input(p, &netif); 00353 /* check if counters are as expected */ 00354 EXPECT_RET(counters.close_calls == 0); 00355 EXPECT_RET(counters.recv_calls == 1); 00356 EXPECT_RET(counters.recved_bytes == data_len); 00357 EXPECT_RET(counters.err_calls == 0); 00358 } 00359 #endif 00360 /* make sure the pcb is freed */ 00361 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); 00362 tcp_abort(pcb); 00363 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); 00364 } 00365 END_TEST 00366 00367 static u8_t tx_data[TCP_WND*2]; 00368 00369 static void 00370 check_seqnos(struct tcp_seg *segs, int num_expected, u32_t *seqnos_expected) 00371 { 00372 struct tcp_seg *s = segs; 00373 int i; 00374 for (i = 0; i < num_expected; i++, s = s->next) { 00375 EXPECT_RET(s != NULL); 00376 EXPECT(s->tcphdr->seqno == htonl(seqnos_expected[i])); 00377 } 00378 EXPECT(s == NULL); 00379 } 00380 00381 /** Send data with sequence numbers that wrap around the u32_t range. 00382 * Then, provoke fast retransmission by duplicate ACKs and check that all 00383 * segment lists are still properly sorted. */ 00384 START_TEST(test_tcp_fast_rexmit_wraparound) 00385 { 00386 struct netif netif; 00387 struct test_tcp_txcounters txcounters; 00388 struct test_tcp_counters counters; 00389 struct tcp_pcb* pcb; 00390 struct pbuf* p; 00391 ip_addr_t remote_ip, local_ip, netmask; 00392 u16_t remote_port = 0x100, local_port = 0x101; 00393 err_t err; 00394 #define SEQNO1 (0xFFFFFF00 - TCP_MSS) 00395 #define ISS 6510 00396 u16_t i, sent_total = 0; 00397 u32_t seqnos[] = { 00398 SEQNO1, 00399 SEQNO1 + (1 * TCP_MSS), 00400 SEQNO1 + (2 * TCP_MSS), 00401 SEQNO1 + (3 * TCP_MSS), 00402 SEQNO1 + (4 * TCP_MSS), 00403 SEQNO1 + (5 * TCP_MSS)}; 00404 LWIP_UNUSED_ARG(_i); 00405 00406 for (i = 0; i < sizeof(tx_data); i++) { 00407 tx_data[i] = (u8_t)i; 00408 } 00409 00410 /* initialize local vars */ 00411 IP_ADDR4(&local_ip, 192, 168, 1, 1); 00412 IP_ADDR4(&remote_ip, 192, 168, 1, 2); 00413 IP_ADDR4(&netmask, 255, 255, 255, 0); 00414 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); 00415 memset(&counters, 0, sizeof(counters)); 00416 00417 /* create and initialize the pcb */ 00418 tcp_ticks = SEQNO1 - ISS; 00419 pcb = test_tcp_new_counters_pcb(&counters); 00420 EXPECT_RET(pcb != NULL); 00421 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); 00422 pcb->mss = TCP_MSS; 00423 /* disable initial congestion window (we don't send a SYN here...) */ 00424 pcb->cwnd = 2*TCP_MSS; 00425 /* start in congestion advoidance */ 00426 pcb->ssthresh = pcb->cwnd; 00427 00428 /* send 6 mss-sized segments */ 00429 for (i = 0; i < 6; i++) { 00430 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); 00431 EXPECT_RET(err == ERR_OK); 00432 sent_total += TCP_MSS; 00433 } 00434 check_seqnos(pcb->unsent, 6, seqnos); 00435 EXPECT(pcb->unacked == NULL); 00436 err = tcp_output(pcb); 00437 EXPECT(txcounters.num_tx_calls == 2); 00438 EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U)); 00439 memset(&txcounters, 0, sizeof(txcounters)); 00440 00441 check_seqnos(pcb->unacked, 2, seqnos); 00442 check_seqnos(pcb->unsent, 4, &seqnos[2]); 00443 00444 /* ACK the first segment */ 00445 p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK); 00446 test_tcp_input(p, &netif); 00447 /* ensure this didn't trigger a retransmission. Only one 00448 segment should be transmitted because cwnd opened up by 00449 TCP_MSS and a fraction since we are in congestion avoidance */ 00450 EXPECT(txcounters.num_tx_calls == 1); 00451 EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); 00452 memset(&txcounters, 0, sizeof(txcounters)); 00453 check_seqnos(pcb->unacked, 2, &seqnos[1]); 00454 check_seqnos(pcb->unsent, 3, &seqnos[3]); 00455 00456 /* 3 dupacks */ 00457 EXPECT(pcb->dupacks == 0); 00458 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); 00459 test_tcp_input(p, &netif); 00460 EXPECT(txcounters.num_tx_calls == 0); 00461 EXPECT(pcb->dupacks == 1); 00462 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); 00463 test_tcp_input(p, &netif); 00464 EXPECT(txcounters.num_tx_calls == 0); 00465 EXPECT(pcb->dupacks == 2); 00466 /* 3rd dupack -> fast rexmit */ 00467 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); 00468 test_tcp_input(p, &netif); 00469 EXPECT(pcb->dupacks == 3); 00470 EXPECT(txcounters.num_tx_calls == 4); 00471 memset(&txcounters, 0, sizeof(txcounters)); 00472 EXPECT(pcb->unsent == NULL); 00473 check_seqnos(pcb->unacked, 5, &seqnos[1]); 00474 00475 /* make sure the pcb is freed */ 00476 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); 00477 tcp_abort(pcb); 00478 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); 00479 } 00480 END_TEST 00481 00482 /** Send data with sequence numbers that wrap around the u32_t range. 00483 * Then, provoke RTO retransmission and check that all 00484 * segment lists are still properly sorted. */ 00485 START_TEST(test_tcp_rto_rexmit_wraparound) 00486 { 00487 struct netif netif; 00488 struct test_tcp_txcounters txcounters; 00489 struct test_tcp_counters counters; 00490 struct tcp_pcb* pcb; 00491 ip_addr_t remote_ip, local_ip, netmask; 00492 u16_t remote_port = 0x100, local_port = 0x101; 00493 err_t err; 00494 #define SEQNO1 (0xFFFFFF00 - TCP_MSS) 00495 #define ISS 6510 00496 u16_t i, sent_total = 0; 00497 u32_t seqnos[] = { 00498 SEQNO1, 00499 SEQNO1 + (1 * TCP_MSS), 00500 SEQNO1 + (2 * TCP_MSS), 00501 SEQNO1 + (3 * TCP_MSS), 00502 SEQNO1 + (4 * TCP_MSS), 00503 SEQNO1 + (5 * TCP_MSS)}; 00504 LWIP_UNUSED_ARG(_i); 00505 00506 for (i = 0; i < sizeof(tx_data); i++) { 00507 tx_data[i] = (u8_t)i; 00508 } 00509 00510 /* initialize local vars */ 00511 IP_ADDR4(&local_ip, 192, 168, 1, 1); 00512 IP_ADDR4(&remote_ip, 192, 168, 1, 2); 00513 IP_ADDR4(&netmask, 255, 255, 255, 0); 00514 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); 00515 memset(&counters, 0, sizeof(counters)); 00516 00517 /* create and initialize the pcb */ 00518 tcp_ticks = 0; 00519 tcp_ticks = 0 - tcp_next_iss(NULL); 00520 tcp_ticks = SEQNO1 - tcp_next_iss(NULL); 00521 pcb = test_tcp_new_counters_pcb(&counters); 00522 EXPECT_RET(pcb != NULL); 00523 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); 00524 pcb->mss = TCP_MSS; 00525 /* disable initial congestion window (we don't send a SYN here...) */ 00526 pcb->cwnd = 2*TCP_MSS; 00527 00528 /* send 6 mss-sized segments */ 00529 for (i = 0; i < 6; i++) { 00530 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); 00531 EXPECT_RET(err == ERR_OK); 00532 sent_total += TCP_MSS; 00533 } 00534 check_seqnos(pcb->unsent, 6, seqnos); 00535 EXPECT(pcb->unacked == NULL); 00536 err = tcp_output(pcb); 00537 EXPECT(txcounters.num_tx_calls == 2); 00538 EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U)); 00539 memset(&txcounters, 0, sizeof(txcounters)); 00540 00541 check_seqnos(pcb->unacked, 2, seqnos); 00542 check_seqnos(pcb->unsent, 4, &seqnos[2]); 00543 00544 /* call the tcp timer some times */ 00545 for (i = 0; i < 10; i++) { 00546 test_tcp_tmr(); 00547 EXPECT(txcounters.num_tx_calls == 0); 00548 } 00549 /* 11th call to tcp_tmr: RTO rexmit fires */ 00550 test_tcp_tmr(); 00551 EXPECT(txcounters.num_tx_calls == 1); 00552 check_seqnos(pcb->unacked, 1, seqnos); 00553 check_seqnos(pcb->unsent, 5, &seqnos[1]); 00554 00555 /* fake greater cwnd */ 00556 pcb->cwnd = pcb->snd_wnd; 00557 /* send more data */ 00558 err = tcp_output(pcb); 00559 EXPECT(err == ERR_OK); 00560 /* check queues are sorted */ 00561 EXPECT(pcb->unsent == NULL); 00562 check_seqnos(pcb->unacked, 6, seqnos); 00563 00564 /* make sure the pcb is freed */ 00565 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); 00566 tcp_abort(pcb); 00567 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); 00568 } 00569 END_TEST 00570 00571 /** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data. 00572 * At the end, send more data. */ 00573 static void test_tcp_tx_full_window_lost(u8_t zero_window_probe_from_unsent) 00574 { 00575 struct netif netif; 00576 struct test_tcp_txcounters txcounters; 00577 struct test_tcp_counters counters; 00578 struct tcp_pcb* pcb; 00579 struct pbuf *p; 00580 ip_addr_t remote_ip, local_ip, netmask; 00581 u16_t remote_port = 0x100, local_port = 0x101; 00582 err_t err; 00583 u16_t sent_total, i; 00584 u8_t expected = 0xFE; 00585 00586 for (i = 0; i < sizeof(tx_data); i++) { 00587 u8_t d = (u8_t)i; 00588 if (d == 0xFE) { 00589 d = 0xF0; 00590 } 00591 tx_data[i] = d; 00592 } 00593 if (zero_window_probe_from_unsent) { 00594 tx_data[TCP_WND] = expected; 00595 } else { 00596 tx_data[0] = expected; 00597 } 00598 00599 /* initialize local vars */ 00600 IP_ADDR4(&local_ip, 192, 168, 1, 1); 00601 IP_ADDR4(&remote_ip, 192, 168, 1, 2); 00602 IP_ADDR4(&netmask, 255, 255, 255, 0); 00603 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); 00604 memset(&counters, 0, sizeof(counters)); 00605 memset(&txcounters, 0, sizeof(txcounters)); 00606 00607 /* create and initialize the pcb */ 00608 pcb = test_tcp_new_counters_pcb(&counters); 00609 EXPECT_RET(pcb != NULL); 00610 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); 00611 pcb->mss = TCP_MSS; 00612 /* disable initial congestion window (we don't send a SYN here...) */ 00613 pcb->cwnd = pcb->snd_wnd; 00614 00615 /* send a full window (minus 1 packets) of TCP data in MSS-sized chunks */ 00616 sent_total = 0; 00617 if ((TCP_WND - TCP_MSS) % TCP_MSS != 0) { 00618 u16_t initial_data_len = (TCP_WND - TCP_MSS) % TCP_MSS; 00619 err = tcp_write(pcb, &tx_data[sent_total], initial_data_len, TCP_WRITE_FLAG_COPY); 00620 EXPECT_RET(err == ERR_OK); 00621 err = tcp_output(pcb); 00622 EXPECT_RET(err == ERR_OK); 00623 EXPECT(txcounters.num_tx_calls == 1); 00624 EXPECT(txcounters.num_tx_bytes == initial_data_len + 40U); 00625 memset(&txcounters, 0, sizeof(txcounters)); 00626 sent_total += initial_data_len; 00627 } 00628 for (; sent_total < (TCP_WND - TCP_MSS); sent_total += TCP_MSS) { 00629 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); 00630 EXPECT_RET(err == ERR_OK); 00631 err = tcp_output(pcb); 00632 EXPECT_RET(err == ERR_OK); 00633 EXPECT(txcounters.num_tx_calls == 1); 00634 EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); 00635 memset(&txcounters, 0, sizeof(txcounters)); 00636 } 00637 EXPECT(sent_total == (TCP_WND - TCP_MSS)); 00638 00639 /* now ACK the packet before the first */ 00640 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); 00641 test_tcp_input(p, &netif); 00642 /* ensure this didn't trigger a retransmission */ 00643 EXPECT(txcounters.num_tx_calls == 0); 00644 EXPECT(txcounters.num_tx_bytes == 0); 00645 00646 EXPECT(pcb->persist_backoff == 0); 00647 /* send the last packet, now a complete window has been sent */ 00648 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); 00649 sent_total += TCP_MSS; 00650 EXPECT_RET(err == ERR_OK); 00651 err = tcp_output(pcb); 00652 EXPECT_RET(err == ERR_OK); 00653 EXPECT(txcounters.num_tx_calls == 1); 00654 EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); 00655 memset(&txcounters, 0, sizeof(txcounters)); 00656 EXPECT(pcb->persist_backoff == 0); 00657 00658 if (zero_window_probe_from_unsent) { 00659 /* ACK all data but close the TX window */ 00660 p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, TCP_WND, TCP_ACK, 0); 00661 test_tcp_input(p, &netif); 00662 /* ensure this didn't trigger any transmission */ 00663 EXPECT(txcounters.num_tx_calls == 0); 00664 EXPECT(txcounters.num_tx_bytes == 0); 00665 EXPECT(pcb->persist_backoff == 1); 00666 } 00667 00668 /* send one byte more (out of window) -> persist timer starts */ 00669 err = tcp_write(pcb, &tx_data[sent_total], 1, TCP_WRITE_FLAG_COPY); 00670 EXPECT_RET(err == ERR_OK); 00671 err = tcp_output(pcb); 00672 EXPECT_RET(err == ERR_OK); 00673 EXPECT(txcounters.num_tx_calls == 0); 00674 EXPECT(txcounters.num_tx_bytes == 0); 00675 memset(&txcounters, 0, sizeof(txcounters)); 00676 if (!zero_window_probe_from_unsent) { 00677 /* no persist timer unless a zero window announcement has been received */ 00678 EXPECT(pcb->persist_backoff == 0); 00679 } else { 00680 EXPECT(pcb->persist_backoff == 1); 00681 00682 /* call tcp_timer some more times to let persist timer count up */ 00683 for (i = 0; i < 4; i++) { 00684 test_tcp_tmr(); 00685 EXPECT(txcounters.num_tx_calls == 0); 00686 EXPECT(txcounters.num_tx_bytes == 0); 00687 } 00688 00689 /* this should trigger the zero-window-probe */ 00690 txcounters.copy_tx_packets = 1; 00691 test_tcp_tmr(); 00692 txcounters.copy_tx_packets = 0; 00693 EXPECT(txcounters.num_tx_calls == 1); 00694 EXPECT(txcounters.num_tx_bytes == 1 + 40U); 00695 EXPECT(txcounters.tx_packets != NULL); 00696 if (txcounters.tx_packets != NULL) { 00697 u8_t sent; 00698 u16_t ret; 00699 ret = pbuf_copy_partial(txcounters.tx_packets, &sent, 1, 40U); 00700 EXPECT(ret == 1); 00701 EXPECT(sent == expected); 00702 } 00703 if (txcounters.tx_packets != NULL) { 00704 pbuf_free(txcounters.tx_packets); 00705 txcounters.tx_packets = NULL; 00706 } 00707 } 00708 00709 /* make sure the pcb is freed */ 00710 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); 00711 tcp_abort(pcb); 00712 EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); 00713 } 00714 00715 START_TEST(test_tcp_tx_full_window_lost_from_unsent) 00716 { 00717 LWIP_UNUSED_ARG(_i); 00718 test_tcp_tx_full_window_lost(1); 00719 } 00720 END_TEST 00721 00722 START_TEST(test_tcp_tx_full_window_lost_from_unacked) 00723 { 00724 LWIP_UNUSED_ARG(_i); 00725 test_tcp_tx_full_window_lost(0); 00726 } 00727 END_TEST 00728 00729 /** Create the suite including all tests for this module */ 00730 Suite * 00731 tcp_suite(void) 00732 { 00733 testfunc tests[] = { 00734 TESTFUNC(test_tcp_new_abort), 00735 TESTFUNC(test_tcp_recv_inseq), 00736 TESTFUNC(test_tcp_malformed_header), 00737 TESTFUNC(test_tcp_fast_retx_recover), 00738 TESTFUNC(test_tcp_fast_rexmit_wraparound), 00739 TESTFUNC(test_tcp_rto_rexmit_wraparound), 00740 TESTFUNC(test_tcp_tx_full_window_lost_from_unacked), 00741 TESTFUNC(test_tcp_tx_full_window_lost_from_unsent) 00742 }; 00743 return create_suite("TCP", tests, sizeof(tests)/sizeof(testfunc), tcp_setup, tcp_teardown); 00744 }
Generated on Sun Jul 17 2022 08:25:32 by 1.7.2