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...");
110 static session_cb_vft_t placeholder_session_cbs = {
111 .session_reset_callback = placeholder_session_reset_callback,
112 .session_connected_callback = placeholder_session_connected_callback,
113 .session_accept_callback = placeholder_session_accept_callback,
114 .session_disconnect_callback = placeholder_session_disconnect_callback,
115 .builtin_app_rx_callback = placeholder_server_rx_callback,
116 .add_segment_callback = placeholder_add_segment_callback,
117 .del_segment_callback = placeholder_del_segment_callback,
121 session_create_lookpback (u32 table_id, u32 * sw_if_index,
122 ip4_address_t * intf_addr)
126 clib_memset (intf_mac, 0, sizeof (intf_mac));
128 if (vnet_create_loopback_interface (sw_if_index, intf_mac, 0, 0))
130 clib_warning ("couldn't create loopback. stopping the test!");
136 ip_table_create (FIB_PROTOCOL_IP4, table_id, 0, 0);
137 ip_table_bind (FIB_PROTOCOL_IP4, *sw_if_index, table_id);
140 vnet_sw_interface_set_flags (vnet_get_main (), *sw_if_index,
141 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
143 if (ip4_add_del_interface_address (vlib_get_main (), *sw_if_index,
146 clib_warning ("couldn't assign loopback ip %U", format_ip4_address,
155 session_delete_loopback (u32 sw_if_index)
157 /* fails spectacularly */
158 /* vnet_delete_loopback_interface (sw_if_index); */
160 vnet_sw_interface_set_flags (vnet_get_main (), sw_if_index, 0);
164 session_test_basic (vlib_main_t * vm, unformat_input_t * input)
166 session_endpoint_cfg_t server_sep = SESSION_ENDPOINT_CFG_NULL;
167 u64 options[APP_OPTIONS_N_OPTIONS], bind4_handle, bind6_handle;
171 clib_memset (options, 0, sizeof (options));
172 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
173 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
174 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
175 vnet_app_attach_args_t attach_args = {
176 .api_client_index = ~0,
179 .session_cb_vft = &placeholder_session_cbs,
180 .name = format (0, "session_test"),
183 error = vnet_application_attach (&attach_args);
184 SESSION_TEST ((error == 0), "app attached");
185 server_index = attach_args.app_index;
186 vec_free (attach_args.name);
188 server_sep.is_ip4 = 1;
189 vnet_listen_args_t bind_args = {
190 .sep_ext = server_sep,
195 bind_args.app_index = server_index;
196 error = vnet_listen (&bind_args);
197 SESSION_TEST ((error == 0), "server bind4 should work");
198 bind4_handle = bind_args.handle;
200 error = vnet_listen (&bind_args);
201 SESSION_TEST ((error != 0), "double server bind4 should not work");
203 bind_args.sep.is_ip4 = 0;
204 error = vnet_listen (&bind_args);
205 SESSION_TEST ((error == 0), "server bind6 should work");
206 bind6_handle = bind_args.handle;
208 error = vnet_listen (&bind_args);
209 SESSION_TEST ((error != 0), "double server bind6 should not work");
211 vnet_unlisten_args_t unbind_args = {
212 .handle = bind4_handle,
213 .app_index = server_index,
215 error = vnet_unlisten (&unbind_args);
216 SESSION_TEST ((error == 0), "unbind4 should work");
218 unbind_args.handle = bind6_handle;
219 error = vnet_unlisten (&unbind_args);
220 SESSION_TEST ((error == 0), "unbind6 should work");
222 vnet_app_detach_args_t detach_args = {
223 .app_index = server_index,
224 .api_client_index = ~0,
226 vnet_application_detach (&detach_args);
231 session_add_del_route_via_lookup_in_table (u32 in_table_id, u32 via_table_id,
232 ip4_address_t * ip, u8 mask,
235 fib_route_path_t *rpaths = 0, *rpath;
236 u32 in_fib_index, via_fib_index;
238 fib_prefix_t prefix = {
239 .fp_addr.ip4.as_u32 = ip->as_u32,
241 .fp_proto = FIB_PROTOCOL_IP4,
244 via_fib_index = fib_table_find (FIB_PROTOCOL_IP4, via_table_id);
245 if (via_fib_index == ~0)
247 clib_warning ("couldn't resolve via table id to index");
250 in_fib_index = fib_table_find (FIB_PROTOCOL_IP4, in_table_id);
251 if (in_fib_index == ~0)
253 clib_warning ("couldn't resolve in table id to index");
257 vec_add2 (rpaths, rpath, 1);
258 clib_memset (rpath, 0, sizeof (*rpath));
259 rpath->frp_weight = 1;
260 rpath->frp_fib_index = via_fib_index;
261 rpath->frp_proto = DPO_PROTO_IP4;
262 rpath->frp_sw_if_index = ~0;
263 rpath->frp_flags |= FIB_ROUTE_PATH_DEAG;
266 fib_table_entry_path_add2 (in_fib_index, &prefix, FIB_SOURCE_CLI,
267 FIB_ENTRY_FLAG_NONE, rpath);
269 fib_table_entry_path_remove2 (in_fib_index, &prefix, FIB_SOURCE_CLI,
275 session_test_endpoint_cfg (vlib_main_t * vm, unformat_input_t * input)
277 session_endpoint_cfg_t client_sep = SESSION_ENDPOINT_CFG_NULL;
278 u32 server_index, client_index, sw_if_index[2], tries = 0;
279 u64 options[APP_OPTIONS_N_OPTIONS], placeholder_secret = 1234;
280 u16 placeholder_server_port = 1234, placeholder_client_port = 5678;
281 session_endpoint_cfg_t server_sep = SESSION_ENDPOINT_CFG_NULL;
282 ip4_address_t intf_addr[3];
283 transport_connection_t *tc;
289 * Create the loopbacks
291 intf_addr[0].as_u32 = clib_host_to_net_u32 (0x01010101);
292 session_create_lookpback (0, &sw_if_index[0], &intf_addr[0]);
294 intf_addr[1].as_u32 = clib_host_to_net_u32 (0x02020202);
295 session_create_lookpback (1, &sw_if_index[1], &intf_addr[1]);
297 session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
299 session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
305 appns_id = format (0, "appns1");
306 vnet_app_namespace_add_del_args_t ns_args = {
308 .secret = placeholder_secret,
309 .sw_if_index = sw_if_index[1],
313 error = vnet_app_namespace_add_del (&ns_args);
314 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
317 * Attach client/server
319 clib_memset (options, 0, sizeof (options));
320 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
321 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
323 vnet_app_attach_args_t attach_args = {
324 .api_client_index = ~0,
327 .session_cb_vft = &placeholder_session_cbs,
328 .name = format (0, "session_test_client"),
331 error = vnet_application_attach (&attach_args);
332 SESSION_TEST ((error == 0), "client app attached");
333 client_index = attach_args.app_index;
334 vec_free (attach_args.name);
336 attach_args.name = format (0, "session_test_server");
337 attach_args.namespace_id = appns_id;
338 /* Allow server to allocate another segment for listens. Needed
339 * because by default we do not allow segment additions */
340 attach_args.options[APP_OPTIONS_ADD_SEGMENT_SIZE] = 32 << 20;
341 attach_args.options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret;
342 error = vnet_application_attach (&attach_args);
343 SESSION_TEST ((error == 0), "server app attached: %U", format_clib_error,
345 vec_free (attach_args.name);
346 server_index = attach_args.app_index;
348 server_sep.is_ip4 = 1;
349 server_sep.port = placeholder_server_port;
350 vnet_listen_args_t bind_args = {
351 .sep_ext = server_sep,
352 .app_index = server_index,
354 error = vnet_listen (&bind_args);
355 SESSION_TEST ((error == 0), "server bind should work");
358 * Connect and force lcl ip
360 client_sep.is_ip4 = 1;
361 client_sep.ip.ip4.as_u32 = clib_host_to_net_u32 (0x02020202);
362 client_sep.port = placeholder_server_port;
363 client_sep.peer.is_ip4 = 1;
364 client_sep.peer.ip.ip4.as_u32 = clib_host_to_net_u32 (0x01010101);
365 client_sep.peer.port = placeholder_client_port;
366 client_sep.transport_proto = TRANSPORT_PROTO_TCP;
368 vnet_connect_args_t connect_args = {
369 .sep_ext = client_sep,
370 .app_index = client_index,
373 connected_session_index = connected_session_thread = ~0;
374 accepted_session_index = accepted_session_thread = ~0;
375 error = vnet_connect (&connect_args);
376 SESSION_TEST ((error == 0), "connect should work");
378 /* wait for stuff to happen */
379 while (connected_session_index == ~0 && ++tries < 100)
381 vlib_worker_thread_barrier_release (vm);
382 vlib_process_suspend (vm, 100e-3);
383 vlib_worker_thread_barrier_sync (vm);
385 while (accepted_session_index == ~0 && ++tries < 100)
387 vlib_worker_thread_barrier_release (vm);
388 vlib_process_suspend (vm, 100e-3);
389 vlib_worker_thread_barrier_sync (vm);
392 clib_warning ("waited %.1f seconds for connections", tries / 10.0);
393 SESSION_TEST ((connected_session_index != ~0), "session should exist");
394 SESSION_TEST ((connected_session_thread != ~0), "thread should exist");
395 SESSION_TEST ((accepted_session_index != ~0), "session should exist");
396 SESSION_TEST ((accepted_session_thread != ~0), "thread should exist");
397 s = session_get (connected_session_index, connected_session_thread);
398 tc = session_get_transport (s);
399 SESSION_TEST ((tc != 0), "transport should exist");
400 SESSION_TEST ((memcmp (&tc->lcl_ip, &client_sep.peer.ip,
401 sizeof (tc->lcl_ip)) == 0), "ips should be equal");
402 SESSION_TEST ((tc->lcl_port == placeholder_client_port),
403 "ports should be equal");
405 vnet_app_detach_args_t detach_args = {
406 .app_index = server_index,
407 .api_client_index = ~0,
409 vnet_application_detach (&detach_args);
410 detach_args.app_index = client_index;
411 vnet_application_detach (&detach_args);
414 error = vnet_app_namespace_add_del (&ns_args);
415 SESSION_TEST ((error == 0), "app ns delete should succeed: %d", error);
417 /* Allow the disconnects to finish before removing the routes. */
418 vlib_process_suspend (vm, 10e-3);
420 session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
422 session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
425 session_delete_loopback (sw_if_index[0]);
426 session_delete_loopback (sw_if_index[1]);
431 session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
433 u64 options[APP_OPTIONS_N_OPTIONS], placeholder_secret = 1234, tries;
434 u32 server_index, server_st_index, server_local_st_index;
435 u32 placeholder_port = 1234, client_index, server_wrk_index;
436 u32 placeholder_api_context = 4321, placeholder_client_api_index = ~0;
437 u32 placeholder_server_api_index = ~0, sw_if_index = 0;
438 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
439 session_endpoint_t client_sep = SESSION_ENDPOINT_NULL;
440 session_endpoint_t intf_sep = SESSION_ENDPOINT_NULL;
441 u8 *ns_id, *server_name, *client_name;
442 app_namespace_t *app_ns;
443 application_t *server;
448 ns_id = format (0, "appns1");
449 server_name = format (0, "session_test");
450 client_name = format (0, "session_test_client");
452 server_sep.is_ip4 = 1;
453 server_sep.port = placeholder_port;
454 client_sep.is_ip4 = 1;
455 client_sep.port = placeholder_port;
456 clib_memset (options, 0, sizeof (options));
458 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
459 vnet_app_attach_args_t attach_args = {
460 .api_client_index = ~0,
463 .session_cb_vft = &placeholder_session_cbs,
467 vnet_listen_args_t bind_args = {
472 vnet_connect_args_t connect_args = {
476 clib_memcpy (&connect_args.sep, &client_sep, sizeof (client_sep));
478 vnet_unlisten_args_t unbind_args = {
479 .handle = bind_args.handle,
483 vnet_app_detach_args_t detach_args = {
485 .api_client_index = ~0,
488 ip4_address_t intf_addr = {
489 .as_u32 = clib_host_to_net_u32 (0x07000105),
492 intf_sep.ip.ip4 = intf_addr;
494 intf_sep.port = placeholder_port;
497 * Insert namespace and lookup
500 vnet_app_namespace_add_del_args_t ns_args = {
502 .secret = placeholder_secret,
503 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
506 error = vnet_app_namespace_add_del (&ns_args);
507 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
509 app_ns = app_namespace_get_from_id (ns_id);
510 SESSION_TEST ((app_ns != 0), "should find ns %v status", ns_id);
511 SESSION_TEST ((app_ns->ns_secret == placeholder_secret),
512 "secret should be %d", placeholder_secret);
513 SESSION_TEST ((app_ns->sw_if_index == APP_NAMESPACE_INVALID_INDEX),
514 "sw_if_index should be invalid");
517 * Try application attach with wrong secret
520 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
521 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
522 options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret - 1;
523 attach_args.namespace_id = ns_id;
524 attach_args.api_client_index = placeholder_server_api_index;
526 error = vnet_application_attach (&attach_args);
527 SESSION_TEST ((error != 0), "app attachment should fail");
528 SESSION_TEST ((error == SESSION_E_WRONG_NS_SECRET),
529 "code should be wrong ns secret: %d", error);
532 * Attach server with global default scope
534 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
535 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
536 options[APP_OPTIONS_NAMESPACE_SECRET] = 0;
537 attach_args.namespace_id = 0;
538 attach_args.api_client_index = placeholder_server_api_index;
539 error = vnet_application_attach (&attach_args);
540 SESSION_TEST ((error == 0), "server attachment should work");
541 server_index = attach_args.app_index;
542 server = application_get (server_index);
543 server_wrk_index = application_get_default_worker (server)->wrk_index;
544 SESSION_TEST ((server->ns_index == 0),
545 "server should be in the default ns");
547 bind_args.app_index = server_index;
548 error = vnet_listen (&bind_args);
549 SESSION_TEST ((error == 0), "server bind should work");
551 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
552 s = session_lookup_listener (server_st_index, &server_sep);
553 SESSION_TEST ((s != 0), "listener should exist in global table");
554 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
555 " that of the server");
556 server_local_st_index = application_local_session_table (server);
557 SESSION_TEST ((server_local_st_index == APP_INVALID_INDEX),
558 "server shouldn't have access to local table");
560 unbind_args.app_index = server_index;
561 unbind_args.handle = bind_args.handle;
562 error = vnet_unlisten (&unbind_args);
563 SESSION_TEST ((error == 0), "unbind should work");
565 s = session_lookup_listener (server_st_index, &server_sep);
566 SESSION_TEST ((s == 0), "listener should not exist in global table");
568 detach_args.app_index = server_index;
569 vnet_application_detach (&detach_args);
572 * Attach server with local and global scope
574 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
575 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
576 options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret;
577 attach_args.namespace_id = ns_id;
578 attach_args.api_client_index = placeholder_server_api_index;
579 error = vnet_application_attach (&attach_args);
580 SESSION_TEST ((error == 0), "server attachment should work");
581 server_index = attach_args.app_index;
582 server = application_get (server_index);
583 server_wrk_index = application_get_default_worker (server)->wrk_index;
584 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
585 "server should be in the right ns");
587 bind_args.app_index = server_index;
588 error = vnet_listen (&bind_args);
589 SESSION_TEST ((error == 0), "bind should work");
590 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
591 s = session_lookup_listener (server_st_index, &server_sep);
592 SESSION_TEST ((s != 0), "listener should exist in global table");
593 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
594 " that of the server");
595 server_local_st_index = application_local_session_table (server);
596 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
597 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
598 "listener should exist in local table");
601 * Try client connect with 1) local scope 2) global scope
603 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
604 attach_args.name = client_name;
605 attach_args.api_client_index = placeholder_client_api_index;
606 error = vnet_application_attach (&attach_args);
607 SESSION_TEST ((error == 0), "client attachment should work");
608 client_index = attach_args.app_index;
609 connect_args.api_context = placeholder_api_context;
610 connect_args.app_index = client_index;
611 error = vnet_connect (&connect_args);
612 SESSION_TEST ((error != 0), "client connect should return error code");
613 SESSION_TEST ((error == SESSION_E_INVALID_RMT_IP),
614 "error code should be invalid value (zero ip)");
615 SESSION_TEST ((placeholder_segment_count == 0),
616 "shouldn't have received request to map new segment");
617 connect_args.sep.ip.ip4.as_u8[0] = 127;
618 error = vnet_connect (&connect_args);
619 SESSION_TEST ((error == 0), "client connect should not return error code");
621 /* wait for accept */
623 while (!placeholder_accept && ++tries < 100)
625 vlib_worker_thread_barrier_release (vm);
626 vlib_process_suspend (vm, 100e-3);
627 vlib_worker_thread_barrier_sync (vm);
630 SESSION_TEST ((placeholder_segment_count == 1),
631 "should've received request to map new segment");
632 SESSION_TEST ((placeholder_accept == 1),
633 "should've received accept request");
634 detach_args.app_index = client_index;
635 vnet_application_detach (&detach_args);
637 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
638 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
639 attach_args.api_client_index = placeholder_client_api_index;
640 error = vnet_application_attach (&attach_args);
641 SESSION_TEST ((error == 0), "client attachment should work");
642 error = vnet_connect (&connect_args);
643 SESSION_TEST ((error != 0), "client connect should return error code");
644 SESSION_TEST ((error == SESSION_E_NOINTF),
645 "error code should be connect (nothing in local scope)");
646 detach_args.app_index = client_index;
647 vnet_application_detach (&detach_args);
650 * Unbind and detach server and then re-attach with local scope only
652 unbind_args.handle = bind_args.handle;
653 unbind_args.app_index = server_index;
654 error = vnet_unlisten (&unbind_args);
655 SESSION_TEST ((error == 0), "unbind should work");
657 s = session_lookup_listener (server_st_index, &server_sep);
658 SESSION_TEST ((s == 0), "listener should not exist in global table");
659 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
660 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
661 "listener should not exist in local table");
663 detach_args.app_index = server_index;
664 vnet_application_detach (&detach_args);
666 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
667 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
668 attach_args.api_client_index = placeholder_server_api_index;
669 attach_args.name = server_name;
670 error = vnet_application_attach (&attach_args);
671 SESSION_TEST ((error == 0), "app attachment should work");
672 server_index = attach_args.app_index;
673 server = application_get (server_index);
674 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
675 "app should be in the right ns");
677 bind_args.app_index = server_index;
678 error = vnet_listen (&bind_args);
679 SESSION_TEST ((error == 0), "bind should work");
681 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
682 s = session_lookup_listener (server_st_index, &server_sep);
683 SESSION_TEST ((s == 0), "listener should not exist in global table");
684 server_local_st_index = application_local_session_table (server);
685 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
686 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
687 "listener should exist in local table");
689 unbind_args.handle = bind_args.handle;
690 error = vnet_unlisten (&unbind_args);
691 SESSION_TEST ((error == 0), "unbind should work");
693 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
694 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
695 "listener should not exist in local table");
698 * Client attach + connect in default ns with local scope
700 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
701 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
702 attach_args.namespace_id = 0;
703 attach_args.api_client_index = placeholder_client_api_index;
704 attach_args.name = client_name;
705 vnet_application_attach (&attach_args);
706 error = vnet_connect (&connect_args);
707 SESSION_TEST ((error != 0), "client connect should return error code");
708 SESSION_TEST ((error == SESSION_E_NOROUTE),
709 "error code should be noroute (not in same ns)");
710 detach_args.app_index = client_index;
711 vnet_application_detach (&detach_args);
716 detach_args.app_index = server_index;
717 vnet_application_detach (&detach_args);
720 * Create loopback interface
722 session_create_lookpback (0, &sw_if_index, &intf_addr);
725 * Update namespace with interface
727 ns_args.sw_if_index = sw_if_index;
728 error = vnet_app_namespace_add_del (&ns_args);
729 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
732 * Attach server with local and global scope
734 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
735 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
736 options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret;
737 attach_args.namespace_id = ns_id;
738 attach_args.api_client_index = placeholder_server_api_index;
739 attach_args.name = server_name;
740 error = vnet_application_attach (&attach_args);
741 SESSION_TEST ((error == 0), "server attachment should work");
742 server_index = attach_args.app_index;
743 server = application_get (server_index);
744 server_wrk_index = application_get_default_worker (server)->wrk_index;
746 bind_args.app_index = server_index;
747 error = vnet_listen (&bind_args);
748 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
749 s = session_lookup_listener (server_st_index, &server_sep);
750 SESSION_TEST ((s == 0), "zero listener should not exist in global table");
752 s = session_lookup_listener (server_st_index, &intf_sep);
753 SESSION_TEST ((s != 0), "intf listener should exist in global table");
754 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be "
755 "that of the server");
756 server_local_st_index = application_local_session_table (server);
757 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
758 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
759 "zero listener should exist in local table");
760 detach_args.app_index = server_index;
761 vnet_application_detach (&detach_args);
764 error = vnet_app_namespace_add_del (&ns_args);
765 SESSION_TEST ((error == 0), "app ns delete should succeed: %d", error);
770 vec_free (server_name);
771 vec_free (client_name);
773 session_delete_loopback (sw_if_index);
778 session_test_rule_table (vlib_main_t * vm, unformat_input_t * input)
780 session_rules_table_t _srt, *srt = &_srt;
781 u16 lcl_port = 1234, rmt_port = 4321;
782 u32 action_index = 1, res;
783 ip4_address_t lcl_lkup, rmt_lkup;
784 int verbose = 0, error;
786 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
788 if (unformat (input, "verbose"))
792 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
798 clib_memset (srt, 0, sizeof (*srt));
799 session_rules_table_init (srt);
801 ip4_address_t lcl_ip = {
802 .as_u32 = clib_host_to_net_u32 (0x01020304),
804 ip4_address_t rmt_ip = {
805 .as_u32 = clib_host_to_net_u32 (0x05060708),
807 ip4_address_t lcl_ip2 = {
808 .as_u32 = clib_host_to_net_u32 (0x02020202),
810 ip4_address_t rmt_ip2 = {
811 .as_u32 = clib_host_to_net_u32 (0x06060606),
813 ip4_address_t lcl_ip3 = {
814 .as_u32 = clib_host_to_net_u32 (0x03030303),
816 ip4_address_t rmt_ip3 = {
817 .as_u32 = clib_host_to_net_u32 (0x07070707),
819 fib_prefix_t lcl_pref = {
820 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
822 .fp_proto = FIB_PROTOCOL_IP4,
824 fib_prefix_t rmt_pref = {
825 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
827 .fp_proto = FIB_PROTOCOL_IP4,
830 session_rule_table_add_del_args_t args = {
833 .lcl_port = lcl_port,
834 .rmt_port = rmt_port,
835 .action_index = action_index++,
838 error = session_rules_table_add_del (srt, &args);
839 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
843 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
844 SESSION_TEST ((res == 1),
845 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 1: %d",
849 * 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
851 args.lcl.fp_addr.ip4 = lcl_ip;
852 args.lcl.fp_len = 24;
853 args.action_index = action_index++;
854 error = session_rules_table_add_del (srt, &args);
855 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/16 4321 action %d",
857 args.rmt.fp_addr.ip4 = rmt_ip;
858 args.rmt.fp_len = 24;
859 args.action_index = action_index++;
860 error = session_rules_table_add_del (srt, &args);
861 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/24 4321 action %d",
865 * 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
867 args.lcl.fp_addr.ip4 = lcl_ip2;
868 args.lcl.fp_len = 24;
869 args.rmt.fp_addr.ip4 = rmt_ip2;
870 args.rmt.fp_len = 16;
871 args.action_index = action_index++;
872 error = session_rules_table_add_del (srt, &args);
873 SESSION_TEST ((error == 0), "Add 2.2.2.2/24 1234 6.6.6.6/16 4321 action %d",
875 args.lcl.fp_addr.ip4 = lcl_ip3;
876 args.rmt.fp_addr.ip4 = rmt_ip3;
877 args.action_index = action_index++;
878 error = session_rules_table_add_del (srt, &args);
879 SESSION_TEST ((error == 0), "Add 3.3.3.3/24 1234 7.7.7.7/16 4321 action %d",
883 * Add again 3.3.3.3/24 1234 7.7.7.7/16 4321
885 args.lcl.fp_addr.ip4 = lcl_ip3;
886 args.rmt.fp_addr.ip4 = rmt_ip3;
887 args.action_index = action_index++;
888 error = session_rules_table_add_del (srt, &args);
889 SESSION_TEST ((error == 0), "overwrite 3.3.3.3/24 1234 7.7.7.7/16 4321 "
890 "action %d", action_index - 1);
893 * 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
894 * and 3.3.3.3 1234 7.7.7.7 4321
897 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
898 SESSION_TEST ((res == 3),
899 "Lookup 1.2.3.4 1234 5.6.7.8 4321 action " "should be 3: %d",
902 lcl_lkup.as_u32 = clib_host_to_net_u32 (0x01020204);
903 rmt_lkup.as_u32 = clib_host_to_net_u32 (0x05060709);
905 session_rules_table_lookup4 (srt, &lcl_lkup,
906 &rmt_lkup, lcl_port, rmt_port);
907 SESSION_TEST ((res == 1),
908 "Lookup 1.2.2.4 1234 5.6.7.9 4321, action " "should be 1: %d",
912 session_rules_table_lookup4 (srt, &lcl_ip3, &rmt_ip3, lcl_port, rmt_port);
913 SESSION_TEST ((res == 6),
914 "Lookup 3.3.3.3 1234 7.7.7.7 4321, action "
915 "should be 6 (updated): %d", res);
918 * Add 1.2.3.4/24 * 5.6.7.8/24 *
919 * Lookup 1.2.3.4 1234 5.6.7.8 4321 and 1.2.3.4 1235 5.6.7.8 4321
921 args.lcl.fp_addr.ip4 = lcl_ip;
922 args.rmt.fp_addr.ip4 = rmt_ip;
923 args.lcl.fp_len = 24;
924 args.rmt.fp_len = 24;
927 args.action_index = action_index++;
928 error = session_rules_table_add_del (srt, &args);
929 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 * 5.6.7.8/24 * action %d",
932 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
933 SESSION_TEST ((res == 7),
934 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should"
935 " be 7 (lpm dst): %d", res);
937 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
938 lcl_port + 1, rmt_port);
939 SESSION_TEST ((res == 7),
940 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 7: %d",
944 * Del 1.2.3.4/24 * 5.6.7.8/24 *
945 * Add 1.2.3.4/16 * 5.6.7.8/16 * and 1.2.3.4/24 1235 5.6.7.8/24 4321
946 * Lookup 1.2.3.4 1234 5.6.7.8 4321, 1.2.3.4 1235 5.6.7.8 4321 and
947 * 1.2.3.4 1235 5.6.7.8 4322
950 error = session_rules_table_add_del (srt, &args);
951 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 * 5.6.7.8/24 *");
953 args.lcl.fp_addr.ip4 = lcl_ip;
954 args.rmt.fp_addr.ip4 = rmt_ip;
955 args.lcl.fp_len = 16;
956 args.rmt.fp_len = 16;
959 args.action_index = action_index++;
961 error = session_rules_table_add_del (srt, &args);
962 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 * action %d",
965 args.lcl.fp_addr.ip4 = lcl_ip;
966 args.rmt.fp_addr.ip4 = rmt_ip;
967 args.lcl.fp_len = 24;
968 args.rmt.fp_len = 24;
969 args.lcl_port = lcl_port + 1;
970 args.rmt_port = rmt_port;
971 args.action_index = action_index++;
973 error = session_rules_table_add_del (srt, &args);
974 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1235 5.6.7.8/24 4321 action %d",
978 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
981 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
982 SESSION_TEST ((res == 3),
983 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
986 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
987 lcl_port + 1, rmt_port);
988 SESSION_TEST ((res == 9),
989 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 9: %d",
992 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
993 lcl_port + 1, rmt_port + 1);
994 SESSION_TEST ((res == 8),
995 "Lookup 1.2.3.4 1235 5.6.7.8 4322, action should " "be 8: %d",
999 * Delete 1.2.0.0/16 1234 5.6.0.0/16 4321 and 1.2.0.0/16 * 5.6.0.0/16 *
1000 * Lookup 1.2.3.4 1234 5.6.7.8 4321
1002 args.lcl_port = 1234;
1003 args.rmt_port = 4321;
1004 args.lcl.fp_len = 16;
1005 args.rmt.fp_len = 16;
1007 error = session_rules_table_add_del (srt, &args);
1008 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 1234 5.6.0.0/16 4321");
1010 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1011 SESSION_TEST ((res == 3),
1012 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
1018 error = session_rules_table_add_del (srt, &args);
1019 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 * 5.6.0.0/16 *");
1021 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1022 SESSION_TEST ((res == 3),
1023 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
1027 * Delete 1.2.3.4/24 1234 5.6.7.5/24
1029 args.lcl.fp_addr.ip4 = lcl_ip;
1030 args.rmt.fp_addr.ip4 = rmt_ip;
1031 args.lcl.fp_len = 24;
1032 args.rmt.fp_len = 24;
1033 args.lcl_port = 1234;
1034 args.rmt_port = 4321;
1036 error = session_rules_table_add_del (srt, &args);
1037 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 1234 5.6.7.5/24");
1039 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1040 SESSION_TEST ((res == 2), "Action should be 2: %d", res);
1046 session_test_rules (vlib_main_t * vm, unformat_input_t * input)
1048 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
1049 u64 options[APP_OPTIONS_N_OPTIONS];
1050 u16 lcl_port = 1234, rmt_port = 4321;
1051 u32 server_index, server_index2;
1052 u32 placeholder_server_api_index = ~0;
1053 transport_connection_t *tc;
1054 u32 placeholder_port = 1111;
1055 u8 is_filtered = 0, *ns_id = format (0, "appns1");
1056 session_t *listener, *s;
1057 app_namespace_t *default_ns = app_namespace_get_default ();
1058 u32 local_ns_index = default_ns->local_table_index;
1060 app_namespace_t *app_ns;
1065 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1067 if (unformat (input, "verbose"))
1071 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1077 server_sep.is_ip4 = 1;
1078 server_sep.port = placeholder_port;
1079 clib_memset (options, 0, sizeof (options));
1081 vnet_app_attach_args_t attach_args = {
1082 .api_client_index = ~0,
1085 .session_cb_vft = &placeholder_session_cbs,
1086 .name = format (0, "session_test"),
1089 vnet_listen_args_t bind_args = {
1095 * Attach server with global and local default scope
1097 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1098 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1099 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1100 attach_args.namespace_id = 0;
1101 attach_args.api_client_index = placeholder_server_api_index;
1102 error = vnet_application_attach (&attach_args);
1103 SESSION_TEST ((error == 0), "server attached");
1104 server_index = attach_args.app_index;
1106 bind_args.app_index = server_index;
1107 error = vnet_listen (&bind_args);
1108 SESSION_TEST ((error == 0), "server bound to %U/%d", format_ip46_address,
1109 &server_sep.ip, 1, server_sep.port);
1110 al = app_listener_get_w_handle (bind_args.handle);
1111 listener = app_listener_get_session (al);
1112 ip4_address_t lcl_ip = {
1113 .as_u32 = clib_host_to_net_u32 (0x01020304),
1115 ip4_address_t rmt_ip = {
1116 .as_u32 = clib_host_to_net_u32 (0x05060708),
1118 fib_prefix_t lcl_pref = {
1119 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
1121 .fp_proto = FIB_PROTOCOL_IP4,
1123 fib_prefix_t rmt_pref = {
1124 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1126 .fp_proto = FIB_PROTOCOL_IP4,
1129 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1130 &rmt_pref.fp_addr.ip4, lcl_port,
1131 rmt_port, TRANSPORT_PROTO_TCP, 0,
1133 SESSION_TEST ((tc == 0), "optimized lookup should not work (port)");
1136 * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
1138 session_rule_add_del_args_t args = {
1139 .table_args.lcl = lcl_pref,
1140 .table_args.rmt = rmt_pref,
1141 .table_args.lcl_port = lcl_port,
1142 .table_args.rmt_port = rmt_port,
1143 .table_args.action_index = server_index,
1144 .table_args.is_add = 1,
1147 error = vnet_session_rule_add_del (&args);
1148 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
1149 args.table_args.action_index);
1151 tc = session_lookup_connection4 (0, &lcl_pref.fp_addr.ip4,
1152 &rmt_pref.fp_addr.ip4, lcl_port, rmt_port,
1153 TRANSPORT_PROTO_TCP);
1154 SESSION_TEST ((tc->c_index == listener->connection_index),
1155 "optimized lookup should return the listener");
1156 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1157 &rmt_pref.fp_addr.ip4, lcl_port,
1158 rmt_port, TRANSPORT_PROTO_TCP, 0,
1160 SESSION_TEST ((tc->c_index == listener->connection_index),
1161 "lookup should return the listener");
1162 s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4,
1163 lcl_port, rmt_port, TRANSPORT_PROTO_TCP);
1164 SESSION_TEST ((s->connection_index == listener->connection_index),
1165 "safe lookup should return the listener");
1166 session_endpoint_t sep = {
1167 .ip = rmt_pref.fp_addr,
1170 .transport_proto = TRANSPORT_PROTO_TCP,
1172 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1173 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1174 "should not work (global scope)");
1176 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1177 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1178 rmt_port, TRANSPORT_PROTO_TCP, 0,
1180 SESSION_TEST ((tc == 0),
1181 "optimized lookup for wrong lcl port + 1 should not work");
1184 * Add 1.2.3.4/16 * 5.6.7.8/16 4321
1186 args.table_args.lcl_port = 0;
1187 args.scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1188 error = vnet_session_rule_add_del (&args);
1189 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 4321 action %d",
1190 args.table_args.action_index);
1191 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1192 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1193 rmt_port, TRANSPORT_PROTO_TCP, 0,
1195 SESSION_TEST ((tc->c_index == listener->connection_index),
1196 "optimized lookup for lcl port + 1 should work");
1197 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1198 SESSION_TEST ((handle == server_index), "local session endpoint lookup "
1199 "should work (lcl ip was zeroed)");
1202 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1204 args.table_args.lcl_port = 1234;
1205 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1206 args.table_args.lcl.fp_len = 30;
1207 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1208 args.table_args.rmt.fp_len = 30;
1209 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1210 error = vnet_session_rule_add_del (&args);
1211 SESSION_TEST ((error == 0), "Add 1.2.3.4/30 1234 5.6.7.8/30 4321 action %d",
1212 args.table_args.action_index);
1216 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1217 TRANSPORT_PROTO_TCP);
1218 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1219 TRANSPORT_PROTO_TCP);
1222 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1223 &rmt_pref.fp_addr.ip4, lcl_port,
1224 rmt_port, TRANSPORT_PROTO_TCP, 0,
1226 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1227 "should fail (deny rule)");
1228 SESSION_TEST ((is_filtered == SESSION_LOOKUP_RESULT_FILTERED),
1229 "lookup should be filtered (deny)");
1231 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1232 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1233 "5.6.7.8/16 4321 in local table should return deny");
1235 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1236 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1237 rmt_port, TRANSPORT_PROTO_TCP, 0,
1239 SESSION_TEST ((tc->c_index == listener->connection_index),
1240 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should work");
1243 * "Mask" deny rule with more specific allow:
1244 * Add allow rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -3 (allow)
1246 args.table_args.is_add = 1;
1247 args.table_args.lcl_port = 1234;
1248 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1249 args.table_args.lcl.fp_len = 32;
1250 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1251 args.table_args.rmt.fp_len = 32;
1252 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1253 error = vnet_session_rule_add_del (&args);
1254 SESSION_TEST ((error == 0), "Add masking rule 1.2.3.4/30 1234 5.6.7.8/32 "
1255 "4321 action %d", args.table_args.action_index);
1258 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1259 &rmt_pref.fp_addr.ip4, lcl_port,
1260 rmt_port, TRANSPORT_PROTO_TCP, 0,
1262 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1263 "should fail (allow without app)");
1264 SESSION_TEST ((is_filtered == 0), "lookup should NOT be filtered");
1266 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1267 SESSION_TEST ((handle == SESSION_INVALID_HANDLE), "lookup for 1.2.3.4/32 "
1268 "1234 5.6.7.8/32 4321 in local table should return invalid");
1272 vlib_cli_output (vm, "Local rules");
1273 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1274 TRANSPORT_PROTO_TCP);
1277 sep.ip.ip4.as_u32 += 1 << 24;
1278 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1279 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234"
1280 " 5.6.7.9/32 4321 in local table should return deny");
1282 vnet_connect_args_t connect_args = {
1283 .app_index = attach_args.app_index,
1286 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1288 /* Try connecting */
1289 error = vnet_connect (&connect_args);
1290 SESSION_TEST ((error != 0), "connect should fail");
1291 SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1293 sep.ip.ip4.as_u32 -= 1 << 24;
1296 * Delete masking rule: 1.2.3.4/32 1234 5.6.7.8/32 4321 allow
1298 args.table_args.is_add = 0;
1299 args.table_args.lcl_port = 1234;
1300 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1301 args.table_args.lcl.fp_len = 32;
1302 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1303 args.table_args.rmt.fp_len = 32;
1304 error = vnet_session_rule_add_del (&args);
1305 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 allow");
1309 * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
1311 args.table_args.is_add = 1;
1312 args.table_args.lcl_port = 0;
1313 args.table_args.lcl.fp_len = 0;
1314 args.table_args.rmt.fp_len = 16;
1315 args.table_args.action_index = -1;
1316 error = vnet_session_rule_add_del (&args);
1317 SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d",
1318 args.table_args.action_index);
1322 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1323 TRANSPORT_PROTO_TCP);
1324 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1325 TRANSPORT_PROTO_TCP);
1328 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1329 SESSION_TEST ((handle == SESSION_DROP_HANDLE),
1330 "local session endpoint lookup should return deny");
1333 * Delete 1.2.3.4/32 1234 5.6.7.8/32 4321 deny
1335 args.table_args.is_add = 0;
1336 args.table_args.lcl_port = 1234;
1337 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1338 args.table_args.lcl.fp_len = 30;
1339 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1340 args.table_args.rmt.fp_len = 30;
1341 error = vnet_session_rule_add_del (&args);
1342 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1344 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1345 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1346 "local session endpoint lookup should return invalid");
1349 * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and
1350 * 1.2.3.4/16 1234 5.6.7.8/16 4321
1352 args.table_args.is_add = 0;
1353 args.table_args.lcl_port = 0;
1354 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1355 args.table_args.lcl.fp_len = 0;
1356 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1357 args.table_args.rmt.fp_len = 16;
1358 args.table_args.rmt_port = 4321;
1359 error = vnet_session_rule_add_del (&args);
1360 SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
1361 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1362 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1363 "should not work (removed)");
1365 args.table_args.is_add = 0;
1366 args.table_args.lcl = lcl_pref;
1368 args.table_args.is_add = 0;
1369 args.table_args.lcl_port = 0;
1370 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1371 args.table_args.lcl.fp_len = 16;
1372 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1373 args.table_args.rmt.fp_len = 16;
1374 args.table_args.rmt_port = 4321;
1375 error = vnet_session_rule_add_del (&args);
1376 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321");
1377 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1378 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1379 rmt_port, TRANSPORT_PROTO_TCP, 0,
1381 SESSION_TEST ((tc == 0),
1382 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should not "
1385 args.table_args.is_add = 0;
1386 args.table_args.lcl_port = 1234;
1387 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1388 args.table_args.lcl.fp_len = 16;
1389 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1390 args.table_args.rmt.fp_len = 16;
1391 args.table_args.rmt_port = 4321;
1392 error = vnet_session_rule_add_del (&args);
1393 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321");
1394 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1395 &rmt_pref.fp_addr.ip4, lcl_port,
1396 rmt_port, TRANSPORT_PROTO_TCP, 0,
1398 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should "
1399 "not work (del + deny)");
1401 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1402 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1403 &rmt_pref.fp_addr.ip4, lcl_port,
1404 rmt_port, TRANSPORT_PROTO_TCP, 0,
1406 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should"
1407 " not work (no-rule)");
1410 * Test tags. Add/overwrite/del rule with tag
1412 args.table_args.is_add = 1;
1413 args.table_args.lcl_port = 1234;
1414 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1415 args.table_args.lcl.fp_len = 16;
1416 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1417 args.table_args.rmt.fp_len = 16;
1418 args.table_args.rmt_port = 4321;
1419 args.table_args.tag = format (0, "test_rule");
1420 args.table_args.action_index = server_index;
1421 error = vnet_session_rule_add_del (&args);
1422 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 deny "
1426 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1427 TRANSPORT_PROTO_TCP);
1428 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1429 TRANSPORT_PROTO_TCP);
1431 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1432 &rmt_pref.fp_addr.ip4, lcl_port,
1433 rmt_port, TRANSPORT_PROTO_TCP, 0,
1435 SESSION_TEST ((tc->c_index == listener->connection_index),
1436 "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should work");
1438 vec_free (args.table_args.tag);
1439 args.table_args.lcl_port = 1234;
1440 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1441 args.table_args.lcl.fp_len = 16;
1442 args.table_args.tag = format (0, "test_rule_overwrite");
1443 error = vnet_session_rule_add_del (&args);
1444 SESSION_TEST ((error == 0),
1445 "Overwrite 1.2.3.4/16 1234 5.6.7.8/16 4321 deny tag test_rule"
1449 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1450 TRANSPORT_PROTO_TCP);
1451 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1452 TRANSPORT_PROTO_TCP);
1455 args.table_args.is_add = 0;
1456 args.table_args.lcl_port += 1;
1457 error = vnet_session_rule_add_del (&args);
1458 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny "
1459 "tag %v", args.table_args.tag);
1462 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1463 TRANSPORT_PROTO_TCP);
1464 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1465 TRANSPORT_PROTO_TCP);
1467 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1468 &rmt_pref.fp_addr.ip4, lcl_port,
1469 rmt_port, TRANSPORT_PROTO_TCP, 0,
1471 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/32 4321 should not"
1476 * Test local rules with multiple namespaces
1480 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1482 args.table_args.is_add = 1;
1483 args.table_args.lcl_port = 1234;
1484 args.table_args.rmt_port = 0;
1485 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1486 args.table_args.lcl.fp_len = 32;
1487 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1488 args.table_args.rmt.fp_len = 32;
1489 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1490 args.table_args.tag = 0;
1491 args.scope = SESSION_RULE_SCOPE_LOCAL;
1492 error = vnet_session_rule_add_del (&args);
1493 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d",
1494 args.table_args.action_index);
1496 * Add 'white' rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1498 args.table_args.is_add = 1;
1499 args.table_args.lcl_port = 1234;
1500 args.table_args.rmt_port = 4321;
1501 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1502 args.table_args.lcl.fp_len = 32;
1503 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1504 args.table_args.rmt.fp_len = 32;
1505 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1506 error = vnet_session_rule_add_del (&args);
1510 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1511 TRANSPORT_PROTO_TCP);
1514 vnet_app_namespace_add_del_args_t ns_args = {
1517 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
1520 error = vnet_app_namespace_add_del (&ns_args);
1521 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
1522 app_ns = app_namespace_get_from_id (ns_id);
1524 attach_args.namespace_id = ns_id;
1525 attach_args.api_client_index = placeholder_server_api_index;
1526 vec_free (attach_args.name);
1527 attach_args.name = format (0, "server_test2");
1528 error = vnet_application_attach (&attach_args);
1529 SESSION_TEST ((error == 0), "server2 attached");
1530 server_index2 = attach_args.app_index;
1533 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1535 args.table_args.lcl_port = 1234;
1536 args.table_args.rmt_port = 0;
1537 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1538 args.table_args.lcl.fp_len = 32;
1539 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1540 args.table_args.rmt.fp_len = 32;
1541 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1542 args.appns_index = app_namespace_index (app_ns);
1544 error = vnet_session_rule_add_del (&args);
1545 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d "
1546 "in test namespace", args.table_args.action_index);
1548 * Lookup default namespace
1550 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1551 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1552 "lookup for 1.2.3.4/32 1234 5.6.7.8/32 4321 in local table "
1553 "should return allow (invalid)");
1556 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1557 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1558 "5.6.7.8/16 432*2* in local table should return deny");
1561 connect_args.app_index = server_index;
1562 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1564 error = vnet_connect (&connect_args);
1565 SESSION_TEST ((error != 0), "connect should fail");
1566 SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1569 * Lookup test namespace
1571 handle = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1572 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1573 "5.6.7.8/16 4321 in local table should return deny");
1575 connect_args.app_index = server_index;
1576 error = vnet_connect (&connect_args);
1577 SESSION_TEST ((error != 0), "connect should fail");
1578 SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1580 args.table_args.is_add = 0;
1581 vnet_session_rule_add_del (&args);
1583 args.appns_index = 0;
1584 args.table_args.is_add = 0;
1585 vnet_session_rule_add_del (&args);
1587 args.table_args.rmt_port = 4321;
1588 vnet_session_rule_add_del (&args);
1592 vec_free (args.table_args.tag);
1593 vnet_app_detach_args_t detach_args = {
1594 .app_index = server_index,
1595 .api_client_index = ~0,
1597 vnet_application_detach (&detach_args);
1599 detach_args.app_index = server_index2;
1600 vnet_application_detach (&detach_args);
1603 error = vnet_app_namespace_add_del (&ns_args);
1604 SESSION_TEST ((error == 0), "app ns delete should succeed: %d", error);
1607 vec_free (attach_args.name);
1612 session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
1614 u64 options[APP_OPTIONS_N_OPTIONS];
1615 char *show_listeners = "sh session listeners tcp verbose";
1616 char *show_local_listeners = "sh app ns table default";
1617 unformat_input_t tmp_input;
1618 u32 server_index, app_index;
1619 u32 placeholder_server_api_index = ~0, sw_if_index = 0;
1622 transport_connection_t *tc;
1623 u16 lcl_port = 1234, rmt_port = 4321;
1624 app_namespace_t *app_ns;
1625 int verbose = 0, error = 0;
1628 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1630 if (unformat (input, "verbose"))
1634 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1640 ip4_address_t lcl_ip = {
1641 .as_u32 = clib_host_to_net_u32 (0x01020304),
1643 ip4_address_t rmt_ip = {
1644 .as_u32 = clib_host_to_net_u32 (0x05060708),
1646 fib_prefix_t rmt_pref = {
1647 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1649 .fp_proto = FIB_PROTOCOL_IP4,
1651 session_endpoint_t sep = {
1652 .ip = rmt_pref.fp_addr,
1655 .transport_proto = TRANSPORT_PROTO_TCP,
1659 * Create loopback interface
1661 session_create_lookpback (0, &sw_if_index, &lcl_ip);
1663 app_ns = app_namespace_get_default ();
1664 app_ns->sw_if_index = sw_if_index;
1666 clib_memset (options, 0, sizeof (options));
1667 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1668 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
1669 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_PROXY;
1670 options[APP_OPTIONS_PROXY_TRANSPORT] = 1 << TRANSPORT_PROTO_TCP;
1671 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1672 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1673 vnet_app_attach_args_t attach_args = {
1674 .api_client_index = ~0,
1677 .session_cb_vft = &placeholder_session_cbs,
1678 .name = format (0, "session_test"),
1681 attach_args.api_client_index = placeholder_server_api_index;
1682 error = vnet_application_attach (&attach_args);
1683 SESSION_TEST ((error == 0), "server attachment should work");
1684 server_index = attach_args.app_index;
1688 unformat_init_string (&tmp_input, show_listeners,
1689 strlen (show_listeners));
1690 vlib_cli_input (vm, &tmp_input, 0, 0);
1691 unformat_init_string (&tmp_input, show_local_listeners,
1692 strlen (show_local_listeners));
1693 vlib_cli_input (vm, &tmp_input, 0, 0);
1696 tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port,
1697 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1698 SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be "
1700 s = listen_session_get (tc->s_index);
1701 al = app_listener_get (s->al_index);
1702 SESSION_TEST ((al->app_index == server_index), "lookup should return"
1705 tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port,
1706 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1707 SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should"
1710 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1711 SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1714 vnet_app_detach_args_t detach_args = {
1715 .app_index = server_index,
1716 .api_client_index = ~0,
1718 vnet_application_detach (&detach_args);
1722 unformat_init_string (&tmp_input, show_listeners,
1723 strlen (show_listeners));
1724 vlib_cli_input (vm, &tmp_input, 0, 0);
1725 unformat_init_string (&tmp_input, show_local_listeners,
1726 strlen (show_local_listeners));
1727 vlib_cli_input (vm, &tmp_input, 0, 0);
1730 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1731 SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX),
1732 "local session endpoint lookup should not work after detach");
1734 unformat_free (&tmp_input);
1735 vec_free (attach_args.name);
1736 session_delete_loopback (sw_if_index);
1741 wait_for_event (svm_msg_q_t * mq, int fd, int epfd, u8 use_eventfd)
1745 svm_msg_q_wait (mq, SVM_MQ_WAIT_EMPTY);
1749 int __clib_unused n_read, rv;
1750 struct epoll_event ep_evt;
1755 rv = epoll_wait (epfd, &ep_evt, 1, -1);
1758 ST_DBG ("epoll error");
1761 else if (rv > 0 && (ep_evt.events & EPOLLIN))
1763 n_read = read (fd, &buf, sizeof (buf));
1768 if (!svm_msg_q_is_empty (mq))
1774 /* Used to be part of application_worker.c prior to adding support for
1778 test_mq_try_lock_and_alloc_msg (svm_msg_q_t *mq, session_mq_rings_e ring,
1779 svm_msg_q_msg_t *msg)
1785 rv = svm_msg_q_lock_and_alloc_msg_w_ring (mq, ring, SVM_Q_NOWAIT, msg);
1789 * Break the loop if mq is full, usually this is because the
1790 * app has crashed or is hanging on somewhere.
1801 /* Used to be part of application_worker.c prior to adding support for
1802 * async rx and was used for delivering io events over mq
1803 * NB: removed handling of mq congestion
1806 test_app_send_io_evt_rx (app_worker_t *app_wrk, session_t *s)
1808 svm_msg_q_msg_t _mq_msg = { 0 }, *mq_msg = &_mq_msg;
1809 session_event_t *evt;
1814 if (app_worker_application_is_builtin (app_wrk))
1815 return app_worker_rx_notify (app_wrk, s);
1817 if (svm_fifo_has_event (s->rx_fifo))
1820 app_session = s->rx_fifo->shr->client_session_index;
1821 mq = app_wrk->event_queue;
1823 rv = test_mq_try_lock_and_alloc_msg (mq, SESSION_MQ_IO_EVT_RING, mq_msg);
1825 if (PREDICT_FALSE (rv))
1827 clib_warning ("failed to alloc mq message");
1831 evt = svm_msg_q_msg_data (mq, mq_msg);
1832 evt->event_type = SESSION_IO_EVT_RX;
1833 evt->session_index = app_session;
1835 (void) svm_fifo_set_event (s->rx_fifo);
1837 svm_msg_q_add_and_unlock (mq, mq_msg);
1843 session_test_mq_speed (vlib_main_t * vm, unformat_input_t * input)
1845 int error, __clib_unused verbose, use_eventfd = 0;
1846 u64 i, n_test_msgs = 1 << 10, *counter;
1847 u64 options[APP_OPTIONS_N_OPTIONS];
1848 int epfd = -1, rv, prod_fd = -1;
1849 svm_fifo_t *rx_fifo, *tx_fifo;
1850 vl_api_registration_t *reg;
1851 struct epoll_event ep_evt;
1852 u32 app_index, api_index;
1853 app_worker_t *app_wrk;
1854 segment_manager_t *sm;
1855 svm_msg_q_msg_t msg;
1863 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1865 if (unformat (input, "verbose"))
1867 else if (unformat (input, "%d", &n_test_msgs))
1869 else if (unformat (input, "use-eventfd"))
1873 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1879 q = clib_mem_alloc (sizeof (*q));
1880 api_index = vl_api_memclnt_create_internal ("session_mq_test_api", q);
1882 clib_memset (options, 0, sizeof (options));
1883 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1884 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1885 options[APP_OPTIONS_EVT_QUEUE_SIZE] = 2048;
1887 reg = vl_api_client_index_to_registration (api_index);
1888 /* Shut up coverity */
1892 vnet_app_attach_args_t attach_args = {
1893 .api_client_index = api_index,
1896 .session_cb_vft = &placeholder_session_cbs,
1897 .name = format (0, "session_mq_test"),
1899 error = vnet_application_attach (&attach_args);
1900 SESSION_TEST ((error == 0), "server attachment should work");
1902 app_index = attach_args.app_index;
1904 app = application_get (app_index);
1905 app_wrk = application_get_worker (app, 0);
1906 mq = app_wrk->event_queue;
1909 svm_msg_q_alloc_eventfd (mq);
1910 prod_fd = svm_msg_q_get_eventfd (mq);
1911 SESSION_TEST (prod_fd != -1, "mq producer eventd valid %u", prod_fd);
1914 sm = app_worker_get_connect_segment_manager (app_wrk);
1915 segment_manager_alloc_session_fifos (sm, 0, &rx_fifo, &tx_fifo);
1916 s.rx_fifo = rx_fifo;
1917 s.tx_fifo = tx_fifo;
1918 s.session_state = SESSION_STATE_READY;
1919 counter = (u64 *) f_head_cptr (rx_fifo)->data;
1920 start = vlib_time_now (vm);
1924 SESSION_TEST (0, "fork failed");
1930 epfd = epoll_create1 (0);
1931 SESSION_TEST (epfd != -1, "epfd created");
1932 ep_evt.events = EPOLLIN;
1933 ep_evt.data.u64 = prod_fd;
1934 rv = epoll_ctl (epfd, EPOLL_CTL_ADD, prod_fd, &ep_evt);
1935 SESSION_TEST (rv == 0, "epoll returned %d", rv);
1938 for (i = 0; i < n_test_msgs; i++)
1940 wait_for_event (mq, prod_fd, epfd, use_eventfd);
1941 svm_msg_q_sub_raw (mq, &msg);
1942 svm_msg_q_free_msg (mq, &msg);
1943 svm_msg_q_unlock (mq);
1944 *counter = *counter + 1;
1945 svm_fifo_unset_event (rx_fifo);
1951 ST_DBG ("client pid %u", pid);
1952 for (i = 0; i < n_test_msgs; i++)
1954 while (svm_fifo_has_event (rx_fifo))
1956 test_app_send_io_evt_rx (app_wrk, &s);
1960 diff = vlib_time_now (vm) - start;
1961 ST_DBG ("done %u events in %.2f sec: %f evts/s", *counter,
1962 diff, *counter / diff);
1964 vnet_app_detach_args_t detach_args = {
1965 .app_index = app_index,
1966 .api_client_index = ~0,
1968 vnet_application_detach (&detach_args);
1973 session_test_mq_basic (vlib_main_t * vm, unformat_input_t * input)
1975 svm_msg_q_cfg_t _cfg, *cfg = &_cfg;
1976 svm_msg_q_msg_t msg1, msg2, msg[12];
1977 int __clib_unused verbose, i, rv;
1978 svm_msg_q_shared_t *smq;
1979 svm_msg_q_ring_t *ring;
1980 svm_msg_q_t _mq = { 0 }, *mq = &_mq;
1983 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1985 if (unformat (input, "verbose"))
1989 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1995 svm_msg_q_ring_cfg_t rc[2] = { {8, 8, 0}
1998 cfg->consumer_pid = ~0;
2001 cfg->ring_cfgs = rc;
2003 smq = svm_msg_q_alloc (cfg);
2004 svm_msg_q_attach (mq, smq);
2005 SESSION_TEST (smq != 0, "svm_msg_q_alloc");
2006 SESSION_TEST (vec_len (mq->rings) == 2, "ring allocation");
2007 rings_ptr = (u8 *) mq->rings[0].shr->data;
2008 vec_foreach (ring, mq->rings)
2010 SESSION_TEST (ring->shr->data == rings_ptr, "ring data");
2011 rings_ptr += (uword) ring->nitems * ring->elsize;
2012 rings_ptr += sizeof (svm_msg_q_ring_shared_t);
2015 msg1 = svm_msg_q_alloc_msg (mq, 8);
2016 rv = (mq->rings[0].shr->cursize != 1 || msg1.ring_index != 0 ||
2017 msg1.elt_index != 0);
2018 SESSION_TEST (rv == 0, "msg alloc1");
2020 msg2 = svm_msg_q_alloc_msg (mq, 15);
2021 rv = (mq->rings[1].shr->cursize != 1 || msg2.ring_index != 1 ||
2022 msg2.elt_index != 0);
2023 SESSION_TEST (rv == 0, "msg alloc2");
2025 svm_msg_q_free_msg (mq, &msg1);
2026 SESSION_TEST (mq->rings[0].shr->cursize == 0, "free msg");
2028 for (i = 0; i < 12; i++)
2030 msg[i] = svm_msg_q_alloc_msg (mq, 7);
2031 *(u32 *) svm_msg_q_msg_data (mq, &msg[i]) = i;
2034 rv = (mq->rings[0].shr->cursize != 8 || mq->rings[1].shr->cursize != 5);
2035 SESSION_TEST (rv == 0, "msg alloc3");
2037 *(u32 *) svm_msg_q_msg_data (mq, &msg2) = 123;
2038 svm_msg_q_add (mq, &msg2, SVM_Q_NOWAIT);
2039 for (i = 0; i < 12; i++)
2040 svm_msg_q_add (mq, &msg[i], SVM_Q_NOWAIT);
2042 rv = svm_msg_q_sub (mq, &msg2, SVM_Q_NOWAIT, 0);
2043 SESSION_TEST (rv == 0, "dequeue1");
2045 SESSION_TEST (msg2.ring_index == 1 && msg2.elt_index == 0,
2047 rv = (*(u32 *) svm_msg_q_msg_data (mq, &msg2) == 123);
2048 SESSION_TEST (rv, "dequeue 1 data");
2050 svm_msg_q_free_msg (mq, &msg2);
2052 for (i = 0; i < 12; i++)
2054 if (svm_msg_q_sub (mq, &msg[i], SVM_Q_NOWAIT, 0))
2055 SESSION_TEST (0, "dequeue2");
2058 if (msg[i].ring_index != 0 || msg[i].elt_index != (i + 1) % 8)
2059 SESSION_TEST (0, "dequeue2 result2");
2063 if (msg[i].ring_index != 1 || msg[i].elt_index != (i - 8) + 1)
2064 SESSION_TEST (0, "dequeue2 result3");
2066 if (*(u32 *) svm_msg_q_msg_data (mq, &msg[i]) != i)
2067 SESSION_TEST (0, "dequeue2 wrong data");
2068 svm_msg_q_free_msg (mq, &msg[i]);
2070 rv = (mq->rings[0].shr->cursize == 0 && mq->rings[1].shr->cursize == 0);
2071 SESSION_TEST (rv, "post dequeue");
2076 static clib_error_t *
2077 session_test (vlib_main_t * vm,
2078 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
2082 vnet_session_enable_disable (vm, 1);
2084 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2086 if (unformat (input, "basic"))
2087 res = session_test_basic (vm, input);
2088 else if (unformat (input, "namespace"))
2089 res = session_test_namespace (vm, input);
2090 else if (unformat (input, "rules-table"))
2091 res = session_test_rule_table (vm, input);
2092 else if (unformat (input, "rules"))
2093 res = session_test_rules (vm, input);
2094 else if (unformat (input, "proxy"))
2095 res = session_test_proxy (vm, input);
2096 else if (unformat (input, "endpt-cfg"))
2097 res = session_test_endpoint_cfg (vm, input);
2098 else if (unformat (input, "mq-speed"))
2099 res = session_test_mq_speed (vm, input);
2100 else if (unformat (input, "mq-basic"))
2101 res = session_test_mq_basic (vm, input);
2102 else if (unformat (input, "all"))
2104 if ((res = session_test_basic (vm, input)))
2106 if ((res = session_test_namespace (vm, input)))
2108 if ((res = session_test_rule_table (vm, input)))
2110 if ((res = session_test_rules (vm, input)))
2112 if ((res = session_test_proxy (vm, input)))
2114 if ((res = session_test_endpoint_cfg (vm, input)))
2116 if ((res = session_test_mq_speed (vm, input)))
2118 if ((res = session_test_mq_basic (vm, input)))
2127 return clib_error_return (0, "Session unit test failed");
2131 VLIB_CLI_COMMAND (tcp_test_command, static) =
2133 .path = "test session",
2134 .short_help = "internal session unit tests",
2135 .function = session_test,
2139 * fd.io coding-style-patch-verification: ON
2142 * eval: (c-set-style "gnu")