@@ -32,6 +32,29 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_TCP_LOG_LEVEL);
3232#define MY_PORT 4242
3333#define PEER_PORT 4242
3434
35+ /* Data (1280 bytes) to be sent */
36+ static const char lorem_ipsum [] =
37+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris id "
38+ "sodales lacus. Proin vel rhoncus sapien. Morbi semper, enim in "
39+ "ullamcorper luctus, urna mi efficitur ex, laoreet eleifend massa "
40+ "felis ac dui. Duis ut magna convallis, tristique leo eu, ornare "
41+ "eros. Mauris a neque dictum, lobortis quam ut, rutrum erat. Vivamus "
42+ "vulputate neque vel auctor porta. Duis consectetur justo ac molestie "
43+ "tristique. In hac habitasse platea dictumst. Cras augue metus, "
44+ "aliquet sodales elit eget suscipit rutrum tellus. Nulla ante purus, "
45+ "dictum id tellus at, mattis cursus lectus. Mauris fringilla eros "
46+ "lorem, in auctor erat consequat nec. Ut pharetra sollicitudin dolor "
47+ "vel laoreet. Praesent eu lectus a dolor fringilla aliquet varius "
48+ "eget erat. Ut vitae mauris commodo, feugiat arcu non vehicula nunc. "
49+ "Nam ac enim elit. Praesent sit amet erat massa. Suspendisse potenti. "
50+ "Etiam diam justo, tempus vel lobortis tincidunt, scelerisque vitae "
51+ "mauris. Aenean vestibulum venenatis dapibus. Curabitur id ullamcorper"
52+ " diam. Ut eu turpis mauris. Aliquam et ligula est. Proin a velit non "
53+ "velit interdum vulputate. Proin vehicula eleifend suscipit. Cras "
54+ "condimentum non massa egestas tempor. Donec quis scelerisque est, id "
55+ "suscipit neque. Ut lobortis cursus ultrices. Aenean malesuada, nibh "
56+ "ut laoreet." ;
57+
3558static struct in_addr my_addr = { { { 192 , 0 , 2 , 1 } } };
3659static struct sockaddr_in my_addr_s = {
3760 .sin_family = AF_INET ,
@@ -95,12 +118,15 @@ static void handle_server_test(sa_family_t af, struct tcphdr *th);
95118static void handle_syn_resend (void );
96119static void handle_client_fin_wait_2_test (sa_family_t af , struct tcphdr * th );
97120static void handle_client_closing_test (sa_family_t af , struct tcphdr * th );
121+ static void handle_server_recv_out_of_order (struct net_pkt * pkt );
98122
99123static void verify_flags (struct tcphdr * th , uint8_t flags ,
100124 const char * fun , int line )
101125{
102126 if (!(th && FL (& th -> th_flags , = = , flags ))) {
103- zassert_true (false, "%s:%d flags mismatch" , fun , line );
127+ zassert_true (false,
128+ "%s:%d flags mismatch (0x%04x vs 0x%04x)" ,
129+ fun , line , th -> th_flags , flags );
104130 }
105131}
106132
@@ -182,8 +208,10 @@ static uint8_t tcp_options[20] = {
182208 0x03 , 0x03 , 0x07 /* Win scale*/ };
183209
184210static struct net_pkt * tester_prepare_tcp_pkt (sa_family_t af ,
185- uint16_t src_port , uint16_t dst_port ,
186- uint8_t flags , uint8_t * data ,
211+ uint16_t src_port ,
212+ uint16_t dst_port ,
213+ uint8_t flags ,
214+ const uint8_t * data ,
187215 size_t len )
188216{
189217 NET_PKT_DATA_ACCESS_DEFINE (tcp_access , struct tcphdr );
@@ -302,7 +330,8 @@ static struct net_pkt *prepare_ack_packet(sa_family_t af, uint16_t src_port,
302330}
303331
304332static struct net_pkt * prepare_data_packet (sa_family_t af , uint16_t src_port ,
305- uint16_t dst_port , uint8_t * data ,
333+ uint16_t dst_port ,
334+ const uint8_t * data ,
306335 size_t len )
307336{
308337 return tester_prepare_tcp_pkt (af , src_port , dst_port , PSH | ACK , data ,
@@ -382,6 +411,9 @@ static int tester_send(const struct device *dev, struct net_pkt *pkt)
382411 case 8 :
383412 handle_client_closing_test (net_pkt_family (pkt ), & th );
384413 break ;
414+ case 9 :
415+ handle_server_recv_out_of_order (pkt );
416+ break ;
385417 default :
386418 zassert_true (false, "Undefined test case" );
387419 }
@@ -603,8 +635,6 @@ static void handle_server_test(sa_family_t af, struct tcphdr *th)
603635
604636 switch (t_state ) {
605637 case T_SYN :
606- seq = 0U ;
607- ack = 0U ;
608638 reply = prepare_syn_packet (af , htons (MY_PORT ),
609639 htons (PEER_PORT ));
610640 t_state = T_SYN_ACK ;
@@ -1172,14 +1202,16 @@ static void test_client_closing_ipv6(void)
11721202 k_sleep (K_MSEC (CONFIG_NET_TCP_TIME_WAIT_DELAY ));
11731203}
11741204
1175- static struct net_context * create_server_socket (void )
1205+ static struct net_context * create_server_socket (uint32_t my_seq ,
1206+ uint32_t my_ack )
11761207{
11771208 struct net_context * ctx ;
11781209 int ret ;
11791210
11801211 t_state = T_SYN ;
11811212 test_case_no = 5 ;
1182- seq = ack = 0 ;
1213+ seq = my_seq ;
1214+ ack = my_ack ;
11831215
11841216 ret = net_context_get (AF_INET6 , SOCK_STREAM , IPPROTO_TCP , & ctx );
11851217 if (ret < 0 ) {
@@ -1248,7 +1280,7 @@ static void check_rst_succeed(struct net_context *ctx,
12481280
12491281 /* Make sure that various other corner cases work */
12501282 if (ctx == NULL ) {
1251- ctx = create_server_socket ();
1283+ ctx = create_server_socket (0 , 0 );
12521284 }
12531285
12541286 /* Another valid seq in the RST packet */
@@ -1279,7 +1311,7 @@ static void test_client_invalid_rst(void)
12791311 struct tcp * conn ;
12801312 uint16_t wnd ;
12811313
1282- ctx = create_server_socket ();
1314+ ctx = create_server_socket (0 , 0 );
12831315
12841316 conn = ctx -> tcp ;
12851317 wnd = conn -> recv_win ;
@@ -1292,6 +1324,158 @@ static void test_client_invalid_rst(void)
12921324 check_rst_succeed (ctx , wnd - 1 );
12931325 check_rst_succeed (NULL , 0 );
12941326 check_rst_succeed (NULL , 1 );
1327+
1328+ net_tcp_put (ctx );
1329+ }
1330+
1331+ #define MAX_DATA 100
1332+ static uint32_t expected_ack = MAX_DATA + 1 - 15 ;
1333+ static struct net_context * ooo_ctx ;
1334+
1335+ static void handle_server_recv_out_of_order (struct net_pkt * pkt )
1336+ {
1337+ struct tcphdr th ;
1338+ int ret ;
1339+
1340+ ret = read_tcp_header (pkt , & th );
1341+ if (ret < 0 ) {
1342+ goto fail ;
1343+ }
1344+
1345+ /* Verify that we received all the queued data */
1346+ zassert_equal (expected_ack , ntohl (th .th_ack ),
1347+ "Not all pending data received. "
1348+ "Expected ACK %u but got %u" ,
1349+ expected_ack , ntohl (th .th_ack ));
1350+
1351+ test_sem_give ();
1352+
1353+ return ;
1354+
1355+ fail :
1356+ zassert_true (false, "%s failed" , __func__ );
1357+ net_pkt_unref (pkt );
1358+ }
1359+
1360+ static void test_server_recv_out_of_order_data (void )
1361+ {
1362+ const uint8_t * data = lorem_ipsum + 10 ;
1363+ struct net_pkt * pkt ;
1364+ int ret , i ;
1365+
1366+ /* Only run the tests if queueing is enabled */
1367+ if (CONFIG_NET_TCP_RECV_QUEUE_TIMEOUT == 0 ) {
1368+ return ;
1369+ }
1370+
1371+ /* Start the sequence numbering so that we will wrap it (just for
1372+ * testing purposes)
1373+ */
1374+ ooo_ctx = create_server_socket (-15U , -15U );
1375+
1376+ /* This will force the packet to be routed to our checker func
1377+ * handle_server_recv_out_of_order()
1378+ */
1379+ test_case_no = 9 ;
1380+
1381+ /* First packet will be out-of-order */
1382+ seq += MAX_DATA - 20 ;
1383+ pkt = prepare_data_packet (AF_INET6 , htons (MY_PORT ), htons (PEER_PORT ),
1384+ & data [seq ], 10 );
1385+ zassert_not_null (pkt , "Cannot create pkt" );
1386+
1387+ ret = net_recv_data (iface , pkt );
1388+ zassert_true (ret == 0 , "recv data failed (%d)" , ret );
1389+
1390+ /* Let the IP stack to process the packet properly */
1391+ k_msleep (1 );
1392+
1393+ /* Then we send a packet that is after the previous packet */
1394+ seq += 10 ;
1395+
1396+ pkt = prepare_data_packet (AF_INET6 , htons (MY_PORT ), htons (PEER_PORT ),
1397+ & data [seq ], 10 );
1398+ zassert_not_null (pkt , "Cannot create pkt" );
1399+
1400+ ret = net_recv_data (iface , pkt );
1401+ zassert_true (ret == 0 , "recv data failed (%d)" , ret );
1402+
1403+ k_msleep (1 );
1404+
1405+ /* Then send packets that are before the first packet. The final packet
1406+ * will flush the receive queue as the seq will be 1
1407+ */
1408+ for (i = MAX_DATA - 10 ; i > 0 ; i -= 10 ) {
1409+ seq -= 10 ;
1410+
1411+ pkt = prepare_data_packet (AF_INET6 , htons (MY_PORT ),
1412+ htons (PEER_PORT ),
1413+ & data [i ], 10 );
1414+ zassert_not_null (pkt , "Cannot create pkt" );
1415+
1416+ ret = net_recv_data (iface , pkt );
1417+ zassert_true (ret == 0 , "recv data failed (%d)" , ret );
1418+
1419+ k_msleep (1 );
1420+ }
1421+
1422+ /* Then the final packet that will flush the receive queue */
1423+ pkt = prepare_data_packet (AF_INET6 , htons (MY_PORT ),
1424+ htons (PEER_PORT ),
1425+ & data [i ], 10 );
1426+ zassert_not_null (pkt , "Cannot create pkt" );
1427+
1428+ ret = net_recv_data (iface , pkt );
1429+ zassert_true (ret == 0 , "recv data failed (%d)" , ret );
1430+
1431+ /* Peer will release the semaphone after it sends proper ACK to the
1432+ * queued data.
1433+ */
1434+ test_sem_take (K_MSEC (1000 ), __LINE__ );
1435+ }
1436+
1437+ /* This test expects that the system is in correct state after a call to
1438+ * test_server_recv_out_of_order_data(), so this test must be run after that
1439+ * test.
1440+ */
1441+ static void test_server_timeout_out_of_order_data (void )
1442+ {
1443+ const uint8_t * data = lorem_ipsum + 10 ;
1444+ struct net_pkt * pkt ;
1445+ int ret , i ;
1446+
1447+ if (CONFIG_NET_TCP_RECV_QUEUE_TIMEOUT == 0 ) {
1448+ return ;
1449+ }
1450+
1451+ k_sem_reset (& test_sem );
1452+
1453+ /* The +1 will cause the seq to be not sequential thus we should
1454+ * get a timeout.
1455+ */
1456+ seq = expected_ack + MAX_DATA + 1 ;
1457+
1458+ /* Then special handling to send out-of-order TCP segments */
1459+ for (i = MAX_DATA ; i > 10 ; i -= 10 ) {
1460+ seq -= 10 ;
1461+
1462+ pkt = prepare_data_packet (AF_INET6 , htons (MY_PORT ),
1463+ htons (PEER_PORT ),
1464+ & data [i ], 10 );
1465+ zassert_not_null (pkt , "Cannot create pkt" );
1466+
1467+ ret = net_recv_data (iface , pkt );
1468+ zassert_true (ret == 0 , "recv data failed (%d)" , ret );
1469+ }
1470+
1471+ /* Because the pending seq values are not sequential,
1472+ * the recv queue in tcp2 should timeout.
1473+ */
1474+ ret = k_sem_take (& test_sem ,
1475+ K_MSEC (CONFIG_NET_TCP_RECV_QUEUE_TIMEOUT + 10 ));
1476+ zassert_equal (ret , - EAGAIN , "semaphore did not time out (%d)" , ret );
1477+
1478+ net_tcp_put (ooo_ctx );
12951479}
12961480
12971481/** Test case main entry */
@@ -1307,7 +1491,9 @@ void test_main(void)
13071491 ztest_unit_test (test_client_syn_resend ),
13081492 ztest_unit_test (test_client_fin_wait_2_ipv4 ),
13091493 ztest_unit_test (test_client_closing_ipv6 ),
1310- ztest_unit_test (test_client_invalid_rst )
1494+ ztest_unit_test (test_client_invalid_rst ),
1495+ ztest_unit_test (test_server_recv_out_of_order_data ),
1496+ ztest_unit_test (test_server_timeout_out_of_order_data )
13111497 );
13121498
13131499 ztest_run_test_suite (test_tcp_fn );
0 commit comments