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