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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
24 #define SESSION_TEST_I(_cond, _comment, _args...) \
26 int _evald = (_cond); \
28 fformat(stderr, "FAIL:%d: " _comment "\n", \
31 fformat(stderr, "PASS:%d: " _comment "\n", \
37 #define SESSION_TEST(_cond, _comment, _args...) \
39 if (!SESSION_TEST_I(_cond, _comment, ##_args)) { \
44 #define ST_DBG(_comment, _args...) \
45 fformat(stderr, _comment "\n", ##_args); \
48 placeholder_session_reset_callback (session_t * s)
50 clib_warning ("called...");
53 volatile u32 connected_session_index = ~0;
54 volatile u32 connected_session_thread = ~0;
56 placeholder_session_connected_callback (u32 app_index, u32 api_context,
57 session_t * s, session_error_t err)
61 connected_session_index = s->session_index;
62 connected_session_thread = s->thread_index;
67 static u32 placeholder_segment_count;
70 placeholder_add_segment_callback (u32 client_index, u64 segment_handle)
72 placeholder_segment_count = 1;
77 placeholder_del_segment_callback (u32 client_index, u64 segment_handle)
79 placeholder_segment_count = 0;
84 placeholder_session_disconnect_callback (session_t * s)
86 clib_warning ("called...");
89 static u32 placeholder_accept;
90 volatile u32 accepted_session_index;
91 volatile u32 accepted_session_thread;
94 placeholder_session_accept_callback (session_t * s)
96 placeholder_accept = 1;
97 accepted_session_index = s->session_index;
98 accepted_session_thread = s->thread_index;
99 s->session_state = SESSION_STATE_READY;
104 placeholder_server_rx_callback (session_t * s)
106 clib_warning ("called...");
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,
123 session_create_lookpback (u32 table_id, u32 * sw_if_index,
124 ip4_address_t * intf_addr)
128 clib_memset (intf_mac, 0, sizeof (intf_mac));
130 if (vnet_create_loopback_interface (sw_if_index, intf_mac, 0, 0))
132 clib_warning ("couldn't create loopback. stopping the test!");
138 ip_table_create (FIB_PROTOCOL_IP4, table_id, 0, 0);
139 ip_table_bind (FIB_PROTOCOL_IP4, *sw_if_index, table_id, 0);
142 vnet_sw_interface_set_flags (vnet_get_main (), *sw_if_index,
143 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
145 if (ip4_add_del_interface_address (vlib_get_main (), *sw_if_index,
148 clib_warning ("couldn't assign loopback ip %U", format_ip4_address,
157 session_delete_loopback (u32 sw_if_index)
159 /* fails spectacularly */
160 /* vnet_delete_loopback_interface (sw_if_index); */
162 vnet_sw_interface_set_flags (vnet_get_main (), sw_if_index, 0);
166 session_test_basic (vlib_main_t * vm, unformat_input_t * input)
168 session_endpoint_cfg_t server_sep = SESSION_ENDPOINT_CFG_NULL;
169 u64 options[APP_OPTIONS_N_OPTIONS], bind4_handle, bind6_handle;
173 clib_memset (options, 0, sizeof (options));
174 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
175 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
176 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
177 vnet_app_attach_args_t attach_args = {
178 .api_client_index = ~0,
181 .session_cb_vft = &placeholder_session_cbs,
182 .name = format (0, "session_test"),
185 error = vnet_application_attach (&attach_args);
186 SESSION_TEST ((error == 0), "app attached");
187 server_index = attach_args.app_index;
188 vec_free (attach_args.name);
190 server_sep.is_ip4 = 1;
191 vnet_listen_args_t bind_args = {
192 .sep_ext = server_sep,
197 bind_args.app_index = server_index;
198 error = vnet_listen (&bind_args);
199 SESSION_TEST ((error == 0), "server bind4 should work");
200 bind4_handle = bind_args.handle;
202 error = vnet_listen (&bind_args);
203 SESSION_TEST ((error != 0), "double server bind4 should not work");
205 bind_args.sep.is_ip4 = 0;
206 error = vnet_listen (&bind_args);
207 SESSION_TEST ((error == 0), "server bind6 should work");
208 bind6_handle = bind_args.handle;
210 error = vnet_listen (&bind_args);
211 SESSION_TEST ((error != 0), "double server bind6 should not work");
213 vnet_unlisten_args_t unbind_args = {
214 .handle = bind4_handle,
215 .app_index = server_index,
217 error = vnet_unlisten (&unbind_args);
218 SESSION_TEST ((error == 0), "unbind4 should work");
220 unbind_args.handle = bind6_handle;
221 error = vnet_unlisten (&unbind_args);
222 SESSION_TEST ((error == 0), "unbind6 should work");
224 vnet_app_detach_args_t detach_args = {
225 .app_index = server_index,
226 .api_client_index = ~0,
228 vnet_application_detach (&detach_args);
233 session_add_del_route_via_lookup_in_table (u32 in_table_id, u32 via_table_id,
234 ip4_address_t * ip, u8 mask,
237 fib_route_path_t *rpaths = 0, *rpath;
238 u32 in_fib_index, via_fib_index;
240 fib_prefix_t prefix = {
241 .fp_addr.ip4.as_u32 = ip->as_u32,
243 .fp_proto = FIB_PROTOCOL_IP4,
246 via_fib_index = fib_table_find (FIB_PROTOCOL_IP4, via_table_id);
247 if (via_fib_index == ~0)
249 clib_warning ("couldn't resolve via table id to index");
252 in_fib_index = fib_table_find (FIB_PROTOCOL_IP4, in_table_id);
253 if (in_fib_index == ~0)
255 clib_warning ("couldn't resolve in table id to index");
259 vec_add2 (rpaths, rpath, 1);
260 clib_memset (rpath, 0, sizeof (*rpath));
261 rpath->frp_weight = 1;
262 rpath->frp_fib_index = via_fib_index;
263 rpath->frp_proto = DPO_PROTO_IP4;
264 rpath->frp_sw_if_index = ~0;
265 rpath->frp_flags |= FIB_ROUTE_PATH_DEAG;
268 fib_table_entry_path_add2 (in_fib_index, &prefix, FIB_SOURCE_CLI,
269 FIB_ENTRY_FLAG_NONE, rpath);
271 fib_table_entry_path_remove2 (in_fib_index, &prefix, FIB_SOURCE_CLI,
277 session_test_endpoint_cfg (vlib_main_t * vm, unformat_input_t * input)
279 session_endpoint_cfg_t client_sep = SESSION_ENDPOINT_CFG_NULL;
280 u32 server_index, client_index, sw_if_index[2], tries = 0;
281 u64 options[APP_OPTIONS_N_OPTIONS], placeholder_secret = 1234;
282 u16 placeholder_server_port = 1234, placeholder_client_port = 5678;
283 session_endpoint_cfg_t server_sep = SESSION_ENDPOINT_CFG_NULL;
284 ip4_address_t intf_addr[3];
285 transport_connection_t *tc;
291 * Create the loopbacks
293 intf_addr[0].as_u32 = clib_host_to_net_u32 (0x01010101),
294 session_create_lookpback (0, &sw_if_index[0], &intf_addr[0]);
296 intf_addr[1].as_u32 = clib_host_to_net_u32 (0x02020202),
297 session_create_lookpback (1, &sw_if_index[1], &intf_addr[1]);
299 session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
301 session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
307 appns_id = format (0, "appns1");
308 vnet_app_namespace_add_del_args_t ns_args = {
310 .secret = placeholder_secret,
311 .sw_if_index = sw_if_index[1],
315 error = vnet_app_namespace_add_del (&ns_args);
316 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
319 * Attach client/server
321 clib_memset (options, 0, sizeof (options));
322 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
323 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
325 vnet_app_attach_args_t attach_args = {
326 .api_client_index = ~0,
329 .session_cb_vft = &placeholder_session_cbs,
330 .name = format (0, "session_test_client"),
333 error = vnet_application_attach (&attach_args);
334 SESSION_TEST ((error == 0), "client app attached");
335 client_index = attach_args.app_index;
336 vec_free (attach_args.name);
338 attach_args.name = format (0, "session_test_server");
339 attach_args.namespace_id = appns_id;
340 attach_args.options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret;
341 error = vnet_application_attach (&attach_args);
342 SESSION_TEST ((error == 0), "server app attached: %U", format_clib_error,
344 vec_free (attach_args.name);
345 server_index = attach_args.app_index;
347 server_sep.is_ip4 = 1;
348 server_sep.port = placeholder_server_port;
349 vnet_listen_args_t bind_args = {
350 .sep_ext = server_sep,
351 .app_index = server_index,
353 error = vnet_listen (&bind_args);
354 SESSION_TEST ((error == 0), "server bind should work");
357 * Connect and force lcl ip
359 client_sep.is_ip4 = 1;
360 client_sep.ip.ip4.as_u32 = clib_host_to_net_u32 (0x02020202);
361 client_sep.port = placeholder_server_port;
362 client_sep.peer.is_ip4 = 1;
363 client_sep.peer.ip.ip4.as_u32 = clib_host_to_net_u32 (0x01010101);
364 client_sep.peer.port = placeholder_client_port;
365 client_sep.transport_proto = TRANSPORT_PROTO_TCP;
367 vnet_connect_args_t connect_args = {
368 .sep_ext = client_sep,
369 .app_index = client_index,
372 connected_session_index = connected_session_thread = ~0;
373 accepted_session_index = accepted_session_thread = ~0;
374 error = vnet_connect (&connect_args);
375 SESSION_TEST ((error == 0), "connect should work");
377 /* wait for stuff to happen */
378 while (connected_session_index == ~0 && ++tries < 100)
379 vlib_process_suspend (vm, 100e-3);
380 clib_warning ("waited %.1f seconds for connections", tries / 10.0);
381 SESSION_TEST ((connected_session_index != ~0), "session should exist");
382 SESSION_TEST ((connected_session_thread != ~0), "thread should exist");
383 SESSION_TEST ((accepted_session_index != ~0), "session should exist");
384 SESSION_TEST ((accepted_session_thread != ~0), "thread should exist");
385 s = session_get (connected_session_index, connected_session_thread);
386 tc = session_get_transport (s);
387 SESSION_TEST ((tc != 0), "transport should exist");
388 SESSION_TEST ((memcmp (&tc->lcl_ip, &client_sep.peer.ip,
389 sizeof (tc->lcl_ip)) == 0), "ips should be equal");
390 SESSION_TEST ((tc->lcl_port == placeholder_client_port),
391 "ports should be equal");
393 /* These sessions, because of the way they're established are pinned to
394 * main thread, even when we have workers and we avoid polling main thread,
395 * i.e., we can't cleanup pending disconnects, so force cleanup for both
397 session_transport_cleanup (s);
398 s = session_get (accepted_session_index, accepted_session_thread);
399 session_transport_cleanup (s);
401 vnet_app_detach_args_t detach_args = {
402 .app_index = server_index,
403 .api_client_index = ~0,
405 vnet_application_detach (&detach_args);
406 detach_args.app_index = client_index;
407 vnet_application_detach (&detach_args);
409 /* Allow the disconnects to finish before removing the routes. */
410 vlib_process_suspend (vm, 10e-3);
412 session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
414 session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
417 session_delete_loopback (sw_if_index[0]);
418 session_delete_loopback (sw_if_index[1]);
423 session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
425 u64 options[APP_OPTIONS_N_OPTIONS], placeholder_secret = 1234;
426 u32 server_index, server_st_index, server_local_st_index;
427 u32 placeholder_port = 1234, client_index, server_wrk_index;
428 u32 placeholder_api_context = 4321, placeholder_client_api_index = ~0;
429 u32 placeholder_server_api_index = ~0, sw_if_index = 0;
430 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
431 session_endpoint_t client_sep = SESSION_ENDPOINT_NULL;
432 session_endpoint_t intf_sep = SESSION_ENDPOINT_NULL;
433 u8 *ns_id, *server_name, *client_name;
434 app_namespace_t *app_ns;
435 application_t *server;
440 ns_id = format (0, "appns1");
441 server_name = format (0, "session_test");
442 client_name = format (0, "session_test_client");
444 server_sep.is_ip4 = 1;
445 server_sep.port = placeholder_port;
446 client_sep.is_ip4 = 1;
447 client_sep.port = placeholder_port;
448 clib_memset (options, 0, sizeof (options));
450 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
451 vnet_app_attach_args_t attach_args = {
452 .api_client_index = ~0,
455 .session_cb_vft = &placeholder_session_cbs,
459 vnet_listen_args_t bind_args = {
464 vnet_connect_args_t connect_args = {
468 clib_memcpy (&connect_args.sep, &client_sep, sizeof (client_sep));
470 vnet_unlisten_args_t unbind_args = {
471 .handle = bind_args.handle,
475 vnet_app_detach_args_t detach_args = {
477 .api_client_index = ~0,
480 ip4_address_t intf_addr = {
481 .as_u32 = clib_host_to_net_u32 (0x07000105),
484 intf_sep.ip.ip4 = intf_addr;
486 intf_sep.port = placeholder_port;
489 * Insert namespace and lookup
492 vnet_app_namespace_add_del_args_t ns_args = {
494 .secret = placeholder_secret,
495 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
498 error = vnet_app_namespace_add_del (&ns_args);
499 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
501 app_ns = app_namespace_get_from_id (ns_id);
502 SESSION_TEST ((app_ns != 0), "should find ns %v status", ns_id);
503 SESSION_TEST ((app_ns->ns_secret == placeholder_secret),
504 "secret should be %d", placeholder_secret);
505 SESSION_TEST ((app_ns->sw_if_index == APP_NAMESPACE_INVALID_INDEX),
506 "sw_if_index should be invalid");
509 * Try application attach with wrong secret
512 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
513 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
514 options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret - 1;
515 attach_args.namespace_id = ns_id;
516 attach_args.api_client_index = placeholder_server_api_index;
518 error = vnet_application_attach (&attach_args);
519 SESSION_TEST ((error != 0), "app attachment should fail");
520 SESSION_TEST ((error == VNET_API_ERROR_APP_WRONG_NS_SECRET),
521 "code should be wrong ns secret: %d", error);
524 * Attach server with global default scope
526 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
527 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
528 options[APP_OPTIONS_NAMESPACE_SECRET] = 0;
529 attach_args.namespace_id = 0;
530 attach_args.api_client_index = placeholder_server_api_index;
531 error = vnet_application_attach (&attach_args);
532 SESSION_TEST ((error == 0), "server attachment should work");
533 server_index = attach_args.app_index;
534 server = application_get (server_index);
535 server_wrk_index = application_get_default_worker (server)->wrk_index;
536 SESSION_TEST ((server->ns_index == 0),
537 "server should be in the default ns");
539 bind_args.app_index = server_index;
540 error = vnet_listen (&bind_args);
541 SESSION_TEST ((error == 0), "server bind should work");
543 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
544 s = session_lookup_listener (server_st_index, &server_sep);
545 SESSION_TEST ((s != 0), "listener should exist in global table");
546 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
547 " that of the server");
548 server_local_st_index = application_local_session_table (server);
549 SESSION_TEST ((server_local_st_index == APP_INVALID_INDEX),
550 "server shouldn't have access to local table");
552 unbind_args.app_index = server_index;
553 unbind_args.handle = bind_args.handle;
554 error = vnet_unlisten (&unbind_args);
555 SESSION_TEST ((error == 0), "unbind should work");
557 s = session_lookup_listener (server_st_index, &server_sep);
558 SESSION_TEST ((s == 0), "listener should not exist in global table");
560 detach_args.app_index = server_index;
561 vnet_application_detach (&detach_args);
564 * Attach server with local and global scope
566 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
567 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
568 options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret;
569 attach_args.namespace_id = ns_id;
570 attach_args.api_client_index = placeholder_server_api_index;
571 error = vnet_application_attach (&attach_args);
572 SESSION_TEST ((error == 0), "server attachment should work");
573 server_index = attach_args.app_index;
574 server = application_get (server_index);
575 server_wrk_index = application_get_default_worker (server)->wrk_index;
576 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
577 "server should be in the right ns");
579 bind_args.app_index = server_index;
580 error = vnet_listen (&bind_args);
581 SESSION_TEST ((error == 0), "bind should work");
582 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
583 s = session_lookup_listener (server_st_index, &server_sep);
584 SESSION_TEST ((s != 0), "listener should exist in global table");
585 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
586 " that of the server");
587 server_local_st_index = application_local_session_table (server);
588 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
589 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
590 "listener should exist in local table");
593 * Try client connect with 1) local scope 2) global scope
595 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
596 attach_args.name = client_name;
597 attach_args.api_client_index = placeholder_client_api_index;
598 error = vnet_application_attach (&attach_args);
599 SESSION_TEST ((error == 0), "client attachment should work");
600 client_index = attach_args.app_index;
601 connect_args.api_context = placeholder_api_context;
602 connect_args.app_index = client_index;
603 error = vnet_connect (&connect_args);
604 SESSION_TEST ((error != 0), "client connect should return error code");
605 SESSION_TEST ((error == SESSION_E_INVALID_RMT_IP),
606 "error code should be invalid value (zero ip)");
607 SESSION_TEST ((placeholder_segment_count == 0),
608 "shouldn't have received request to map new segment");
609 connect_args.sep.ip.ip4.as_u8[0] = 127;
610 error = vnet_connect (&connect_args);
611 SESSION_TEST ((error == 0), "client connect should not return error code");
612 SESSION_TEST ((placeholder_segment_count == 1),
613 "should've received request to map new segment");
614 SESSION_TEST ((placeholder_accept == 1),
615 "should've received accept request");
616 detach_args.app_index = client_index;
617 vnet_application_detach (&detach_args);
619 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
620 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
621 attach_args.api_client_index = placeholder_client_api_index;
622 error = vnet_application_attach (&attach_args);
623 SESSION_TEST ((error == 0), "client attachment should work");
624 error = vnet_connect (&connect_args);
625 SESSION_TEST ((error != 0), "client connect should return error code");
626 SESSION_TEST ((error == SESSION_E_NOINTF),
627 "error code should be connect (nothing in local scope)");
628 detach_args.app_index = client_index;
629 vnet_application_detach (&detach_args);
632 * Unbind and detach server and then re-attach with local scope only
634 unbind_args.handle = bind_args.handle;
635 unbind_args.app_index = server_index;
636 error = vnet_unlisten (&unbind_args);
637 SESSION_TEST ((error == 0), "unbind should work");
639 s = session_lookup_listener (server_st_index, &server_sep);
640 SESSION_TEST ((s == 0), "listener should not exist in global table");
641 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
642 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
643 "listener should not exist in local table");
645 detach_args.app_index = server_index;
646 vnet_application_detach (&detach_args);
648 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
649 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
650 attach_args.api_client_index = placeholder_server_api_index;
651 attach_args.name = server_name;
652 error = vnet_application_attach (&attach_args);
653 SESSION_TEST ((error == 0), "app attachment should work");
654 server_index = attach_args.app_index;
655 server = application_get (server_index);
656 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
657 "app should be in the right ns");
659 bind_args.app_index = server_index;
660 error = vnet_listen (&bind_args);
661 SESSION_TEST ((error == 0), "bind should work");
663 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
664 s = session_lookup_listener (server_st_index, &server_sep);
665 SESSION_TEST ((s == 0), "listener should not exist in global table");
666 server_local_st_index = application_local_session_table (server);
667 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
668 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
669 "listener should exist in local table");
671 unbind_args.handle = bind_args.handle;
672 error = vnet_unlisten (&unbind_args);
673 SESSION_TEST ((error == 0), "unbind should work");
675 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
676 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
677 "listener should not exist in local table");
680 * Client attach + connect in default ns with local scope
682 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
683 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
684 attach_args.namespace_id = 0;
685 attach_args.api_client_index = placeholder_client_api_index;
686 attach_args.name = client_name;
687 vnet_application_attach (&attach_args);
688 error = vnet_connect (&connect_args);
689 SESSION_TEST ((error != 0), "client connect should return error code");
690 SESSION_TEST ((error == SESSION_E_NOROUTE),
691 "error code should be noroute (not in same ns)");
692 detach_args.app_index = client_index;
693 vnet_application_detach (&detach_args);
698 detach_args.app_index = server_index;
699 vnet_application_detach (&detach_args);
702 * Create loopback interface
704 session_create_lookpback (0, &sw_if_index, &intf_addr);
707 * Update namespace with interface
709 ns_args.sw_if_index = sw_if_index;
710 error = vnet_app_namespace_add_del (&ns_args);
711 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
714 * Attach server with local and global scope
716 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
717 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
718 options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret;
719 attach_args.namespace_id = ns_id;
720 attach_args.api_client_index = placeholder_server_api_index;
721 attach_args.name = server_name;
722 error = vnet_application_attach (&attach_args);
723 SESSION_TEST ((error == 0), "server attachment should work");
724 server_index = attach_args.app_index;
725 server = application_get (server_index);
726 server_wrk_index = application_get_default_worker (server)->wrk_index;
728 bind_args.app_index = server_index;
729 error = vnet_listen (&bind_args);
730 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
731 s = session_lookup_listener (server_st_index, &server_sep);
732 SESSION_TEST ((s == 0), "zero listener should not exist in global table");
734 s = session_lookup_listener (server_st_index, &intf_sep);
735 SESSION_TEST ((s != 0), "intf listener should exist in global table");
736 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be "
737 "that of the server");
738 server_local_st_index = application_local_session_table (server);
739 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
740 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
741 "zero listener should exist in local table");
742 detach_args.app_index = server_index;
743 vnet_application_detach (&detach_args);
748 vec_free (server_name);
749 vec_free (client_name);
751 session_delete_loopback (sw_if_index);
756 session_test_rule_table (vlib_main_t * vm, unformat_input_t * input)
758 session_rules_table_t _srt, *srt = &_srt;
759 u16 lcl_port = 1234, rmt_port = 4321;
760 u32 action_index = 1, res;
761 ip4_address_t lcl_lkup, rmt_lkup;
762 int verbose = 0, error;
764 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
766 if (unformat (input, "verbose"))
770 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
776 clib_memset (srt, 0, sizeof (*srt));
777 session_rules_table_init (srt);
779 ip4_address_t lcl_ip = {
780 .as_u32 = clib_host_to_net_u32 (0x01020304),
782 ip4_address_t rmt_ip = {
783 .as_u32 = clib_host_to_net_u32 (0x05060708),
785 ip4_address_t lcl_ip2 = {
786 .as_u32 = clib_host_to_net_u32 (0x02020202),
788 ip4_address_t rmt_ip2 = {
789 .as_u32 = clib_host_to_net_u32 (0x06060606),
791 ip4_address_t lcl_ip3 = {
792 .as_u32 = clib_host_to_net_u32 (0x03030303),
794 ip4_address_t rmt_ip3 = {
795 .as_u32 = clib_host_to_net_u32 (0x07070707),
797 fib_prefix_t lcl_pref = {
798 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
800 .fp_proto = FIB_PROTOCOL_IP4,
802 fib_prefix_t rmt_pref = {
803 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
805 .fp_proto = FIB_PROTOCOL_IP4,
808 session_rule_table_add_del_args_t args = {
811 .lcl_port = lcl_port,
812 .rmt_port = rmt_port,
813 .action_index = action_index++,
816 error = session_rules_table_add_del (srt, &args);
817 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
821 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
822 SESSION_TEST ((res == 1),
823 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 1: %d",
827 * 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
829 args.lcl.fp_addr.ip4 = lcl_ip;
830 args.lcl.fp_len = 24;
831 args.action_index = action_index++;
832 error = session_rules_table_add_del (srt, &args);
833 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/16 4321 action %d",
835 args.rmt.fp_addr.ip4 = rmt_ip;
836 args.rmt.fp_len = 24;
837 args.action_index = action_index++;
838 error = session_rules_table_add_del (srt, &args);
839 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/24 4321 action %d",
843 * 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
845 args.lcl.fp_addr.ip4 = lcl_ip2;
846 args.lcl.fp_len = 24;
847 args.rmt.fp_addr.ip4 = rmt_ip2;
848 args.rmt.fp_len = 16;
849 args.action_index = action_index++;
850 error = session_rules_table_add_del (srt, &args);
851 SESSION_TEST ((error == 0), "Add 2.2.2.2/24 1234 6.6.6.6/16 4321 action %d",
853 args.lcl.fp_addr.ip4 = lcl_ip3;
854 args.rmt.fp_addr.ip4 = rmt_ip3;
855 args.action_index = action_index++;
856 error = session_rules_table_add_del (srt, &args);
857 SESSION_TEST ((error == 0), "Add 3.3.3.3/24 1234 7.7.7.7/16 4321 action %d",
861 * Add again 3.3.3.3/24 1234 7.7.7.7/16 4321
863 args.lcl.fp_addr.ip4 = lcl_ip3;
864 args.rmt.fp_addr.ip4 = rmt_ip3;
865 args.action_index = action_index++;
866 error = session_rules_table_add_del (srt, &args);
867 SESSION_TEST ((error == 0), "overwrite 3.3.3.3/24 1234 7.7.7.7/16 4321 "
868 "action %d", action_index - 1);
871 * 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
872 * and 3.3.3.3 1234 7.7.7.7 4321
875 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
876 SESSION_TEST ((res == 3),
877 "Lookup 1.2.3.4 1234 5.6.7.8 4321 action " "should be 3: %d",
880 lcl_lkup.as_u32 = clib_host_to_net_u32 (0x01020204);
881 rmt_lkup.as_u32 = clib_host_to_net_u32 (0x05060709);
883 session_rules_table_lookup4 (srt, &lcl_lkup,
884 &rmt_lkup, lcl_port, rmt_port);
885 SESSION_TEST ((res == 1),
886 "Lookup 1.2.2.4 1234 5.6.7.9 4321, action " "should be 1: %d",
890 session_rules_table_lookup4 (srt, &lcl_ip3, &rmt_ip3, lcl_port, rmt_port);
891 SESSION_TEST ((res == 6),
892 "Lookup 3.3.3.3 1234 7.7.7.7 4321, action "
893 "should be 6 (updated): %d", res);
896 * Add 1.2.3.4/24 * 5.6.7.8/24 *
897 * Lookup 1.2.3.4 1234 5.6.7.8 4321 and 1.2.3.4 1235 5.6.7.8 4321
899 args.lcl.fp_addr.ip4 = lcl_ip;
900 args.rmt.fp_addr.ip4 = rmt_ip;
901 args.lcl.fp_len = 24;
902 args.rmt.fp_len = 24;
905 args.action_index = action_index++;
906 error = session_rules_table_add_del (srt, &args);
907 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 * 5.6.7.8/24 * action %d",
910 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
911 SESSION_TEST ((res == 7),
912 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should"
913 " be 7 (lpm dst): %d", res);
915 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
916 lcl_port + 1, rmt_port);
917 SESSION_TEST ((res == 7),
918 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 7: %d",
922 * Del 1.2.3.4/24 * 5.6.7.8/24 *
923 * Add 1.2.3.4/16 * 5.6.7.8/16 * and 1.2.3.4/24 1235 5.6.7.8/24 4321
924 * Lookup 1.2.3.4 1234 5.6.7.8 4321, 1.2.3.4 1235 5.6.7.8 4321 and
925 * 1.2.3.4 1235 5.6.7.8 4322
928 error = session_rules_table_add_del (srt, &args);
929 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 * 5.6.7.8/24 *");
931 args.lcl.fp_addr.ip4 = lcl_ip;
932 args.rmt.fp_addr.ip4 = rmt_ip;
933 args.lcl.fp_len = 16;
934 args.rmt.fp_len = 16;
937 args.action_index = action_index++;
939 error = session_rules_table_add_del (srt, &args);
940 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 * action %d",
943 args.lcl.fp_addr.ip4 = lcl_ip;
944 args.rmt.fp_addr.ip4 = rmt_ip;
945 args.lcl.fp_len = 24;
946 args.rmt.fp_len = 24;
947 args.lcl_port = lcl_port + 1;
948 args.rmt_port = rmt_port;
949 args.action_index = action_index++;
951 error = session_rules_table_add_del (srt, &args);
952 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1235 5.6.7.8/24 4321 action %d",
956 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
959 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
960 SESSION_TEST ((res == 3),
961 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
964 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
965 lcl_port + 1, rmt_port);
966 SESSION_TEST ((res == 9),
967 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 9: %d",
970 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
971 lcl_port + 1, rmt_port + 1);
972 SESSION_TEST ((res == 8),
973 "Lookup 1.2.3.4 1235 5.6.7.8 4322, action should " "be 8: %d",
977 * Delete 1.2.0.0/16 1234 5.6.0.0/16 4321 and 1.2.0.0/16 * 5.6.0.0/16 *
978 * Lookup 1.2.3.4 1234 5.6.7.8 4321
980 args.lcl_port = 1234;
981 args.rmt_port = 4321;
982 args.lcl.fp_len = 16;
983 args.rmt.fp_len = 16;
985 error = session_rules_table_add_del (srt, &args);
986 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 1234 5.6.0.0/16 4321");
988 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
989 SESSION_TEST ((res == 3),
990 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
996 error = session_rules_table_add_del (srt, &args);
997 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 * 5.6.0.0/16 *");
999 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1000 SESSION_TEST ((res == 3),
1001 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
1005 * Delete 1.2.3.4/24 1234 5.6.7.5/24
1007 args.lcl.fp_addr.ip4 = lcl_ip;
1008 args.rmt.fp_addr.ip4 = rmt_ip;
1009 args.lcl.fp_len = 24;
1010 args.rmt.fp_len = 24;
1011 args.lcl_port = 1234;
1012 args.rmt_port = 4321;
1014 error = session_rules_table_add_del (srt, &args);
1015 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 1234 5.6.7.5/24");
1017 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1018 SESSION_TEST ((res == 2), "Action should be 2: %d", res);
1024 session_test_rules (vlib_main_t * vm, unformat_input_t * input)
1026 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
1027 u64 options[APP_OPTIONS_N_OPTIONS];
1028 u16 lcl_port = 1234, rmt_port = 4321;
1029 u32 server_index, server_index2;
1030 u32 placeholder_server_api_index = ~0;
1031 transport_connection_t *tc;
1032 u32 placeholder_port = 1111;
1033 u8 is_filtered = 0, *ns_id = format (0, "appns1");
1034 session_t *listener, *s;
1035 app_namespace_t *default_ns = app_namespace_get_default ();
1036 u32 local_ns_index = default_ns->local_table_index;
1038 app_namespace_t *app_ns;
1043 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1045 if (unformat (input, "verbose"))
1049 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1055 server_sep.is_ip4 = 1;
1056 server_sep.port = placeholder_port;
1057 clib_memset (options, 0, sizeof (options));
1059 vnet_app_attach_args_t attach_args = {
1060 .api_client_index = ~0,
1063 .session_cb_vft = &placeholder_session_cbs,
1064 .name = format (0, "session_test"),
1067 vnet_listen_args_t bind_args = {
1073 * Attach server with global and local default scope
1075 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1076 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1077 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1078 attach_args.namespace_id = 0;
1079 attach_args.api_client_index = placeholder_server_api_index;
1080 error = vnet_application_attach (&attach_args);
1081 SESSION_TEST ((error == 0), "server attached");
1082 server_index = attach_args.app_index;
1084 bind_args.app_index = server_index;
1085 error = vnet_listen (&bind_args);
1086 SESSION_TEST ((error == 0), "server bound to %U/%d", format_ip46_address,
1087 &server_sep.ip, 1, server_sep.port);
1088 al = app_listener_get_w_handle (bind_args.handle);
1089 listener = app_listener_get_session (al);
1090 ip4_address_t lcl_ip = {
1091 .as_u32 = clib_host_to_net_u32 (0x01020304),
1093 ip4_address_t rmt_ip = {
1094 .as_u32 = clib_host_to_net_u32 (0x05060708),
1096 fib_prefix_t lcl_pref = {
1097 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
1099 .fp_proto = FIB_PROTOCOL_IP4,
1101 fib_prefix_t rmt_pref = {
1102 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1104 .fp_proto = FIB_PROTOCOL_IP4,
1107 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1108 &rmt_pref.fp_addr.ip4, lcl_port,
1109 rmt_port, TRANSPORT_PROTO_TCP, 0,
1111 SESSION_TEST ((tc == 0), "optimized lookup should not work (port)");
1114 * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
1116 session_rule_add_del_args_t args = {
1117 .table_args.lcl = lcl_pref,
1118 .table_args.rmt = rmt_pref,
1119 .table_args.lcl_port = lcl_port,
1120 .table_args.rmt_port = rmt_port,
1121 .table_args.action_index = server_index,
1122 .table_args.is_add = 1,
1125 error = vnet_session_rule_add_del (&args);
1126 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
1127 args.table_args.action_index);
1129 tc = session_lookup_connection4 (0, &lcl_pref.fp_addr.ip4,
1130 &rmt_pref.fp_addr.ip4, lcl_port, rmt_port,
1131 TRANSPORT_PROTO_TCP);
1132 SESSION_TEST ((tc->c_index == listener->connection_index),
1133 "optimized lookup should return the listener");
1134 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1135 &rmt_pref.fp_addr.ip4, lcl_port,
1136 rmt_port, TRANSPORT_PROTO_TCP, 0,
1138 SESSION_TEST ((tc->c_index == listener->connection_index),
1139 "lookup should return the listener");
1140 s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4,
1141 lcl_port, rmt_port, TRANSPORT_PROTO_TCP);
1142 SESSION_TEST ((s->connection_index == listener->connection_index),
1143 "safe lookup should return the listener");
1144 session_endpoint_t sep = {
1145 .ip = rmt_pref.fp_addr,
1148 .transport_proto = TRANSPORT_PROTO_TCP,
1150 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1151 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1152 "should not work (global scope)");
1154 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1155 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1156 rmt_port, TRANSPORT_PROTO_TCP, 0,
1158 SESSION_TEST ((tc == 0),
1159 "optimized lookup for wrong lcl port + 1 should not work");
1162 * Add 1.2.3.4/16 * 5.6.7.8/16 4321
1164 args.table_args.lcl_port = 0;
1165 args.scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1166 error = vnet_session_rule_add_del (&args);
1167 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 4321 action %d",
1168 args.table_args.action_index);
1169 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1170 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1171 rmt_port, TRANSPORT_PROTO_TCP, 0,
1173 SESSION_TEST ((tc->c_index == listener->connection_index),
1174 "optimized lookup for lcl port + 1 should work");
1175 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1176 SESSION_TEST ((handle == server_index), "local session endpoint lookup "
1177 "should work (lcl ip was zeroed)");
1180 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1182 args.table_args.lcl_port = 1234;
1183 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1184 args.table_args.lcl.fp_len = 30;
1185 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1186 args.table_args.rmt.fp_len = 30;
1187 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1188 error = vnet_session_rule_add_del (&args);
1189 SESSION_TEST ((error == 0), "Add 1.2.3.4/30 1234 5.6.7.8/30 4321 action %d",
1190 args.table_args.action_index);
1194 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1195 TRANSPORT_PROTO_TCP);
1196 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1197 TRANSPORT_PROTO_TCP);
1200 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1201 &rmt_pref.fp_addr.ip4, lcl_port,
1202 rmt_port, TRANSPORT_PROTO_TCP, 0,
1204 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1205 "should fail (deny rule)");
1206 SESSION_TEST ((is_filtered == SESSION_LOOKUP_RESULT_FILTERED),
1207 "lookup should be filtered (deny)");
1209 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1210 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1211 "5.6.7.8/16 4321 in local table should return deny");
1213 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1214 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1215 rmt_port, TRANSPORT_PROTO_TCP, 0,
1217 SESSION_TEST ((tc->c_index == listener->connection_index),
1218 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should work");
1221 * "Mask" deny rule with more specific allow:
1222 * Add allow rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -3 (allow)
1224 args.table_args.is_add = 1;
1225 args.table_args.lcl_port = 1234;
1226 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1227 args.table_args.lcl.fp_len = 32;
1228 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1229 args.table_args.rmt.fp_len = 32;
1230 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1231 error = vnet_session_rule_add_del (&args);
1232 SESSION_TEST ((error == 0), "Add masking rule 1.2.3.4/30 1234 5.6.7.8/32 "
1233 "4321 action %d", args.table_args.action_index);
1236 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1237 &rmt_pref.fp_addr.ip4, lcl_port,
1238 rmt_port, TRANSPORT_PROTO_TCP, 0,
1240 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1241 "should fail (allow without app)");
1242 SESSION_TEST ((is_filtered == 0), "lookup should NOT be filtered");
1244 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1245 SESSION_TEST ((handle == SESSION_INVALID_HANDLE), "lookup for 1.2.3.4/32 "
1246 "1234 5.6.7.8/32 4321 in local table should return invalid");
1250 vlib_cli_output (vm, "Local rules");
1251 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1252 TRANSPORT_PROTO_TCP);
1255 sep.ip.ip4.as_u32 += 1 << 24;
1256 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1257 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234"
1258 " 5.6.7.9/32 4321 in local table should return deny");
1260 vnet_connect_args_t connect_args = {
1261 .app_index = attach_args.app_index,
1264 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1266 /* Try connecting */
1267 error = vnet_connect (&connect_args);
1268 SESSION_TEST ((error != 0), "connect should fail");
1269 SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1271 sep.ip.ip4.as_u32 -= 1 << 24;
1274 * Delete masking rule: 1.2.3.4/32 1234 5.6.7.8/32 4321 allow
1276 args.table_args.is_add = 0;
1277 args.table_args.lcl_port = 1234;
1278 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1279 args.table_args.lcl.fp_len = 32;
1280 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1281 args.table_args.rmt.fp_len = 32;
1282 error = vnet_session_rule_add_del (&args);
1283 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 allow");
1287 * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
1289 args.table_args.is_add = 1;
1290 args.table_args.lcl_port = 0;
1291 args.table_args.lcl.fp_len = 0;
1292 args.table_args.rmt.fp_len = 16;
1293 args.table_args.action_index = -1;
1294 error = vnet_session_rule_add_del (&args);
1295 SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d",
1296 args.table_args.action_index);
1300 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1301 TRANSPORT_PROTO_TCP);
1302 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1303 TRANSPORT_PROTO_TCP);
1306 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1307 SESSION_TEST ((handle == SESSION_DROP_HANDLE),
1308 "local session endpoint lookup should return deny");
1311 * Delete 1.2.3.4/32 1234 5.6.7.8/32 4321 deny
1313 args.table_args.is_add = 0;
1314 args.table_args.lcl_port = 1234;
1315 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1316 args.table_args.lcl.fp_len = 30;
1317 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1318 args.table_args.rmt.fp_len = 30;
1319 error = vnet_session_rule_add_del (&args);
1320 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1322 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1323 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1324 "local session endpoint lookup should return invalid");
1327 * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and
1328 * 1.2.3.4/16 1234 5.6.7.8/16 4321
1330 args.table_args.is_add = 0;
1331 args.table_args.lcl_port = 0;
1332 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1333 args.table_args.lcl.fp_len = 0;
1334 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1335 args.table_args.rmt.fp_len = 16;
1336 args.table_args.rmt_port = 4321;
1337 error = vnet_session_rule_add_del (&args);
1338 SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
1339 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1340 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1341 "should not work (removed)");
1343 args.table_args.is_add = 0;
1344 args.table_args.lcl = lcl_pref;
1346 args.table_args.is_add = 0;
1347 args.table_args.lcl_port = 0;
1348 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1349 args.table_args.lcl.fp_len = 16;
1350 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1351 args.table_args.rmt.fp_len = 16;
1352 args.table_args.rmt_port = 4321;
1353 error = vnet_session_rule_add_del (&args);
1354 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321");
1355 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1356 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1357 rmt_port, TRANSPORT_PROTO_TCP, 0,
1359 SESSION_TEST ((tc == 0),
1360 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should not "
1363 args.table_args.is_add = 0;
1364 args.table_args.lcl_port = 1234;
1365 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1366 args.table_args.lcl.fp_len = 16;
1367 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1368 args.table_args.rmt.fp_len = 16;
1369 args.table_args.rmt_port = 4321;
1370 error = vnet_session_rule_add_del (&args);
1371 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321");
1372 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1373 &rmt_pref.fp_addr.ip4, lcl_port,
1374 rmt_port, TRANSPORT_PROTO_TCP, 0,
1376 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should "
1377 "not work (del + deny)");
1379 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1380 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1381 &rmt_pref.fp_addr.ip4, lcl_port,
1382 rmt_port, TRANSPORT_PROTO_TCP, 0,
1384 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should"
1385 " not work (no-rule)");
1388 * Test tags. Add/overwrite/del rule with tag
1390 args.table_args.is_add = 1;
1391 args.table_args.lcl_port = 1234;
1392 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1393 args.table_args.lcl.fp_len = 16;
1394 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1395 args.table_args.rmt.fp_len = 16;
1396 args.table_args.rmt_port = 4321;
1397 args.table_args.tag = format (0, "test_rule");
1398 args.table_args.action_index = server_index;
1399 error = vnet_session_rule_add_del (&args);
1400 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 deny "
1404 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1405 TRANSPORT_PROTO_TCP);
1406 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1407 TRANSPORT_PROTO_TCP);
1409 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1410 &rmt_pref.fp_addr.ip4, lcl_port,
1411 rmt_port, TRANSPORT_PROTO_TCP, 0,
1413 SESSION_TEST ((tc->c_index == listener->connection_index),
1414 "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should work");
1416 vec_free (args.table_args.tag);
1417 args.table_args.lcl_port = 1234;
1418 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1419 args.table_args.lcl.fp_len = 16;
1420 args.table_args.tag = format (0, "test_rule_overwrite");
1421 error = vnet_session_rule_add_del (&args);
1422 SESSION_TEST ((error == 0),
1423 "Overwrite 1.2.3.4/16 1234 5.6.7.8/16 4321 deny tag test_rule"
1427 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1428 TRANSPORT_PROTO_TCP);
1429 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1430 TRANSPORT_PROTO_TCP);
1433 args.table_args.is_add = 0;
1434 args.table_args.lcl_port += 1;
1435 error = vnet_session_rule_add_del (&args);
1436 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny "
1437 "tag %v", args.table_args.tag);
1440 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1441 TRANSPORT_PROTO_TCP);
1442 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1443 TRANSPORT_PROTO_TCP);
1445 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1446 &rmt_pref.fp_addr.ip4, lcl_port,
1447 rmt_port, TRANSPORT_PROTO_TCP, 0,
1449 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/32 4321 should not"
1454 * Test local rules with multiple namespaces
1458 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1460 args.table_args.is_add = 1;
1461 args.table_args.lcl_port = 1234;
1462 args.table_args.rmt_port = 0;
1463 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1464 args.table_args.lcl.fp_len = 32;
1465 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1466 args.table_args.rmt.fp_len = 32;
1467 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1468 args.table_args.tag = 0;
1469 args.scope = SESSION_RULE_SCOPE_LOCAL;
1470 error = vnet_session_rule_add_del (&args);
1471 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d",
1472 args.table_args.action_index);
1474 * Add 'white' rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1476 args.table_args.is_add = 1;
1477 args.table_args.lcl_port = 1234;
1478 args.table_args.rmt_port = 4321;
1479 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1480 args.table_args.lcl.fp_len = 32;
1481 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1482 args.table_args.rmt.fp_len = 32;
1483 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1484 error = vnet_session_rule_add_del (&args);
1488 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1489 TRANSPORT_PROTO_TCP);
1492 vnet_app_namespace_add_del_args_t ns_args = {
1495 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
1498 error = vnet_app_namespace_add_del (&ns_args);
1499 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
1500 app_ns = app_namespace_get_from_id (ns_id);
1502 attach_args.namespace_id = ns_id;
1503 attach_args.api_client_index = placeholder_server_api_index;
1504 vec_free (attach_args.name);
1505 attach_args.name = format (0, "server_test2");
1506 error = vnet_application_attach (&attach_args);
1507 SESSION_TEST ((error == 0), "server2 attached");
1508 server_index2 = attach_args.app_index;
1511 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1513 args.table_args.lcl_port = 1234;
1514 args.table_args.rmt_port = 0;
1515 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1516 args.table_args.lcl.fp_len = 32;
1517 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1518 args.table_args.rmt.fp_len = 32;
1519 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1520 args.appns_index = app_namespace_index (app_ns);
1522 error = vnet_session_rule_add_del (&args);
1523 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d "
1524 "in test namespace", args.table_args.action_index);
1526 * Lookup default namespace
1528 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1529 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1530 "lookup for 1.2.3.4/32 1234 5.6.7.8/32 4321 in local table "
1531 "should return allow (invalid)");
1534 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1535 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1536 "5.6.7.8/16 432*2* in local table should return deny");
1539 connect_args.app_index = server_index;
1540 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1542 error = vnet_connect (&connect_args);
1543 SESSION_TEST ((error != 0), "connect should fail");
1544 SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1547 * Lookup test namespace
1549 handle = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1550 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1551 "5.6.7.8/16 4321 in local table should return deny");
1553 connect_args.app_index = server_index;
1554 error = vnet_connect (&connect_args);
1555 SESSION_TEST ((error != 0), "connect should fail");
1556 SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1558 args.table_args.is_add = 0;
1559 vnet_session_rule_add_del (&args);
1561 args.appns_index = 0;
1562 args.table_args.is_add = 0;
1563 vnet_session_rule_add_del (&args);
1565 args.table_args.rmt_port = 4321;
1566 vnet_session_rule_add_del (&args);
1570 vec_free (args.table_args.tag);
1571 vnet_app_detach_args_t detach_args = {
1572 .app_index = server_index,
1573 .api_client_index = ~0,
1575 vnet_application_detach (&detach_args);
1577 detach_args.app_index = server_index2;
1578 vnet_application_detach (&detach_args);
1581 vec_free (attach_args.name);
1586 session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
1588 u64 options[APP_OPTIONS_N_OPTIONS];
1589 char *show_listeners = "sh session listeners tcp verbose";
1590 char *show_local_listeners = "sh app ns table default";
1591 unformat_input_t tmp_input;
1592 u32 server_index, app_index;
1593 u32 placeholder_server_api_index = ~0, sw_if_index = 0;
1596 transport_connection_t *tc;
1597 u16 lcl_port = 1234, rmt_port = 4321;
1598 app_namespace_t *app_ns;
1599 int verbose = 0, error = 0;
1601 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1603 if (unformat (input, "verbose"))
1607 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1613 ip4_address_t lcl_ip = {
1614 .as_u32 = clib_host_to_net_u32 (0x01020304),
1616 ip4_address_t rmt_ip = {
1617 .as_u32 = clib_host_to_net_u32 (0x05060708),
1619 fib_prefix_t rmt_pref = {
1620 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1622 .fp_proto = FIB_PROTOCOL_IP4,
1624 session_endpoint_t sep = {
1625 .ip = rmt_pref.fp_addr,
1628 .transport_proto = TRANSPORT_PROTO_TCP,
1632 * Create loopback interface
1634 session_create_lookpback (0, &sw_if_index, &lcl_ip);
1636 app_ns = app_namespace_get_default ();
1637 app_ns->sw_if_index = sw_if_index;
1639 clib_memset (options, 0, sizeof (options));
1640 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1641 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
1642 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_PROXY;
1643 options[APP_OPTIONS_PROXY_TRANSPORT] = 1 << TRANSPORT_PROTO_TCP;
1644 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1645 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1646 vnet_app_attach_args_t attach_args = {
1647 .api_client_index = ~0,
1650 .session_cb_vft = &placeholder_session_cbs,
1651 .name = format (0, "session_test"),
1654 attach_args.api_client_index = placeholder_server_api_index;
1655 error = vnet_application_attach (&attach_args);
1656 SESSION_TEST ((error == 0), "server attachment should work");
1657 server_index = attach_args.app_index;
1661 unformat_init_string (&tmp_input, show_listeners,
1662 strlen (show_listeners));
1663 vlib_cli_input (vm, &tmp_input, 0, 0);
1664 unformat_init_string (&tmp_input, show_local_listeners,
1665 strlen (show_local_listeners));
1666 vlib_cli_input (vm, &tmp_input, 0, 0);
1669 tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port,
1670 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1671 SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be "
1673 s = listen_session_get (tc->s_index);
1674 SESSION_TEST ((s->app_index == server_index), "lookup should return"
1677 tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port,
1678 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1679 SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should"
1682 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1683 SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1686 vnet_app_detach_args_t detach_args = {
1687 .app_index = server_index,
1688 .api_client_index = ~0,
1690 vnet_application_detach (&detach_args);
1694 unformat_init_string (&tmp_input, show_listeners,
1695 strlen (show_listeners));
1696 vlib_cli_input (vm, &tmp_input, 0, 0);
1697 unformat_init_string (&tmp_input, show_local_listeners,
1698 strlen (show_local_listeners));
1699 vlib_cli_input (vm, &tmp_input, 0, 0);
1702 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1703 SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX),
1704 "local session endpoint lookup should not work after detach");
1706 unformat_free (&tmp_input);
1707 vec_free (attach_args.name);
1708 session_delete_loopback (sw_if_index);
1713 wait_for_event (svm_msg_q_t * mq, int fd, int epfd, u8 use_eventfd)
1717 svm_msg_q_lock (mq);
1718 while (svm_msg_q_is_empty (mq))
1719 svm_msg_q_wait (mq);
1723 int __clib_unused n_read, rv;
1724 struct epoll_event ep_evt;
1729 rv = epoll_wait (epfd, &ep_evt, 1, -1);
1732 ST_DBG ("epoll error");
1735 else if (rv > 0 && (ep_evt.events & EPOLLIN))
1737 n_read = read (fd, &buf, sizeof (buf));
1742 if (!svm_msg_q_is_empty (mq))
1744 svm_msg_q_lock (mq);
1752 session_test_mq_speed (vlib_main_t * vm, unformat_input_t * input)
1754 int error, __clib_unused verbose, use_eventfd = 0;
1755 u64 i, n_test_msgs = 1 << 10, *counter;
1756 u64 options[APP_OPTIONS_N_OPTIONS];
1757 int epfd = -1, rv, prod_fd = -1;
1758 svm_fifo_t *rx_fifo, *tx_fifo;
1759 vl_api_registration_t *reg;
1760 struct epoll_event ep_evt;
1761 u32 app_index, api_index;
1762 app_worker_t *app_wrk;
1763 segment_manager_t *sm;
1764 svm_msg_q_msg_t msg;
1772 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1774 if (unformat (input, "verbose"))
1776 else if (unformat (input, "%d", &n_test_msgs))
1778 else if (unformat (input, "use-eventfd"))
1782 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1788 q = clib_mem_alloc (sizeof (*q));
1789 api_index = vl_api_memclnt_create_internal ("session_mq_test_api", q);
1791 clib_memset (options, 0, sizeof (options));
1792 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1793 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1794 options[APP_OPTIONS_EVT_QUEUE_SIZE] = 2048;
1796 reg = vl_api_client_index_to_registration (api_index);
1797 /* Shut up coverity */
1800 if (!session_main.evt_qs_use_memfd_seg)
1801 reg->clib_file_index = VL_API_INVALID_FI;
1803 vnet_app_attach_args_t attach_args = {
1804 .api_client_index = api_index,
1807 .session_cb_vft = &placeholder_session_cbs,
1808 .name = format (0, "session_mq_test"),
1810 error = vnet_application_attach (&attach_args);
1811 SESSION_TEST ((error == 0), "server attachment should work");
1813 app_index = attach_args.app_index;
1815 app = application_get (app_index);
1816 app_wrk = application_get_worker (app, 0);
1817 mq = app_wrk->event_queue;
1820 svm_msg_q_alloc_producer_eventfd (mq);
1821 svm_msg_q_alloc_consumer_eventfd (mq);
1822 prod_fd = svm_msg_q_get_producer_eventfd (mq);
1823 SESSION_TEST (prod_fd != -1, "mq producer eventd valid %u", prod_fd);
1826 sm = app_worker_get_or_alloc_connect_segment_manager (app_wrk);
1827 segment_manager_alloc_session_fifos (sm, 0, &rx_fifo, &tx_fifo);
1828 s.rx_fifo = rx_fifo;
1829 s.tx_fifo = tx_fifo;
1830 s.session_state = SESSION_STATE_READY;
1831 counter = (u64 *) rx_fifo->head_chunk->data;
1832 start = vlib_time_now (vm);
1836 SESSION_TEST (0, "fork failed");
1842 epfd = epoll_create1 (0);
1843 SESSION_TEST (epfd != -1, "epfd created");
1844 ep_evt.events = EPOLLIN;
1845 ep_evt.data.u64 = prod_fd;
1846 rv = epoll_ctl (epfd, EPOLL_CTL_ADD, prod_fd, &ep_evt);
1847 SESSION_TEST (rv == 0, "epoll returned %d", rv);
1850 for (i = 0; i < n_test_msgs; i++)
1852 wait_for_event (mq, prod_fd, epfd, use_eventfd);
1853 svm_msg_q_sub_w_lock (mq, &msg);
1854 svm_msg_q_free_msg (mq, &msg);
1855 svm_msg_q_unlock (mq);
1856 *counter = *counter + 1;
1857 svm_fifo_unset_event (rx_fifo);
1863 ST_DBG ("client pid %u", pid);
1864 for (i = 0; i < n_test_msgs; i++)
1866 while (svm_fifo_has_event (rx_fifo))
1868 app_worker_lock_and_send_event (app_wrk, &s, SESSION_IO_EVT_RX);
1872 diff = vlib_time_now (vm) - start;
1873 ST_DBG ("done %u events in %.2f sec: %f evts/s", *counter,
1874 diff, *counter / diff);
1876 vnet_app_detach_args_t detach_args = {
1877 .app_index = app_index,
1878 .api_client_index = ~0,
1880 vnet_application_detach (&detach_args);
1885 session_test_mq_basic (vlib_main_t * vm, unformat_input_t * input)
1887 svm_msg_q_cfg_t _cfg, *cfg = &_cfg;
1888 svm_msg_q_msg_t msg1, msg2, msg[12];
1889 int __clib_unused verbose, i, rv;
1891 svm_msg_q_ring_t *ring;
1894 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1896 if (unformat (input, "verbose"))
1900 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1906 svm_msg_q_ring_cfg_t rc[2] = { {8, 8, 0}
1909 cfg->consumer_pid = ~0;
1912 cfg->ring_cfgs = rc;
1914 mq = svm_msg_q_alloc (cfg);
1915 SESSION_TEST (mq != 0, "svm_msg_q_alloc");
1916 SESSION_TEST (vec_len (mq->rings) == 2, "ring allocation");
1917 rings_ptr = (u8 *) mq->rings + vec_bytes (mq->rings);
1918 vec_foreach (ring, mq->rings)
1920 SESSION_TEST (ring->data == rings_ptr, "ring data");
1921 rings_ptr += (uword) ring->nitems * ring->elsize;
1924 msg1 = svm_msg_q_alloc_msg (mq, 8);
1925 rv = (mq->rings[0].cursize != 1
1926 || msg1.ring_index != 0 || msg1.elt_index != 0);
1927 SESSION_TEST (rv == 0, "msg alloc1");
1929 msg2 = svm_msg_q_alloc_msg (mq, 15);
1930 rv = (mq->rings[1].cursize != 1
1931 || msg2.ring_index != 1 || msg2.elt_index != 0);
1932 SESSION_TEST (rv == 0, "msg alloc2");
1934 svm_msg_q_free_msg (mq, &msg1);
1935 SESSION_TEST (mq->rings[0].cursize == 0, "free msg");
1937 for (i = 0; i < 12; i++)
1939 msg[i] = svm_msg_q_alloc_msg (mq, 7);
1940 *(u32 *) svm_msg_q_msg_data (mq, &msg[i]) = i;
1943 rv = (mq->rings[0].cursize != 8 || mq->rings[1].cursize != 5);
1944 SESSION_TEST (rv == 0, "msg alloc3");
1946 *(u32 *) svm_msg_q_msg_data (mq, &msg2) = 123;
1947 svm_msg_q_add (mq, &msg2, SVM_Q_NOWAIT);
1948 for (i = 0; i < 12; i++)
1949 svm_msg_q_add (mq, &msg[i], SVM_Q_NOWAIT);
1951 rv = svm_msg_q_sub (mq, &msg2, SVM_Q_NOWAIT, 0);
1952 SESSION_TEST (rv == 0, "dequeue1");
1954 SESSION_TEST (msg2.ring_index == 1 && msg2.elt_index == 0,
1956 rv = (*(u32 *) svm_msg_q_msg_data (mq, &msg2) == 123);
1957 SESSION_TEST (rv, "dequeue 1 data");
1959 svm_msg_q_free_msg (mq, &msg2);
1961 for (i = 0; i < 12; i++)
1963 if (svm_msg_q_sub (mq, &msg[i], SVM_Q_NOWAIT, 0))
1964 SESSION_TEST (0, "dequeue2");
1967 if (msg[i].ring_index != 0 || msg[i].elt_index != (i + 1) % 8)
1968 SESSION_TEST (0, "dequeue2 result2");
1972 if (msg[i].ring_index != 1 || msg[i].elt_index != (i - 8) + 1)
1973 SESSION_TEST (0, "dequeue2 result3");
1975 if (*(u32 *) svm_msg_q_msg_data (mq, &msg[i]) != i)
1976 SESSION_TEST (0, "dequeue2 wrong data");
1977 svm_msg_q_free_msg (mq, &msg[i]);
1979 rv = (mq->rings[0].cursize == 0 && mq->rings[1].cursize == 0);
1980 SESSION_TEST (rv, "post dequeue");
1985 static clib_error_t *
1986 session_test (vlib_main_t * vm,
1987 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1991 vnet_session_enable_disable (vm, 1);
1993 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1995 if (unformat (input, "basic"))
1996 res = session_test_basic (vm, input);
1997 else if (unformat (input, "namespace"))
1998 res = session_test_namespace (vm, input);
1999 else if (unformat (input, "rules-table"))
2000 res = session_test_rule_table (vm, input);
2001 else if (unformat (input, "rules"))
2002 res = session_test_rules (vm, input);
2003 else if (unformat (input, "proxy"))
2004 res = session_test_proxy (vm, input);
2005 else if (unformat (input, "endpt-cfg"))
2006 res = session_test_endpoint_cfg (vm, input);
2007 else if (unformat (input, "mq-speed"))
2008 res = session_test_mq_speed (vm, input);
2009 else if (unformat (input, "mq-basic"))
2010 res = session_test_mq_basic (vm, input);
2011 else if (unformat (input, "all"))
2013 if ((res = session_test_basic (vm, input)))
2015 if ((res = session_test_namespace (vm, input)))
2017 if ((res = session_test_rule_table (vm, input)))
2019 if ((res = session_test_rules (vm, input)))
2021 if ((res = session_test_proxy (vm, input)))
2023 if ((res = session_test_endpoint_cfg (vm, input)))
2025 if ((res = session_test_mq_speed (vm, input)))
2027 if ((res = session_test_mq_basic (vm, input)))
2036 return clib_error_return (0, "Session unit test failed");
2041 VLIB_CLI_COMMAND (tcp_test_command, static) =
2043 .path = "test session",
2044 .short_help = "internal session unit tests",
2045 .function = session_test,
2050 * fd.io coding-style-patch-verification: ON
2053 * eval: (c-set-style "gnu")