@@ -116,6 +116,7 @@ static enum test_case_no {
116
116
TEST_CLIENT_FIN_ACK_WITH_DATA = 18 ,
117
117
TEST_CLIENT_SEQ_VALIDATION = 19 ,
118
118
TEST_SERVER_ACK_VALIDATION = 20 ,
119
+ TEST_SERVER_FIN_ACK_AFTER_DATA = 21 ,
119
120
} test_case_no ;
120
121
121
122
static enum test_state t_state ;
@@ -142,6 +143,7 @@ static void handle_syn_invalid_ack(sa_family_t af, struct tcphdr *th);
142
143
static void handle_client_fin_ack_with_data_test (sa_family_t af , struct tcphdr * th );
143
144
static void handle_client_seq_validation_test (sa_family_t af , struct tcphdr * th );
144
145
static void handle_server_ack_validation_test (struct net_pkt * pkt );
146
+ static void handle_server_fin_ack_after_data_test (sa_family_t af , struct tcphdr * th );
145
147
146
148
static void verify_flags (struct tcphdr * th , uint8_t flags ,
147
149
const char * fun , int line )
@@ -494,6 +496,9 @@ static int tester_send(const struct device *dev, struct net_pkt *pkt)
494
496
case TEST_SERVER_ACK_VALIDATION :
495
497
handle_server_ack_validation_test (pkt );
496
498
break ;
499
+ case TEST_SERVER_FIN_ACK_AFTER_DATA :
500
+ handle_server_fin_ack_after_data_test (net_pkt_family (pkt ), & th );
501
+ break ;
497
502
default :
498
503
zassert_true (false, "Undefined test case" );
499
504
}
@@ -3002,4 +3007,204 @@ ZTEST(net_tcp, test_server_ack_validation)
3002
3007
net_context_put (accepted_ctx );
3003
3008
}
3004
3009
3010
+ #define TEST_FIN_ACK_AFTER_DATA_REQ "request"
3011
+ #define TEST_FIN_ACK_AFTER_DATA_RSP "test data response"
3012
+
3013
+ /* In this test we check that FIN,ACK packet acknowledging latest data is
3014
+ * handled correctly by the TCP stack.
3015
+ */
3016
+ static void handle_server_fin_ack_after_data_test (sa_family_t af , struct tcphdr * th )
3017
+ {
3018
+ struct net_pkt * reply = NULL ;
3019
+
3020
+ zassert_false (th == NULL && t_state != T_SYN ,
3021
+ "NULL pkt only expected in T_SYN state" );
3022
+
3023
+ switch (t_state ) {
3024
+ case T_SYN :
3025
+ reply = prepare_syn_packet (af , htons (MY_PORT ), htons (PEER_PORT ));
3026
+ seq ++ ;
3027
+ t_state = T_SYN_ACK ;
3028
+ break ;
3029
+ case T_SYN_ACK :
3030
+ test_verify_flags (th , SYN | ACK );
3031
+ zassert_equal (ntohl (th -> th_ack ), seq ,
3032
+ "Unexpected ACK in T_SYN_ACK, got %d, expected %d" ,
3033
+ ntohl (th -> th_ack ), seq );
3034
+ device_initial_seq = ntohl (th -> th_seq );
3035
+ ack = ntohl (th -> th_seq ) + 1U ;
3036
+ t_state = T_DATA_ACK ;
3037
+
3038
+ /* Dummy "request" packet */
3039
+ reply = prepare_data_packet (af , htons (MY_PORT ), htons (PEER_PORT ),
3040
+ TEST_FIN_ACK_AFTER_DATA_REQ ,
3041
+ sizeof (TEST_FIN_ACK_AFTER_DATA_REQ ) - 1 );
3042
+ seq += sizeof (TEST_FIN_ACK_AFTER_DATA_REQ ) - 1 ;
3043
+ break ;
3044
+ case T_DATA_ACK :
3045
+ test_verify_flags (th , ACK );
3046
+ t_state = T_DATA ;
3047
+ zassert_equal (ntohl (th -> th_seq ), ack ,
3048
+ "Unexpected SEQ in T_DATA_ACK, got %d, expected %d" ,
3049
+ get_rel_seq (th ), ack );
3050
+ zassert_equal (ntohl (th -> th_ack ), seq ,
3051
+ "Unexpected ACK in T_DATA_ACK, got %d, expected %d" ,
3052
+ ntohl (th -> th_ack ), seq );
3053
+ break ;
3054
+ case T_DATA :
3055
+ test_verify_flags (th , PSH | ACK );
3056
+ zassert_equal (ntohl (th -> th_seq ), ack ,
3057
+ "Unexpected SEQ in T_DATA, got %d, expected %d" ,
3058
+ get_rel_seq (th ), ack );
3059
+ zassert_equal (ntohl (th -> th_ack ), seq ,
3060
+ "Unexpected ACK in T_DATA, got %d, expected %d" ,
3061
+ ntohl (th -> th_ack ), seq );
3062
+ ack += sizeof (TEST_FIN_ACK_AFTER_DATA_RSP ) - 1 ;
3063
+ t_state = T_FIN_ACK ;
3064
+
3065
+ reply = prepare_fin_ack_packet (af , htons (MY_PORT ), htons (PEER_PORT ));
3066
+ seq ++ ;
3067
+ break ;
3068
+ case T_FIN_ACK :
3069
+ test_verify_flags (th , FIN | ACK );
3070
+ zassert_equal (ntohl (th -> th_seq ), ack ,
3071
+ "Unexpected SEQ in T_FIN_ACK, got %d, expected %d" ,
3072
+ get_rel_seq (th ), ack );
3073
+ zassert_equal (ntohl (th -> th_ack ), seq ,
3074
+ "Unexpected ACK in T_FIN_ACK, got %d, expected %d" ,
3075
+ ntohl (th -> th_ack ), seq );
3076
+
3077
+ ack ++ ;
3078
+ t_state = T_CLOSING ;
3079
+
3080
+ reply = prepare_ack_packet (af , htons (MY_PORT ), htons (PEER_PORT ));
3081
+ seq ++ ;
3082
+ break ;
3083
+ case T_CLOSING :
3084
+ zassert_true (false, "Should not receive anything after final ACK" );
3085
+ break ;
3086
+ default :
3087
+ zassert_true (false, "%s unexpected state" , __func__ );
3088
+ return ;
3089
+ }
3090
+
3091
+ if (reply != NULL ) {
3092
+ zassert_ok (net_recv_data (net_iface , reply ), "%s failed" , __func__ );
3093
+ }
3094
+ }
3095
+
3096
+ /* Receive callback to be installed in the accept handler */
3097
+ static void test_fin_ack_after_data_recv_cb (struct net_context * context ,
3098
+ struct net_pkt * pkt ,
3099
+ union net_ip_header * ip_hdr ,
3100
+ union net_proto_header * proto_hdr ,
3101
+ int status ,
3102
+ void * user_data )
3103
+ {
3104
+ zassert_ok (status , "failed to recv the data" );
3105
+
3106
+ if (pkt != NULL ) {
3107
+ uint8_t buf [sizeof (TEST_FIN_ACK_AFTER_DATA_REQ )] = { 0 };
3108
+ int data_len = net_pkt_remaining_data (pkt );
3109
+
3110
+ zassert_equal (data_len , sizeof (TEST_FIN_ACK_AFTER_DATA_REQ ) - 1 ,
3111
+ "Invalid packet length, %d" , data_len );
3112
+ zassert_ok (net_pkt_read (pkt , buf , data_len ));
3113
+ zassert_mem_equal (buf , TEST_FIN_ACK_AFTER_DATA_REQ , data_len );
3114
+
3115
+ net_pkt_unref (pkt );
3116
+ }
3117
+
3118
+ test_sem_give ();
3119
+ }
3120
+
3121
+ static void test_fin_ack_after_data_accept_cb (struct net_context * ctx ,
3122
+ struct sockaddr * addr ,
3123
+ socklen_t addrlen ,
3124
+ int status ,
3125
+ void * user_data )
3126
+ {
3127
+ int ret ;
3128
+
3129
+ zassert_ok (status , "failed to accept the conn" );
3130
+
3131
+ /* set callback on newly created context */
3132
+ accepted_ctx = ctx ;
3133
+ ret = net_context_recv (ctx , test_fin_ack_after_data_recv_cb ,
3134
+ K_NO_WAIT , NULL );
3135
+ zassert_ok (ret , "Failed to recv data from peer" );
3136
+
3137
+ /* Ref the context on the app behalf. */
3138
+ net_context_ref (ctx );
3139
+ }
3140
+
3141
+ /* Verify that the TCP stack replies with a valid FIN,ACK after the peer
3142
+ * acknowledges the latest data in the FIN packet.
3143
+ * Test case scenario IPv4
3144
+ * send SYN,
3145
+ * expect SYN ACK,
3146
+ * send ACK with Data,
3147
+ * expect ACK,
3148
+ * expect Data,
3149
+ * send FIN,ACK
3150
+ * expect FIN,ACK
3151
+ * send ACK
3152
+ * any failures cause test case to fail.
3153
+ */
3154
+ ZTEST (net_tcp , test_server_fin_ack_after_data )
3155
+ {
3156
+ struct net_context * ctx ;
3157
+ int ret ;
3158
+
3159
+ test_case_no = TEST_SERVER_FIN_ACK_AFTER_DATA ;
3160
+
3161
+ t_state = T_SYN ;
3162
+ seq = ack = 0 ;
3163
+
3164
+ ret = net_context_get (AF_INET , SOCK_STREAM , IPPROTO_TCP , & ctx );
3165
+ zassert_ok (ret , "Failed to get net_context" );
3166
+
3167
+ net_context_ref (ctx );
3168
+
3169
+ ret = net_context_bind (ctx , (struct sockaddr * )& my_addr_s ,
3170
+ sizeof (struct sockaddr_in ));
3171
+ zassert_ok (ret , "Failed to bind net_context" );
3172
+
3173
+ /* Put context into listening mode and install accept cb */
3174
+ ret = net_context_listen (ctx , 1 );
3175
+ zassert_ok (ret , "Failed to listen on net_context" );
3176
+
3177
+ ret = net_context_accept (ctx , test_fin_ack_after_data_accept_cb ,
3178
+ K_NO_WAIT , NULL );
3179
+ zassert_ok (ret , "Failed to set accept on net_context" );
3180
+
3181
+ /* Trigger the peer to send SYN */
3182
+ handle_server_fin_ack_after_data_test (AF_INET , NULL );
3183
+
3184
+ /* test_fin_ack_after_data_recv_cb will release the semaphore after
3185
+ * dummy request is read.
3186
+ */
3187
+ test_sem_take (K_MSEC (100 ), __LINE__ );
3188
+
3189
+ /* Send dummy "response" */
3190
+ ret = net_context_send (accepted_ctx , TEST_FIN_ACK_AFTER_DATA_RSP ,
3191
+ sizeof (TEST_FIN_ACK_AFTER_DATA_RSP ) - 1 , NULL ,
3192
+ K_NO_WAIT , NULL );
3193
+ zassert_equal (ret , sizeof (TEST_FIN_ACK_AFTER_DATA_RSP ) - 1 ,
3194
+ "Failed to send data to peer %d" , ret );
3195
+
3196
+ /* test_fin_ack_after_data_recv_cb will release the semaphore after
3197
+ * the connection is marked closed.
3198
+ */
3199
+ test_sem_take (K_MSEC (100 ), __LINE__ );
3200
+
3201
+ net_context_put (ctx );
3202
+ net_context_put (accepted_ctx );
3203
+
3204
+ /* Connection is in TIME_WAIT state, context will be released
3205
+ * after K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY), so wait for it.
3206
+ */
3207
+ k_sleep (K_MSEC (CONFIG_NET_TCP_TIME_WAIT_DELAY ));
3208
+ }
3209
+
3005
3210
ZTEST_SUITE (net_tcp , NULL , presetup , NULL , NULL , NULL );
0 commit comments