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);
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 /* Allow server to allocate another segment for listens. Needed
341 * because by default we do not allow segment additions */
342 attach_args.options[APP_OPTIONS_ADD_SEGMENT_SIZE] = 32 << 20;
343 attach_args.options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret;
344 error = vnet_application_attach (&attach_args);
345 SESSION_TEST ((error == 0), "server app attached: %U", format_clib_error,
347 vec_free (attach_args.name);
348 server_index = attach_args.app_index;
350 server_sep.is_ip4 = 1;
351 server_sep.port = placeholder_server_port;
352 vnet_listen_args_t bind_args = {
353 .sep_ext = server_sep,
354 .app_index = server_index,
356 error = vnet_listen (&bind_args);
357 SESSION_TEST ((error == 0), "server bind should work");
360 * Connect and force lcl ip
362 client_sep.is_ip4 = 1;
363 client_sep.ip.ip4.as_u32 = clib_host_to_net_u32 (0x02020202);
364 client_sep.port = placeholder_server_port;
365 client_sep.peer.is_ip4 = 1;
366 client_sep.peer.ip.ip4.as_u32 = clib_host_to_net_u32 (0x01010101);
367 client_sep.peer.port = placeholder_client_port;
368 client_sep.transport_proto = TRANSPORT_PROTO_TCP;
370 vnet_connect_args_t connect_args = {
371 .sep_ext = client_sep,
372 .app_index = client_index,
375 connected_session_index = connected_session_thread = ~0;
376 accepted_session_index = accepted_session_thread = ~0;
377 error = vnet_connect (&connect_args);
378 SESSION_TEST ((error == 0), "connect should work");
380 /* wait for stuff to happen */
381 while (connected_session_index == ~0 && ++tries < 100)
383 vlib_worker_thread_barrier_release (vm);
384 vlib_process_suspend (vm, 100e-3);
385 vlib_worker_thread_barrier_sync (vm);
387 while (accepted_session_index == ~0 && ++tries < 100)
389 vlib_worker_thread_barrier_release (vm);
390 vlib_process_suspend (vm, 100e-3);
391 vlib_worker_thread_barrier_sync (vm);
394 clib_warning ("waited %.1f seconds for connections", tries / 10.0);
395 SESSION_TEST ((connected_session_index != ~0), "session should exist");
396 SESSION_TEST ((connected_session_thread != ~0), "thread should exist");
397 SESSION_TEST ((accepted_session_index != ~0), "session should exist");
398 SESSION_TEST ((accepted_session_thread != ~0), "thread should exist");
399 s = session_get (connected_session_index, connected_session_thread);
400 tc = session_get_transport (s);
401 SESSION_TEST ((tc != 0), "transport should exist");
402 SESSION_TEST ((memcmp (&tc->lcl_ip, &client_sep.peer.ip,
403 sizeof (tc->lcl_ip)) == 0), "ips should be equal");
404 SESSION_TEST ((tc->lcl_port == placeholder_client_port),
405 "ports should be equal");
407 /* These sessions, because of the way they're established are pinned to
408 * main thread, even when we have workers and we avoid polling main thread,
409 * i.e., we can't cleanup pending disconnects, so force cleanup for both
411 session_transport_cleanup (s);
412 s = session_get (accepted_session_index, accepted_session_thread);
413 session_transport_cleanup (s);
415 vnet_app_detach_args_t detach_args = {
416 .app_index = server_index,
417 .api_client_index = ~0,
419 vnet_application_detach (&detach_args);
420 detach_args.app_index = client_index;
421 vnet_application_detach (&detach_args);
424 error = vnet_app_namespace_add_del (&ns_args);
425 SESSION_TEST ((error == 0), "app ns delete should succeed: %d", error);
427 /* Allow the disconnects to finish before removing the routes. */
428 vlib_process_suspend (vm, 10e-3);
430 session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
432 session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
435 session_delete_loopback (sw_if_index[0]);
436 session_delete_loopback (sw_if_index[1]);
441 session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
443 u64 options[APP_OPTIONS_N_OPTIONS], placeholder_secret = 1234, tries;
444 u32 server_index, server_st_index, server_local_st_index;
445 u32 placeholder_port = 1234, client_index, server_wrk_index;
446 u32 placeholder_api_context = 4321, placeholder_client_api_index = ~0;
447 u32 placeholder_server_api_index = ~0, sw_if_index = 0;
448 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
449 session_endpoint_t client_sep = SESSION_ENDPOINT_NULL;
450 session_endpoint_t intf_sep = SESSION_ENDPOINT_NULL;
451 u8 *ns_id, *server_name, *client_name;
452 app_namespace_t *app_ns;
453 application_t *server;
458 ns_id = format (0, "appns1");
459 server_name = format (0, "session_test");
460 client_name = format (0, "session_test_client");
462 server_sep.is_ip4 = 1;
463 server_sep.port = placeholder_port;
464 client_sep.is_ip4 = 1;
465 client_sep.port = placeholder_port;
466 clib_memset (options, 0, sizeof (options));
468 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
469 vnet_app_attach_args_t attach_args = {
470 .api_client_index = ~0,
473 .session_cb_vft = &placeholder_session_cbs,
477 vnet_listen_args_t bind_args = {
482 vnet_connect_args_t connect_args = {
486 clib_memcpy (&connect_args.sep, &client_sep, sizeof (client_sep));
488 vnet_unlisten_args_t unbind_args = {
489 .handle = bind_args.handle,
493 vnet_app_detach_args_t detach_args = {
495 .api_client_index = ~0,
498 ip4_address_t intf_addr = {
499 .as_u32 = clib_host_to_net_u32 (0x07000105),
502 intf_sep.ip.ip4 = intf_addr;
504 intf_sep.port = placeholder_port;
507 * Insert namespace and lookup
510 vnet_app_namespace_add_del_args_t ns_args = {
512 .secret = placeholder_secret,
513 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
516 error = vnet_app_namespace_add_del (&ns_args);
517 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
519 app_ns = app_namespace_get_from_id (ns_id);
520 SESSION_TEST ((app_ns != 0), "should find ns %v status", ns_id);
521 SESSION_TEST ((app_ns->ns_secret == placeholder_secret),
522 "secret should be %d", placeholder_secret);
523 SESSION_TEST ((app_ns->sw_if_index == APP_NAMESPACE_INVALID_INDEX),
524 "sw_if_index should be invalid");
527 * Try application attach with wrong secret
530 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
531 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
532 options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret - 1;
533 attach_args.namespace_id = ns_id;
534 attach_args.api_client_index = placeholder_server_api_index;
536 error = vnet_application_attach (&attach_args);
537 SESSION_TEST ((error != 0), "app attachment should fail");
538 SESSION_TEST ((error == VNET_API_ERROR_APP_WRONG_NS_SECRET),
539 "code should be wrong ns secret: %d", error);
542 * Attach server with global default scope
544 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
545 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
546 options[APP_OPTIONS_NAMESPACE_SECRET] = 0;
547 attach_args.namespace_id = 0;
548 attach_args.api_client_index = placeholder_server_api_index;
549 error = vnet_application_attach (&attach_args);
550 SESSION_TEST ((error == 0), "server attachment should work");
551 server_index = attach_args.app_index;
552 server = application_get (server_index);
553 server_wrk_index = application_get_default_worker (server)->wrk_index;
554 SESSION_TEST ((server->ns_index == 0),
555 "server should be in the default ns");
557 bind_args.app_index = server_index;
558 error = vnet_listen (&bind_args);
559 SESSION_TEST ((error == 0), "server bind should work");
561 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
562 s = session_lookup_listener (server_st_index, &server_sep);
563 SESSION_TEST ((s != 0), "listener should exist in global table");
564 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
565 " that of the server");
566 server_local_st_index = application_local_session_table (server);
567 SESSION_TEST ((server_local_st_index == APP_INVALID_INDEX),
568 "server shouldn't have access to local table");
570 unbind_args.app_index = server_index;
571 unbind_args.handle = bind_args.handle;
572 error = vnet_unlisten (&unbind_args);
573 SESSION_TEST ((error == 0), "unbind should work");
575 s = session_lookup_listener (server_st_index, &server_sep);
576 SESSION_TEST ((s == 0), "listener should not exist in global table");
578 detach_args.app_index = server_index;
579 vnet_application_detach (&detach_args);
582 * Attach server with local and global scope
584 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
585 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
586 options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret;
587 attach_args.namespace_id = ns_id;
588 attach_args.api_client_index = placeholder_server_api_index;
589 error = vnet_application_attach (&attach_args);
590 SESSION_TEST ((error == 0), "server attachment should work");
591 server_index = attach_args.app_index;
592 server = application_get (server_index);
593 server_wrk_index = application_get_default_worker (server)->wrk_index;
594 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
595 "server should be in the right ns");
597 bind_args.app_index = server_index;
598 error = vnet_listen (&bind_args);
599 SESSION_TEST ((error == 0), "bind should work");
600 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
601 s = session_lookup_listener (server_st_index, &server_sep);
602 SESSION_TEST ((s != 0), "listener should exist in global table");
603 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
604 " that of the server");
605 server_local_st_index = application_local_session_table (server);
606 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
607 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
608 "listener should exist in local table");
611 * Try client connect with 1) local scope 2) global scope
613 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
614 attach_args.name = client_name;
615 attach_args.api_client_index = placeholder_client_api_index;
616 error = vnet_application_attach (&attach_args);
617 SESSION_TEST ((error == 0), "client attachment should work");
618 client_index = attach_args.app_index;
619 connect_args.api_context = placeholder_api_context;
620 connect_args.app_index = client_index;
621 error = vnet_connect (&connect_args);
622 SESSION_TEST ((error != 0), "client connect should return error code");
623 SESSION_TEST ((error == SESSION_E_INVALID_RMT_IP),
624 "error code should be invalid value (zero ip)");
625 SESSION_TEST ((placeholder_segment_count == 0),
626 "shouldn't have received request to map new segment");
627 connect_args.sep.ip.ip4.as_u8[0] = 127;
628 error = vnet_connect (&connect_args);
629 SESSION_TEST ((error == 0), "client connect should not return error code");
631 /* wait for accept */
633 while (!placeholder_accept && ++tries < 100)
635 vlib_worker_thread_barrier_release (vm);
636 vlib_process_suspend (vm, 100e-3);
637 vlib_worker_thread_barrier_sync (vm);
640 SESSION_TEST ((placeholder_segment_count == 1),
641 "should've received request to map new segment");
642 SESSION_TEST ((placeholder_accept == 1),
643 "should've received accept request");
644 detach_args.app_index = client_index;
645 vnet_application_detach (&detach_args);
647 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
648 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
649 attach_args.api_client_index = placeholder_client_api_index;
650 error = vnet_application_attach (&attach_args);
651 SESSION_TEST ((error == 0), "client attachment should work");
652 error = vnet_connect (&connect_args);
653 SESSION_TEST ((error != 0), "client connect should return error code");
654 SESSION_TEST ((error == SESSION_E_NOINTF),
655 "error code should be connect (nothing in local scope)");
656 detach_args.app_index = client_index;
657 vnet_application_detach (&detach_args);
660 * Unbind and detach server and then re-attach with local scope only
662 unbind_args.handle = bind_args.handle;
663 unbind_args.app_index = server_index;
664 error = vnet_unlisten (&unbind_args);
665 SESSION_TEST ((error == 0), "unbind should work");
667 s = session_lookup_listener (server_st_index, &server_sep);
668 SESSION_TEST ((s == 0), "listener should not exist in global table");
669 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
670 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
671 "listener should not exist in local table");
673 detach_args.app_index = server_index;
674 vnet_application_detach (&detach_args);
676 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
677 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
678 attach_args.api_client_index = placeholder_server_api_index;
679 attach_args.name = server_name;
680 error = vnet_application_attach (&attach_args);
681 SESSION_TEST ((error == 0), "app attachment should work");
682 server_index = attach_args.app_index;
683 server = application_get (server_index);
684 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
685 "app should be in the right ns");
687 bind_args.app_index = server_index;
688 error = vnet_listen (&bind_args);
689 SESSION_TEST ((error == 0), "bind should work");
691 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
692 s = session_lookup_listener (server_st_index, &server_sep);
693 SESSION_TEST ((s == 0), "listener should not exist in global table");
694 server_local_st_index = application_local_session_table (server);
695 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
696 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
697 "listener should exist in local table");
699 unbind_args.handle = bind_args.handle;
700 error = vnet_unlisten (&unbind_args);
701 SESSION_TEST ((error == 0), "unbind should work");
703 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
704 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
705 "listener should not exist in local table");
708 * Client attach + connect in default ns with local scope
710 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
711 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
712 attach_args.namespace_id = 0;
713 attach_args.api_client_index = placeholder_client_api_index;
714 attach_args.name = client_name;
715 vnet_application_attach (&attach_args);
716 error = vnet_connect (&connect_args);
717 SESSION_TEST ((error != 0), "client connect should return error code");
718 SESSION_TEST ((error == SESSION_E_NOROUTE),
719 "error code should be noroute (not in same ns)");
720 detach_args.app_index = client_index;
721 vnet_application_detach (&detach_args);
726 detach_args.app_index = server_index;
727 vnet_application_detach (&detach_args);
730 * Create loopback interface
732 session_create_lookpback (0, &sw_if_index, &intf_addr);
735 * Update namespace with interface
737 ns_args.sw_if_index = sw_if_index;
738 error = vnet_app_namespace_add_del (&ns_args);
739 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
742 * Attach server with local and global scope
744 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
745 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
746 options[APP_OPTIONS_NAMESPACE_SECRET] = placeholder_secret;
747 attach_args.namespace_id = ns_id;
748 attach_args.api_client_index = placeholder_server_api_index;
749 attach_args.name = server_name;
750 error = vnet_application_attach (&attach_args);
751 SESSION_TEST ((error == 0), "server attachment should work");
752 server_index = attach_args.app_index;
753 server = application_get (server_index);
754 server_wrk_index = application_get_default_worker (server)->wrk_index;
756 bind_args.app_index = server_index;
757 error = vnet_listen (&bind_args);
758 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
759 s = session_lookup_listener (server_st_index, &server_sep);
760 SESSION_TEST ((s == 0), "zero listener should not exist in global table");
762 s = session_lookup_listener (server_st_index, &intf_sep);
763 SESSION_TEST ((s != 0), "intf listener should exist in global table");
764 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be "
765 "that of the server");
766 server_local_st_index = application_local_session_table (server);
767 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
768 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
769 "zero listener should exist in local table");
770 detach_args.app_index = server_index;
771 vnet_application_detach (&detach_args);
774 error = vnet_app_namespace_add_del (&ns_args);
775 SESSION_TEST ((error == 0), "app ns delete should succeed: %d", error);
780 vec_free (server_name);
781 vec_free (client_name);
783 session_delete_loopback (sw_if_index);
788 session_test_rule_table (vlib_main_t * vm, unformat_input_t * input)
790 session_rules_table_t _srt, *srt = &_srt;
791 u16 lcl_port = 1234, rmt_port = 4321;
792 u32 action_index = 1, res;
793 ip4_address_t lcl_lkup, rmt_lkup;
794 int verbose = 0, error;
796 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
798 if (unformat (input, "verbose"))
802 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
808 clib_memset (srt, 0, sizeof (*srt));
809 session_rules_table_init (srt);
811 ip4_address_t lcl_ip = {
812 .as_u32 = clib_host_to_net_u32 (0x01020304),
814 ip4_address_t rmt_ip = {
815 .as_u32 = clib_host_to_net_u32 (0x05060708),
817 ip4_address_t lcl_ip2 = {
818 .as_u32 = clib_host_to_net_u32 (0x02020202),
820 ip4_address_t rmt_ip2 = {
821 .as_u32 = clib_host_to_net_u32 (0x06060606),
823 ip4_address_t lcl_ip3 = {
824 .as_u32 = clib_host_to_net_u32 (0x03030303),
826 ip4_address_t rmt_ip3 = {
827 .as_u32 = clib_host_to_net_u32 (0x07070707),
829 fib_prefix_t lcl_pref = {
830 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
832 .fp_proto = FIB_PROTOCOL_IP4,
834 fib_prefix_t rmt_pref = {
835 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
837 .fp_proto = FIB_PROTOCOL_IP4,
840 session_rule_table_add_del_args_t args = {
843 .lcl_port = lcl_port,
844 .rmt_port = rmt_port,
845 .action_index = action_index++,
848 error = session_rules_table_add_del (srt, &args);
849 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
853 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
854 SESSION_TEST ((res == 1),
855 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 1: %d",
859 * 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
861 args.lcl.fp_addr.ip4 = lcl_ip;
862 args.lcl.fp_len = 24;
863 args.action_index = action_index++;
864 error = session_rules_table_add_del (srt, &args);
865 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/16 4321 action %d",
867 args.rmt.fp_addr.ip4 = rmt_ip;
868 args.rmt.fp_len = 24;
869 args.action_index = action_index++;
870 error = session_rules_table_add_del (srt, &args);
871 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/24 4321 action %d",
875 * 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
877 args.lcl.fp_addr.ip4 = lcl_ip2;
878 args.lcl.fp_len = 24;
879 args.rmt.fp_addr.ip4 = rmt_ip2;
880 args.rmt.fp_len = 16;
881 args.action_index = action_index++;
882 error = session_rules_table_add_del (srt, &args);
883 SESSION_TEST ((error == 0), "Add 2.2.2.2/24 1234 6.6.6.6/16 4321 action %d",
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), "Add 3.3.3.3/24 1234 7.7.7.7/16 4321 action %d",
893 * Add again 3.3.3.3/24 1234 7.7.7.7/16 4321
895 args.lcl.fp_addr.ip4 = lcl_ip3;
896 args.rmt.fp_addr.ip4 = rmt_ip3;
897 args.action_index = action_index++;
898 error = session_rules_table_add_del (srt, &args);
899 SESSION_TEST ((error == 0), "overwrite 3.3.3.3/24 1234 7.7.7.7/16 4321 "
900 "action %d", action_index - 1);
903 * 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
904 * and 3.3.3.3 1234 7.7.7.7 4321
907 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
908 SESSION_TEST ((res == 3),
909 "Lookup 1.2.3.4 1234 5.6.7.8 4321 action " "should be 3: %d",
912 lcl_lkup.as_u32 = clib_host_to_net_u32 (0x01020204);
913 rmt_lkup.as_u32 = clib_host_to_net_u32 (0x05060709);
915 session_rules_table_lookup4 (srt, &lcl_lkup,
916 &rmt_lkup, lcl_port, rmt_port);
917 SESSION_TEST ((res == 1),
918 "Lookup 1.2.2.4 1234 5.6.7.9 4321, action " "should be 1: %d",
922 session_rules_table_lookup4 (srt, &lcl_ip3, &rmt_ip3, lcl_port, rmt_port);
923 SESSION_TEST ((res == 6),
924 "Lookup 3.3.3.3 1234 7.7.7.7 4321, action "
925 "should be 6 (updated): %d", res);
928 * Add 1.2.3.4/24 * 5.6.7.8/24 *
929 * Lookup 1.2.3.4 1234 5.6.7.8 4321 and 1.2.3.4 1235 5.6.7.8 4321
931 args.lcl.fp_addr.ip4 = lcl_ip;
932 args.rmt.fp_addr.ip4 = rmt_ip;
933 args.lcl.fp_len = 24;
934 args.rmt.fp_len = 24;
937 args.action_index = action_index++;
938 error = session_rules_table_add_del (srt, &args);
939 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 * 5.6.7.8/24 * action %d",
942 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
943 SESSION_TEST ((res == 7),
944 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should"
945 " be 7 (lpm dst): %d", res);
947 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
948 lcl_port + 1, rmt_port);
949 SESSION_TEST ((res == 7),
950 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 7: %d",
954 * Del 1.2.3.4/24 * 5.6.7.8/24 *
955 * Add 1.2.3.4/16 * 5.6.7.8/16 * and 1.2.3.4/24 1235 5.6.7.8/24 4321
956 * Lookup 1.2.3.4 1234 5.6.7.8 4321, 1.2.3.4 1235 5.6.7.8 4321 and
957 * 1.2.3.4 1235 5.6.7.8 4322
960 error = session_rules_table_add_del (srt, &args);
961 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 * 5.6.7.8/24 *");
963 args.lcl.fp_addr.ip4 = lcl_ip;
964 args.rmt.fp_addr.ip4 = rmt_ip;
965 args.lcl.fp_len = 16;
966 args.rmt.fp_len = 16;
969 args.action_index = action_index++;
971 error = session_rules_table_add_del (srt, &args);
972 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 * action %d",
975 args.lcl.fp_addr.ip4 = lcl_ip;
976 args.rmt.fp_addr.ip4 = rmt_ip;
977 args.lcl.fp_len = 24;
978 args.rmt.fp_len = 24;
979 args.lcl_port = lcl_port + 1;
980 args.rmt_port = rmt_port;
981 args.action_index = action_index++;
983 error = session_rules_table_add_del (srt, &args);
984 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1235 5.6.7.8/24 4321 action %d",
988 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
991 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
992 SESSION_TEST ((res == 3),
993 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
996 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
997 lcl_port + 1, rmt_port);
998 SESSION_TEST ((res == 9),
999 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 9: %d",
1002 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
1003 lcl_port + 1, rmt_port + 1);
1004 SESSION_TEST ((res == 8),
1005 "Lookup 1.2.3.4 1235 5.6.7.8 4322, action should " "be 8: %d",
1009 * Delete 1.2.0.0/16 1234 5.6.0.0/16 4321 and 1.2.0.0/16 * 5.6.0.0/16 *
1010 * Lookup 1.2.3.4 1234 5.6.7.8 4321
1012 args.lcl_port = 1234;
1013 args.rmt_port = 4321;
1014 args.lcl.fp_len = 16;
1015 args.rmt.fp_len = 16;
1017 error = session_rules_table_add_del (srt, &args);
1018 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 1234 5.6.0.0/16 4321");
1020 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1021 SESSION_TEST ((res == 3),
1022 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
1028 error = session_rules_table_add_del (srt, &args);
1029 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 * 5.6.0.0/16 *");
1031 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1032 SESSION_TEST ((res == 3),
1033 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
1037 * Delete 1.2.3.4/24 1234 5.6.7.5/24
1039 args.lcl.fp_addr.ip4 = lcl_ip;
1040 args.rmt.fp_addr.ip4 = rmt_ip;
1041 args.lcl.fp_len = 24;
1042 args.rmt.fp_len = 24;
1043 args.lcl_port = 1234;
1044 args.rmt_port = 4321;
1046 error = session_rules_table_add_del (srt, &args);
1047 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 1234 5.6.7.5/24");
1049 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1050 SESSION_TEST ((res == 2), "Action should be 2: %d", res);
1056 session_test_rules (vlib_main_t * vm, unformat_input_t * input)
1058 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
1059 u64 options[APP_OPTIONS_N_OPTIONS];
1060 u16 lcl_port = 1234, rmt_port = 4321;
1061 u32 server_index, server_index2;
1062 u32 placeholder_server_api_index = ~0;
1063 transport_connection_t *tc;
1064 u32 placeholder_port = 1111;
1065 u8 is_filtered = 0, *ns_id = format (0, "appns1");
1066 session_t *listener, *s;
1067 app_namespace_t *default_ns = app_namespace_get_default ();
1068 u32 local_ns_index = default_ns->local_table_index;
1070 app_namespace_t *app_ns;
1075 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1077 if (unformat (input, "verbose"))
1081 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1087 server_sep.is_ip4 = 1;
1088 server_sep.port = placeholder_port;
1089 clib_memset (options, 0, sizeof (options));
1091 vnet_app_attach_args_t attach_args = {
1092 .api_client_index = ~0,
1095 .session_cb_vft = &placeholder_session_cbs,
1096 .name = format (0, "session_test"),
1099 vnet_listen_args_t bind_args = {
1105 * Attach server with global and local default scope
1107 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1108 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1109 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1110 attach_args.namespace_id = 0;
1111 attach_args.api_client_index = placeholder_server_api_index;
1112 error = vnet_application_attach (&attach_args);
1113 SESSION_TEST ((error == 0), "server attached");
1114 server_index = attach_args.app_index;
1116 bind_args.app_index = server_index;
1117 error = vnet_listen (&bind_args);
1118 SESSION_TEST ((error == 0), "server bound to %U/%d", format_ip46_address,
1119 &server_sep.ip, 1, server_sep.port);
1120 al = app_listener_get_w_handle (bind_args.handle);
1121 listener = app_listener_get_session (al);
1122 ip4_address_t lcl_ip = {
1123 .as_u32 = clib_host_to_net_u32 (0x01020304),
1125 ip4_address_t rmt_ip = {
1126 .as_u32 = clib_host_to_net_u32 (0x05060708),
1128 fib_prefix_t lcl_pref = {
1129 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
1131 .fp_proto = FIB_PROTOCOL_IP4,
1133 fib_prefix_t rmt_pref = {
1134 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1136 .fp_proto = FIB_PROTOCOL_IP4,
1139 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1140 &rmt_pref.fp_addr.ip4, lcl_port,
1141 rmt_port, TRANSPORT_PROTO_TCP, 0,
1143 SESSION_TEST ((tc == 0), "optimized lookup should not work (port)");
1146 * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
1148 session_rule_add_del_args_t args = {
1149 .table_args.lcl = lcl_pref,
1150 .table_args.rmt = rmt_pref,
1151 .table_args.lcl_port = lcl_port,
1152 .table_args.rmt_port = rmt_port,
1153 .table_args.action_index = server_index,
1154 .table_args.is_add = 1,
1157 error = vnet_session_rule_add_del (&args);
1158 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
1159 args.table_args.action_index);
1161 tc = session_lookup_connection4 (0, &lcl_pref.fp_addr.ip4,
1162 &rmt_pref.fp_addr.ip4, lcl_port, rmt_port,
1163 TRANSPORT_PROTO_TCP);
1164 SESSION_TEST ((tc->c_index == listener->connection_index),
1165 "optimized lookup should return the listener");
1166 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1167 &rmt_pref.fp_addr.ip4, lcl_port,
1168 rmt_port, TRANSPORT_PROTO_TCP, 0,
1170 SESSION_TEST ((tc->c_index == listener->connection_index),
1171 "lookup should return the listener");
1172 s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4,
1173 lcl_port, rmt_port, TRANSPORT_PROTO_TCP);
1174 SESSION_TEST ((s->connection_index == listener->connection_index),
1175 "safe lookup should return the listener");
1176 session_endpoint_t sep = {
1177 .ip = rmt_pref.fp_addr,
1180 .transport_proto = TRANSPORT_PROTO_TCP,
1182 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1183 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1184 "should not work (global scope)");
1186 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1187 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1188 rmt_port, TRANSPORT_PROTO_TCP, 0,
1190 SESSION_TEST ((tc == 0),
1191 "optimized lookup for wrong lcl port + 1 should not work");
1194 * Add 1.2.3.4/16 * 5.6.7.8/16 4321
1196 args.table_args.lcl_port = 0;
1197 args.scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1198 error = vnet_session_rule_add_del (&args);
1199 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 4321 action %d",
1200 args.table_args.action_index);
1201 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1202 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1203 rmt_port, TRANSPORT_PROTO_TCP, 0,
1205 SESSION_TEST ((tc->c_index == listener->connection_index),
1206 "optimized lookup for lcl port + 1 should work");
1207 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1208 SESSION_TEST ((handle == server_index), "local session endpoint lookup "
1209 "should work (lcl ip was zeroed)");
1212 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1214 args.table_args.lcl_port = 1234;
1215 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1216 args.table_args.lcl.fp_len = 30;
1217 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1218 args.table_args.rmt.fp_len = 30;
1219 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1220 error = vnet_session_rule_add_del (&args);
1221 SESSION_TEST ((error == 0), "Add 1.2.3.4/30 1234 5.6.7.8/30 4321 action %d",
1222 args.table_args.action_index);
1226 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1227 TRANSPORT_PROTO_TCP);
1228 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1229 TRANSPORT_PROTO_TCP);
1232 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1233 &rmt_pref.fp_addr.ip4, lcl_port,
1234 rmt_port, TRANSPORT_PROTO_TCP, 0,
1236 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1237 "should fail (deny rule)");
1238 SESSION_TEST ((is_filtered == SESSION_LOOKUP_RESULT_FILTERED),
1239 "lookup should be filtered (deny)");
1241 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1242 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1243 "5.6.7.8/16 4321 in local table should return deny");
1245 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1246 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1247 rmt_port, TRANSPORT_PROTO_TCP, 0,
1249 SESSION_TEST ((tc->c_index == listener->connection_index),
1250 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should work");
1253 * "Mask" deny rule with more specific allow:
1254 * Add allow rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -3 (allow)
1256 args.table_args.is_add = 1;
1257 args.table_args.lcl_port = 1234;
1258 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1259 args.table_args.lcl.fp_len = 32;
1260 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1261 args.table_args.rmt.fp_len = 32;
1262 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1263 error = vnet_session_rule_add_del (&args);
1264 SESSION_TEST ((error == 0), "Add masking rule 1.2.3.4/30 1234 5.6.7.8/32 "
1265 "4321 action %d", args.table_args.action_index);
1268 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1269 &rmt_pref.fp_addr.ip4, lcl_port,
1270 rmt_port, TRANSPORT_PROTO_TCP, 0,
1272 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1273 "should fail (allow without app)");
1274 SESSION_TEST ((is_filtered == 0), "lookup should NOT be filtered");
1276 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1277 SESSION_TEST ((handle == SESSION_INVALID_HANDLE), "lookup for 1.2.3.4/32 "
1278 "1234 5.6.7.8/32 4321 in local table should return invalid");
1282 vlib_cli_output (vm, "Local rules");
1283 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1284 TRANSPORT_PROTO_TCP);
1287 sep.ip.ip4.as_u32 += 1 << 24;
1288 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1289 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234"
1290 " 5.6.7.9/32 4321 in local table should return deny");
1292 vnet_connect_args_t connect_args = {
1293 .app_index = attach_args.app_index,
1296 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1298 /* Try connecting */
1299 error = vnet_connect (&connect_args);
1300 SESSION_TEST ((error != 0), "connect should fail");
1301 SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1303 sep.ip.ip4.as_u32 -= 1 << 24;
1306 * Delete masking rule: 1.2.3.4/32 1234 5.6.7.8/32 4321 allow
1308 args.table_args.is_add = 0;
1309 args.table_args.lcl_port = 1234;
1310 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1311 args.table_args.lcl.fp_len = 32;
1312 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1313 args.table_args.rmt.fp_len = 32;
1314 error = vnet_session_rule_add_del (&args);
1315 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 allow");
1319 * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
1321 args.table_args.is_add = 1;
1322 args.table_args.lcl_port = 0;
1323 args.table_args.lcl.fp_len = 0;
1324 args.table_args.rmt.fp_len = 16;
1325 args.table_args.action_index = -1;
1326 error = vnet_session_rule_add_del (&args);
1327 SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d",
1328 args.table_args.action_index);
1332 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1333 TRANSPORT_PROTO_TCP);
1334 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1335 TRANSPORT_PROTO_TCP);
1338 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1339 SESSION_TEST ((handle == SESSION_DROP_HANDLE),
1340 "local session endpoint lookup should return deny");
1343 * Delete 1.2.3.4/32 1234 5.6.7.8/32 4321 deny
1345 args.table_args.is_add = 0;
1346 args.table_args.lcl_port = 1234;
1347 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1348 args.table_args.lcl.fp_len = 30;
1349 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1350 args.table_args.rmt.fp_len = 30;
1351 error = vnet_session_rule_add_del (&args);
1352 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1354 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1355 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1356 "local session endpoint lookup should return invalid");
1359 * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and
1360 * 1.2.3.4/16 1234 5.6.7.8/16 4321
1362 args.table_args.is_add = 0;
1363 args.table_args.lcl_port = 0;
1364 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1365 args.table_args.lcl.fp_len = 0;
1366 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1367 args.table_args.rmt.fp_len = 16;
1368 args.table_args.rmt_port = 4321;
1369 error = vnet_session_rule_add_del (&args);
1370 SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
1371 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1372 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1373 "should not work (removed)");
1375 args.table_args.is_add = 0;
1376 args.table_args.lcl = lcl_pref;
1378 args.table_args.is_add = 0;
1379 args.table_args.lcl_port = 0;
1380 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1381 args.table_args.lcl.fp_len = 16;
1382 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1383 args.table_args.rmt.fp_len = 16;
1384 args.table_args.rmt_port = 4321;
1385 error = vnet_session_rule_add_del (&args);
1386 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321");
1387 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1388 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1389 rmt_port, TRANSPORT_PROTO_TCP, 0,
1391 SESSION_TEST ((tc == 0),
1392 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should not "
1395 args.table_args.is_add = 0;
1396 args.table_args.lcl_port = 1234;
1397 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1398 args.table_args.lcl.fp_len = 16;
1399 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1400 args.table_args.rmt.fp_len = 16;
1401 args.table_args.rmt_port = 4321;
1402 error = vnet_session_rule_add_del (&args);
1403 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321");
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 (del + deny)");
1411 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1412 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1413 &rmt_pref.fp_addr.ip4, lcl_port,
1414 rmt_port, TRANSPORT_PROTO_TCP, 0,
1416 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should"
1417 " not work (no-rule)");
1420 * Test tags. Add/overwrite/del rule with tag
1422 args.table_args.is_add = 1;
1423 args.table_args.lcl_port = 1234;
1424 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1425 args.table_args.lcl.fp_len = 16;
1426 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1427 args.table_args.rmt.fp_len = 16;
1428 args.table_args.rmt_port = 4321;
1429 args.table_args.tag = format (0, "test_rule");
1430 args.table_args.action_index = server_index;
1431 error = vnet_session_rule_add_del (&args);
1432 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 deny "
1436 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1437 TRANSPORT_PROTO_TCP);
1438 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1439 TRANSPORT_PROTO_TCP);
1441 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1442 &rmt_pref.fp_addr.ip4, lcl_port,
1443 rmt_port, TRANSPORT_PROTO_TCP, 0,
1445 SESSION_TEST ((tc->c_index == listener->connection_index),
1446 "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should work");
1448 vec_free (args.table_args.tag);
1449 args.table_args.lcl_port = 1234;
1450 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1451 args.table_args.lcl.fp_len = 16;
1452 args.table_args.tag = format (0, "test_rule_overwrite");
1453 error = vnet_session_rule_add_del (&args);
1454 SESSION_TEST ((error == 0),
1455 "Overwrite 1.2.3.4/16 1234 5.6.7.8/16 4321 deny tag test_rule"
1459 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1460 TRANSPORT_PROTO_TCP);
1461 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1462 TRANSPORT_PROTO_TCP);
1465 args.table_args.is_add = 0;
1466 args.table_args.lcl_port += 1;
1467 error = vnet_session_rule_add_del (&args);
1468 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny "
1469 "tag %v", args.table_args.tag);
1472 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1473 TRANSPORT_PROTO_TCP);
1474 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1475 TRANSPORT_PROTO_TCP);
1477 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1478 &rmt_pref.fp_addr.ip4, lcl_port,
1479 rmt_port, TRANSPORT_PROTO_TCP, 0,
1481 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/32 4321 should not"
1486 * Test local rules with multiple namespaces
1490 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1492 args.table_args.is_add = 1;
1493 args.table_args.lcl_port = 1234;
1494 args.table_args.rmt_port = 0;
1495 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1496 args.table_args.lcl.fp_len = 32;
1497 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1498 args.table_args.rmt.fp_len = 32;
1499 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1500 args.table_args.tag = 0;
1501 args.scope = SESSION_RULE_SCOPE_LOCAL;
1502 error = vnet_session_rule_add_del (&args);
1503 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d",
1504 args.table_args.action_index);
1506 * Add 'white' rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1508 args.table_args.is_add = 1;
1509 args.table_args.lcl_port = 1234;
1510 args.table_args.rmt_port = 4321;
1511 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1512 args.table_args.lcl.fp_len = 32;
1513 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1514 args.table_args.rmt.fp_len = 32;
1515 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1516 error = vnet_session_rule_add_del (&args);
1520 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1521 TRANSPORT_PROTO_TCP);
1524 vnet_app_namespace_add_del_args_t ns_args = {
1527 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
1530 error = vnet_app_namespace_add_del (&ns_args);
1531 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
1532 app_ns = app_namespace_get_from_id (ns_id);
1534 attach_args.namespace_id = ns_id;
1535 attach_args.api_client_index = placeholder_server_api_index;
1536 vec_free (attach_args.name);
1537 attach_args.name = format (0, "server_test2");
1538 error = vnet_application_attach (&attach_args);
1539 SESSION_TEST ((error == 0), "server2 attached");
1540 server_index2 = attach_args.app_index;
1543 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1545 args.table_args.lcl_port = 1234;
1546 args.table_args.rmt_port = 0;
1547 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1548 args.table_args.lcl.fp_len = 32;
1549 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1550 args.table_args.rmt.fp_len = 32;
1551 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1552 args.appns_index = app_namespace_index (app_ns);
1554 error = vnet_session_rule_add_del (&args);
1555 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d "
1556 "in test namespace", args.table_args.action_index);
1558 * Lookup default namespace
1560 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1561 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1562 "lookup for 1.2.3.4/32 1234 5.6.7.8/32 4321 in local table "
1563 "should return allow (invalid)");
1566 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1567 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1568 "5.6.7.8/16 432*2* in local table should return deny");
1571 connect_args.app_index = server_index;
1572 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1574 error = vnet_connect (&connect_args);
1575 SESSION_TEST ((error != 0), "connect should fail");
1576 SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1579 * Lookup test namespace
1581 handle = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1582 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1583 "5.6.7.8/16 4321 in local table should return deny");
1585 connect_args.app_index = server_index;
1586 error = vnet_connect (&connect_args);
1587 SESSION_TEST ((error != 0), "connect should fail");
1588 SESSION_TEST ((error == SESSION_E_FILTERED), "connect should be filtered");
1590 args.table_args.is_add = 0;
1591 vnet_session_rule_add_del (&args);
1593 args.appns_index = 0;
1594 args.table_args.is_add = 0;
1595 vnet_session_rule_add_del (&args);
1597 args.table_args.rmt_port = 4321;
1598 vnet_session_rule_add_del (&args);
1602 vec_free (args.table_args.tag);
1603 vnet_app_detach_args_t detach_args = {
1604 .app_index = server_index,
1605 .api_client_index = ~0,
1607 vnet_application_detach (&detach_args);
1609 detach_args.app_index = server_index2;
1610 vnet_application_detach (&detach_args);
1613 error = vnet_app_namespace_add_del (&ns_args);
1614 SESSION_TEST ((error == 0), "app ns delete should succeed: %d", error);
1617 vec_free (attach_args.name);
1622 session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
1624 u64 options[APP_OPTIONS_N_OPTIONS];
1625 char *show_listeners = "sh session listeners tcp verbose";
1626 char *show_local_listeners = "sh app ns table default";
1627 unformat_input_t tmp_input;
1628 u32 server_index, app_index;
1629 u32 placeholder_server_api_index = ~0, sw_if_index = 0;
1632 transport_connection_t *tc;
1633 u16 lcl_port = 1234, rmt_port = 4321;
1634 app_namespace_t *app_ns;
1635 int verbose = 0, error = 0;
1637 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1639 if (unformat (input, "verbose"))
1643 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1649 ip4_address_t lcl_ip = {
1650 .as_u32 = clib_host_to_net_u32 (0x01020304),
1652 ip4_address_t rmt_ip = {
1653 .as_u32 = clib_host_to_net_u32 (0x05060708),
1655 fib_prefix_t rmt_pref = {
1656 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1658 .fp_proto = FIB_PROTOCOL_IP4,
1660 session_endpoint_t sep = {
1661 .ip = rmt_pref.fp_addr,
1664 .transport_proto = TRANSPORT_PROTO_TCP,
1668 * Create loopback interface
1670 session_create_lookpback (0, &sw_if_index, &lcl_ip);
1672 app_ns = app_namespace_get_default ();
1673 app_ns->sw_if_index = sw_if_index;
1675 clib_memset (options, 0, sizeof (options));
1676 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1677 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
1678 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_PROXY;
1679 options[APP_OPTIONS_PROXY_TRANSPORT] = 1 << TRANSPORT_PROTO_TCP;
1680 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1681 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1682 vnet_app_attach_args_t attach_args = {
1683 .api_client_index = ~0,
1686 .session_cb_vft = &placeholder_session_cbs,
1687 .name = format (0, "session_test"),
1690 attach_args.api_client_index = placeholder_server_api_index;
1691 error = vnet_application_attach (&attach_args);
1692 SESSION_TEST ((error == 0), "server attachment should work");
1693 server_index = attach_args.app_index;
1697 unformat_init_string (&tmp_input, show_listeners,
1698 strlen (show_listeners));
1699 vlib_cli_input (vm, &tmp_input, 0, 0);
1700 unformat_init_string (&tmp_input, show_local_listeners,
1701 strlen (show_local_listeners));
1702 vlib_cli_input (vm, &tmp_input, 0, 0);
1705 tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port,
1706 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1707 SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be "
1709 s = listen_session_get (tc->s_index);
1710 SESSION_TEST ((s->app_index == server_index), "lookup should return"
1713 tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port,
1714 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1715 SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should"
1718 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1719 SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1722 vnet_app_detach_args_t detach_args = {
1723 .app_index = server_index,
1724 .api_client_index = ~0,
1726 vnet_application_detach (&detach_args);
1730 unformat_init_string (&tmp_input, show_listeners,
1731 strlen (show_listeners));
1732 vlib_cli_input (vm, &tmp_input, 0, 0);
1733 unformat_init_string (&tmp_input, show_local_listeners,
1734 strlen (show_local_listeners));
1735 vlib_cli_input (vm, &tmp_input, 0, 0);
1738 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1739 SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX),
1740 "local session endpoint lookup should not work after detach");
1742 unformat_free (&tmp_input);
1743 vec_free (attach_args.name);
1744 session_delete_loopback (sw_if_index);
1749 wait_for_event (svm_msg_q_t * mq, int fd, int epfd, u8 use_eventfd)
1753 svm_msg_q_wait (mq, SVM_MQ_WAIT_EMPTY);
1757 int __clib_unused n_read, rv;
1758 struct epoll_event ep_evt;
1763 rv = epoll_wait (epfd, &ep_evt, 1, -1);
1766 ST_DBG ("epoll error");
1769 else if (rv > 0 && (ep_evt.events & EPOLLIN))
1771 n_read = read (fd, &buf, sizeof (buf));
1776 if (!svm_msg_q_is_empty (mq))
1783 session_test_mq_speed (vlib_main_t * vm, unformat_input_t * input)
1785 int error, __clib_unused verbose, use_eventfd = 0;
1786 u64 i, n_test_msgs = 1 << 10, *counter;
1787 u64 options[APP_OPTIONS_N_OPTIONS];
1788 int epfd = -1, rv, prod_fd = -1;
1789 svm_fifo_t *rx_fifo, *tx_fifo;
1790 vl_api_registration_t *reg;
1791 struct epoll_event ep_evt;
1792 u32 app_index, api_index;
1793 app_worker_t *app_wrk;
1794 segment_manager_t *sm;
1795 svm_msg_q_msg_t msg;
1803 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1805 if (unformat (input, "verbose"))
1807 else if (unformat (input, "%d", &n_test_msgs))
1809 else if (unformat (input, "use-eventfd"))
1813 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1819 q = clib_mem_alloc (sizeof (*q));
1820 api_index = vl_api_memclnt_create_internal ("session_mq_test_api", q);
1822 clib_memset (options, 0, sizeof (options));
1823 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1824 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1825 options[APP_OPTIONS_EVT_QUEUE_SIZE] = 2048;
1827 reg = vl_api_client_index_to_registration (api_index);
1828 /* Shut up coverity */
1832 vnet_app_attach_args_t attach_args = {
1833 .api_client_index = api_index,
1836 .session_cb_vft = &placeholder_session_cbs,
1837 .name = format (0, "session_mq_test"),
1839 error = vnet_application_attach (&attach_args);
1840 SESSION_TEST ((error == 0), "server attachment should work");
1842 app_index = attach_args.app_index;
1844 app = application_get (app_index);
1845 app_wrk = application_get_worker (app, 0);
1846 mq = app_wrk->event_queue;
1849 svm_msg_q_alloc_eventfd (mq);
1850 prod_fd = svm_msg_q_get_eventfd (mq);
1851 SESSION_TEST (prod_fd != -1, "mq producer eventd valid %u", prod_fd);
1854 sm = app_worker_get_connect_segment_manager (app_wrk);
1855 segment_manager_alloc_session_fifos (sm, 0, &rx_fifo, &tx_fifo);
1856 s.rx_fifo = rx_fifo;
1857 s.tx_fifo = tx_fifo;
1858 s.session_state = SESSION_STATE_READY;
1859 counter = (u64 *) f_head_cptr (rx_fifo)->data;
1860 start = vlib_time_now (vm);
1864 SESSION_TEST (0, "fork failed");
1870 epfd = epoll_create1 (0);
1871 SESSION_TEST (epfd != -1, "epfd created");
1872 ep_evt.events = EPOLLIN;
1873 ep_evt.data.u64 = prod_fd;
1874 rv = epoll_ctl (epfd, EPOLL_CTL_ADD, prod_fd, &ep_evt);
1875 SESSION_TEST (rv == 0, "epoll returned %d", rv);
1878 for (i = 0; i < n_test_msgs; i++)
1880 wait_for_event (mq, prod_fd, epfd, use_eventfd);
1881 svm_msg_q_sub_raw (mq, &msg);
1882 svm_msg_q_free_msg (mq, &msg);
1883 svm_msg_q_unlock (mq);
1884 *counter = *counter + 1;
1885 svm_fifo_unset_event (rx_fifo);
1891 ST_DBG ("client pid %u", pid);
1892 for (i = 0; i < n_test_msgs; i++)
1894 while (svm_fifo_has_event (rx_fifo))
1896 app_worker_lock_and_send_event (app_wrk, &s, SESSION_IO_EVT_RX);
1900 diff = vlib_time_now (vm) - start;
1901 ST_DBG ("done %u events in %.2f sec: %f evts/s", *counter,
1902 diff, *counter / diff);
1904 vnet_app_detach_args_t detach_args = {
1905 .app_index = app_index,
1906 .api_client_index = ~0,
1908 vnet_application_detach (&detach_args);
1913 session_test_mq_basic (vlib_main_t * vm, unformat_input_t * input)
1915 svm_msg_q_cfg_t _cfg, *cfg = &_cfg;
1916 svm_msg_q_msg_t msg1, msg2, msg[12];
1917 int __clib_unused verbose, i, rv;
1918 svm_msg_q_shared_t *smq;
1919 svm_msg_q_ring_t *ring;
1920 svm_msg_q_t _mq = { 0 }, *mq = &_mq;
1923 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1925 if (unformat (input, "verbose"))
1929 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1935 svm_msg_q_ring_cfg_t rc[2] = { {8, 8, 0}
1938 cfg->consumer_pid = ~0;
1941 cfg->ring_cfgs = rc;
1943 smq = svm_msg_q_alloc (cfg);
1944 svm_msg_q_attach (mq, smq);
1945 SESSION_TEST (smq != 0, "svm_msg_q_alloc");
1946 SESSION_TEST (vec_len (mq->rings) == 2, "ring allocation");
1947 rings_ptr = (u8 *) mq->rings[0].shr->data;
1948 vec_foreach (ring, mq->rings)
1950 SESSION_TEST (ring->shr->data == rings_ptr, "ring data");
1951 rings_ptr += (uword) ring->nitems * ring->elsize;
1952 rings_ptr += sizeof (svm_msg_q_ring_shared_t);
1955 msg1 = svm_msg_q_alloc_msg (mq, 8);
1956 rv = (mq->rings[0].shr->cursize != 1 || msg1.ring_index != 0 ||
1957 msg1.elt_index != 0);
1958 SESSION_TEST (rv == 0, "msg alloc1");
1960 msg2 = svm_msg_q_alloc_msg (mq, 15);
1961 rv = (mq->rings[1].shr->cursize != 1 || msg2.ring_index != 1 ||
1962 msg2.elt_index != 0);
1963 SESSION_TEST (rv == 0, "msg alloc2");
1965 svm_msg_q_free_msg (mq, &msg1);
1966 SESSION_TEST (mq->rings[0].shr->cursize == 0, "free msg");
1968 for (i = 0; i < 12; i++)
1970 msg[i] = svm_msg_q_alloc_msg (mq, 7);
1971 *(u32 *) svm_msg_q_msg_data (mq, &msg[i]) = i;
1974 rv = (mq->rings[0].shr->cursize != 8 || mq->rings[1].shr->cursize != 5);
1975 SESSION_TEST (rv == 0, "msg alloc3");
1977 *(u32 *) svm_msg_q_msg_data (mq, &msg2) = 123;
1978 svm_msg_q_add (mq, &msg2, SVM_Q_NOWAIT);
1979 for (i = 0; i < 12; i++)
1980 svm_msg_q_add (mq, &msg[i], SVM_Q_NOWAIT);
1982 rv = svm_msg_q_sub (mq, &msg2, SVM_Q_NOWAIT, 0);
1983 SESSION_TEST (rv == 0, "dequeue1");
1985 SESSION_TEST (msg2.ring_index == 1 && msg2.elt_index == 0,
1987 rv = (*(u32 *) svm_msg_q_msg_data (mq, &msg2) == 123);
1988 SESSION_TEST (rv, "dequeue 1 data");
1990 svm_msg_q_free_msg (mq, &msg2);
1992 for (i = 0; i < 12; i++)
1994 if (svm_msg_q_sub (mq, &msg[i], SVM_Q_NOWAIT, 0))
1995 SESSION_TEST (0, "dequeue2");
1998 if (msg[i].ring_index != 0 || msg[i].elt_index != (i + 1) % 8)
1999 SESSION_TEST (0, "dequeue2 result2");
2003 if (msg[i].ring_index != 1 || msg[i].elt_index != (i - 8) + 1)
2004 SESSION_TEST (0, "dequeue2 result3");
2006 if (*(u32 *) svm_msg_q_msg_data (mq, &msg[i]) != i)
2007 SESSION_TEST (0, "dequeue2 wrong data");
2008 svm_msg_q_free_msg (mq, &msg[i]);
2010 rv = (mq->rings[0].shr->cursize == 0 && mq->rings[1].shr->cursize == 0);
2011 SESSION_TEST (rv, "post dequeue");
2016 static clib_error_t *
2017 session_test (vlib_main_t * vm,
2018 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
2022 vnet_session_enable_disable (vm, 1);
2024 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2026 if (unformat (input, "basic"))
2027 res = session_test_basic (vm, input);
2028 else if (unformat (input, "namespace"))
2029 res = session_test_namespace (vm, input);
2030 else if (unformat (input, "rules-table"))
2031 res = session_test_rule_table (vm, input);
2032 else if (unformat (input, "rules"))
2033 res = session_test_rules (vm, input);
2034 else if (unformat (input, "proxy"))
2035 res = session_test_proxy (vm, input);
2036 else if (unformat (input, "endpt-cfg"))
2037 res = session_test_endpoint_cfg (vm, input);
2038 else if (unformat (input, "mq-speed"))
2039 res = session_test_mq_speed (vm, input);
2040 else if (unformat (input, "mq-basic"))
2041 res = session_test_mq_basic (vm, input);
2042 else if (unformat (input, "all"))
2044 if ((res = session_test_basic (vm, input)))
2046 if ((res = session_test_namespace (vm, input)))
2048 if ((res = session_test_rule_table (vm, input)))
2050 if ((res = session_test_rules (vm, input)))
2052 if ((res = session_test_proxy (vm, input)))
2054 if ((res = session_test_endpoint_cfg (vm, input)))
2056 if ((res = session_test_mq_speed (vm, input)))
2058 if ((res = session_test_mq_basic (vm, input)))
2067 return clib_error_return (0, "Session unit test failed");
2072 VLIB_CLI_COMMAND (tcp_test_command, static) =
2074 .path = "test session",
2075 .short_help = "internal session unit tests",
2076 .function = session_test,
2081 * fd.io coding-style-patch-verification: ON
2084 * eval: (c-set-style "gnu")