@@ -134,6 +134,7 @@ static void handle_server_recv_out_of_order(struct net_pkt *pkt);
134
134
static void handle_server_rst_on_closed_port (sa_family_t af , struct tcphdr * th );
135
135
static void handle_server_rst_on_listening_port (sa_family_t af , struct tcphdr * th );
136
136
static void handle_syn_invalid_ack (sa_family_t af , struct tcphdr * th );
137
+ static void handle_client_fin_ack_with_data_test (sa_family_t af , struct tcphdr * th );
137
138
138
139
static void verify_flags (struct tcphdr * th , uint8_t flags ,
139
140
const char * fun , int line )
@@ -469,6 +470,10 @@ static int tester_send(const struct device *dev, struct net_pkt *pkt)
469
470
handle_syn_invalid_ack (net_pkt_family (pkt ), & th );
470
471
break ;
471
472
473
+ case 18 :
474
+ handle_client_fin_ack_with_data_test (net_pkt_family (pkt ), & th );
475
+ break ;
476
+
472
477
default :
473
478
zassert_true (false, "Undefined test case" );
474
479
}
@@ -2127,4 +2132,191 @@ ZTEST(net_tcp, test_client_rst_on_unexpected_ack_on_syn)
2127
2132
test_sem_take (K_MSEC (100 ), __LINE__ );
2128
2133
}
2129
2134
2135
+ #define TEST_FIN_DATA "test_data"
2136
+
2137
+ static enum fin_data_variant {
2138
+ FIN_DATA_FIN ,
2139
+ FIN_DATA_FIN_ACK ,
2140
+ FIN_DATA_FIN_ACK_PSH ,
2141
+ } test_fin_data_variant ;
2142
+
2143
+ static struct k_work_delayable test_fin_data_work ;
2144
+
2145
+ /* In this test we check that FIN packet containing data is handled correctly
2146
+ * by the TCP stack.
2147
+ */
2148
+ static void handle_client_fin_ack_with_data_test (sa_family_t af , struct tcphdr * th )
2149
+ {
2150
+ static uint16_t peer_port ;
2151
+ struct net_pkt * reply ;
2152
+ uint8_t flags = 0 ;
2153
+
2154
+ switch (t_state ) {
2155
+ case T_SYN :
2156
+ test_verify_flags (th , SYN );
2157
+ device_initial_seq = ntohl (th -> th_seq );
2158
+ seq = 0U ;
2159
+ ack = ntohl (th -> th_seq ) + 1U ;
2160
+ peer_port = th -> th_sport ;
2161
+ reply = prepare_syn_ack_packet (af , htons (MY_PORT ), peer_port );
2162
+ seq ++ ;
2163
+ t_state = T_SYN_ACK ;
2164
+ break ;
2165
+ case T_SYN_ACK :
2166
+ test_verify_flags (th , ACK );
2167
+ t_state = T_DATA ;
2168
+
2169
+ /* FIN packet with DATA needs to be rescheduled for later - if
2170
+ * we send it here, the net_context_recv() won't have a chance
2171
+ * to execute, hence no callback will be registered and data
2172
+ * will be dropped.
2173
+ */
2174
+ k_work_reschedule (& test_fin_data_work , K_MSEC (1 ));
2175
+ return ;
2176
+ case T_DATA :
2177
+ switch (test_fin_data_variant ) {
2178
+ case FIN_DATA_FIN :
2179
+ flags = FIN ;
2180
+ t_state = T_FIN ;
2181
+ break ;
2182
+ case FIN_DATA_FIN_ACK :
2183
+ flags = FIN | ACK ;
2184
+ t_state = T_FIN_ACK ;
2185
+ break ;
2186
+ case FIN_DATA_FIN_ACK_PSH :
2187
+ flags = FIN | ACK | PSH ;
2188
+ t_state = T_FIN_ACK ;
2189
+ break ;
2190
+ }
2191
+
2192
+ reply = tester_prepare_tcp_pkt (af , htons (MY_PORT ), peer_port ,
2193
+ flags , TEST_FIN_DATA ,
2194
+ strlen (TEST_FIN_DATA ));
2195
+ seq += strlen (TEST_FIN_DATA ) + 1 ;
2196
+
2197
+ break ;
2198
+ case T_FIN :
2199
+ test_verify_flags (th , ACK );
2200
+ zassert_equal (get_rel_seq (th ), 1 , "Unexpected SEQ number in T_FIN, got %d" ,
2201
+ get_rel_seq (th ));
2202
+ zassert_equal (ntohl (th -> th_ack ), seq , "Unexpected ACK in T_FIN, got %d" ,
2203
+ ntohl (th -> th_ack ));
2204
+
2205
+ t_state = T_CLOSING ;
2206
+ return ;
2207
+ case T_FIN_ACK :
2208
+ test_verify_flags (th , FIN | ACK );
2209
+ zassert_equal (get_rel_seq (th ), 1 , "Unexpected SEQ number in T_FIN_ACK, got %d" ,
2210
+ get_rel_seq (th ));
2211
+ zassert_equal (ntohl (th -> th_ack ), seq , "Unexpected ACK in T_FIN_ACK, got %d" ,
2212
+ ntohl (th -> th_ack ));
2213
+
2214
+ ack ++ ;
2215
+ reply = prepare_ack_packet (af , htons (MY_PORT ), peer_port );
2216
+ t_state = T_SYN ;
2217
+ break ;
2218
+
2219
+ case T_CLOSING :
2220
+ test_verify_flags (th , FIN );
2221
+ zassert_equal (get_rel_seq (th ), 1 , "Unexpected SEQ number in T_CLOSING, got %d" ,
2222
+ get_rel_seq (th ));
2223
+
2224
+ ack ++ ;
2225
+ reply = prepare_ack_packet (af , htons (MY_PORT ), peer_port );
2226
+ t_state = T_SYN ;
2227
+ break ;
2228
+
2229
+ default :
2230
+ zassert_true (false, "%s unexpected state" , __func__ );
2231
+ return ;
2232
+ }
2233
+
2234
+ zassert_ok (net_recv_data (net_iface , reply ), "%s failed" , __func__ );
2235
+ }
2236
+
2237
+
2238
+ static void test_fin_data_handler (struct k_work * work )
2239
+ {
2240
+ ARG_UNUSED (work );
2241
+
2242
+ handle_client_fin_ack_with_data_test (AF_INET , NULL );
2243
+ }
2244
+
2245
+ static void test_fin_ack_data_recv_cb (struct net_context * context ,
2246
+ struct net_pkt * pkt ,
2247
+ union net_ip_header * ip_hdr ,
2248
+ union net_proto_header * proto_hdr ,
2249
+ int status ,
2250
+ void * user_data )
2251
+ {
2252
+ if (status ) {
2253
+ zassert_true (false, "failed to recv the data" );
2254
+ }
2255
+
2256
+ if (pkt ) {
2257
+ uint8_t buf [sizeof (TEST_FIN_DATA )] = { 0 };
2258
+ int data_len = net_pkt_remaining_data (pkt );
2259
+
2260
+ zassert_equal (data_len , strlen (TEST_FIN_DATA ),
2261
+ "Invalid packet length, %d" , data_len );
2262
+ zassert_ok (net_pkt_read (pkt , buf , data_len ));
2263
+ zassert_mem_equal (buf , TEST_FIN_DATA , data_len );
2264
+
2265
+ net_pkt_unref (pkt );
2266
+ }
2267
+
2268
+ test_sem_give ();
2269
+ }
2270
+
2271
+ /* Test case scenario IPv4
2272
+ * expect SYN,
2273
+ * send SYN ACK,
2274
+ * expect ACK,
2275
+ * send FIN/FIN,ACK/FIN,ACK,PSH with Data,
2276
+ * expect FIN/FIN,ACK/ACK,
2277
+ * send ACK
2278
+ * any failures cause test case to fail.
2279
+ */
2280
+ ZTEST (net_tcp , test_client_fin_ack_with_data )
2281
+ {
2282
+ struct net_context * ctx ;
2283
+
2284
+ test_case_no = 18 ;
2285
+
2286
+ k_work_init_delayable (& test_fin_data_work , test_fin_data_handler );
2287
+
2288
+ for (enum fin_data_variant variant = FIN_DATA_FIN ;
2289
+ variant <= FIN_DATA_FIN_ACK_PSH ; variant ++ ) {
2290
+ test_fin_data_variant = variant ;
2291
+ t_state = T_SYN ;
2292
+ seq = ack = 0 ;
2293
+
2294
+ zassert_ok (net_context_get (AF_INET , SOCK_STREAM , IPPROTO_TCP , & ctx ),
2295
+ "Failed to get net_context" );
2296
+
2297
+ net_context_ref (ctx );
2298
+
2299
+ zassert_ok (net_context_connect (ctx , (struct sockaddr * )& peer_addr_s ,
2300
+ sizeof (struct sockaddr_in ), NULL ,
2301
+ K_MSEC (1000 ), NULL ),
2302
+ "Failed to connect to peer" );
2303
+ zassert_ok (net_context_recv (ctx , test_fin_ack_data_recv_cb ,
2304
+ K_NO_WAIT , NULL ),
2305
+ "Failed to recv data from peer" );
2306
+
2307
+ /* Take sem twice, one for data packet, second for conn close
2308
+ * (NULL net_pkt).
2309
+ */
2310
+ test_sem_take (K_MSEC (100 ), __LINE__ );
2311
+ test_sem_take (K_MSEC (100 ), __LINE__ );
2312
+
2313
+ net_context_put (ctx );
2314
+
2315
+ /* Connection is in TIME_WAIT state, context will be released
2316
+ * after K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY), so wait for it.
2317
+ */
2318
+ k_sleep (K_MSEC (CONFIG_NET_TCP_TIME_WAIT_DELAY ));
2319
+ }
2320
+ }
2321
+
2130
2322
ZTEST_SUITE (net_tcp , NULL , presetup , NULL , NULL , NULL );
0 commit comments