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)
380 vlib_worker_thread_barrier_release (vm);
381 vlib_process_suspend (vm, 100e-3);
382 vlib_worker_thread_barrier_sync (vm);
384 while (accepted_session_index == ~0 && ++tries < 100)
386 vlib_worker_thread_barrier_release (vm);
387 vlib_process_suspend (vm, 100e-3);
388 vlib_worker_thread_barrier_sync (vm);
391 clib_warning ("waited %.1f seconds for connections", tries / 10.0);
392 SESSION_TEST ((connected_session_index != ~0), "session should exist");
393 SESSION_TEST ((connected_session_thread != ~0), "thread should exist");
394 SESSION_TEST ((accepted_session_index != ~0), "session should exist");
395 SESSION_TEST ((accepted_session_thread != ~0), "thread should exist");
396 s = session_get (connected_session_index, connected_session_thread);
397 tc = session_get_transport (s);
398 SESSION_TEST ((tc != 0), "transport should exist");
399 SESSION_TEST ((memcmp (&tc->lcl_ip, &client_sep.peer.ip,
400 sizeof (tc->lcl_ip)) == 0), "ips should be equal");
401 SESSION_TEST ((tc->lcl_port == placeholder_client_port),
402 "ports should be equal");
404 /* These sessions, because of the way they're established are pinned to
405 * main thread, even when we have workers and we avoid polling main thread,
406 * i.e., we can't cleanup pending disconnects, so force cleanup for both
408 session_transport_cleanup (s);
409 s = session_get (accepted_session_index, accepted_session_thread);
410 session_transport_cleanup (s);
412 vnet_app_detach_args_t detach_args = {
413 .app_index = server_index,
414 .api_client_index = ~0,
416 vnet_application_detach (&detach_args);
417 detach_args.app_index = client_index;
418 vnet_application_detach (&detach_args);
420 /* Allow the disconnects to finish before removing the routes. */
421 vlib_process_suspend (vm, 10e-3);
423 session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
425 session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
428 session_delete_loopback (sw_if_index[0]);
429 session_delete_loopback (sw_if_index[1]);
434 session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
436 u64 options[APP_OPTIONS_N_OPTIONS], placeholder_secret = 1234, tries;
437 u32 server_index, server_st_index, server_local_st_index;
438 u32 placeholder_port = 1234, client_index, server_wrk_index;
439 u32 placeholder_api_context = 4321, placeholder_client_api_index = ~0;
440 u32 placeholder_server_api_index = ~0, sw_if_index = 0;
441 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
442 session_endpoint_t client_sep = SESSION_ENDPOINT_NULL;
443 session_endpoint_t intf_sep = SESSION_ENDPOINT_NULL;
444 u8 *ns_id, *server_name, *client_name;
445 app_namespace_t *app_ns;
446 application_t *server;
451 ns_id = format (0, "appns1");
452 server_name = format (0, "session_test");
453 client_name = format (0, "session_test_client");
455 server_sep.is_ip4 = 1;
456 server_sep.port = placeholder_port;
457 client_sep.is_ip4 = 1;
458 client_sep.port = placeholder_port;
459 clib_memset (options, 0, sizeof (options));
461 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
462 vnet_app_attach_args_t attach_args = {
463 .api_client_index = ~0,
466 .session_cb_vft = &placeholder_session_cbs,
470 vnet_listen_args_t bind_args = {
475 vnet_connect_args_t connect_args = {
479 clib_memcpy (&connect_args.sep, &client_sep, sizeof (client_sep));
481 vnet_unlisten_args_t unbind_args = {
482 .handle = bind_args.handle,
486 vnet_app_detach_args_t detach_args = {
488 .api_client_index = ~0,
491 ip4_address_t intf_addr = {
492 .as_u32 = clib_host_to_net_u32 (0x07000105),
495 intf_sep.ip.ip4 = intf_addr;
497 intf_sep.port = placeholder_port;
500 * Insert namespace and lookup
503 vnet_app_namespace_add_del_args_t ns_args = {
505 .secret = placeholder_secret,
506 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
509 error = vnet_app_namespace_add_del (&ns_args);
510 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
512 app_ns = app_namespace_get_from_id (ns_id);
513 SESSION_TEST ((app_ns != 0), "should find ns %v status", ns_id);
514 SESSION_TEST ((app_ns->ns_secret == placeholder_secret),
515 "secret should be %d", placeholder_secret);
516 SESSION_TEST ((app_ns->sw_if_index == APP_NAMESPACE_INVALID_INDEX),
517 "sw_if_index should be invalid");
520 * Try application attach with wrong secret
523 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
524 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
525 options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret - 1;
526 attach_args.namespace_id = ns_id;
527 attach_args.api_client_index = placeholder_server_api_index;
529 error = vnet_application_attach (&attach_args);
530 SESSION_TEST ((error != 0), "app attachment should fail");
531 SESSION_TEST ((error == VNET_API_ERROR_APP_WRONG_NS_SECRET),
532 "code should be wrong ns secret: %d", error);
535 * Attach server with global default scope
537 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
538 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
539 options[APP_OPTIONS_NAMESPACE_SECRET] = 0;
540 attach_args.namespace_id = 0;
541 attach_args.api_client_index = placeholder_server_api_index;
542 error = vnet_application_attach (&attach_args);
543 SESSION_TEST ((error == 0), "server attachment should work");
544 server_index = attach_args.app_index;
545 server = application_get (server_index);
546 server_wrk_index = application_get_default_worker (server)->wrk_index;
547 SESSION_TEST ((server->ns_index == 0),
548 "server should be in the default ns");
550 bind_args.app_index = server_index;
551 error = vnet_listen (&bind_args);
552 SESSION_TEST ((error == 0), "server bind should work");
554 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
555 s = session_lookup_listener (server_st_index, &server_sep);
556 SESSION_TEST ((s != 0), "listener should exist in global table");
557 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
558 " that of the server");
559 server_local_st_index = application_local_session_table (server);
560 SESSION_TEST ((server_local_st_index == APP_INVALID_INDEX),
561 "server shouldn't have access to local table");
563 unbind_args.app_index = server_index;
564 unbind_args.handle = bind_args.handle;
565 error = vnet_unlisten (&unbind_args);
566 SESSION_TEST ((error == 0), "unbind should work");
568 s = session_lookup_listener (server_st_index, &server_sep);
569 SESSION_TEST ((s == 0), "listener should not exist in global table");
571 detach_args.app_index = server_index;
572 vnet_application_detach (&detach_args);
575 * Attach server with local and global scope
577 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
578 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
579 options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret;
580 attach_args.namespace_id = ns_id;
581 attach_args.api_client_index = placeholder_server_api_index;
582 error = vnet_application_attach (&attach_args);
583 SESSION_TEST ((error == 0), "server attachment should work");
584 server_index = attach_args.app_index;
585 server = application_get (server_index);
586 server_wrk_index = application_get_default_worker (server)->wrk_index;
587 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
588 "server should be in the right ns");
590 bind_args.app_index = server_index;
591 error = vnet_listen (&bind_args);
592 SESSION_TEST ((error == 0), "bind should work");
593 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
594 s = session_lookup_listener (server_st_index, &server_sep);
595 SESSION_TEST ((s != 0), "listener should exist in global table");
596 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
597 " that of the server");
598 server_local_st_index = application_local_session_table (server);
599 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
600 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
601 "listener should exist in local table");
604 * Try client connect with 1) local scope 2) global scope
606 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
607 attach_args.name = client_name;
608 attach_args.api_client_index = placeholder_client_api_index;
609 error = vnet_application_attach (&attach_args);
610 SESSION_TEST ((error == 0), "client attachment should work");
611 client_index = attach_args.app_index;
612 connect_args.api_context = placeholder_api_context;
613 connect_args.app_index = client_index;
614 error = vnet_connect (&connect_args);
615 SESSION_TEST ((error != 0), "client connect should return error code");
616 SESSION_TEST ((error == SESSION_E_INVALID_RMT_IP),
617 "error code should be invalid value (zero ip)");
618 SESSION_TEST ((placeholder_segment_count == 0),
619 "shouldn't have received request to map new segment");
620 connect_args.sep.ip.ip4.as_u8[0] = 127;
621 error = vnet_connect (&connect_args);
622 SESSION_TEST ((error == 0), "client connect should not return error code");
624 /* wait for accept */
625 if (vlib_num_workers ())
628 while (!placeholder_accept && ++tries < 100)
630 vlib_worker_thread_barrier_release (vm);
631 vlib_process_suspend (vm, 100e-3);
632 vlib_worker_thread_barrier_sync (vm);
636 SESSION_TEST ((placeholder_segment_count == 1),
637 "should've received request to map new segment");
638 SESSION_TEST ((placeholder_accept == 1),
639 "should've received accept request");
640 detach_args.app_index = client_index;
641 vnet_application_detach (&detach_args);
643 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
644 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
645 attach_args.api_client_index = placeholder_client_api_index;
646 error = vnet_application_attach (&attach_args);
647 SESSION_TEST ((error == 0), "client attachment should work");
648 error = vnet_connect (&connect_args);
649 SESSION_TEST ((error != 0), "client connect should return error code");
650 SESSION_TEST ((error == SESSION_E_NOINTF),
651 "error code should be connect (nothing in local scope)");
652 detach_args.app_index = client_index;
653 vnet_application_detach (&detach_args);
656 * Unbind and detach server and then re-attach with local scope only
658 unbind_args.handle = bind_args.handle;
659 unbind_args.app_index = server_index;
660 error = vnet_unlisten (&unbind_args);
661 SESSION_TEST ((error == 0), "unbind should work");
663 s = session_lookup_listener (server_st_index, &server_sep);
664 SESSION_TEST ((s == 0), "listener should not exist in global table");
665 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
666 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
667 "listener should not exist in local table");
669 detach_args.app_index = server_index;
670 vnet_application_detach (&detach_args);
672 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
673 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
674 attach_args.api_client_index = placeholder_server_api_index;
675 attach_args.name = server_name;
676 error = vnet_application_attach (&attach_args);
677 SESSION_TEST ((error == 0), "app attachment should work");
678 server_index = attach_args.app_index;
679 server = application_get (server_index);
680 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
681 "app should be in the right ns");
683 bind_args.app_index = server_index;
684 error = vnet_listen (&bind_args);
685 SESSION_TEST ((error == 0), "bind should work");
687 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
688 s = session_lookup_listener (server_st_index, &server_sep);
689 SESSION_TEST ((s == 0), "listener should not exist in global table");
690 server_local_st_index = application_local_session_table (server);
691 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
692 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
693 "listener should exist in local table");
695 unbind_args.handle = bind_args.handle;
696 error = vnet_unlisten (&unbind_args);
697 SESSION_TEST ((error == 0), "unbind should work");
699 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
700 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
701 "listener should not exist in local table");
704 * Client attach + connect in default ns with local scope
706 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
707 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
708 attach_args.namespace_id = 0;
709 attach_args.api_client_index = placeholder_client_api_index;
710 attach_args.name = client_name;
711 vnet_application_attach (&attach_args);
712 error = vnet_connect (&connect_args);
713 SESSION_TEST ((error != 0), "client connect should return error code");
714 SESSION_TEST ((error == SESSION_E_NOROUTE),
715 "error code should be noroute (not in same ns)");
716 detach_args.app_index = client_index;
717 vnet_application_detach (&detach_args);
722 detach_args.app_index = server_index;
723 vnet_application_detach (&detach_args);
726 * Create loopback interface
728 session_create_lookpback (0, &sw_if_index, &intf_addr);
731 * Update namespace with interface
733 ns_args.sw_if_index = sw_if_index;
734 error = vnet_app_namespace_add_del (&ns_args);
735 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
738 * Attach server with local and global scope
740 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
741 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
742 options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret;
743 attach_args.namespace_id = ns_id;
744 attach_args.api_client_index = placeholder_server_api_index;
745 attach_args.name = server_name;
746 error = vnet_application_attach (&attach_args);
747 SESSION_TEST ((error == 0), "server attachment should work");
748 server_index = attach_args.app_index;
749 server = application_get (server_index);
750 server_wrk_index = application_get_default_worker (server)->wrk_index;
752 bind_args.app_index = server_index;
753 error = vnet_listen (&bind_args);
754 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
755 s = session_lookup_listener (server_st_index, &server_sep);
756 SESSION_TEST ((s == 0), "zero listener should not exist in global table");
758 s = session_lookup_listener (server_st_index, &intf_sep);
759 SESSION_TEST ((s != 0), "intf listener should exist in global table");
760 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be "
761 "that of the server");
762 server_local_st_index = application_local_session_table (server);
763 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
764 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
765 "zero listener should exist in local table");
766 detach_args.app_index = server_index;
767 vnet_application_detach (&detach_args);
772 vec_free (server_name);
773 vec_free (client_name);
775 session_delete_loopback (sw_if_index);
780 session_test_rule_table (vlib_main_t * vm, unformat_input_t * input)
782 session_rules_table_t _srt, *srt = &_srt;
783 u16 lcl_port = 1234, rmt_port = 4321;
784 u32 action_index = 1, res;
785 ip4_address_t lcl_lkup, rmt_lkup;
786 int verbose = 0, error;
788 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
790 if (unformat (input, "verbose"))
794 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
800 clib_memset (srt, 0, sizeof (*srt));
801 session_rules_table_init (srt);
803 ip4_address_t lcl_ip = {
804 .as_u32 = clib_host_to_net_u32 (0x01020304),
806 ip4_address_t rmt_ip = {
807 .as_u32 = clib_host_to_net_u32 (0x05060708),
809 ip4_address_t lcl_ip2 = {
810 .as_u32 = clib_host_to_net_u32 (0x02020202),
812 ip4_address_t rmt_ip2 = {
813 .as_u32 = clib_host_to_net_u32 (0x06060606),
815 ip4_address_t lcl_ip3 = {
816 .as_u32 = clib_host_to_net_u32 (0x03030303),
818 ip4_address_t rmt_ip3 = {
819 .as_u32 = clib_host_to_net_u32 (0x07070707),
821 fib_prefix_t lcl_pref = {
822 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
824 .fp_proto = FIB_PROTOCOL_IP4,
826 fib_prefix_t rmt_pref = {
827 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
829 .fp_proto = FIB_PROTOCOL_IP4,
832 session_rule_table_add_del_args_t args = {
835 .lcl_port = lcl_port,
836 .rmt_port = rmt_port,
837 .action_index = action_index++,
840 error = session_rules_table_add_del (srt, &args);
841 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
845 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
846 SESSION_TEST ((res == 1),
847 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 1: %d",
851 * Add 1.2.3.4/24 1234 5.6.7.8/16 4321 and 1.2.3.4/24 1234 5.6.7.8/24 4321
853 args.lcl.fp_addr.ip4 = lcl_ip;
854 args.lcl.fp_len = 24;
855 args.action_index = action_index++;
856 error = session_rules_table_add_del (srt, &args);
857 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/16 4321 action %d",
859 args.rmt.fp_addr.ip4 = rmt_ip;
860 args.rmt.fp_len = 24;
861 args.action_index = action_index++;
862 error = session_rules_table_add_del (srt, &args);
863 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/24 4321 action %d",
867 * Add 2.2.2.2/24 1234 6.6.6.6/16 4321 and 3.3.3.3/24 1234 7.7.7.7/16 4321
869 args.lcl.fp_addr.ip4 = lcl_ip2;
870 args.lcl.fp_len = 24;
871 args.rmt.fp_addr.ip4 = rmt_ip2;
872 args.rmt.fp_len = 16;
873 args.action_index = action_index++;
874 error = session_rules_table_add_del (srt, &args);
875 SESSION_TEST ((error == 0), "Add 2.2.2.2/24 1234 6.6.6.6/16 4321 action %d",
877 args.lcl.fp_addr.ip4 = lcl_ip3;
878 args.rmt.fp_addr.ip4 = rmt_ip3;
879 args.action_index = action_index++;
880 error = session_rules_table_add_del (srt, &args);
881 SESSION_TEST ((error == 0), "Add 3.3.3.3/24 1234 7.7.7.7/16 4321 action %d",
885 * Add again 3.3.3.3/24 1234 7.7.7.7/16 4321
887 args.lcl.fp_addr.ip4 = lcl_ip3;
888 args.rmt.fp_addr.ip4 = rmt_ip3;
889 args.action_index = action_index++;
890 error = session_rules_table_add_del (srt, &args);
891 SESSION_TEST ((error == 0), "overwrite 3.3.3.3/24 1234 7.7.7.7/16 4321 "
892 "action %d", action_index - 1);
895 * Lookup 1.2.3.4/32 1234 5.6.7.8/32 4321, 1.2.2.4/32 1234 5.6.7.9/32 4321
896 * and 3.3.3.3 1234 7.7.7.7 4321
899 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
900 SESSION_TEST ((res == 3),
901 "Lookup 1.2.3.4 1234 5.6.7.8 4321 action " "should be 3: %d",
904 lcl_lkup.as_u32 = clib_host_to_net_u32 (0x01020204);
905 rmt_lkup.as_u32 = clib_host_to_net_u32 (0x05060709);
907 session_rules_table_lookup4 (srt, &lcl_lkup,
908 &rmt_lkup, lcl_port, rmt_port);
909 SESSION_TEST ((res == 1),
910 "Lookup 1.2.2.4 1234 5.6.7.9 4321, action " "should be 1: %d",
914 session_rules_table_lookup4 (srt, &lcl_ip3, &rmt_ip3, lcl_port, rmt_port);
915 SESSION_TEST ((res == 6),
916 "Lookup 3.3.3.3 1234 7.7.7.7 4321, action "
917 "should be 6 (updated): %d", res);
920 * Add 1.2.3.4/24 * 5.6.7.8/24 *
921 * Lookup 1.2.3.4 1234 5.6.7.8 4321 and 1.2.3.4 1235 5.6.7.8 4321
923 args.lcl.fp_addr.ip4 = lcl_ip;
924 args.rmt.fp_addr.ip4 = rmt_ip;
925 args.lcl.fp_len = 24;
926 args.rmt.fp_len = 24;
929 args.action_index = action_index++;
930 error = session_rules_table_add_del (srt, &args);
931 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 * 5.6.7.8/24 * action %d",
934 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
935 SESSION_TEST ((res == 7),
936 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should"
937 " be 7 (lpm dst): %d", res);
939 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
940 lcl_port + 1, rmt_port);
941 SESSION_TEST ((res == 7),
942 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 7: %d",
946 * Del 1.2.3.4/24 * 5.6.7.8/24 *
947 * Add 1.2.3.4/16 * 5.6.7.8/16 * and 1.2.3.4/24 1235 5.6.7.8/24 4321
948 * Lookup 1.2.3.4 1234 5.6.7.8 4321, 1.2.3.4 1235 5.6.7.8 4321 and
949 * 1.2.3.4 1235 5.6.7.8 4322
952 error = session_rules_table_add_del (srt, &args);
953 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 * 5.6.7.8/24 *");
955 args.lcl.fp_addr.ip4 = lcl_ip;
956 args.rmt.fp_addr.ip4 = rmt_ip;
957 args.lcl.fp_len = 16;
958 args.rmt.fp_len = 16;
961 args.action_index = action_index++;
963 error = session_rules_table_add_del (srt, &args);
964 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 * action %d",
967 args.lcl.fp_addr.ip4 = lcl_ip;
968 args.rmt.fp_addr.ip4 = rmt_ip;
969 args.lcl.fp_len = 24;
970 args.rmt.fp_len = 24;
971 args.lcl_port = lcl_port + 1;
972 args.rmt_port = rmt_port;
973 args.action_index = action_index++;
975 error = session_rules_table_add_del (srt, &args);
976 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1235 5.6.7.8/24 4321 action %d",
980 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
983 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
984 SESSION_TEST ((res == 3),
985 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
988 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
989 lcl_port + 1, rmt_port);
990 SESSION_TEST ((res == 9),
991 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 9: %d",
994 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
995 lcl_port + 1, rmt_port + 1);
996 SESSION_TEST ((res == 8),
997 "Lookup 1.2.3.4 1235 5.6.7.8 4322, action should " "be 8: %d",
1001 * Delete 1.2.0.0/16 1234 5.6.0.0/16 4321 and 1.2.0.0/16 * 5.6.0.0/16 *
1002 * Lookup 1.2.3.4 1234 5.6.7.8 4321
1004 args.lcl_port = 1234;
1005 args.rmt_port = 4321;
1006 args.lcl.fp_len = 16;
1007 args.rmt.fp_len = 16;
1009 error = session_rules_table_add_del (srt, &args);
1010 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 1234 5.6.0.0/16 4321");
1012 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1013 SESSION_TEST ((res == 3),
1014 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
1020 error = session_rules_table_add_del (srt, &args);
1021 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 * 5.6.0.0/16 *");
1023 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1024 SESSION_TEST ((res == 3),
1025 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
1029 * Delete 1.2.3.4/24 1234 5.6.7.5/24
1031 args.lcl.fp_addr.ip4 = lcl_ip;
1032 args.rmt.fp_addr.ip4 = rmt_ip;
1033 args.lcl.fp_len = 24;
1034 args.rmt.fp_len = 24;
1035 args.lcl_port = 1234;
1036 args.rmt_port = 4321;
1038 error = session_rules_table_add_del (srt, &args);
1039 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 1234 5.6.7.5/24");
1041 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1042 SESSION_TEST ((res == 2), "Action should be 2: %d", res);
1048 session_test_rules (vlib_main_t * vm, unformat_input_t * input)
1050 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
1051 u64 options[APP_OPTIONS_N_OPTIONS];
1052 u16 lcl_port = 1234, rmt_port = 4321;
1053 u32 server_index, server_index2;
1054 u32 placeholder_server_api_index = ~0;
1055 transport_connection_t *tc;
1056 u32 placeholder_port = 1111;
1057 u8 is_filtered = 0, *ns_id = format (0, "appns1");
1058 session_t *listener, *s;
1059 app_namespace_t *default_ns = app_namespace_get_default ();
1060 u32 local_ns_index = default_ns->local_table_index;
1062 app_namespace_t *app_ns;
1067 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1069 if (unformat (input, "verbose"))
1073 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1079 server_sep.is_ip4 = 1;
1080 server_sep.port = placeholder_port;
1081 clib_memset (options, 0, sizeof (options));
1083 vnet_app_attach_args_t attach_args = {
1084 .api_client_index = ~0,
1087 .session_cb_vft = &placeholder_session_cbs,
1088 .name = format (0, "session_test"),
1091 vnet_listen_args_t bind_args = {
1097 * Attach server with global and local default scope
1099 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1100 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1101 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1102 attach_args.namespace_id = 0;
1103 attach_args.api_client_index = placeholder_server_api_index;
1104 error = vnet_application_attach (&attach_args);
1105 SESSION_TEST ((error == 0), "server attached");
1106 server_index = attach_args.app_index;
1108 bind_args.app_index = server_index;
1109 error = vnet_listen (&bind_args);
1110 SESSION_TEST ((error == 0), "server bound to %U/%d", format_ip46_address,
1111 &server_sep.ip, 1, server_sep.port);
1112 al = app_listener_get_w_handle (bind_args.handle);
1113 listener = app_listener_get_session (al);
1114 ip4_address_t lcl_ip = {
1115 .as_u32 = clib_host_to_net_u32 (0x01020304),
1117 ip4_address_t rmt_ip = {
1118 .as_u32 = clib_host_to_net_u32 (0x05060708),
1120 fib_prefix_t lcl_pref = {
1121 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
1123 .fp_proto = FIB_PROTOCOL_IP4,
1125 fib_prefix_t rmt_pref = {
1126 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1128 .fp_proto = FIB_PROTOCOL_IP4,
1131 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1132 &rmt_pref.fp_addr.ip4, lcl_port,
1133 rmt_port, TRANSPORT_PROTO_TCP, 0,
1135 SESSION_TEST ((tc == 0), "optimized lookup should not work (port)");
1138 * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
1140 session_rule_add_del_args_t args = {
1141 .table_args.lcl = lcl_pref,
1142 .table_args.rmt = rmt_pref,
1143 .table_args.lcl_port = lcl_port,
1144 .table_args.rmt_port = rmt_port,
1145 .table_args.action_index = server_index,
1146 .table_args.is_add = 1,
1149 error = vnet_session_rule_add_del (&args);
1150 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
1151 args.table_args.action_index);
1153 tc = session_lookup_connection4 (0, &lcl_pref.fp_addr.ip4,
1154 &rmt_pref.fp_addr.ip4, lcl_port, rmt_port,
1155 TRANSPORT_PROTO_TCP);
1156 SESSION_TEST ((tc->c_index == listener->connection_index),
1157 "optimized lookup should return the listener");
1158 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1159 &rmt_pref.fp_addr.ip4, lcl_port,
1160 rmt_port, TRANSPORT_PROTO_TCP, 0,
1162 SESSION_TEST ((tc->c_index == listener->connection_index),
1163 "lookup should return the listener");
1164 s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4,
1165 lcl_port, rmt_port, TRANSPORT_PROTO_TCP);
1166 SESSION_TEST ((s->connection_index == listener->connection_index),
1167 "safe lookup should return the listener");
1168 session_endpoint_t sep = {
1169 .ip = rmt_pref.fp_addr,
1172 .transport_proto = TRANSPORT_PROTO_TCP,
1174 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1175 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1176 "should not work (global scope)");
1178 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1179 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1180 rmt_port, TRANSPORT_PROTO_TCP, 0,
1182 SESSION_TEST ((tc == 0),
1183 "optimized lookup for wrong lcl port + 1 should not work");
1186 * Add 1.2.3.4/16 * 5.6.7.8/16 4321
1188 args.table_args.lcl_port = 0;
1189 args.scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1190 error = vnet_session_rule_add_del (&args);
1191 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 4321 action %d",
1192 args.table_args.action_index);
1193 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1194 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1195 rmt_port, TRANSPORT_PROTO_TCP, 0,
1197 SESSION_TEST ((tc->c_index == listener->connection_index),
1198 "optimized lookup for lcl port + 1 should work");
1199 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1200 SESSION_TEST ((handle == server_index), "local session endpoint lookup "
1201 "should work (lcl ip was zeroed)");
1204 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1206 args.table_args.lcl_port = 1234;
1207 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1208 args.table_args.lcl.fp_len = 30;
1209 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1210 args.table_args.rmt.fp_len = 30;
1211 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1212 error = vnet_session_rule_add_del (&args);
1213 SESSION_TEST ((error == 0), "Add 1.2.3.4/30 1234 5.6.7.8/30 4321 action %d",
1214 args.table_args.action_index);
1218 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1219 TRANSPORT_PROTO_TCP);
1220 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1221 TRANSPORT_PROTO_TCP);
1224 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1225 &rmt_pref.fp_addr.ip4, lcl_port,
1226 rmt_port, TRANSPORT_PROTO_TCP, 0,
1228 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1229 "should fail (deny rule)");
1230 SESSION_TEST ((is_filtered == SESSION_LOOKUP_RESULT_FILTERED),
1231 "lookup should be filtered (deny)");
1233 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1234 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1235 "5.6.7.8/16 4321 in local table should return deny");
1237 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1238 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1239 rmt_port, TRANSPORT_PROTO_TCP, 0,
1241 SESSION_TEST ((tc->c_index == listener->connection_index),
1242 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should work");
1245 * "Mask" deny rule with more specific allow:
1246 * Add allow rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -3 (allow)
1248 args.table_args.is_add = 1;
1249 args.table_args.lcl_port = 1234;
1250 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1251 args.table_args.lcl.fp_len = 32;
1252 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1253 args.table_args.rmt.fp_len = 32;
1254 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1255 error = vnet_session_rule_add_del (&args);
1256 SESSION_TEST ((error == 0), "Add masking rule 1.2.3.4/30 1234 5.6.7.8/32 "
1257 "4321 action %d", args.table_args.action_index);
1260 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1261 &rmt_pref.fp_addr.ip4, lcl_port,
1262 rmt_port, TRANSPORT_PROTO_TCP, 0,
1264 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1265 "should fail (allow without app)");
1266 SESSION_TEST ((is_filtered == 0), "lookup should NOT be filtered");
1268 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1269 SESSION_TEST ((handle == SESSION_INVALID_HANDLE), "lookup for 1.2.3.4/32 "
1270 "1234 5.6.7.8/32 4321 in local table should return invalid");
1274 vlib_cli_output (vm, "Local rules");
1275 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1276 TRANSPORT_PROTO_TCP);
1279 sep.ip.ip4.as_u32 += 1 << 24;
1280 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1281 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234"
1282 " 5.6.7.9/32 4321 in local table should return deny");
1284 vnet_connect_args_t connect_args = {
1285 .app_index = attach_args.app_index,
1288 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1290 /* Try connecting */
1291 error = vnet_connect (&connect_args);
1292 SESSION_TEST ((error != 0), "connect should fail");
1293 SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1295 sep.ip.ip4.as_u32 -= 1 << 24;
1298 * Delete masking rule: 1.2.3.4/32 1234 5.6.7.8/32 4321 allow
1300 args.table_args.is_add = 0;
1301 args.table_args.lcl_port = 1234;
1302 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1303 args.table_args.lcl.fp_len = 32;
1304 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1305 args.table_args.rmt.fp_len = 32;
1306 error = vnet_session_rule_add_del (&args);
1307 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 allow");
1311 * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
1313 args.table_args.is_add = 1;
1314 args.table_args.lcl_port = 0;
1315 args.table_args.lcl.fp_len = 0;
1316 args.table_args.rmt.fp_len = 16;
1317 args.table_args.action_index = -1;
1318 error = vnet_session_rule_add_del (&args);
1319 SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d",
1320 args.table_args.action_index);
1324 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1325 TRANSPORT_PROTO_TCP);
1326 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1327 TRANSPORT_PROTO_TCP);
1330 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1331 SESSION_TEST ((handle == SESSION_DROP_HANDLE),
1332 "local session endpoint lookup should return deny");
1335 * Delete 1.2.3.4/32 1234 5.6.7.8/32 4321 deny
1337 args.table_args.is_add = 0;
1338 args.table_args.lcl_port = 1234;
1339 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1340 args.table_args.lcl.fp_len = 30;
1341 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1342 args.table_args.rmt.fp_len = 30;
1343 error = vnet_session_rule_add_del (&args);
1344 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1346 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1347 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1348 "local session endpoint lookup should return invalid");
1351 * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and
1352 * 1.2.3.4/16 1234 5.6.7.8/16 4321
1354 args.table_args.is_add = 0;
1355 args.table_args.lcl_port = 0;
1356 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1357 args.table_args.lcl.fp_len = 0;
1358 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1359 args.table_args.rmt.fp_len = 16;
1360 args.table_args.rmt_port = 4321;
1361 error = vnet_session_rule_add_del (&args);
1362 SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
1363 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1364 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1365 "should not work (removed)");
1367 args.table_args.is_add = 0;
1368 args.table_args.lcl = lcl_pref;
1370 args.table_args.is_add = 0;
1371 args.table_args.lcl_port = 0;
1372 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1373 args.table_args.lcl.fp_len = 16;
1374 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1375 args.table_args.rmt.fp_len = 16;
1376 args.table_args.rmt_port = 4321;
1377 error = vnet_session_rule_add_del (&args);
1378 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321");
1379 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1380 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1381 rmt_port, TRANSPORT_PROTO_TCP, 0,
1383 SESSION_TEST ((tc == 0),
1384 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should not "
1387 args.table_args.is_add = 0;
1388 args.table_args.lcl_port = 1234;
1389 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1390 args.table_args.lcl.fp_len = 16;
1391 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1392 args.table_args.rmt.fp_len = 16;
1393 args.table_args.rmt_port = 4321;
1394 error = vnet_session_rule_add_del (&args);
1395 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321");
1396 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1397 &rmt_pref.fp_addr.ip4, lcl_port,
1398 rmt_port, TRANSPORT_PROTO_TCP, 0,
1400 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should "
1401 "not work (del + deny)");
1403 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1404 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1405 &rmt_pref.fp_addr.ip4, lcl_port,
1406 rmt_port, TRANSPORT_PROTO_TCP, 0,
1408 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should"
1409 " not work (no-rule)");
1412 * Test tags. Add/overwrite/del rule with tag
1414 args.table_args.is_add = 1;
1415 args.table_args.lcl_port = 1234;
1416 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1417 args.table_args.lcl.fp_len = 16;
1418 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1419 args.table_args.rmt.fp_len = 16;
1420 args.table_args.rmt_port = 4321;
1421 args.table_args.tag = format (0, "test_rule");
1422 args.table_args.action_index = server_index;
1423 error = vnet_session_rule_add_del (&args);
1424 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 deny "
1428 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1429 TRANSPORT_PROTO_TCP);
1430 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1431 TRANSPORT_PROTO_TCP);
1433 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1434 &rmt_pref.fp_addr.ip4, lcl_port,
1435 rmt_port, TRANSPORT_PROTO_TCP, 0,
1437 SESSION_TEST ((tc->c_index == listener->connection_index),
1438 "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should work");
1440 vec_free (args.table_args.tag);
1441 args.table_args.lcl_port = 1234;
1442 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1443 args.table_args.lcl.fp_len = 16;
1444 args.table_args.tag = format (0, "test_rule_overwrite");
1445 error = vnet_session_rule_add_del (&args);
1446 SESSION_TEST ((error == 0),
1447 "Overwrite 1.2.3.4/16 1234 5.6.7.8/16 4321 deny tag test_rule"
1451 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1452 TRANSPORT_PROTO_TCP);
1453 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1454 TRANSPORT_PROTO_TCP);
1457 args.table_args.is_add = 0;
1458 args.table_args.lcl_port += 1;
1459 error = vnet_session_rule_add_del (&args);
1460 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny "
1461 "tag %v", args.table_args.tag);
1464 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1465 TRANSPORT_PROTO_TCP);
1466 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1467 TRANSPORT_PROTO_TCP);
1469 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1470 &rmt_pref.fp_addr.ip4, lcl_port,
1471 rmt_port, TRANSPORT_PROTO_TCP, 0,
1473 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/32 4321 should not"
1478 * Test local rules with multiple namespaces
1482 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1484 args.table_args.is_add = 1;
1485 args.table_args.lcl_port = 1234;
1486 args.table_args.rmt_port = 0;
1487 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1488 args.table_args.lcl.fp_len = 32;
1489 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1490 args.table_args.rmt.fp_len = 32;
1491 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1492 args.table_args.tag = 0;
1493 args.scope = SESSION_RULE_SCOPE_LOCAL;
1494 error = vnet_session_rule_add_del (&args);
1495 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d",
1496 args.table_args.action_index);
1498 * Add 'white' rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1500 args.table_args.is_add = 1;
1501 args.table_args.lcl_port = 1234;
1502 args.table_args.rmt_port = 4321;
1503 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1504 args.table_args.lcl.fp_len = 32;
1505 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1506 args.table_args.rmt.fp_len = 32;
1507 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1508 error = vnet_session_rule_add_del (&args);
1512 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1513 TRANSPORT_PROTO_TCP);
1516 vnet_app_namespace_add_del_args_t ns_args = {
1519 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
1522 error = vnet_app_namespace_add_del (&ns_args);
1523 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
1524 app_ns = app_namespace_get_from_id (ns_id);
1526 attach_args.namespace_id = ns_id;
1527 attach_args.api_client_index = placeholder_server_api_index;
1528 vec_free (attach_args.name);
1529 attach_args.name = format (0, "server_test2");
1530 error = vnet_application_attach (&attach_args);
1531 SESSION_TEST ((error == 0), "server2 attached");
1532 server_index2 = attach_args.app_index;
1535 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1537 args.table_args.lcl_port = 1234;
1538 args.table_args.rmt_port = 0;
1539 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1540 args.table_args.lcl.fp_len = 32;
1541 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1542 args.table_args.rmt.fp_len = 32;
1543 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1544 args.appns_index = app_namespace_index (app_ns);
1546 error = vnet_session_rule_add_del (&args);
1547 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d "
1548 "in test namespace", args.table_args.action_index);
1550 * Lookup default namespace
1552 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1553 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1554 "lookup for 1.2.3.4/32 1234 5.6.7.8/32 4321 in local table "
1555 "should return allow (invalid)");
1558 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1559 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1560 "5.6.7.8/16 432*2* in local table should return deny");
1563 connect_args.app_index = server_index;
1564 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1566 error = vnet_connect (&connect_args);
1567 SESSION_TEST ((error != 0), "connect should fail");
1568 SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1571 * Lookup test namespace
1573 handle = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1574 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1575 "5.6.7.8/16 4321 in local table should return deny");
1577 connect_args.app_index = server_index;
1578 error = vnet_connect (&connect_args);
1579 SESSION_TEST ((error != 0), "connect should fail");
1580 SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1582 args.table_args.is_add = 0;
1583 vnet_session_rule_add_del (&args);
1585 args.appns_index = 0;
1586 args.table_args.is_add = 0;
1587 vnet_session_rule_add_del (&args);
1589 args.table_args.rmt_port = 4321;
1590 vnet_session_rule_add_del (&args);
1594 vec_free (args.table_args.tag);
1595 vnet_app_detach_args_t detach_args = {
1596 .app_index = server_index,
1597 .api_client_index = ~0,
1599 vnet_application_detach (&detach_args);
1601 detach_args.app_index = server_index2;
1602 vnet_application_detach (&detach_args);
1605 vec_free (attach_args.name);
1610 session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
1612 u64 options[APP_OPTIONS_N_OPTIONS];
1613 char *show_listeners = "sh session listeners tcp verbose";
1614 char *show_local_listeners = "sh app ns table default";
1615 unformat_input_t tmp_input;
1616 u32 server_index, app_index;
1617 u32 placeholder_server_api_index = ~0, sw_if_index = 0;
1620 transport_connection_t *tc;
1621 u16 lcl_port = 1234, rmt_port = 4321;
1622 app_namespace_t *app_ns;
1623 int verbose = 0, error = 0;
1625 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1627 if (unformat (input, "verbose"))
1631 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1637 ip4_address_t lcl_ip = {
1638 .as_u32 = clib_host_to_net_u32 (0x01020304),
1640 ip4_address_t rmt_ip = {
1641 .as_u32 = clib_host_to_net_u32 (0x05060708),
1643 fib_prefix_t rmt_pref = {
1644 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1646 .fp_proto = FIB_PROTOCOL_IP4,
1648 session_endpoint_t sep = {
1649 .ip = rmt_pref.fp_addr,
1652 .transport_proto = TRANSPORT_PROTO_TCP,
1656 * Create loopback interface
1658 session_create_lookpback (0, &sw_if_index, &lcl_ip);
1660 app_ns = app_namespace_get_default ();
1661 app_ns->sw_if_index = sw_if_index;
1663 clib_memset (options, 0, sizeof (options));
1664 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1665 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
1666 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_PROXY;
1667 options[APP_OPTIONS_PROXY_TRANSPORT] = 1 << TRANSPORT_PROTO_TCP;
1668 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1669 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1670 vnet_app_attach_args_t attach_args = {
1671 .api_client_index = ~0,
1674 .session_cb_vft = &placeholder_session_cbs,
1675 .name = format (0, "session_test"),
1678 attach_args.api_client_index = placeholder_server_api_index;
1679 error = vnet_application_attach (&attach_args);
1680 SESSION_TEST ((error == 0), "server attachment should work");
1681 server_index = attach_args.app_index;
1685 unformat_init_string (&tmp_input, show_listeners,
1686 strlen (show_listeners));
1687 vlib_cli_input (vm, &tmp_input, 0, 0);
1688 unformat_init_string (&tmp_input, show_local_listeners,
1689 strlen (show_local_listeners));
1690 vlib_cli_input (vm, &tmp_input, 0, 0);
1693 tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port,
1694 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1695 SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be "
1697 s = listen_session_get (tc->s_index);
1698 SESSION_TEST ((s->app_index == server_index), "lookup should return"
1701 tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port,
1702 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1703 SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should"
1706 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1707 SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1710 vnet_app_detach_args_t detach_args = {
1711 .app_index = server_index,
1712 .api_client_index = ~0,
1714 vnet_application_detach (&detach_args);
1718 unformat_init_string (&tmp_input, show_listeners,
1719 strlen (show_listeners));
1720 vlib_cli_input (vm, &tmp_input, 0, 0);
1721 unformat_init_string (&tmp_input, show_local_listeners,
1722 strlen (show_local_listeners));
1723 vlib_cli_input (vm, &tmp_input, 0, 0);
1726 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1727 SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX),
1728 "local session endpoint lookup should not work after detach");
1730 unformat_free (&tmp_input);
1731 vec_free (attach_args.name);
1732 session_delete_loopback (sw_if_index);
1737 wait_for_event (svm_msg_q_t * mq, int fd, int epfd, u8 use_eventfd)
1741 svm_msg_q_lock (mq);
1742 while (svm_msg_q_is_empty (mq))
1743 svm_msg_q_wait (mq);
1747 int __clib_unused n_read, rv;
1748 struct epoll_event ep_evt;
1753 rv = epoll_wait (epfd, &ep_evt, 1, -1);
1756 ST_DBG ("epoll error");
1759 else if (rv > 0 && (ep_evt.events & EPOLLIN))
1761 n_read = read (fd, &buf, sizeof (buf));
1766 if (!svm_msg_q_is_empty (mq))
1768 svm_msg_q_lock (mq);
1776 session_test_mq_speed (vlib_main_t * vm, unformat_input_t * input)
1778 int error, __clib_unused verbose, use_eventfd = 0;
1779 u64 i, n_test_msgs = 1 << 10, *counter;
1780 u64 options[APP_OPTIONS_N_OPTIONS];
1781 int epfd = -1, rv, prod_fd = -1;
1782 svm_fifo_t *rx_fifo, *tx_fifo;
1783 vl_api_registration_t *reg;
1784 struct epoll_event ep_evt;
1785 u32 app_index, api_index;
1786 app_worker_t *app_wrk;
1787 segment_manager_t *sm;
1788 svm_msg_q_msg_t msg;
1796 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1798 if (unformat (input, "verbose"))
1800 else if (unformat (input, "%d", &n_test_msgs))
1802 else if (unformat (input, "use-eventfd"))
1806 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1812 q = clib_mem_alloc (sizeof (*q));
1813 api_index = vl_api_memclnt_create_internal ("session_mq_test_api", q);
1815 clib_memset (options, 0, sizeof (options));
1816 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1817 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1818 options[APP_OPTIONS_EVT_QUEUE_SIZE] = 2048;
1820 reg = vl_api_client_index_to_registration (api_index);
1821 /* Shut up coverity */
1825 vnet_app_attach_args_t attach_args = {
1826 .api_client_index = api_index,
1829 .session_cb_vft = &placeholder_session_cbs,
1830 .name = format (0, "session_mq_test"),
1832 error = vnet_application_attach (&attach_args);
1833 SESSION_TEST ((error == 0), "server attachment should work");
1835 app_index = attach_args.app_index;
1837 app = application_get (app_index);
1838 app_wrk = application_get_worker (app, 0);
1839 mq = app_wrk->event_queue;
1842 svm_msg_q_alloc_eventfd (mq);
1843 prod_fd = svm_msg_q_get_eventfd (mq);
1844 SESSION_TEST (prod_fd != -1, "mq producer eventd valid %u", prod_fd);
1847 sm = app_worker_get_or_alloc_connect_segment_manager (app_wrk);
1848 segment_manager_alloc_session_fifos (sm, 0, &rx_fifo, &tx_fifo);
1849 s.rx_fifo = rx_fifo;
1850 s.tx_fifo = tx_fifo;
1851 s.session_state = SESSION_STATE_READY;
1852 counter = (u64 *) f_head_cptr (rx_fifo)->data;
1853 start = vlib_time_now (vm);
1857 SESSION_TEST (0, "fork failed");
1863 epfd = epoll_create1 (0);
1864 SESSION_TEST (epfd != -1, "epfd created");
1865 ep_evt.events = EPOLLIN;
1866 ep_evt.data.u64 = prod_fd;
1867 rv = epoll_ctl (epfd, EPOLL_CTL_ADD, prod_fd, &ep_evt);
1868 SESSION_TEST (rv == 0, "epoll returned %d", rv);
1871 for (i = 0; i < n_test_msgs; i++)
1873 wait_for_event (mq, prod_fd, epfd, use_eventfd);
1874 svm_msg_q_sub_w_lock (mq, &msg);
1875 svm_msg_q_free_msg (mq, &msg);
1876 svm_msg_q_unlock (mq);
1877 *counter = *counter + 1;
1878 svm_fifo_unset_event (rx_fifo);
1884 ST_DBG ("client pid %u", pid);
1885 for (i = 0; i < n_test_msgs; i++)
1887 while (svm_fifo_has_event (rx_fifo))
1889 app_worker_lock_and_send_event (app_wrk, &s, SESSION_IO_EVT_RX);
1893 diff = vlib_time_now (vm) - start;
1894 ST_DBG ("done %u events in %.2f sec: %f evts/s", *counter,
1895 diff, *counter / diff);
1897 vnet_app_detach_args_t detach_args = {
1898 .app_index = app_index,
1899 .api_client_index = ~0,
1901 vnet_application_detach (&detach_args);
1906 session_test_mq_basic (vlib_main_t * vm, unformat_input_t * input)
1908 svm_msg_q_cfg_t _cfg, *cfg = &_cfg;
1909 svm_msg_q_msg_t msg1, msg2, msg[12];
1910 int __clib_unused verbose, i, rv;
1911 svm_msg_q_shared_t *smq;
1912 svm_msg_q_ring_t *ring;
1913 svm_msg_q_t _mq = { 0 }, *mq = &_mq;
1916 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1918 if (unformat (input, "verbose"))
1922 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1928 svm_msg_q_ring_cfg_t rc[2] = { {8, 8, 0}
1931 cfg->consumer_pid = ~0;
1934 cfg->ring_cfgs = rc;
1936 smq = svm_msg_q_alloc (cfg);
1937 svm_msg_q_attach (mq, smq);
1938 SESSION_TEST (mq != 0, "svm_msg_q_alloc");
1939 SESSION_TEST (vec_len (mq->rings) == 2, "ring allocation");
1940 rings_ptr = (u8 *) mq->rings[0].shr->data;
1941 vec_foreach (ring, mq->rings)
1943 SESSION_TEST (ring->shr->data == rings_ptr, "ring data");
1944 rings_ptr += (uword) ring->nitems * ring->elsize;
1945 rings_ptr += sizeof (svm_msg_q_ring_shared_t);
1948 msg1 = svm_msg_q_alloc_msg (mq, 8);
1949 rv = (mq->rings[0].shr->cursize != 1 || msg1.ring_index != 0 ||
1950 msg1.elt_index != 0);
1951 SESSION_TEST (rv == 0, "msg alloc1");
1953 msg2 = svm_msg_q_alloc_msg (mq, 15);
1954 rv = (mq->rings[1].shr->cursize != 1 || msg2.ring_index != 1 ||
1955 msg2.elt_index != 0);
1956 SESSION_TEST (rv == 0, "msg alloc2");
1958 svm_msg_q_free_msg (mq, &msg1);
1959 SESSION_TEST (mq->rings[0].shr->cursize == 0, "free msg");
1961 for (i = 0; i < 12; i++)
1963 msg[i] = svm_msg_q_alloc_msg (mq, 7);
1964 *(u32 *) svm_msg_q_msg_data (mq, &msg[i]) = i;
1967 rv = (mq->rings[0].shr->cursize != 8 || mq->rings[1].shr->cursize != 5);
1968 SESSION_TEST (rv == 0, "msg alloc3");
1970 *(u32 *) svm_msg_q_msg_data (mq, &msg2) = 123;
1971 svm_msg_q_add (mq, &msg2, SVM_Q_NOWAIT);
1972 for (i = 0; i < 12; i++)
1973 svm_msg_q_add (mq, &msg[i], SVM_Q_NOWAIT);
1975 rv = svm_msg_q_sub (mq, &msg2, SVM_Q_NOWAIT, 0);
1976 SESSION_TEST (rv == 0, "dequeue1");
1978 SESSION_TEST (msg2.ring_index == 1 && msg2.elt_index == 0,
1980 rv = (*(u32 *) svm_msg_q_msg_data (mq, &msg2) == 123);
1981 SESSION_TEST (rv, "dequeue 1 data");
1983 svm_msg_q_free_msg (mq, &msg2);
1985 for (i = 0; i < 12; i++)
1987 if (svm_msg_q_sub (mq, &msg[i], SVM_Q_NOWAIT, 0))
1988 SESSION_TEST (0, "dequeue2");
1991 if (msg[i].ring_index != 0 || msg[i].elt_index != (i + 1) % 8)
1992 SESSION_TEST (0, "dequeue2 result2");
1996 if (msg[i].ring_index != 1 || msg[i].elt_index != (i - 8) + 1)
1997 SESSION_TEST (0, "dequeue2 result3");
1999 if (*(u32 *) svm_msg_q_msg_data (mq, &msg[i]) != i)
2000 SESSION_TEST (0, "dequeue2 wrong data");
2001 svm_msg_q_free_msg (mq, &msg[i]);
2003 rv = (mq->rings[0].shr->cursize == 0 && mq->rings[1].shr->cursize == 0);
2004 SESSION_TEST (rv, "post dequeue");
2009 static clib_error_t *
2010 session_test (vlib_main_t * vm,
2011 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
2015 vnet_session_enable_disable (vm, 1);
2017 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2019 if (unformat (input, "basic"))
2020 res = session_test_basic (vm, input);
2021 else if (unformat (input, "namespace"))
2022 res = session_test_namespace (vm, input);
2023 else if (unformat (input, "rules-table"))
2024 res = session_test_rule_table (vm, input);
2025 else if (unformat (input, "rules"))
2026 res = session_test_rules (vm, input);
2027 else if (unformat (input, "proxy"))
2028 res = session_test_proxy (vm, input);
2029 else if (unformat (input, "endpt-cfg"))
2030 res = session_test_endpoint_cfg (vm, input);
2031 else if (unformat (input, "mq-speed"))
2032 res = session_test_mq_speed (vm, input);
2033 else if (unformat (input, "mq-basic"))
2034 res = session_test_mq_basic (vm, input);
2035 else if (unformat (input, "all"))
2037 if ((res = session_test_basic (vm, input)))
2039 if ((res = session_test_namespace (vm, input)))
2041 if ((res = session_test_rule_table (vm, input)))
2043 if ((res = session_test_rules (vm, input)))
2045 if ((res = session_test_proxy (vm, input)))
2047 if ((res = session_test_endpoint_cfg (vm, input)))
2049 if ((res = session_test_mq_speed (vm, input)))
2051 if ((res = session_test_mq_basic (vm, input)))
2060 return clib_error_return (0, "Session unit test failed");
2065 VLIB_CLI_COMMAND (tcp_test_command, static) =
2067 .path = "test session",
2068 .short_help = "internal session unit tests",
2069 .function = session_test,
2074 * fd.io coding-style-patch-verification: ON
2077 * eval: (c-set-style "gnu")