Line data Source code
1 : /*
2 : * Copyright (c) 2017 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 :
16 : #include <vnet/session/application_namespace.h>
17 : #include <vnet/session/application_interface.h>
18 : #include <vnet/session/application.h>
19 : #include <vnet/session/session.h>
20 : #include <vnet/session/session_rules_table.h>
21 : #include <vnet/tcp/tcp.h>
22 : #include <sys/epoll.h>
23 :
24 : #define SESSION_TEST_I(_cond, _comment, _args...) \
25 : ({ \
26 : int _evald = (_cond); \
27 : if (!(_evald)) { \
28 : fformat(stderr, "FAIL:%d: " _comment "\n", \
29 : __LINE__, ##_args); \
30 : } else { \
31 : fformat(stderr, "PASS:%d: " _comment "\n", \
32 : __LINE__, ##_args); \
33 : } \
34 : _evald; \
35 : })
36 :
37 : #define SESSION_TEST(_cond, _comment, _args...) \
38 : { \
39 : if (!SESSION_TEST_I(_cond, _comment, ##_args)) { \
40 : return 1; \
41 : } \
42 : }
43 :
44 : #define ST_DBG(_comment, _args...) \
45 : fformat(stderr, _comment "\n", ##_args); \
46 :
47 : void
48 0 : placeholder_session_reset_callback (session_t * s)
49 : {
50 0 : clib_warning ("called...");
51 0 : }
52 :
53 : volatile u32 connected_session_index = ~0;
54 : volatile u32 connected_session_thread = ~0;
55 : int
56 1 : placeholder_session_connected_callback (u32 app_index, u32 api_context,
57 : session_t * s, session_error_t err)
58 : {
59 1 : if (s)
60 : {
61 1 : connected_session_index = s->session_index;
62 1 : connected_session_thread = s->thread_index;
63 : }
64 1 : return 0;
65 : }
66 :
67 : static u32 placeholder_segment_count;
68 :
69 : int
70 3 : placeholder_add_segment_callback (u32 client_index, u64 segment_handle)
71 : {
72 3 : placeholder_segment_count = 1;
73 3 : return 0;
74 : }
75 :
76 : int
77 0 : placeholder_del_segment_callback (u32 client_index, u64 segment_handle)
78 : {
79 0 : placeholder_segment_count = 0;
80 0 : return 0;
81 : }
82 :
83 : void
84 0 : placeholder_session_disconnect_callback (session_t * s)
85 : {
86 0 : clib_warning ("called...");
87 0 : }
88 :
89 : static u32 placeholder_accept;
90 : volatile u32 accepted_session_index;
91 : volatile u32 accepted_session_thread;
92 :
93 : int
94 2 : placeholder_session_accept_callback (session_t * s)
95 : {
96 2 : placeholder_accept = 1;
97 2 : accepted_session_index = s->session_index;
98 2 : accepted_session_thread = s->thread_index;
99 2 : s->session_state = SESSION_STATE_READY;
100 2 : return 0;
101 : }
102 :
103 : int
104 0 : placeholder_server_rx_callback (session_t * s)
105 : {
106 0 : clib_warning ("called...");
107 0 : return -1;
108 : }
109 :
110 : /* *INDENT-OFF* */
111 : static session_cb_vft_t placeholder_session_cbs = {
112 : .session_reset_callback = placeholder_session_reset_callback,
113 : .session_connected_callback = placeholder_session_connected_callback,
114 : .session_accept_callback = placeholder_session_accept_callback,
115 : .session_disconnect_callback = placeholder_session_disconnect_callback,
116 : .builtin_app_rx_callback = placeholder_server_rx_callback,
117 : .add_segment_callback = placeholder_add_segment_callback,
118 : .del_segment_callback = placeholder_del_segment_callback,
119 : };
120 : /* *INDENT-ON* */
121 :
122 : static int
123 4 : session_create_lookpback (u32 table_id, u32 * sw_if_index,
124 : ip4_address_t * intf_addr)
125 : {
126 : u8 intf_mac[6];
127 :
128 4 : clib_memset (intf_mac, 0, sizeof (intf_mac));
129 :
130 4 : if (vnet_create_loopback_interface (sw_if_index, intf_mac, 0, 0))
131 : {
132 0 : clib_warning ("couldn't create loopback. stopping the test!");
133 0 : return -1;
134 : }
135 :
136 4 : if (table_id != 0)
137 : {
138 1 : ip_table_create (FIB_PROTOCOL_IP4, table_id, 0, 0);
139 1 : ip_table_bind (FIB_PROTOCOL_IP4, *sw_if_index, table_id);
140 : }
141 :
142 4 : vnet_sw_interface_set_flags (vnet_get_main (), *sw_if_index,
143 : VNET_SW_INTERFACE_FLAG_ADMIN_UP);
144 :
145 4 : if (ip4_add_del_interface_address (vlib_get_main (), *sw_if_index,
146 : intf_addr, 24, 0))
147 : {
148 0 : clib_warning ("couldn't assign loopback ip %U", format_ip4_address,
149 : intf_addr);
150 0 : return -1;
151 : }
152 :
153 4 : return 0;
154 : }
155 :
156 : static void
157 4 : session_delete_loopback (u32 sw_if_index)
158 : {
159 : /* fails spectacularly */
160 : /* vnet_delete_loopback_interface (sw_if_index); */
161 :
162 4 : vnet_sw_interface_set_flags (vnet_get_main (), sw_if_index, 0);
163 4 : }
164 :
165 : static int
166 1 : session_test_basic (vlib_main_t * vm, unformat_input_t * input)
167 : {
168 1 : session_endpoint_cfg_t server_sep = SESSION_ENDPOINT_CFG_NULL;
169 : u64 options[APP_OPTIONS_N_OPTIONS], bind4_handle, bind6_handle;
170 : u32 server_index;
171 1 : int error = 0;
172 :
173 1 : clib_memset (options, 0, sizeof (options));
174 1 : options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
175 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
176 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
177 2 : vnet_app_attach_args_t attach_args = {
178 : .api_client_index = ~0,
179 : .options = options,
180 : .namespace_id = 0,
181 : .session_cb_vft = &placeholder_session_cbs,
182 1 : .name = format (0, "session_test"),
183 : };
184 :
185 1 : error = vnet_application_attach (&attach_args);
186 1 : SESSION_TEST ((error == 0), "app attached");
187 1 : server_index = attach_args.app_index;
188 1 : vec_free (attach_args.name);
189 :
190 1 : server_sep.is_ip4 = 1;
191 1 : vnet_listen_args_t bind_args = {
192 : .sep_ext = server_sep,
193 : .app_index = 0,
194 : .wrk_map_index = 0,
195 : };
196 :
197 1 : bind_args.app_index = server_index;
198 1 : error = vnet_listen (&bind_args);
199 1 : SESSION_TEST ((error == 0), "server bind4 should work");
200 1 : bind4_handle = bind_args.handle;
201 :
202 1 : error = vnet_listen (&bind_args);
203 1 : SESSION_TEST ((error != 0), "double server bind4 should not work");
204 :
205 1 : bind_args.sep.is_ip4 = 0;
206 1 : error = vnet_listen (&bind_args);
207 1 : SESSION_TEST ((error == 0), "server bind6 should work");
208 1 : bind6_handle = bind_args.handle;
209 :
210 1 : error = vnet_listen (&bind_args);
211 1 : SESSION_TEST ((error != 0), "double server bind6 should not work");
212 :
213 1 : vnet_unlisten_args_t unbind_args = {
214 : .handle = bind4_handle,
215 : .app_index = server_index,
216 : };
217 1 : error = vnet_unlisten (&unbind_args);
218 1 : SESSION_TEST ((error == 0), "unbind4 should work");
219 :
220 1 : unbind_args.handle = bind6_handle;
221 1 : error = vnet_unlisten (&unbind_args);
222 1 : SESSION_TEST ((error == 0), "unbind6 should work");
223 :
224 1 : vnet_app_detach_args_t detach_args = {
225 : .app_index = server_index,
226 : .api_client_index = ~0,
227 : };
228 1 : vnet_application_detach (&detach_args);
229 1 : return 0;
230 : }
231 :
232 : static void
233 4 : session_add_del_route_via_lookup_in_table (u32 in_table_id, u32 via_table_id,
234 : ip4_address_t * ip, u8 mask,
235 : u8 is_add)
236 : {
237 4 : fib_route_path_t *rpaths = 0, *rpath;
238 : u32 in_fib_index, via_fib_index;
239 :
240 4 : fib_prefix_t prefix = {
241 4 : .fp_addr.ip4.as_u32 = ip->as_u32,
242 : .fp_len = mask,
243 : .fp_proto = FIB_PROTOCOL_IP4,
244 : };
245 :
246 4 : via_fib_index = fib_table_find (FIB_PROTOCOL_IP4, via_table_id);
247 4 : if (via_fib_index == ~0)
248 : {
249 0 : clib_warning ("couldn't resolve via table id to index");
250 0 : return;
251 : }
252 4 : in_fib_index = fib_table_find (FIB_PROTOCOL_IP4, in_table_id);
253 4 : if (in_fib_index == ~0)
254 : {
255 0 : clib_warning ("couldn't resolve in table id to index");
256 0 : return;
257 : }
258 :
259 4 : vec_add2 (rpaths, rpath, 1);
260 4 : clib_memset (rpath, 0, sizeof (*rpath));
261 4 : rpath->frp_weight = 1;
262 4 : rpath->frp_fib_index = via_fib_index;
263 4 : rpath->frp_proto = DPO_PROTO_IP4;
264 4 : rpath->frp_sw_if_index = ~0;
265 4 : rpath->frp_flags |= FIB_ROUTE_PATH_DEAG;
266 :
267 4 : if (is_add)
268 2 : fib_table_entry_path_add2 (in_fib_index, &prefix, FIB_SOURCE_CLI,
269 : FIB_ENTRY_FLAG_NONE, rpath);
270 : else
271 2 : fib_table_entry_path_remove2 (in_fib_index, &prefix, FIB_SOURCE_CLI,
272 : rpath);
273 4 : vec_free (rpaths);
274 : }
275 :
276 : static int
277 1 : session_test_endpoint_cfg (vlib_main_t * vm, unformat_input_t * input)
278 : {
279 1 : session_endpoint_cfg_t client_sep = SESSION_ENDPOINT_CFG_NULL;
280 1 : u32 server_index, client_index, sw_if_index[2], tries = 0;
281 1 : u64 options[APP_OPTIONS_N_OPTIONS], placeholder_secret = 1234;
282 1 : u16 placeholder_server_port = 1234, placeholder_client_port = 5678;
283 1 : session_endpoint_cfg_t server_sep = SESSION_ENDPOINT_CFG_NULL;
284 : ip4_address_t intf_addr[3];
285 : transport_connection_t *tc;
286 : session_t *s;
287 : u8 *appns_id;
288 : int error;
289 :
290 : /*
291 : * Create the loopbacks
292 : */
293 1 : intf_addr[0].as_u32 = clib_host_to_net_u32 (0x01010101);
294 1 : session_create_lookpback (0, &sw_if_index[0], &intf_addr[0]);
295 :
296 1 : intf_addr[1].as_u32 = clib_host_to_net_u32 (0x02020202);
297 1 : session_create_lookpback (1, &sw_if_index[1], &intf_addr[1]);
298 :
299 1 : session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
300 : 1 /* is_add */ );
301 1 : session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
302 : 1 /* is_add */ );
303 :
304 : /*
305 : * Insert namespace
306 : */
307 1 : appns_id = format (0, "appns1");
308 1 : vnet_app_namespace_add_del_args_t ns_args = {
309 : .ns_id = appns_id,
310 : .secret = placeholder_secret,
311 1 : .sw_if_index = sw_if_index[1],
312 : .ip4_fib_id = 0,
313 : .is_add = 1
314 : };
315 1 : error = vnet_app_namespace_add_del (&ns_args);
316 1 : SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
317 :
318 : /*
319 : * Attach client/server
320 : */
321 1 : clib_memset (options, 0, sizeof (options));
322 1 : options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
323 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
324 :
325 2 : vnet_app_attach_args_t attach_args = {
326 : .api_client_index = ~0,
327 : .options = options,
328 : .namespace_id = 0,
329 : .session_cb_vft = &placeholder_session_cbs,
330 1 : .name = format (0, "session_test_client"),
331 : };
332 :
333 1 : error = vnet_application_attach (&attach_args);
334 1 : SESSION_TEST ((error == 0), "client app attached");
335 1 : client_index = attach_args.app_index;
336 1 : vec_free (attach_args.name);
337 :
338 1 : attach_args.name = format (0, "session_test_server");
339 1 : attach_args.namespace_id = appns_id;
340 : /* Allow server to allocate another segment for listens. Needed
341 : * because by default we do not allow segment additions */
342 1 : attach_args.options[APP_OPTIONS_ADD_SEGMENT_SIZE] = 32 << 20;
343 1 : attach_args.options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret;
344 1 : error = vnet_application_attach (&attach_args);
345 1 : SESSION_TEST ((error == 0), "server app attached: %U", format_clib_error,
346 : error);
347 1 : vec_free (attach_args.name);
348 1 : server_index = attach_args.app_index;
349 :
350 1 : server_sep.is_ip4 = 1;
351 1 : server_sep.port = placeholder_server_port;
352 1 : vnet_listen_args_t bind_args = {
353 : .sep_ext = server_sep,
354 : .app_index = server_index,
355 : };
356 1 : error = vnet_listen (&bind_args);
357 1 : SESSION_TEST ((error == 0), "server bind should work");
358 :
359 : /*
360 : * Connect and force lcl ip
361 : */
362 1 : client_sep.is_ip4 = 1;
363 1 : client_sep.ip.ip4.as_u32 = clib_host_to_net_u32 (0x02020202);
364 1 : client_sep.port = placeholder_server_port;
365 1 : client_sep.peer.is_ip4 = 1;
366 1 : client_sep.peer.ip.ip4.as_u32 = clib_host_to_net_u32 (0x01010101);
367 1 : client_sep.peer.port = placeholder_client_port;
368 1 : client_sep.transport_proto = TRANSPORT_PROTO_TCP;
369 :
370 1 : vnet_connect_args_t connect_args = {
371 : .sep_ext = client_sep,
372 : .app_index = client_index,
373 : };
374 :
375 1 : connected_session_index = connected_session_thread = ~0;
376 1 : accepted_session_index = accepted_session_thread = ~0;
377 1 : error = vnet_connect (&connect_args);
378 1 : SESSION_TEST ((error == 0), "connect should work");
379 :
380 : /* wait for stuff to happen */
381 2 : while (connected_session_index == ~0 && ++tries < 100)
382 : {
383 1 : vlib_worker_thread_barrier_release (vm);
384 1 : vlib_process_suspend (vm, 100e-3);
385 1 : vlib_worker_thread_barrier_sync (vm);
386 : }
387 1 : while (accepted_session_index == ~0 && ++tries < 100)
388 : {
389 0 : vlib_worker_thread_barrier_release (vm);
390 0 : vlib_process_suspend (vm, 100e-3);
391 0 : vlib_worker_thread_barrier_sync (vm);
392 : }
393 :
394 1 : clib_warning ("waited %.1f seconds for connections", tries / 10.0);
395 1 : SESSION_TEST ((connected_session_index != ~0), "session should exist");
396 1 : SESSION_TEST ((connected_session_thread != ~0), "thread should exist");
397 1 : SESSION_TEST ((accepted_session_index != ~0), "session should exist");
398 1 : SESSION_TEST ((accepted_session_thread != ~0), "thread should exist");
399 1 : s = session_get (connected_session_index, connected_session_thread);
400 1 : tc = session_get_transport (s);
401 1 : SESSION_TEST ((tc != 0), "transport should exist");
402 1 : SESSION_TEST ((memcmp (&tc->lcl_ip, &client_sep.peer.ip,
403 : sizeof (tc->lcl_ip)) == 0), "ips should be equal");
404 1 : SESSION_TEST ((tc->lcl_port == placeholder_client_port),
405 : "ports should be equal");
406 :
407 1 : vnet_app_detach_args_t detach_args = {
408 : .app_index = server_index,
409 : .api_client_index = ~0,
410 : };
411 1 : vnet_application_detach (&detach_args);
412 1 : detach_args.app_index = client_index;
413 1 : vnet_application_detach (&detach_args);
414 :
415 1 : ns_args.is_add = 0;
416 1 : error = vnet_app_namespace_add_del (&ns_args);
417 1 : SESSION_TEST ((error == 0), "app ns delete should succeed: %d", error);
418 :
419 : /* Allow the disconnects to finish before removing the routes. */
420 1 : vlib_process_suspend (vm, 10e-3);
421 :
422 1 : session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
423 : 0 /* is_add */ );
424 1 : session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
425 : 0 /* is_add */ );
426 :
427 1 : session_delete_loopback (sw_if_index[0]);
428 1 : session_delete_loopback (sw_if_index[1]);
429 1 : return 0;
430 : }
431 :
432 : static int
433 1 : session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
434 : {
435 1 : u64 options[APP_OPTIONS_N_OPTIONS], placeholder_secret = 1234, tries;
436 : u32 server_index, server_st_index, server_local_st_index;
437 1 : u32 placeholder_port = 1234, client_index, server_wrk_index;
438 1 : u32 placeholder_api_context = 4321, placeholder_client_api_index = ~0;
439 1 : u32 placeholder_server_api_index = ~0, sw_if_index = 0;
440 1 : session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
441 1 : session_endpoint_t client_sep = SESSION_ENDPOINT_NULL;
442 1 : session_endpoint_t intf_sep = SESSION_ENDPOINT_NULL;
443 : u8 *ns_id, *server_name, *client_name;
444 : app_namespace_t *app_ns;
445 : application_t *server;
446 : session_t *s;
447 : u64 handle;
448 1 : int error = 0;
449 :
450 1 : ns_id = format (0, "appns1");
451 1 : server_name = format (0, "session_test");
452 1 : client_name = format (0, "session_test_client");
453 :
454 1 : server_sep.is_ip4 = 1;
455 1 : server_sep.port = placeholder_port;
456 1 : client_sep.is_ip4 = 1;
457 1 : client_sep.port = placeholder_port;
458 1 : clib_memset (options, 0, sizeof (options));
459 :
460 1 : options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
461 1 : vnet_app_attach_args_t attach_args = {
462 : .api_client_index = ~0,
463 : .options = options,
464 : .namespace_id = 0,
465 : .session_cb_vft = &placeholder_session_cbs,
466 : .name = server_name,
467 : };
468 :
469 1 : vnet_listen_args_t bind_args = {
470 : .sep = server_sep,
471 : .app_index = 0,
472 : };
473 :
474 1 : vnet_connect_args_t connect_args = {
475 : .app_index = 0,
476 : .api_context = 0,
477 : };
478 1 : clib_memcpy (&connect_args.sep, &client_sep, sizeof (client_sep));
479 :
480 1 : vnet_unlisten_args_t unbind_args = {
481 1 : .handle = bind_args.handle,
482 : .app_index = 0,
483 : };
484 :
485 1 : vnet_app_detach_args_t detach_args = {
486 : .app_index = 0,
487 : .api_client_index = ~0,
488 : };
489 :
490 1 : ip4_address_t intf_addr = {
491 1 : .as_u32 = clib_host_to_net_u32 (0x07000105),
492 : };
493 :
494 1 : intf_sep.ip.ip4 = intf_addr;
495 1 : intf_sep.is_ip4 = 1;
496 1 : intf_sep.port = placeholder_port;
497 :
498 : /*
499 : * Insert namespace and lookup
500 : */
501 :
502 1 : vnet_app_namespace_add_del_args_t ns_args = {
503 : .ns_id = ns_id,
504 : .secret = placeholder_secret,
505 : .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
506 : .is_add = 1
507 : };
508 1 : error = vnet_app_namespace_add_del (&ns_args);
509 1 : SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
510 :
511 1 : app_ns = app_namespace_get_from_id (ns_id);
512 1 : SESSION_TEST ((app_ns != 0), "should find ns %v status", ns_id);
513 1 : SESSION_TEST ((app_ns->ns_secret == placeholder_secret),
514 : "secret should be %d", placeholder_secret);
515 1 : SESSION_TEST ((app_ns->sw_if_index == APP_NAMESPACE_INVALID_INDEX),
516 : "sw_if_index should be invalid");
517 :
518 : /*
519 : * Try application attach with wrong secret
520 : */
521 :
522 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
523 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
524 1 : options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret - 1;
525 1 : attach_args.namespace_id = ns_id;
526 1 : attach_args.api_client_index = placeholder_server_api_index;
527 :
528 1 : error = vnet_application_attach (&attach_args);
529 1 : SESSION_TEST ((error != 0), "app attachment should fail");
530 1 : SESSION_TEST ((error == VNET_API_ERROR_APP_WRONG_NS_SECRET),
531 : "code should be wrong ns secret: %d", error);
532 :
533 : /*
534 : * Attach server with global default scope
535 : */
536 1 : options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
537 1 : options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
538 1 : options[APP_OPTIONS_NAMESPACE_SECRET] = 0;
539 1 : attach_args.namespace_id = 0;
540 1 : attach_args.api_client_index = placeholder_server_api_index;
541 1 : error = vnet_application_attach (&attach_args);
542 1 : SESSION_TEST ((error == 0), "server attachment should work");
543 1 : server_index = attach_args.app_index;
544 1 : server = application_get (server_index);
545 1 : server_wrk_index = application_get_default_worker (server)->wrk_index;
546 1 : SESSION_TEST ((server->ns_index == 0),
547 : "server should be in the default ns");
548 :
549 1 : bind_args.app_index = server_index;
550 1 : error = vnet_listen (&bind_args);
551 1 : SESSION_TEST ((error == 0), "server bind should work");
552 :
553 1 : server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
554 1 : s = session_lookup_listener (server_st_index, &server_sep);
555 1 : SESSION_TEST ((s != 0), "listener should exist in global table");
556 1 : SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
557 : " that of the server");
558 1 : server_local_st_index = application_local_session_table (server);
559 1 : SESSION_TEST ((server_local_st_index == APP_INVALID_INDEX),
560 : "server shouldn't have access to local table");
561 :
562 1 : unbind_args.app_index = server_index;
563 1 : unbind_args.handle = bind_args.handle;
564 1 : error = vnet_unlisten (&unbind_args);
565 1 : SESSION_TEST ((error == 0), "unbind should work");
566 :
567 1 : s = session_lookup_listener (server_st_index, &server_sep);
568 1 : SESSION_TEST ((s == 0), "listener should not exist in global table");
569 :
570 1 : detach_args.app_index = server_index;
571 1 : vnet_application_detach (&detach_args);
572 :
573 : /*
574 : * Attach server with local and global scope
575 : */
576 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
577 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
578 1 : options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret;
579 1 : attach_args.namespace_id = ns_id;
580 1 : attach_args.api_client_index = placeholder_server_api_index;
581 1 : error = vnet_application_attach (&attach_args);
582 1 : SESSION_TEST ((error == 0), "server attachment should work");
583 1 : server_index = attach_args.app_index;
584 1 : server = application_get (server_index);
585 1 : server_wrk_index = application_get_default_worker (server)->wrk_index;
586 1 : SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
587 : "server should be in the right ns");
588 :
589 1 : bind_args.app_index = server_index;
590 1 : error = vnet_listen (&bind_args);
591 1 : SESSION_TEST ((error == 0), "bind should work");
592 1 : server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
593 1 : s = session_lookup_listener (server_st_index, &server_sep);
594 1 : SESSION_TEST ((s != 0), "listener should exist in global table");
595 1 : SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
596 : " that of the server");
597 1 : server_local_st_index = application_local_session_table (server);
598 1 : handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
599 1 : SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
600 : "listener should exist in local table");
601 :
602 : /*
603 : * Try client connect with 1) local scope 2) global scope
604 : */
605 1 : options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
606 1 : attach_args.name = client_name;
607 1 : attach_args.api_client_index = placeholder_client_api_index;
608 1 : error = vnet_application_attach (&attach_args);
609 1 : SESSION_TEST ((error == 0), "client attachment should work");
610 1 : client_index = attach_args.app_index;
611 1 : connect_args.api_context = placeholder_api_context;
612 1 : connect_args.app_index = client_index;
613 1 : error = vnet_connect (&connect_args);
614 1 : SESSION_TEST ((error != 0), "client connect should return error code");
615 1 : SESSION_TEST ((error == SESSION_E_INVALID_RMT_IP),
616 : "error code should be invalid value (zero ip)");
617 1 : SESSION_TEST ((placeholder_segment_count == 0),
618 : "shouldn't have received request to map new segment");
619 1 : connect_args.sep.ip.ip4.as_u8[0] = 127;
620 1 : error = vnet_connect (&connect_args);
621 1 : SESSION_TEST ((error == 0), "client connect should not return error code");
622 :
623 : /* wait for accept */
624 1 : tries = 0;
625 2 : while (!placeholder_accept && ++tries < 100)
626 : {
627 1 : vlib_worker_thread_barrier_release (vm);
628 1 : vlib_process_suspend (vm, 100e-3);
629 1 : vlib_worker_thread_barrier_sync (vm);
630 : }
631 :
632 1 : SESSION_TEST ((placeholder_segment_count == 1),
633 : "should've received request to map new segment");
634 1 : SESSION_TEST ((placeholder_accept == 1),
635 : "should've received accept request");
636 1 : detach_args.app_index = client_index;
637 1 : vnet_application_detach (&detach_args);
638 :
639 1 : options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
640 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
641 1 : attach_args.api_client_index = placeholder_client_api_index;
642 1 : error = vnet_application_attach (&attach_args);
643 1 : SESSION_TEST ((error == 0), "client attachment should work");
644 1 : error = vnet_connect (&connect_args);
645 1 : SESSION_TEST ((error != 0), "client connect should return error code");
646 1 : SESSION_TEST ((error == SESSION_E_NOINTF),
647 : "error code should be connect (nothing in local scope)");
648 1 : detach_args.app_index = client_index;
649 1 : vnet_application_detach (&detach_args);
650 :
651 : /*
652 : * Unbind and detach server and then re-attach with local scope only
653 : */
654 1 : unbind_args.handle = bind_args.handle;
655 1 : unbind_args.app_index = server_index;
656 1 : error = vnet_unlisten (&unbind_args);
657 1 : SESSION_TEST ((error == 0), "unbind should work");
658 :
659 1 : s = session_lookup_listener (server_st_index, &server_sep);
660 1 : SESSION_TEST ((s == 0), "listener should not exist in global table");
661 1 : handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
662 1 : SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
663 : "listener should not exist in local table");
664 :
665 1 : detach_args.app_index = server_index;
666 1 : vnet_application_detach (&detach_args);
667 :
668 1 : options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
669 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
670 1 : attach_args.api_client_index = placeholder_server_api_index;
671 1 : attach_args.name = server_name;
672 1 : error = vnet_application_attach (&attach_args);
673 1 : SESSION_TEST ((error == 0), "app attachment should work");
674 1 : server_index = attach_args.app_index;
675 1 : server = application_get (server_index);
676 1 : SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
677 : "app should be in the right ns");
678 :
679 1 : bind_args.app_index = server_index;
680 1 : error = vnet_listen (&bind_args);
681 1 : SESSION_TEST ((error == 0), "bind should work");
682 :
683 1 : server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
684 1 : s = session_lookup_listener (server_st_index, &server_sep);
685 1 : SESSION_TEST ((s == 0), "listener should not exist in global table");
686 1 : server_local_st_index = application_local_session_table (server);
687 1 : handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
688 1 : SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
689 : "listener should exist in local table");
690 :
691 1 : unbind_args.handle = bind_args.handle;
692 1 : error = vnet_unlisten (&unbind_args);
693 1 : SESSION_TEST ((error == 0), "unbind should work");
694 :
695 1 : handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
696 1 : SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
697 : "listener should not exist in local table");
698 :
699 : /*
700 : * Client attach + connect in default ns with local scope
701 : */
702 1 : options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
703 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
704 1 : attach_args.namespace_id = 0;
705 1 : attach_args.api_client_index = placeholder_client_api_index;
706 1 : attach_args.name = client_name;
707 1 : vnet_application_attach (&attach_args);
708 1 : error = vnet_connect (&connect_args);
709 1 : SESSION_TEST ((error != 0), "client connect should return error code");
710 1 : SESSION_TEST ((error == SESSION_E_NOROUTE),
711 : "error code should be noroute (not in same ns)");
712 1 : detach_args.app_index = client_index;
713 1 : vnet_application_detach (&detach_args);
714 :
715 : /*
716 : * Detach server
717 : */
718 1 : detach_args.app_index = server_index;
719 1 : vnet_application_detach (&detach_args);
720 :
721 : /*
722 : * Create loopback interface
723 : */
724 1 : session_create_lookpback (0, &sw_if_index, &intf_addr);
725 :
726 : /*
727 : * Update namespace with interface
728 : */
729 1 : ns_args.sw_if_index = sw_if_index;
730 1 : error = vnet_app_namespace_add_del (&ns_args);
731 1 : SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
732 :
733 : /*
734 : * Attach server with local and global scope
735 : */
736 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
737 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
738 1 : options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret;
739 1 : attach_args.namespace_id = ns_id;
740 1 : attach_args.api_client_index = placeholder_server_api_index;
741 1 : attach_args.name = server_name;
742 1 : error = vnet_application_attach (&attach_args);
743 1 : SESSION_TEST ((error == 0), "server attachment should work");
744 1 : server_index = attach_args.app_index;
745 1 : server = application_get (server_index);
746 1 : server_wrk_index = application_get_default_worker (server)->wrk_index;
747 :
748 1 : bind_args.app_index = server_index;
749 1 : error = vnet_listen (&bind_args);
750 1 : server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
751 1 : s = session_lookup_listener (server_st_index, &server_sep);
752 1 : SESSION_TEST ((s == 0), "zero listener should not exist in global table");
753 :
754 1 : s = session_lookup_listener (server_st_index, &intf_sep);
755 1 : SESSION_TEST ((s != 0), "intf listener should exist in global table");
756 1 : SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be "
757 : "that of the server");
758 1 : server_local_st_index = application_local_session_table (server);
759 1 : handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
760 1 : SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
761 : "zero listener should exist in local table");
762 1 : detach_args.app_index = server_index;
763 1 : vnet_application_detach (&detach_args);
764 :
765 1 : ns_args.is_add = 0;
766 1 : error = vnet_app_namespace_add_del (&ns_args);
767 1 : SESSION_TEST ((error == 0), "app ns delete should succeed: %d", error);
768 :
769 : /*
770 : * Cleanup
771 : */
772 1 : vec_free (server_name);
773 1 : vec_free (client_name);
774 1 : vec_free (ns_id);
775 1 : session_delete_loopback (sw_if_index);
776 1 : return 0;
777 : }
778 :
779 : static int
780 1 : session_test_rule_table (vlib_main_t * vm, unformat_input_t * input)
781 : {
782 1 : session_rules_table_t _srt, *srt = &_srt;
783 1 : u16 lcl_port = 1234, rmt_port = 4321;
784 1 : u32 action_index = 1, res;
785 : ip4_address_t lcl_lkup, rmt_lkup;
786 1 : int verbose = 0, error;
787 :
788 1 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
789 : {
790 0 : if (unformat (input, "verbose"))
791 0 : verbose = 1;
792 : else
793 : {
794 0 : vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
795 : input);
796 0 : return -1;
797 : }
798 : }
799 :
800 1 : clib_memset (srt, 0, sizeof (*srt));
801 1 : session_rules_table_init (srt);
802 :
803 1 : ip4_address_t lcl_ip = {
804 1 : .as_u32 = clib_host_to_net_u32 (0x01020304),
805 : };
806 1 : ip4_address_t rmt_ip = {
807 1 : .as_u32 = clib_host_to_net_u32 (0x05060708),
808 : };
809 1 : ip4_address_t lcl_ip2 = {
810 1 : .as_u32 = clib_host_to_net_u32 (0x02020202),
811 : };
812 1 : ip4_address_t rmt_ip2 = {
813 1 : .as_u32 = clib_host_to_net_u32 (0x06060606),
814 : };
815 1 : ip4_address_t lcl_ip3 = {
816 1 : .as_u32 = clib_host_to_net_u32 (0x03030303),
817 : };
818 1 : ip4_address_t rmt_ip3 = {
819 1 : .as_u32 = clib_host_to_net_u32 (0x07070707),
820 : };
821 1 : fib_prefix_t lcl_pref = {
822 1 : .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
823 : .fp_len = 16,
824 : .fp_proto = FIB_PROTOCOL_IP4,
825 : };
826 1 : fib_prefix_t rmt_pref = {
827 1 : .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
828 : .fp_len = 16,
829 : .fp_proto = FIB_PROTOCOL_IP4,
830 : };
831 :
832 1 : session_rule_table_add_del_args_t args = {
833 : .lcl = lcl_pref,
834 : .rmt = rmt_pref,
835 : .lcl_port = lcl_port,
836 : .rmt_port = rmt_port,
837 1 : .action_index = action_index++,
838 : .is_add = 1,
839 : };
840 1 : error = session_rules_table_add_del (srt, &args);
841 1 : SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
842 : action_index - 1);
843 :
844 : res =
845 1 : session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
846 1 : SESSION_TEST ((res == 1),
847 : "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 1: %d",
848 : res);
849 :
850 : /*
851 : * Add 1.2.3.4/24 1234 5.6.7.8/16 4321 and 1.2.3.4/24 1234 5.6.7.8/24 4321
852 : */
853 1 : args.lcl.fp_addr.ip4 = lcl_ip;
854 1 : args.lcl.fp_len = 24;
855 1 : args.action_index = action_index++;
856 1 : error = session_rules_table_add_del (srt, &args);
857 1 : SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/16 4321 action %d",
858 : action_index - 1);
859 1 : args.rmt.fp_addr.ip4 = rmt_ip;
860 1 : args.rmt.fp_len = 24;
861 1 : args.action_index = action_index++;
862 1 : error = session_rules_table_add_del (srt, &args);
863 1 : SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/24 4321 action %d",
864 : action_index - 1);
865 :
866 : /*
867 : * Add 2.2.2.2/24 1234 6.6.6.6/16 4321 and 3.3.3.3/24 1234 7.7.7.7/16 4321
868 : */
869 1 : args.lcl.fp_addr.ip4 = lcl_ip2;
870 1 : args.lcl.fp_len = 24;
871 1 : args.rmt.fp_addr.ip4 = rmt_ip2;
872 1 : args.rmt.fp_len = 16;
873 1 : args.action_index = action_index++;
874 1 : error = session_rules_table_add_del (srt, &args);
875 1 : SESSION_TEST ((error == 0), "Add 2.2.2.2/24 1234 6.6.6.6/16 4321 action %d",
876 : action_index - 1);
877 1 : args.lcl.fp_addr.ip4 = lcl_ip3;
878 1 : args.rmt.fp_addr.ip4 = rmt_ip3;
879 1 : args.action_index = action_index++;
880 1 : error = session_rules_table_add_del (srt, &args);
881 1 : SESSION_TEST ((error == 0), "Add 3.3.3.3/24 1234 7.7.7.7/16 4321 action %d",
882 : action_index - 1);
883 :
884 : /*
885 : * Add again 3.3.3.3/24 1234 7.7.7.7/16 4321
886 : */
887 1 : args.lcl.fp_addr.ip4 = lcl_ip3;
888 1 : args.rmt.fp_addr.ip4 = rmt_ip3;
889 1 : args.action_index = action_index++;
890 1 : error = session_rules_table_add_del (srt, &args);
891 1 : SESSION_TEST ((error == 0), "overwrite 3.3.3.3/24 1234 7.7.7.7/16 4321 "
892 : "action %d", action_index - 1);
893 :
894 : /*
895 : * Lookup 1.2.3.4/32 1234 5.6.7.8/32 4321, 1.2.2.4/32 1234 5.6.7.9/32 4321
896 : * and 3.3.3.3 1234 7.7.7.7 4321
897 : */
898 : res =
899 1 : session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
900 1 : SESSION_TEST ((res == 3),
901 : "Lookup 1.2.3.4 1234 5.6.7.8 4321 action " "should be 3: %d",
902 : res);
903 :
904 1 : lcl_lkup.as_u32 = clib_host_to_net_u32 (0x01020204);
905 1 : rmt_lkup.as_u32 = clib_host_to_net_u32 (0x05060709);
906 : res =
907 1 : session_rules_table_lookup4 (srt, &lcl_lkup,
908 : &rmt_lkup, lcl_port, rmt_port);
909 1 : SESSION_TEST ((res == 1),
910 : "Lookup 1.2.2.4 1234 5.6.7.9 4321, action " "should be 1: %d",
911 : res);
912 :
913 : res =
914 1 : session_rules_table_lookup4 (srt, &lcl_ip3, &rmt_ip3, lcl_port, rmt_port);
915 1 : SESSION_TEST ((res == 6),
916 : "Lookup 3.3.3.3 1234 7.7.7.7 4321, action "
917 : "should be 6 (updated): %d", res);
918 :
919 : /*
920 : * Add 1.2.3.4/24 * 5.6.7.8/24 *
921 : * Lookup 1.2.3.4 1234 5.6.7.8 4321 and 1.2.3.4 1235 5.6.7.8 4321
922 : */
923 1 : args.lcl.fp_addr.ip4 = lcl_ip;
924 1 : args.rmt.fp_addr.ip4 = rmt_ip;
925 1 : args.lcl.fp_len = 24;
926 1 : args.rmt.fp_len = 24;
927 1 : args.lcl_port = 0;
928 1 : args.rmt_port = 0;
929 1 : args.action_index = action_index++;
930 1 : error = session_rules_table_add_del (srt, &args);
931 1 : SESSION_TEST ((error == 0), "Add 1.2.3.4/24 * 5.6.7.8/24 * action %d",
932 : action_index - 1);
933 : res =
934 1 : session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
935 1 : SESSION_TEST ((res == 7),
936 : "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should"
937 : " be 7 (lpm dst): %d", res);
938 : res =
939 1 : session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
940 1 : lcl_port + 1, rmt_port);
941 1 : SESSION_TEST ((res == 7),
942 : "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 7: %d",
943 : res);
944 :
945 : /*
946 : * Del 1.2.3.4/24 * 5.6.7.8/24 *
947 : * Add 1.2.3.4/16 * 5.6.7.8/16 * and 1.2.3.4/24 1235 5.6.7.8/24 4321
948 : * Lookup 1.2.3.4 1234 5.6.7.8 4321, 1.2.3.4 1235 5.6.7.8 4321 and
949 : * 1.2.3.4 1235 5.6.7.8 4322
950 : */
951 1 : args.is_add = 0;
952 1 : error = session_rules_table_add_del (srt, &args);
953 1 : SESSION_TEST ((error == 0), "Del 1.2.3.4/24 * 5.6.7.8/24 *");
954 :
955 1 : args.lcl.fp_addr.ip4 = lcl_ip;
956 1 : args.rmt.fp_addr.ip4 = rmt_ip;
957 1 : args.lcl.fp_len = 16;
958 1 : args.rmt.fp_len = 16;
959 1 : args.lcl_port = 0;
960 1 : args.rmt_port = 0;
961 1 : args.action_index = action_index++;
962 1 : args.is_add = 1;
963 1 : error = session_rules_table_add_del (srt, &args);
964 1 : SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 * action %d",
965 : action_index - 1);
966 :
967 1 : args.lcl.fp_addr.ip4 = lcl_ip;
968 1 : args.rmt.fp_addr.ip4 = rmt_ip;
969 1 : args.lcl.fp_len = 24;
970 1 : args.rmt.fp_len = 24;
971 1 : args.lcl_port = lcl_port + 1;
972 1 : args.rmt_port = rmt_port;
973 1 : args.action_index = action_index++;
974 1 : args.is_add = 1;
975 1 : error = session_rules_table_add_del (srt, &args);
976 1 : SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1235 5.6.7.8/24 4321 action %d",
977 : action_index - 1);
978 :
979 1 : if (verbose)
980 0 : session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
981 :
982 : res =
983 1 : session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
984 1 : SESSION_TEST ((res == 3),
985 : "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
986 : res);
987 : res =
988 1 : session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
989 1 : lcl_port + 1, rmt_port);
990 1 : SESSION_TEST ((res == 9),
991 : "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 9: %d",
992 : res);
993 : res =
994 1 : session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
995 1 : lcl_port + 1, rmt_port + 1);
996 1 : SESSION_TEST ((res == 8),
997 : "Lookup 1.2.3.4 1235 5.6.7.8 4322, action should " "be 8: %d",
998 : res);
999 :
1000 : /*
1001 : * Delete 1.2.0.0/16 1234 5.6.0.0/16 4321 and 1.2.0.0/16 * 5.6.0.0/16 *
1002 : * Lookup 1.2.3.4 1234 5.6.7.8 4321
1003 : */
1004 1 : args.lcl_port = 1234;
1005 1 : args.rmt_port = 4321;
1006 1 : args.lcl.fp_len = 16;
1007 1 : args.rmt.fp_len = 16;
1008 1 : args.is_add = 0;
1009 1 : error = session_rules_table_add_del (srt, &args);
1010 1 : SESSION_TEST ((error == 0), "Del 1.2.0.0/16 1234 5.6.0.0/16 4321");
1011 : res =
1012 1 : session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1013 1 : SESSION_TEST ((res == 3),
1014 : "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
1015 : res);
1016 :
1017 1 : args.lcl_port = 0;
1018 1 : args.rmt_port = 0;
1019 1 : args.is_add = 0;
1020 1 : error = session_rules_table_add_del (srt, &args);
1021 1 : SESSION_TEST ((error == 0), "Del 1.2.0.0/16 * 5.6.0.0/16 *");
1022 : res =
1023 1 : session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1024 1 : SESSION_TEST ((res == 3),
1025 : "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
1026 : res);
1027 :
1028 : /*
1029 : * Delete 1.2.3.4/24 1234 5.6.7.5/24
1030 : */
1031 1 : args.lcl.fp_addr.ip4 = lcl_ip;
1032 1 : args.rmt.fp_addr.ip4 = rmt_ip;
1033 1 : args.lcl.fp_len = 24;
1034 1 : args.rmt.fp_len = 24;
1035 1 : args.lcl_port = 1234;
1036 1 : args.rmt_port = 4321;
1037 1 : args.is_add = 0;
1038 1 : error = session_rules_table_add_del (srt, &args);
1039 1 : SESSION_TEST ((error == 0), "Del 1.2.3.4/24 1234 5.6.7.5/24");
1040 : res =
1041 1 : session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1042 1 : SESSION_TEST ((res == 2), "Action should be 2: %d", res);
1043 :
1044 1 : return 0;
1045 : }
1046 :
1047 : static int
1048 1 : session_test_rules (vlib_main_t * vm, unformat_input_t * input)
1049 : {
1050 1 : session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
1051 : u64 options[APP_OPTIONS_N_OPTIONS];
1052 1 : u16 lcl_port = 1234, rmt_port = 4321;
1053 : u32 server_index, server_index2;
1054 1 : u32 placeholder_server_api_index = ~0;
1055 : transport_connection_t *tc;
1056 1 : u32 placeholder_port = 1111;
1057 1 : u8 is_filtered = 0, *ns_id = format (0, "appns1");
1058 : session_t *listener, *s;
1059 1 : app_namespace_t *default_ns = app_namespace_get_default ();
1060 1 : u32 local_ns_index = default_ns->local_table_index;
1061 1 : int verbose = 0;
1062 : app_namespace_t *app_ns;
1063 : app_listener_t *al;
1064 1 : int error = 0;
1065 : u64 handle;
1066 :
1067 1 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1068 : {
1069 0 : if (unformat (input, "verbose"))
1070 0 : verbose = 1;
1071 : else
1072 : {
1073 0 : vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1074 : input);
1075 0 : return -1;
1076 : }
1077 : }
1078 :
1079 1 : server_sep.is_ip4 = 1;
1080 1 : server_sep.port = placeholder_port;
1081 1 : clib_memset (options, 0, sizeof (options));
1082 :
1083 2 : vnet_app_attach_args_t attach_args = {
1084 : .api_client_index = ~0,
1085 : .options = options,
1086 : .namespace_id = 0,
1087 : .session_cb_vft = &placeholder_session_cbs,
1088 1 : .name = format (0, "session_test"),
1089 : };
1090 :
1091 1 : vnet_listen_args_t bind_args = {
1092 : .sep = server_sep,
1093 : .app_index = 0,
1094 : };
1095 :
1096 : /*
1097 : * Attach server with global and local default scope
1098 : */
1099 1 : options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1100 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1101 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1102 1 : attach_args.namespace_id = 0;
1103 1 : attach_args.api_client_index = placeholder_server_api_index;
1104 1 : error = vnet_application_attach (&attach_args);
1105 1 : SESSION_TEST ((error == 0), "server attached");
1106 1 : server_index = attach_args.app_index;
1107 :
1108 1 : bind_args.app_index = server_index;
1109 1 : error = vnet_listen (&bind_args);
1110 1 : SESSION_TEST ((error == 0), "server bound to %U/%d", format_ip46_address,
1111 : &server_sep.ip, 1, server_sep.port);
1112 1 : al = app_listener_get_w_handle (bind_args.handle);
1113 1 : listener = app_listener_get_session (al);
1114 1 : ip4_address_t lcl_ip = {
1115 1 : .as_u32 = clib_host_to_net_u32 (0x01020304),
1116 : };
1117 1 : ip4_address_t rmt_ip = {
1118 1 : .as_u32 = clib_host_to_net_u32 (0x05060708),
1119 : };
1120 1 : fib_prefix_t lcl_pref = {
1121 1 : .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
1122 : .fp_len = 16,
1123 : .fp_proto = FIB_PROTOCOL_IP4,
1124 : };
1125 1 : fib_prefix_t rmt_pref = {
1126 1 : .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1127 : .fp_len = 16,
1128 : .fp_proto = FIB_PROTOCOL_IP4,
1129 : };
1130 :
1131 1 : tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1132 : &rmt_pref.fp_addr.ip4, lcl_port,
1133 : rmt_port, TRANSPORT_PROTO_TCP, 0,
1134 : &is_filtered);
1135 1 : SESSION_TEST ((tc == 0), "optimized lookup should not work (port)");
1136 :
1137 : /*
1138 : * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
1139 : */
1140 1 : session_rule_add_del_args_t args = {
1141 : .table_args.lcl = lcl_pref,
1142 : .table_args.rmt = rmt_pref,
1143 : .table_args.lcl_port = lcl_port,
1144 : .table_args.rmt_port = rmt_port,
1145 : .table_args.action_index = server_index,
1146 : .table_args.is_add = 1,
1147 : .appns_index = 0,
1148 : };
1149 1 : error = vnet_session_rule_add_del (&args);
1150 1 : SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
1151 : args.table_args.action_index);
1152 :
1153 1 : tc = session_lookup_connection4 (0, &lcl_pref.fp_addr.ip4,
1154 : &rmt_pref.fp_addr.ip4, lcl_port, rmt_port,
1155 : TRANSPORT_PROTO_TCP);
1156 1 : SESSION_TEST ((tc->c_index == listener->connection_index),
1157 : "optimized lookup should return the listener");
1158 1 : tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1159 : &rmt_pref.fp_addr.ip4, lcl_port,
1160 : rmt_port, TRANSPORT_PROTO_TCP, 0,
1161 : &is_filtered);
1162 1 : SESSION_TEST ((tc->c_index == listener->connection_index),
1163 : "lookup should return the listener");
1164 1 : s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4,
1165 : lcl_port, rmt_port, TRANSPORT_PROTO_TCP);
1166 1 : SESSION_TEST ((s->connection_index == listener->connection_index),
1167 : "safe lookup should return the listener");
1168 1 : session_endpoint_t sep = {
1169 : .ip = rmt_pref.fp_addr,
1170 : .is_ip4 = 1,
1171 : .port = rmt_port,
1172 : .transport_proto = TRANSPORT_PROTO_TCP,
1173 : };
1174 1 : handle = session_lookup_local_endpoint (local_ns_index, &sep);
1175 1 : SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1176 : "should not work (global scope)");
1177 :
1178 1 : tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1179 1 : &rmt_pref.fp_addr.ip4, lcl_port + 1,
1180 : rmt_port, TRANSPORT_PROTO_TCP, 0,
1181 : &is_filtered);
1182 1 : SESSION_TEST ((tc == 0),
1183 : "optimized lookup for wrong lcl port + 1 should not work");
1184 :
1185 : /*
1186 : * Add 1.2.3.4/16 * 5.6.7.8/16 4321
1187 : */
1188 1 : args.table_args.lcl_port = 0;
1189 1 : args.scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1190 1 : error = vnet_session_rule_add_del (&args);
1191 1 : SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 4321 action %d",
1192 : args.table_args.action_index);
1193 1 : tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1194 1 : &rmt_pref.fp_addr.ip4, lcl_port + 1,
1195 : rmt_port, TRANSPORT_PROTO_TCP, 0,
1196 : &is_filtered);
1197 1 : SESSION_TEST ((tc->c_index == listener->connection_index),
1198 : "optimized lookup for lcl port + 1 should work");
1199 1 : handle = session_lookup_local_endpoint (local_ns_index, &sep);
1200 1 : SESSION_TEST ((handle == server_index), "local session endpoint lookup "
1201 : "should work (lcl ip was zeroed)");
1202 :
1203 : /*
1204 : * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1205 : */
1206 1 : args.table_args.lcl_port = 1234;
1207 1 : args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1208 1 : args.table_args.lcl.fp_len = 30;
1209 1 : args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1210 1 : args.table_args.rmt.fp_len = 30;
1211 1 : args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1212 1 : error = vnet_session_rule_add_del (&args);
1213 1 : SESSION_TEST ((error == 0), "Add 1.2.3.4/30 1234 5.6.7.8/30 4321 action %d",
1214 : args.table_args.action_index);
1215 :
1216 1 : if (verbose)
1217 : {
1218 0 : session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1219 : TRANSPORT_PROTO_TCP);
1220 0 : session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1221 : TRANSPORT_PROTO_TCP);
1222 : }
1223 :
1224 1 : tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1225 : &rmt_pref.fp_addr.ip4, lcl_port,
1226 : rmt_port, TRANSPORT_PROTO_TCP, 0,
1227 : &is_filtered);
1228 1 : SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1229 : "should fail (deny rule)");
1230 1 : SESSION_TEST ((is_filtered == SESSION_LOOKUP_RESULT_FILTERED),
1231 : "lookup should be filtered (deny)");
1232 :
1233 1 : handle = session_lookup_local_endpoint (local_ns_index, &sep);
1234 1 : SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1235 : "5.6.7.8/16 4321 in local table should return deny");
1236 :
1237 1 : tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1238 1 : &rmt_pref.fp_addr.ip4, lcl_port + 1,
1239 : rmt_port, TRANSPORT_PROTO_TCP, 0,
1240 : &is_filtered);
1241 1 : SESSION_TEST ((tc->c_index == listener->connection_index),
1242 : "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should work");
1243 :
1244 : /*
1245 : * "Mask" deny rule with more specific allow:
1246 : * Add allow rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -3 (allow)
1247 : */
1248 1 : args.table_args.is_add = 1;
1249 1 : args.table_args.lcl_port = 1234;
1250 1 : args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1251 1 : args.table_args.lcl.fp_len = 32;
1252 1 : args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1253 1 : args.table_args.rmt.fp_len = 32;
1254 1 : args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1255 1 : error = vnet_session_rule_add_del (&args);
1256 1 : SESSION_TEST ((error == 0), "Add masking rule 1.2.3.4/30 1234 5.6.7.8/32 "
1257 : "4321 action %d", args.table_args.action_index);
1258 :
1259 1 : is_filtered = 0;
1260 1 : tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1261 : &rmt_pref.fp_addr.ip4, lcl_port,
1262 : rmt_port, TRANSPORT_PROTO_TCP, 0,
1263 : &is_filtered);
1264 1 : SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1265 : "should fail (allow without app)");
1266 1 : SESSION_TEST ((is_filtered == 0), "lookup should NOT be filtered");
1267 :
1268 1 : handle = session_lookup_local_endpoint (local_ns_index, &sep);
1269 1 : SESSION_TEST ((handle == SESSION_INVALID_HANDLE), "lookup for 1.2.3.4/32 "
1270 : "1234 5.6.7.8/32 4321 in local table should return invalid");
1271 :
1272 1 : if (verbose)
1273 : {
1274 0 : vlib_cli_output (vm, "Local rules");
1275 0 : session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1276 : TRANSPORT_PROTO_TCP);
1277 : }
1278 :
1279 1 : sep.ip.ip4.as_u32 += 1 << 24;
1280 1 : handle = session_lookup_local_endpoint (local_ns_index, &sep);
1281 1 : SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234"
1282 : " 5.6.7.9/32 4321 in local table should return deny");
1283 :
1284 1 : vnet_connect_args_t connect_args = {
1285 1 : .app_index = attach_args.app_index,
1286 : .api_context = 0,
1287 : };
1288 1 : clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1289 :
1290 : /* Try connecting */
1291 1 : error = vnet_connect (&connect_args);
1292 1 : SESSION_TEST ((error != 0), "connect should fail");
1293 1 : SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1294 :
1295 1 : sep.ip.ip4.as_u32 -= 1 << 24;
1296 :
1297 : /*
1298 : * Delete masking rule: 1.2.3.4/32 1234 5.6.7.8/32 4321 allow
1299 : */
1300 1 : args.table_args.is_add = 0;
1301 1 : args.table_args.lcl_port = 1234;
1302 1 : args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1303 1 : args.table_args.lcl.fp_len = 32;
1304 1 : args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1305 1 : args.table_args.rmt.fp_len = 32;
1306 1 : error = vnet_session_rule_add_del (&args);
1307 1 : SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 allow");
1308 :
1309 :
1310 : /*
1311 : * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
1312 : */
1313 1 : args.table_args.is_add = 1;
1314 1 : args.table_args.lcl_port = 0;
1315 1 : args.table_args.lcl.fp_len = 0;
1316 1 : args.table_args.rmt.fp_len = 16;
1317 1 : args.table_args.action_index = -1;
1318 1 : error = vnet_session_rule_add_del (&args);
1319 1 : SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d",
1320 : args.table_args.action_index);
1321 :
1322 1 : if (verbose)
1323 : {
1324 0 : session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1325 : TRANSPORT_PROTO_TCP);
1326 0 : session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1327 : TRANSPORT_PROTO_TCP);
1328 : }
1329 :
1330 1 : handle = session_lookup_local_endpoint (local_ns_index, &sep);
1331 1 : SESSION_TEST ((handle == SESSION_DROP_HANDLE),
1332 : "local session endpoint lookup should return deny");
1333 :
1334 : /*
1335 : * Delete 1.2.3.4/32 1234 5.6.7.8/32 4321 deny
1336 : */
1337 1 : args.table_args.is_add = 0;
1338 1 : args.table_args.lcl_port = 1234;
1339 1 : args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1340 1 : args.table_args.lcl.fp_len = 30;
1341 1 : args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1342 1 : args.table_args.rmt.fp_len = 30;
1343 1 : error = vnet_session_rule_add_del (&args);
1344 1 : SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1345 :
1346 1 : handle = session_lookup_local_endpoint (local_ns_index, &sep);
1347 1 : SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1348 : "local session endpoint lookup should return invalid");
1349 :
1350 : /*
1351 : * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and
1352 : * 1.2.3.4/16 1234 5.6.7.8/16 4321
1353 : */
1354 1 : args.table_args.is_add = 0;
1355 1 : args.table_args.lcl_port = 0;
1356 1 : args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1357 1 : args.table_args.lcl.fp_len = 0;
1358 1 : args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1359 1 : args.table_args.rmt.fp_len = 16;
1360 1 : args.table_args.rmt_port = 4321;
1361 1 : error = vnet_session_rule_add_del (&args);
1362 1 : SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
1363 1 : handle = session_lookup_local_endpoint (local_ns_index, &sep);
1364 1 : SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1365 : "should not work (removed)");
1366 :
1367 1 : args.table_args.is_add = 0;
1368 1 : args.table_args.lcl = lcl_pref;
1369 :
1370 1 : args.table_args.is_add = 0;
1371 1 : args.table_args.lcl_port = 0;
1372 1 : args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1373 1 : args.table_args.lcl.fp_len = 16;
1374 1 : args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1375 1 : args.table_args.rmt.fp_len = 16;
1376 1 : args.table_args.rmt_port = 4321;
1377 1 : error = vnet_session_rule_add_del (&args);
1378 1 : SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321");
1379 1 : tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1380 1 : &rmt_pref.fp_addr.ip4, lcl_port + 1,
1381 : rmt_port, TRANSPORT_PROTO_TCP, 0,
1382 : &is_filtered);
1383 1 : SESSION_TEST ((tc == 0),
1384 : "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should not "
1385 : "work (del)");
1386 :
1387 1 : args.table_args.is_add = 0;
1388 1 : args.table_args.lcl_port = 1234;
1389 1 : args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1390 1 : args.table_args.lcl.fp_len = 16;
1391 1 : args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1392 1 : args.table_args.rmt.fp_len = 16;
1393 1 : args.table_args.rmt_port = 4321;
1394 1 : error = vnet_session_rule_add_del (&args);
1395 1 : SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321");
1396 1 : tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1397 : &rmt_pref.fp_addr.ip4, lcl_port,
1398 : rmt_port, TRANSPORT_PROTO_TCP, 0,
1399 : &is_filtered);
1400 1 : SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should "
1401 : "not work (del + deny)");
1402 :
1403 1 : SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1404 1 : tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1405 : &rmt_pref.fp_addr.ip4, lcl_port,
1406 : rmt_port, TRANSPORT_PROTO_TCP, 0,
1407 : &is_filtered);
1408 1 : SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should"
1409 : " not work (no-rule)");
1410 :
1411 : /*
1412 : * Test tags. Add/overwrite/del rule with tag
1413 : */
1414 1 : args.table_args.is_add = 1;
1415 1 : args.table_args.lcl_port = 1234;
1416 1 : args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1417 1 : args.table_args.lcl.fp_len = 16;
1418 1 : args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1419 1 : args.table_args.rmt.fp_len = 16;
1420 1 : args.table_args.rmt_port = 4321;
1421 1 : args.table_args.tag = format (0, "test_rule");
1422 1 : args.table_args.action_index = server_index;
1423 1 : error = vnet_session_rule_add_del (&args);
1424 1 : SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 deny "
1425 : "tag test_rule");
1426 1 : if (verbose)
1427 : {
1428 0 : session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1429 : TRANSPORT_PROTO_TCP);
1430 0 : session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1431 : TRANSPORT_PROTO_TCP);
1432 : }
1433 1 : tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1434 : &rmt_pref.fp_addr.ip4, lcl_port,
1435 : rmt_port, TRANSPORT_PROTO_TCP, 0,
1436 : &is_filtered);
1437 1 : SESSION_TEST ((tc->c_index == listener->connection_index),
1438 : "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should work");
1439 :
1440 1 : vec_free (args.table_args.tag);
1441 1 : args.table_args.lcl_port = 1234;
1442 1 : args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1443 1 : args.table_args.lcl.fp_len = 16;
1444 1 : args.table_args.tag = format (0, "test_rule_overwrite");
1445 1 : error = vnet_session_rule_add_del (&args);
1446 1 : SESSION_TEST ((error == 0),
1447 : "Overwrite 1.2.3.4/16 1234 5.6.7.8/16 4321 deny tag test_rule"
1448 : " should work");
1449 1 : if (verbose)
1450 : {
1451 0 : session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1452 : TRANSPORT_PROTO_TCP);
1453 0 : session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1454 : TRANSPORT_PROTO_TCP);
1455 : }
1456 :
1457 1 : args.table_args.is_add = 0;
1458 1 : args.table_args.lcl_port += 1;
1459 1 : error = vnet_session_rule_add_del (&args);
1460 1 : SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny "
1461 : "tag %v", args.table_args.tag);
1462 1 : if (verbose)
1463 : {
1464 0 : session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1465 : TRANSPORT_PROTO_TCP);
1466 0 : session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1467 : TRANSPORT_PROTO_TCP);
1468 : }
1469 1 : tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1470 : &rmt_pref.fp_addr.ip4, lcl_port,
1471 : rmt_port, TRANSPORT_PROTO_TCP, 0,
1472 : &is_filtered);
1473 1 : SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/32 4321 should not"
1474 : " work (del)");
1475 :
1476 :
1477 : /*
1478 : * Test local rules with multiple namespaces
1479 : */
1480 :
1481 : /*
1482 : * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1483 : */
1484 1 : args.table_args.is_add = 1;
1485 1 : args.table_args.lcl_port = 1234;
1486 1 : args.table_args.rmt_port = 0;
1487 1 : args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1488 1 : args.table_args.lcl.fp_len = 32;
1489 1 : args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1490 1 : args.table_args.rmt.fp_len = 32;
1491 1 : args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1492 1 : args.table_args.tag = 0;
1493 1 : args.scope = SESSION_RULE_SCOPE_LOCAL;
1494 1 : error = vnet_session_rule_add_del (&args);
1495 1 : SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d",
1496 : args.table_args.action_index);
1497 : /*
1498 : * Add 'white' rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1499 : */
1500 1 : args.table_args.is_add = 1;
1501 1 : args.table_args.lcl_port = 1234;
1502 1 : args.table_args.rmt_port = 4321;
1503 1 : args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1504 1 : args.table_args.lcl.fp_len = 32;
1505 1 : args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1506 1 : args.table_args.rmt.fp_len = 32;
1507 1 : args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1508 1 : error = vnet_session_rule_add_del (&args);
1509 :
1510 1 : if (verbose)
1511 : {
1512 0 : session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1513 : TRANSPORT_PROTO_TCP);
1514 : }
1515 :
1516 1 : vnet_app_namespace_add_del_args_t ns_args = {
1517 : .ns_id = ns_id,
1518 : .secret = 0,
1519 : .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
1520 : .is_add = 1
1521 : };
1522 1 : error = vnet_app_namespace_add_del (&ns_args);
1523 1 : SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
1524 1 : app_ns = app_namespace_get_from_id (ns_id);
1525 :
1526 1 : attach_args.namespace_id = ns_id;
1527 1 : attach_args.api_client_index = placeholder_server_api_index;
1528 1 : vec_free (attach_args.name);
1529 1 : attach_args.name = format (0, "server_test2");
1530 1 : error = vnet_application_attach (&attach_args);
1531 1 : SESSION_TEST ((error == 0), "server2 attached");
1532 1 : server_index2 = attach_args.app_index;
1533 :
1534 : /*
1535 : * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1536 : */
1537 1 : args.table_args.lcl_port = 1234;
1538 1 : args.table_args.rmt_port = 0;
1539 1 : args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1540 1 : args.table_args.lcl.fp_len = 32;
1541 1 : args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1542 1 : args.table_args.rmt.fp_len = 32;
1543 1 : args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1544 1 : args.appns_index = app_namespace_index (app_ns);
1545 :
1546 1 : error = vnet_session_rule_add_del (&args);
1547 1 : SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d "
1548 : "in test namespace", args.table_args.action_index);
1549 : /*
1550 : * Lookup default namespace
1551 : */
1552 1 : handle = session_lookup_local_endpoint (local_ns_index, &sep);
1553 1 : SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1554 : "lookup for 1.2.3.4/32 1234 5.6.7.8/32 4321 in local table "
1555 : "should return allow (invalid)");
1556 :
1557 1 : sep.port += 1;
1558 1 : handle = session_lookup_local_endpoint (local_ns_index, &sep);
1559 1 : SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1560 : "5.6.7.8/16 432*2* in local table should return deny");
1561 :
1562 :
1563 1 : connect_args.app_index = server_index;
1564 1 : clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1565 :
1566 1 : error = vnet_connect (&connect_args);
1567 1 : SESSION_TEST ((error != 0), "connect should fail");
1568 1 : SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1569 :
1570 : /*
1571 : * Lookup test namespace
1572 : */
1573 1 : handle = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1574 1 : SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1575 : "5.6.7.8/16 4321 in local table should return deny");
1576 :
1577 1 : connect_args.app_index = server_index;
1578 1 : error = vnet_connect (&connect_args);
1579 1 : SESSION_TEST ((error != 0), "connect should fail");
1580 1 : SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1581 :
1582 1 : args.table_args.is_add = 0;
1583 1 : vnet_session_rule_add_del (&args);
1584 :
1585 1 : args.appns_index = 0;
1586 1 : args.table_args.is_add = 0;
1587 1 : vnet_session_rule_add_del (&args);
1588 :
1589 1 : args.table_args.rmt_port = 4321;
1590 1 : vnet_session_rule_add_del (&args);
1591 : /*
1592 : * Final Cleanup
1593 : */
1594 1 : vec_free (args.table_args.tag);
1595 1 : vnet_app_detach_args_t detach_args = {
1596 : .app_index = server_index,
1597 : .api_client_index = ~0,
1598 : };
1599 1 : vnet_application_detach (&detach_args);
1600 :
1601 1 : detach_args.app_index = server_index2;
1602 1 : vnet_application_detach (&detach_args);
1603 :
1604 1 : ns_args.is_add = 0;
1605 1 : error = vnet_app_namespace_add_del (&ns_args);
1606 1 : SESSION_TEST ((error == 0), "app ns delete should succeed: %d", error);
1607 :
1608 1 : vec_free (ns_id);
1609 1 : vec_free (attach_args.name);
1610 1 : return 0;
1611 : }
1612 :
1613 : static int
1614 1 : session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
1615 : {
1616 : u64 options[APP_OPTIONS_N_OPTIONS];
1617 1 : char *show_listeners = "sh session listeners tcp verbose";
1618 1 : char *show_local_listeners = "sh app ns table default";
1619 : unformat_input_t tmp_input;
1620 : u32 server_index, app_index;
1621 1 : u32 placeholder_server_api_index = ~0, sw_if_index = 0;
1622 1 : u8 is_filtered = 0;
1623 : session_t *s;
1624 : transport_connection_t *tc;
1625 1 : u16 lcl_port = 1234, rmt_port = 4321;
1626 : app_namespace_t *app_ns;
1627 1 : int verbose = 0, error = 0;
1628 :
1629 1 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1630 : {
1631 0 : if (unformat (input, "verbose"))
1632 0 : verbose = 1;
1633 : else
1634 : {
1635 0 : vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1636 : input);
1637 0 : return -1;
1638 : }
1639 : }
1640 :
1641 1 : ip4_address_t lcl_ip = {
1642 1 : .as_u32 = clib_host_to_net_u32 (0x01020304),
1643 : };
1644 1 : ip4_address_t rmt_ip = {
1645 1 : .as_u32 = clib_host_to_net_u32 (0x05060708),
1646 : };
1647 1 : fib_prefix_t rmt_pref = {
1648 1 : .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1649 : .fp_len = 16,
1650 : .fp_proto = FIB_PROTOCOL_IP4,
1651 : };
1652 1 : session_endpoint_t sep = {
1653 : .ip = rmt_pref.fp_addr,
1654 : .is_ip4 = 1,
1655 : .port = rmt_port,
1656 : .transport_proto = TRANSPORT_PROTO_TCP,
1657 : };
1658 :
1659 : /*
1660 : * Create loopback interface
1661 : */
1662 1 : session_create_lookpback (0, &sw_if_index, &lcl_ip);
1663 :
1664 1 : app_ns = app_namespace_get_default ();
1665 1 : app_ns->sw_if_index = sw_if_index;
1666 :
1667 1 : clib_memset (options, 0, sizeof (options));
1668 1 : options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1669 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
1670 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_PROXY;
1671 1 : options[APP_OPTIONS_PROXY_TRANSPORT] = 1 << TRANSPORT_PROTO_TCP;
1672 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1673 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1674 2 : vnet_app_attach_args_t attach_args = {
1675 : .api_client_index = ~0,
1676 : .options = options,
1677 : .namespace_id = 0,
1678 : .session_cb_vft = &placeholder_session_cbs,
1679 1 : .name = format (0, "session_test"),
1680 : };
1681 :
1682 1 : attach_args.api_client_index = placeholder_server_api_index;
1683 1 : error = vnet_application_attach (&attach_args);
1684 1 : SESSION_TEST ((error == 0), "server attachment should work");
1685 1 : server_index = attach_args.app_index;
1686 :
1687 1 : if (verbose)
1688 : {
1689 0 : unformat_init_string (&tmp_input, show_listeners,
1690 0 : strlen (show_listeners));
1691 0 : vlib_cli_input (vm, &tmp_input, 0, 0);
1692 0 : unformat_init_string (&tmp_input, show_local_listeners,
1693 0 : strlen (show_local_listeners));
1694 0 : vlib_cli_input (vm, &tmp_input, 0, 0);
1695 : }
1696 :
1697 1 : tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port,
1698 : TRANSPORT_PROTO_TCP, 0, &is_filtered);
1699 1 : SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be "
1700 : "successful");
1701 1 : s = listen_session_get (tc->s_index);
1702 1 : SESSION_TEST ((s->app_index == server_index), "lookup should return"
1703 : " the server");
1704 :
1705 1 : tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port,
1706 : TRANSPORT_PROTO_TCP, 0, &is_filtered);
1707 1 : SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should"
1708 : " not work");
1709 :
1710 1 : app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1711 1 : SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1712 : " should work");
1713 :
1714 1 : vnet_app_detach_args_t detach_args = {
1715 : .app_index = server_index,
1716 : .api_client_index = ~0,
1717 : };
1718 1 : vnet_application_detach (&detach_args);
1719 :
1720 1 : if (verbose)
1721 : {
1722 0 : unformat_init_string (&tmp_input, show_listeners,
1723 0 : strlen (show_listeners));
1724 0 : vlib_cli_input (vm, &tmp_input, 0, 0);
1725 0 : unformat_init_string (&tmp_input, show_local_listeners,
1726 0 : strlen (show_local_listeners));
1727 0 : vlib_cli_input (vm, &tmp_input, 0, 0);
1728 : }
1729 :
1730 1 : app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1731 1 : SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX),
1732 : "local session endpoint lookup should not work after detach");
1733 1 : if (verbose)
1734 0 : unformat_free (&tmp_input);
1735 1 : vec_free (attach_args.name);
1736 1 : session_delete_loopback (sw_if_index);
1737 1 : return 0;
1738 : }
1739 :
1740 : static inline void
1741 1024 : wait_for_event (svm_msg_q_t * mq, int fd, int epfd, u8 use_eventfd)
1742 : {
1743 1024 : if (!use_eventfd)
1744 : {
1745 1024 : svm_msg_q_wait (mq, SVM_MQ_WAIT_EMPTY);
1746 : }
1747 : else
1748 : {
1749 : int __clib_unused n_read, rv;
1750 : struct epoll_event ep_evt;
1751 : u64 buf;
1752 :
1753 : while (1)
1754 : {
1755 0 : rv = epoll_wait (epfd, &ep_evt, 1, -1);
1756 0 : if (rv < 0)
1757 : {
1758 0 : ST_DBG ("epoll error");
1759 0 : exit (1);
1760 : }
1761 0 : else if (rv > 0 && (ep_evt.events & EPOLLIN))
1762 : {
1763 0 : n_read = read (fd, &buf, sizeof (buf));
1764 : }
1765 : else
1766 0 : continue;
1767 :
1768 0 : if (!svm_msg_q_is_empty (mq))
1769 0 : break;
1770 : }
1771 : }
1772 1024 : }
1773 :
1774 : static int
1775 1 : session_test_mq_speed (vlib_main_t * vm, unformat_input_t * input)
1776 : {
1777 1 : int error, __clib_unused verbose, use_eventfd = 0;
1778 1 : u64 i, n_test_msgs = 1 << 10, *counter;
1779 : u64 options[APP_OPTIONS_N_OPTIONS];
1780 1 : int epfd = -1, rv, prod_fd = -1;
1781 : svm_fifo_t *rx_fifo, *tx_fifo;
1782 : vl_api_registration_t *reg;
1783 : struct epoll_event ep_evt;
1784 : u32 app_index, api_index;
1785 : app_worker_t *app_wrk;
1786 : segment_manager_t *sm;
1787 : svm_msg_q_msg_t msg;
1788 : application_t *app;
1789 : svm_msg_q_t *mq;
1790 : f64 start, diff;
1791 : svm_queue_t *q;
1792 : session_t s;
1793 : pid_t pid;
1794 :
1795 1 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1796 : {
1797 0 : if (unformat (input, "verbose"))
1798 0 : verbose = 1;
1799 0 : else if (unformat (input, "%d", &n_test_msgs))
1800 : ;
1801 0 : else if (unformat (input, "use-eventfd"))
1802 0 : use_eventfd = 1;
1803 : else
1804 : {
1805 0 : vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1806 : input);
1807 0 : return -1;
1808 : }
1809 : }
1810 :
1811 1 : q = clib_mem_alloc (sizeof (*q));
1812 1 : api_index = vl_api_memclnt_create_internal ("session_mq_test_api", q);
1813 :
1814 1 : clib_memset (options, 0, sizeof (options));
1815 1 : options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1816 1 : options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1817 1 : options[APP_OPTIONS_EVT_QUEUE_SIZE] = 2048;
1818 :
1819 1 : reg = vl_api_client_index_to_registration (api_index);
1820 : /* Shut up coverity */
1821 1 : if (reg == 0)
1822 0 : abort ();
1823 :
1824 2 : vnet_app_attach_args_t attach_args = {
1825 : .api_client_index = api_index,
1826 : .options = options,
1827 : .namespace_id = 0,
1828 : .session_cb_vft = &placeholder_session_cbs,
1829 1 : .name = format (0, "session_mq_test"),
1830 : };
1831 1 : error = vnet_application_attach (&attach_args);
1832 1 : SESSION_TEST ((error == 0), "server attachment should work");
1833 :
1834 1 : app_index = attach_args.app_index;
1835 :
1836 1 : app = application_get (app_index);
1837 1 : app_wrk = application_get_worker (app, 0);
1838 1 : mq = app_wrk->event_queue;
1839 1 : if (use_eventfd)
1840 : {
1841 0 : svm_msg_q_alloc_eventfd (mq);
1842 0 : prod_fd = svm_msg_q_get_eventfd (mq);
1843 0 : SESSION_TEST (prod_fd != -1, "mq producer eventd valid %u", prod_fd);
1844 : }
1845 :
1846 1 : sm = app_worker_get_connect_segment_manager (app_wrk);
1847 1 : segment_manager_alloc_session_fifos (sm, 0, &rx_fifo, &tx_fifo);
1848 1 : s.rx_fifo = rx_fifo;
1849 1 : s.tx_fifo = tx_fifo;
1850 1 : s.session_state = SESSION_STATE_READY;
1851 1 : counter = (u64 *) f_head_cptr (rx_fifo)->data;
1852 1 : start = vlib_time_now (vm);
1853 :
1854 1 : pid = fork ();
1855 2 : if (pid < 0)
1856 0 : SESSION_TEST (0, "fork failed");
1857 :
1858 2 : if (pid == 0)
1859 : {
1860 1 : if (use_eventfd)
1861 : {
1862 0 : epfd = epoll_create1 (0);
1863 0 : SESSION_TEST (epfd != -1, "epfd created");
1864 0 : ep_evt.events = EPOLLIN;
1865 0 : ep_evt.data.u64 = prod_fd;
1866 0 : rv = epoll_ctl (epfd, EPOLL_CTL_ADD, prod_fd, &ep_evt);
1867 0 : SESSION_TEST (rv == 0, "epoll returned %d", rv);
1868 : }
1869 :
1870 1025 : for (i = 0; i < n_test_msgs; i++)
1871 : {
1872 1024 : wait_for_event (mq, prod_fd, epfd, use_eventfd);
1873 1024 : svm_msg_q_sub_raw (mq, &msg);
1874 1024 : svm_msg_q_free_msg (mq, &msg);
1875 1024 : svm_msg_q_unlock (mq);
1876 1024 : *counter = *counter + 1;
1877 1024 : svm_fifo_unset_event (rx_fifo);
1878 : }
1879 1 : exit (0);
1880 : }
1881 : else
1882 : {
1883 1 : ST_DBG ("client pid %u", pid);
1884 1025 : for (i = 0; i < n_test_msgs; i++)
1885 : {
1886 13518700 : while (svm_fifo_has_event (rx_fifo))
1887 : ;
1888 1024 : app_worker_lock_and_send_event (app_wrk, &s, SESSION_IO_EVT_RX);
1889 : }
1890 : }
1891 :
1892 1 : diff = vlib_time_now (vm) - start;
1893 1 : ST_DBG ("done %u events in %.2f sec: %f evts/s", *counter,
1894 : diff, *counter / diff);
1895 :
1896 1 : vnet_app_detach_args_t detach_args = {
1897 : .app_index = app_index,
1898 : .api_client_index = ~0,
1899 : };
1900 1 : vnet_application_detach (&detach_args);
1901 1 : return 0;
1902 : }
1903 :
1904 : static int
1905 1 : session_test_mq_basic (vlib_main_t * vm, unformat_input_t * input)
1906 : {
1907 1 : svm_msg_q_cfg_t _cfg, *cfg = &_cfg;
1908 : svm_msg_q_msg_t msg1, msg2, msg[12];
1909 : int __clib_unused verbose, i, rv;
1910 : svm_msg_q_shared_t *smq;
1911 : svm_msg_q_ring_t *ring;
1912 1 : svm_msg_q_t _mq = { 0 }, *mq = &_mq;
1913 : u8 *rings_ptr;
1914 :
1915 1 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1916 : {
1917 0 : if (unformat (input, "verbose"))
1918 0 : verbose = 1;
1919 : else
1920 : {
1921 0 : vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1922 : input);
1923 0 : return -1;
1924 : }
1925 : }
1926 :
1927 1 : svm_msg_q_ring_cfg_t rc[2] = { {8, 8, 0}
1928 : , {8, 16, 0}
1929 : };
1930 1 : cfg->consumer_pid = ~0;
1931 1 : cfg->n_rings = 2;
1932 1 : cfg->q_nitems = 16;
1933 1 : cfg->ring_cfgs = rc;
1934 :
1935 1 : smq = svm_msg_q_alloc (cfg);
1936 1 : svm_msg_q_attach (mq, smq);
1937 1 : SESSION_TEST (smq != 0, "svm_msg_q_alloc");
1938 1 : SESSION_TEST (vec_len (mq->rings) == 2, "ring allocation");
1939 1 : rings_ptr = (u8 *) mq->rings[0].shr->data;
1940 3 : vec_foreach (ring, mq->rings)
1941 : {
1942 2 : SESSION_TEST (ring->shr->data == rings_ptr, "ring data");
1943 2 : rings_ptr += (uword) ring->nitems * ring->elsize;
1944 2 : rings_ptr += sizeof (svm_msg_q_ring_shared_t);
1945 : }
1946 :
1947 1 : msg1 = svm_msg_q_alloc_msg (mq, 8);
1948 2 : rv = (mq->rings[0].shr->cursize != 1 || msg1.ring_index != 0 ||
1949 1 : msg1.elt_index != 0);
1950 1 : SESSION_TEST (rv == 0, "msg alloc1");
1951 :
1952 1 : msg2 = svm_msg_q_alloc_msg (mq, 15);
1953 2 : rv = (mq->rings[1].shr->cursize != 1 || msg2.ring_index != 1 ||
1954 1 : msg2.elt_index != 0);
1955 1 : SESSION_TEST (rv == 0, "msg alloc2");
1956 :
1957 1 : svm_msg_q_free_msg (mq, &msg1);
1958 1 : SESSION_TEST (mq->rings[0].shr->cursize == 0, "free msg");
1959 :
1960 13 : for (i = 0; i < 12; i++)
1961 : {
1962 12 : msg[i] = svm_msg_q_alloc_msg (mq, 7);
1963 12 : *(u32 *) svm_msg_q_msg_data (mq, &msg[i]) = i;
1964 : }
1965 :
1966 1 : rv = (mq->rings[0].shr->cursize != 8 || mq->rings[1].shr->cursize != 5);
1967 1 : SESSION_TEST (rv == 0, "msg alloc3");
1968 :
1969 1 : *(u32 *) svm_msg_q_msg_data (mq, &msg2) = 123;
1970 1 : svm_msg_q_add (mq, &msg2, SVM_Q_NOWAIT);
1971 13 : for (i = 0; i < 12; i++)
1972 12 : svm_msg_q_add (mq, &msg[i], SVM_Q_NOWAIT);
1973 :
1974 1 : rv = svm_msg_q_sub (mq, &msg2, SVM_Q_NOWAIT, 0);
1975 1 : SESSION_TEST (rv == 0, "dequeue1");
1976 :
1977 1 : SESSION_TEST (msg2.ring_index == 1 && msg2.elt_index == 0,
1978 : "dequeue1 result");
1979 1 : rv = (*(u32 *) svm_msg_q_msg_data (mq, &msg2) == 123);
1980 1 : SESSION_TEST (rv, "dequeue 1 data");
1981 :
1982 1 : svm_msg_q_free_msg (mq, &msg2);
1983 :
1984 13 : for (i = 0; i < 12; i++)
1985 : {
1986 12 : if (svm_msg_q_sub (mq, &msg[i], SVM_Q_NOWAIT, 0))
1987 0 : SESSION_TEST (0, "dequeue2");
1988 12 : if (i < 8)
1989 : {
1990 8 : if (msg[i].ring_index != 0 || msg[i].elt_index != (i + 1) % 8)
1991 0 : SESSION_TEST (0, "dequeue2 result2");
1992 : }
1993 : else
1994 : {
1995 4 : if (msg[i].ring_index != 1 || msg[i].elt_index != (i - 8) + 1)
1996 0 : SESSION_TEST (0, "dequeue2 result3");
1997 : }
1998 12 : if (*(u32 *) svm_msg_q_msg_data (mq, &msg[i]) != i)
1999 0 : SESSION_TEST (0, "dequeue2 wrong data");
2000 12 : svm_msg_q_free_msg (mq, &msg[i]);
2001 : }
2002 1 : rv = (mq->rings[0].shr->cursize == 0 && mq->rings[1].shr->cursize == 0);
2003 1 : SESSION_TEST (rv, "post dequeue");
2004 :
2005 1 : return 0;
2006 : }
2007 :
2008 : static clib_error_t *
2009 1 : session_test (vlib_main_t * vm,
2010 : unformat_input_t * input, vlib_cli_command_t * cmd_arg)
2011 : {
2012 1 : int res = 0;
2013 :
2014 1 : vnet_session_enable_disable (vm, 1);
2015 :
2016 2 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2017 : {
2018 1 : if (unformat (input, "basic"))
2019 0 : res = session_test_basic (vm, input);
2020 1 : else if (unformat (input, "namespace"))
2021 0 : res = session_test_namespace (vm, input);
2022 1 : else if (unformat (input, "rules-table"))
2023 0 : res = session_test_rule_table (vm, input);
2024 1 : else if (unformat (input, "rules"))
2025 0 : res = session_test_rules (vm, input);
2026 1 : else if (unformat (input, "proxy"))
2027 0 : res = session_test_proxy (vm, input);
2028 1 : else if (unformat (input, "endpt-cfg"))
2029 0 : res = session_test_endpoint_cfg (vm, input);
2030 1 : else if (unformat (input, "mq-speed"))
2031 0 : res = session_test_mq_speed (vm, input);
2032 1 : else if (unformat (input, "mq-basic"))
2033 0 : res = session_test_mq_basic (vm, input);
2034 1 : else if (unformat (input, "all"))
2035 : {
2036 1 : if ((res = session_test_basic (vm, input)))
2037 0 : goto done;
2038 1 : if ((res = session_test_namespace (vm, input)))
2039 0 : goto done;
2040 1 : if ((res = session_test_rule_table (vm, input)))
2041 0 : goto done;
2042 1 : if ((res = session_test_rules (vm, input)))
2043 0 : goto done;
2044 1 : if ((res = session_test_proxy (vm, input)))
2045 0 : goto done;
2046 1 : if ((res = session_test_endpoint_cfg (vm, input)))
2047 0 : goto done;
2048 1 : if ((res = session_test_mq_speed (vm, input)))
2049 0 : goto done;
2050 1 : if ((res = session_test_mq_basic (vm, input)))
2051 0 : goto done;
2052 : }
2053 : else
2054 0 : break;
2055 : }
2056 :
2057 1 : done:
2058 1 : if (res)
2059 0 : return clib_error_return (0, "Session unit test failed");
2060 1 : return 0;
2061 : }
2062 :
2063 : /* *INDENT-OFF* */
2064 16239 : VLIB_CLI_COMMAND (tcp_test_command, static) =
2065 : {
2066 : .path = "test session",
2067 : .short_help = "internal session unit tests",
2068 : .function = session_test,
2069 : };
2070 : /* *INDENT-ON* */
2071 :
2072 : /*
2073 : * fd.io coding-style-patch-verification: ON
2074 : *
2075 : * Local Variables:
2076 : * eval: (c-set-style "gnu")
2077 : * End:
2078 : */
|