test: net: tcp2: Tests for connection close
Added tests for FIN_WAIT_1, FIN_WAIT_2 and CLOSING states. Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@linux.intel.com>
This commit is contained in:
parent
184a2d5197
commit
4c8ad3b0c6
2 changed files with 279 additions and 3 deletions
|
@ -37,6 +37,9 @@ CONFIG_ZTEST_STACKSIZE=3072
|
|||
|
||||
CONFIG_HEAP_MEM_POOL_SIZE=8192
|
||||
|
||||
# Test purpose keep it short
|
||||
CONFIG_NET_TCP_TIME_WAIT_DELAY=100
|
||||
|
||||
CONFIG_LOG=y
|
||||
CONFIG_NET_LOG=y
|
||||
# Useful for debugging these tests
|
||||
|
|
|
@ -77,7 +77,9 @@ enum test_state {
|
|||
T_DATA,
|
||||
T_DATA_ACK,
|
||||
T_FIN,
|
||||
T_FIN_ACK
|
||||
T_FIN_ACK,
|
||||
T_FIN_2,
|
||||
T_CLOSING
|
||||
};
|
||||
|
||||
static enum test_state t_state;
|
||||
|
@ -90,6 +92,8 @@ static int tester_send(struct device *dev, struct net_pkt *pkt);
|
|||
static void handle_client_test(sa_family_t af, struct tcphdr *th);
|
||||
static void handle_server_test(sa_family_t af, struct tcphdr *th);
|
||||
static void handle_syn_resend(void);
|
||||
static void handle_client_fin_wait_2_test(sa_family_t af, struct tcphdr *th);
|
||||
static void handle_client_closing_test(sa_family_t af, struct tcphdr *th);
|
||||
|
||||
struct net_tcp_context {
|
||||
u8_t mac_addr[sizeof(struct net_eth_addr)];
|
||||
|
@ -301,6 +305,12 @@ static struct net_pkt *prepare_fin_ack_packet(sa_family_t af, u16_t src_port,
|
|||
NULL, 0U);
|
||||
}
|
||||
|
||||
static struct net_pkt *prepare_fin_packet(sa_family_t af, u16_t src_port,
|
||||
u16_t dst_port)
|
||||
{
|
||||
return tester_prepare_tcp_pkt(af, src_port, dst_port, FIN, NULL, 0U);
|
||||
}
|
||||
|
||||
static int read_tcp_header(struct net_pkt *pkt, struct tcphdr *th)
|
||||
{
|
||||
int ret;
|
||||
|
@ -349,6 +359,12 @@ static int tester_send(struct device *dev, struct net_pkt *pkt)
|
|||
case 6:
|
||||
handle_syn_resend();
|
||||
break;
|
||||
case 7:
|
||||
handle_client_fin_wait_2_test(net_pkt_family(pkt), &th);
|
||||
break;
|
||||
case 8:
|
||||
handle_client_closing_test(net_pkt_family(pkt), &th);
|
||||
break;
|
||||
default:
|
||||
zassert_true(false, "Undefined test case");
|
||||
}
|
||||
|
@ -412,8 +428,13 @@ static void handle_client_test(sa_family_t af, struct tcphdr *th)
|
|||
test_sem_give();
|
||||
break;
|
||||
case T_FIN:
|
||||
ack = ntohs(th->th_seq) + 1U;
|
||||
t_state = T_FIN_ACK;
|
||||
reply = prepare_fin_ack_packet(af, htons(MY_PORT),
|
||||
th->th_sport);
|
||||
break;
|
||||
case T_FIN_ACK:
|
||||
test_sem_give();
|
||||
/* TODO in TCP2: it sends FIN, but doesn't wait for FIN | ACK */
|
||||
return;
|
||||
default:
|
||||
zassert_true(false, "%s unexpected state", __func__);
|
||||
|
@ -456,6 +477,8 @@ static void test_client_ipv4(void)
|
|||
zassert_true(false, "Failed to get net_context");
|
||||
}
|
||||
|
||||
net_context_ref(ctx);
|
||||
|
||||
ret = net_context_connect(ctx, (struct sockaddr *)&peer_addr_s,
|
||||
sizeof(struct sockaddr_in),
|
||||
NULL,
|
||||
|
@ -483,6 +506,11 @@ static void test_client_ipv4(void)
|
|||
* proper ACK to FIN | ACK
|
||||
*/
|
||||
test_sem_take(K_MSEC(100), __LINE__);
|
||||
|
||||
/* Connection is in TIME_WAIT state, context will be released
|
||||
* after K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY), so wait for it.
|
||||
*/
|
||||
k_sleep(K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY));
|
||||
}
|
||||
|
||||
/* Test case scenario IPv6
|
||||
|
@ -511,6 +539,8 @@ static void test_client_ipv6(void)
|
|||
zassert_true(false, "Failed to get net_context");
|
||||
}
|
||||
|
||||
net_context_ref(ctx);
|
||||
|
||||
ret = net_context_connect(ctx, (struct sockaddr *)&peer_addr_v6_s,
|
||||
sizeof(struct sockaddr_in6),
|
||||
NULL,
|
||||
|
@ -538,6 +568,11 @@ static void test_client_ipv6(void)
|
|||
* proper ACK to FIN | ACK
|
||||
*/
|
||||
test_sem_take(K_MSEC(100), __LINE__);
|
||||
|
||||
/* Connection is in TIME_WAIT state, context will be released
|
||||
* after K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY), so wait for it.
|
||||
*/
|
||||
k_sleep(K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY));
|
||||
}
|
||||
|
||||
static void handle_server_test(sa_family_t af, struct tcphdr *th)
|
||||
|
@ -868,6 +903,242 @@ static void test_client_syn_resend(void)
|
|||
net_context_put(ctx);
|
||||
}
|
||||
|
||||
static void handle_client_fin_wait_2_test(sa_family_t af, struct tcphdr *th)
|
||||
{
|
||||
struct net_pkt *reply;
|
||||
int ret;
|
||||
|
||||
send_next:
|
||||
switch (t_state) {
|
||||
case T_SYN:
|
||||
seq = 0U;
|
||||
ack = ntohs(th->th_seq) + 1U;
|
||||
reply = prepare_syn_ack_packet(af, htons(MY_PORT),
|
||||
th->th_sport);
|
||||
t_state = T_SYN_ACK;
|
||||
break;
|
||||
case T_SYN_ACK:
|
||||
/* connection is success */
|
||||
t_state = T_DATA;
|
||||
test_sem_give();
|
||||
return;
|
||||
case T_DATA:
|
||||
seq++;
|
||||
ack = ack + 1U;
|
||||
reply = prepare_ack_packet(af, htons(MY_PORT), th->th_sport);
|
||||
t_state = T_FIN;
|
||||
test_sem_give();
|
||||
break;
|
||||
case T_FIN:
|
||||
ack = ntohs(th->th_seq) + 1U;
|
||||
t_state = T_FIN_2;
|
||||
reply = prepare_ack_packet(af, htons(MY_PORT), th->th_sport);
|
||||
break;
|
||||
case T_FIN_2:
|
||||
t_state = T_FIN_ACK;
|
||||
reply = prepare_fin_packet(af, htons(MY_PORT), th->th_sport);
|
||||
break;
|
||||
case T_FIN_ACK:
|
||||
test_sem_give();
|
||||
return;
|
||||
default:
|
||||
zassert_true(false, "%s unexpected state", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = net_recv_data(iface, reply);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (t_state == T_FIN_2) {
|
||||
goto send_next;
|
||||
}
|
||||
|
||||
return;
|
||||
fail:
|
||||
zassert_true(false, "%s failed", __func__);
|
||||
}
|
||||
|
||||
/* Test case scenario IPv4
|
||||
* send SYN,
|
||||
* expect SYN ACK,
|
||||
* send ACK,
|
||||
* send Data,
|
||||
* expect ACK,
|
||||
* send FIN,
|
||||
* expect ACK,
|
||||
* expect FIN,
|
||||
* send ACK,
|
||||
* any failures cause test case to fail.
|
||||
*/
|
||||
static void test_client_fin_wait_2_ipv4(void)
|
||||
{
|
||||
struct net_context *ctx;
|
||||
u8_t data = 0x41; /* "A" */
|
||||
int ret;
|
||||
|
||||
t_state = T_SYN;
|
||||
test_case_no = 7;
|
||||
seq = ack = 0;
|
||||
|
||||
ret = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, &ctx);
|
||||
if (ret < 0) {
|
||||
zassert_true(false, "Failed to get net_context");
|
||||
}
|
||||
|
||||
net_context_ref(ctx);
|
||||
|
||||
ret = net_context_connect(ctx, (struct sockaddr *)&peer_addr_s,
|
||||
sizeof(struct sockaddr_in),
|
||||
NULL,
|
||||
K_NO_WAIT, NULL);
|
||||
if (ret < 0) {
|
||||
zassert_true(false, "Failed to connect to peer");
|
||||
}
|
||||
|
||||
/* Peer will release the semaphone after it receives
|
||||
* proper ACK to SYN | ACK
|
||||
*/
|
||||
test_sem_take(K_MSEC(100), __LINE__);
|
||||
|
||||
ret = net_context_send(ctx, &data, 1, NULL, K_NO_WAIT, NULL);
|
||||
if (ret < 0) {
|
||||
zassert_true(false, "Failed to send data to peer");
|
||||
}
|
||||
|
||||
/* Peer will release the semaphone after it sends ACK for data */
|
||||
test_sem_take(K_MSEC(100), __LINE__);
|
||||
|
||||
net_tcp_put(ctx);
|
||||
|
||||
/* Peer will release the semaphone after it receives
|
||||
* proper ACK to FIN | ACK
|
||||
*/
|
||||
test_sem_take(K_MSEC(300), __LINE__);
|
||||
|
||||
/* Connection is in TIME_WAIT state, context will be released
|
||||
* after K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY), so wait for it.
|
||||
*/
|
||||
k_sleep(K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY));
|
||||
}
|
||||
|
||||
static void handle_client_closing_test(sa_family_t af, struct tcphdr *th)
|
||||
{
|
||||
struct net_pkt *reply;
|
||||
int ret;
|
||||
|
||||
switch (t_state) {
|
||||
case T_SYN:
|
||||
seq = 0U;
|
||||
ack = ntohs(th->th_seq) + 1U;
|
||||
reply = prepare_syn_ack_packet(af, htons(MY_PORT),
|
||||
th->th_sport);
|
||||
t_state = T_SYN_ACK;
|
||||
break;
|
||||
case T_SYN_ACK:
|
||||
/* connection is success */
|
||||
t_state = T_DATA;
|
||||
test_sem_give();
|
||||
return;
|
||||
case T_DATA:
|
||||
seq++;
|
||||
ack = ack + 1U;
|
||||
reply = prepare_ack_packet(af, htons(MY_PORT), th->th_sport);
|
||||
t_state = T_FIN;
|
||||
test_sem_give();
|
||||
break;
|
||||
case T_FIN:
|
||||
ack = ntohs(th->th_seq) + 1U;
|
||||
t_state = T_CLOSING;
|
||||
reply = prepare_fin_packet(af, htons(MY_PORT), th->th_sport);
|
||||
break;
|
||||
case T_CLOSING:
|
||||
t_state = T_FIN_ACK;
|
||||
reply = prepare_ack_packet(af, htons(MY_PORT), th->th_sport);
|
||||
break;
|
||||
default:
|
||||
zassert_true(false, "%s unexpected state", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = net_recv_data(iface, reply);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (t_state == T_FIN_ACK) {
|
||||
test_sem_give();
|
||||
}
|
||||
|
||||
return;
|
||||
fail:
|
||||
zassert_true(false, "%s failed", __func__);
|
||||
}
|
||||
|
||||
/* Test case scenario IPv6
|
||||
* send SYN,
|
||||
* expect SYN ACK,
|
||||
* send ACK,
|
||||
* send Data,
|
||||
* expect ACK,
|
||||
* send FIN,
|
||||
* expect FIN,
|
||||
* send ACK,
|
||||
* expect ACK,
|
||||
* any failures cause test case to fail.
|
||||
*/
|
||||
static void test_client_closing_ipv6(void)
|
||||
{
|
||||
struct net_context *ctx;
|
||||
u8_t data = 0x41; /* "A" */
|
||||
int ret;
|
||||
|
||||
t_state = T_SYN;
|
||||
test_case_no = 8;
|
||||
seq = ack = 0;
|
||||
|
||||
ret = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, &ctx);
|
||||
if (ret < 0) {
|
||||
zassert_true(false, "Failed to get net_context");
|
||||
}
|
||||
|
||||
net_context_ref(ctx);
|
||||
|
||||
ret = net_context_connect(ctx, (struct sockaddr *)&peer_addr_v6_s,
|
||||
sizeof(struct sockaddr_in6),
|
||||
NULL,
|
||||
K_NO_WAIT, NULL);
|
||||
if (ret < 0) {
|
||||
zassert_true(false, "Failed to connect to peer");
|
||||
}
|
||||
|
||||
/* Peer will release the semaphone after it receives
|
||||
* proper ACK to SYN | ACK
|
||||
*/
|
||||
test_sem_take(K_MSEC(100), __LINE__);
|
||||
|
||||
ret = net_context_send(ctx, &data, 1, NULL, K_NO_WAIT, NULL);
|
||||
if (ret < 0) {
|
||||
zassert_true(false, "Failed to send data to peer");
|
||||
}
|
||||
|
||||
/* Peer will release the semaphone after it sends ACK for data */
|
||||
test_sem_take(K_MSEC(100), __LINE__);
|
||||
|
||||
net_tcp_put(ctx);
|
||||
|
||||
/* Peer will release the semaphone after it receives
|
||||
* proper ACK to FIN | ACK
|
||||
*/
|
||||
test_sem_take(K_MSEC(300), __LINE__);
|
||||
|
||||
/* Connection is in TIME_WAIT state, context will be released
|
||||
* after K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY), so wait for it.
|
||||
*/
|
||||
k_sleep(K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY));
|
||||
}
|
||||
|
||||
/** Test case main entry */
|
||||
void test_main(void)
|
||||
{
|
||||
|
@ -878,7 +1149,9 @@ void test_main(void)
|
|||
ztest_unit_test(test_server_ipv4),
|
||||
ztest_unit_test(test_server_with_options_ipv4),
|
||||
ztest_unit_test(test_server_ipv6),
|
||||
ztest_unit_test(test_client_syn_resend)
|
||||
ztest_unit_test(test_client_syn_resend),
|
||||
ztest_unit_test(test_client_fin_wait_2_ipv4),
|
||||
ztest_unit_test(test_client_closing_ipv6)
|
||||
);
|
||||
|
||||
ztest_run_test_suite(test_tcp_fn);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue