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 dummy_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 dummy_session_connected_callback (u32 app_index, u32 api_context,
57 session_t * s, u8 is_fail)
61 connected_session_index = s->session_index;
62 connected_session_thread = s->thread_index;
67 static u32 dummy_segment_count;
70 dummy_add_segment_callback (u32 client_index, u64 segment_handle)
72 dummy_segment_count = 1;
77 dummy_del_segment_callback (u32 client_index, u64 segment_handle)
79 dummy_segment_count = 0;
84 dummy_session_disconnect_callback (session_t * s)
86 clib_warning ("called...");
89 static u32 dummy_accept;
90 volatile u32 accepted_session_index;
91 volatile u32 accepted_session_thread;
94 dummy_session_accept_callback (session_t * s)
97 accepted_session_index = s->session_index;
98 accepted_session_thread = s->thread_index;
99 s->session_state = SESSION_STATE_READY;
104 dummy_server_rx_callback (session_t * s)
106 clib_warning ("called...");
111 static session_cb_vft_t dummy_session_cbs = {
112 .session_reset_callback = dummy_session_reset_callback,
113 .session_connected_callback = dummy_session_connected_callback,
114 .session_accept_callback = dummy_session_accept_callback,
115 .session_disconnect_callback = dummy_session_disconnect_callback,
116 .builtin_app_rx_callback = dummy_server_rx_callback,
117 .add_segment_callback = dummy_add_segment_callback,
118 .del_segment_callback = dummy_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 = &dummy_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], dummy_secret = 1234;
282 u16 dummy_server_port = 1234, dummy_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 = dummy_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 = &dummy_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] = dummy_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 = dummy_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 = dummy_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 = dummy_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
379 || vec_len (tcp_main.wrk_ctx[0].pending_acks)) && ++tries < 100)
380 vlib_process_suspend (vm, 100e-3);
381 clib_warning ("waited %.1f seconds for connections", tries / 10.0);
382 SESSION_TEST ((connected_session_index != ~0), "session should exist");
383 SESSION_TEST ((connected_session_thread != ~0), "thread should exist");
384 SESSION_TEST ((accepted_session_index != ~0), "session should exist");
385 SESSION_TEST ((accepted_session_thread != ~0), "thread should exist");
386 s = session_get (connected_session_index, connected_session_thread);
387 tc = session_get_transport (s);
388 SESSION_TEST ((tc != 0), "transport should exist");
389 SESSION_TEST ((memcmp (&tc->lcl_ip, &client_sep.peer.ip,
390 sizeof (tc->lcl_ip)) == 0), "ips should be equal");
391 SESSION_TEST ((tc->lcl_port == dummy_client_port), "ports should be equal");
393 /* These sessions, because of the way they're established are pinned to
394 * main thread, even when we have workers and we avoid polling main thread,
395 * i.e., we can't cleanup pending disconnects, so force cleanup for both
397 session_transport_cleanup (s);
398 s = session_get (accepted_session_index, accepted_session_thread);
399 session_transport_cleanup (s);
401 vnet_app_detach_args_t detach_args = {
402 .app_index = server_index,
403 .api_client_index = ~0,
405 vnet_application_detach (&detach_args);
406 detach_args.app_index = client_index;
407 vnet_application_detach (&detach_args);
409 /* Allow the disconnects to finish before removing the routes. */
410 vlib_process_suspend (vm, 10e-3);
412 session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
414 session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
417 session_delete_loopback (sw_if_index[0]);
418 session_delete_loopback (sw_if_index[1]);
423 session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
425 u64 options[APP_OPTIONS_N_OPTIONS], dummy_secret = 1234;
426 u32 server_index, server_st_index, server_local_st_index;
427 u32 dummy_port = 1234, client_index, server_wrk_index;
428 u32 dummy_api_context = 4321, dummy_client_api_index = ~0;
429 u32 dummy_server_api_index = ~0, sw_if_index = 0;
430 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
431 session_endpoint_t client_sep = SESSION_ENDPOINT_NULL;
432 session_endpoint_t intf_sep = SESSION_ENDPOINT_NULL;
433 u8 *ns_id = format (0, "appns1");
434 app_namespace_t *app_ns;
435 application_t *server;
440 server_sep.is_ip4 = 1;
441 server_sep.port = dummy_port;
442 client_sep.is_ip4 = 1;
443 client_sep.port = dummy_port;
444 clib_memset (options, 0, sizeof (options));
446 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
447 vnet_app_attach_args_t attach_args = {
448 .api_client_index = ~0,
451 .session_cb_vft = &dummy_session_cbs,
452 .name = format (0, "session_test"),
455 vnet_listen_args_t bind_args = {
460 vnet_connect_args_t connect_args = {
464 clib_memcpy (&connect_args.sep, &client_sep, sizeof (client_sep));
466 vnet_unlisten_args_t unbind_args = {
467 .handle = bind_args.handle,
471 vnet_app_detach_args_t detach_args = {
473 .api_client_index = ~0,
476 ip4_address_t intf_addr = {
477 .as_u32 = clib_host_to_net_u32 (0x07000105),
480 intf_sep.ip.ip4 = intf_addr;
482 intf_sep.port = dummy_port;
485 * Insert namespace and lookup
488 vnet_app_namespace_add_del_args_t ns_args = {
490 .secret = dummy_secret,
491 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
494 error = vnet_app_namespace_add_del (&ns_args);
495 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
497 app_ns = app_namespace_get_from_id (ns_id);
498 SESSION_TEST ((app_ns != 0), "should find ns %v status", ns_id);
499 SESSION_TEST ((app_ns->ns_secret == dummy_secret), "secret should be %d",
501 SESSION_TEST ((app_ns->sw_if_index == APP_NAMESPACE_INVALID_INDEX),
502 "sw_if_index should be invalid");
505 * Try application attach with wrong secret
508 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
509 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
510 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret - 1;
511 attach_args.namespace_id = ns_id;
512 attach_args.api_client_index = dummy_server_api_index;
514 error = vnet_application_attach (&attach_args);
515 SESSION_TEST ((error != 0), "app attachment should fail");
516 SESSION_TEST ((error == VNET_API_ERROR_APP_WRONG_NS_SECRET),
517 "code should be wrong ns secret: %d", error);
520 * Attach server with global default scope
522 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
523 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
524 options[APP_OPTIONS_NAMESPACE_SECRET] = 0;
525 attach_args.namespace_id = 0;
526 attach_args.api_client_index = dummy_server_api_index;
527 error = vnet_application_attach (&attach_args);
528 SESSION_TEST ((error == 0), "server attachment should work");
529 server_index = attach_args.app_index;
530 server = application_get (server_index);
531 server_wrk_index = application_get_default_worker (server)->wrk_index;
532 SESSION_TEST ((server->ns_index == 0),
533 "server should be in the default ns");
535 bind_args.app_index = server_index;
536 error = vnet_listen (&bind_args);
537 SESSION_TEST ((error == 0), "server bind should work");
539 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
540 s = session_lookup_listener (server_st_index, &server_sep);
541 SESSION_TEST ((s != 0), "listener should exist in global table");
542 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
543 " that of the server");
544 server_local_st_index = application_local_session_table (server);
545 SESSION_TEST ((server_local_st_index == APP_INVALID_INDEX),
546 "server shouldn't have access to local table");
548 unbind_args.app_index = server_index;
549 unbind_args.handle = bind_args.handle;
550 error = vnet_unlisten (&unbind_args);
551 SESSION_TEST ((error == 0), "unbind should work");
553 s = session_lookup_listener (server_st_index, &server_sep);
554 SESSION_TEST ((s == 0), "listener should not exist in global table");
556 detach_args.app_index = server_index;
557 vnet_application_detach (&detach_args);
560 * Attach server with local and global scope
562 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
563 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
564 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret;
565 attach_args.namespace_id = ns_id;
566 attach_args.api_client_index = dummy_server_api_index;
567 error = vnet_application_attach (&attach_args);
568 SESSION_TEST ((error == 0), "server attachment should work");
569 server_index = attach_args.app_index;
570 server = application_get (server_index);
571 server_wrk_index = application_get_default_worker (server)->wrk_index;
572 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
573 "server should be in the right ns");
575 bind_args.app_index = server_index;
576 error = vnet_listen (&bind_args);
577 SESSION_TEST ((error == 0), "bind should work");
578 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
579 s = session_lookup_listener (server_st_index, &server_sep);
580 SESSION_TEST ((s != 0), "listener should exist in global table");
581 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
582 " that of the server");
583 server_local_st_index = application_local_session_table (server);
584 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
585 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
586 "listener should exist in local table");
589 * Try client connect with 1) local scope 2) global scope
591 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
592 attach_args.api_client_index = dummy_client_api_index;
593 error = vnet_application_attach (&attach_args);
594 SESSION_TEST ((error == 0), "client attachment should work");
595 client_index = attach_args.app_index;
596 connect_args.api_context = dummy_api_context;
597 connect_args.app_index = client_index;
598 error = vnet_connect (&connect_args);
599 SESSION_TEST ((error != 0), "client connect should return error code");
600 SESSION_TEST ((error == VNET_API_ERROR_INVALID_VALUE),
601 "error code should be invalid value (zero ip)");
602 SESSION_TEST ((dummy_segment_count == 0),
603 "shouldn't have received request to map new segment");
604 connect_args.sep.ip.ip4.as_u8[0] = 127;
605 error = vnet_connect (&connect_args);
606 SESSION_TEST ((error == 0), "client connect should not return error code");
607 SESSION_TEST ((dummy_segment_count == 1),
608 "should've received request to map new segment");
609 SESSION_TEST ((dummy_accept == 1), "should've received accept request");
610 detach_args.app_index = client_index;
611 vnet_application_detach (&detach_args);
613 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
614 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
615 attach_args.api_client_index = dummy_client_api_index;
616 error = vnet_application_attach (&attach_args);
617 SESSION_TEST ((error == 0), "client attachment should work");
618 error = vnet_connect (&connect_args);
619 SESSION_TEST ((error != 0), "client connect should return error code");
620 SESSION_TEST ((error == VNET_API_ERROR_SESSION_CONNECT),
621 "error code should be connect (nothing in local scope)");
622 detach_args.app_index = client_index;
623 vnet_application_detach (&detach_args);
626 * Unbind and detach server and then re-attach with local scope only
628 unbind_args.handle = bind_args.handle;
629 unbind_args.app_index = server_index;
630 error = vnet_unlisten (&unbind_args);
631 SESSION_TEST ((error == 0), "unbind should work");
633 s = session_lookup_listener (server_st_index, &server_sep);
634 SESSION_TEST ((s == 0), "listener should not exist in global table");
635 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
636 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
637 "listener should not exist in local table");
639 detach_args.app_index = server_index;
640 vnet_application_detach (&detach_args);
642 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
643 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
644 attach_args.api_client_index = dummy_server_api_index;
645 error = vnet_application_attach (&attach_args);
646 SESSION_TEST ((error == 0), "app attachment should work");
647 server_index = attach_args.app_index;
648 server = application_get (server_index);
649 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
650 "app should be in the right ns");
652 bind_args.app_index = server_index;
653 error = vnet_listen (&bind_args);
654 SESSION_TEST ((error == 0), "bind should work");
656 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
657 s = session_lookup_listener (server_st_index, &server_sep);
658 SESSION_TEST ((s == 0), "listener should not exist in global table");
659 server_local_st_index = application_local_session_table (server);
660 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
661 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
662 "listener should exist in local table");
664 unbind_args.handle = bind_args.handle;
665 error = vnet_unlisten (&unbind_args);
666 SESSION_TEST ((error == 0), "unbind should work");
668 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
669 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
670 "listener should not exist in local table");
673 * Client attach + connect in default ns with local scope
675 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
676 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
677 attach_args.namespace_id = 0;
678 attach_args.api_client_index = dummy_client_api_index;
679 vnet_application_attach (&attach_args);
680 error = vnet_connect (&connect_args);
681 SESSION_TEST ((error != 0), "client connect should return error code");
682 SESSION_TEST ((error == VNET_API_ERROR_SESSION_CONNECT),
683 "error code should be connect (not in same ns)");
684 detach_args.app_index = client_index;
685 vnet_application_detach (&detach_args);
690 detach_args.app_index = server_index;
691 vnet_application_detach (&detach_args);
694 * Create loopback interface
696 session_create_lookpback (0, &sw_if_index, &intf_addr);
699 * Update namespace with interface
701 ns_args.sw_if_index = sw_if_index;
702 error = vnet_app_namespace_add_del (&ns_args);
703 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
706 * Attach server with local and global scope
708 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
709 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
710 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret;
711 attach_args.namespace_id = ns_id;
712 attach_args.api_client_index = dummy_server_api_index;
713 error = vnet_application_attach (&attach_args);
714 SESSION_TEST ((error == 0), "server attachment should work");
715 server_index = attach_args.app_index;
716 server = application_get (server_index);
717 server_wrk_index = application_get_default_worker (server)->wrk_index;
719 bind_args.app_index = server_index;
720 error = vnet_listen (&bind_args);
721 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
722 s = session_lookup_listener (server_st_index, &server_sep);
723 SESSION_TEST ((s == 0), "zero listener should not exist in global table");
725 s = session_lookup_listener (server_st_index, &intf_sep);
726 SESSION_TEST ((s != 0), "intf listener should exist in global table");
727 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be "
728 "that of the server");
729 server_local_st_index = application_local_session_table (server);
730 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
731 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
732 "zero listener should exist in local table");
733 detach_args.app_index = server_index;
734 vnet_application_detach (&detach_args);
739 vec_free (attach_args.name);
741 session_delete_loopback (sw_if_index);
746 session_test_rule_table (vlib_main_t * vm, unformat_input_t * input)
748 session_rules_table_t _srt, *srt = &_srt;
749 u16 lcl_port = 1234, rmt_port = 4321;
750 u32 action_index = 1, res;
751 ip4_address_t lcl_lkup, rmt_lkup;
752 int verbose = 0, error;
754 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
756 if (unformat (input, "verbose"))
760 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
766 clib_memset (srt, 0, sizeof (*srt));
767 session_rules_table_init (srt);
769 ip4_address_t lcl_ip = {
770 .as_u32 = clib_host_to_net_u32 (0x01020304),
772 ip4_address_t rmt_ip = {
773 .as_u32 = clib_host_to_net_u32 (0x05060708),
775 ip4_address_t lcl_ip2 = {
776 .as_u32 = clib_host_to_net_u32 (0x02020202),
778 ip4_address_t rmt_ip2 = {
779 .as_u32 = clib_host_to_net_u32 (0x06060606),
781 ip4_address_t lcl_ip3 = {
782 .as_u32 = clib_host_to_net_u32 (0x03030303),
784 ip4_address_t rmt_ip3 = {
785 .as_u32 = clib_host_to_net_u32 (0x07070707),
787 fib_prefix_t lcl_pref = {
788 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
790 .fp_proto = FIB_PROTOCOL_IP4,
792 fib_prefix_t rmt_pref = {
793 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
795 .fp_proto = FIB_PROTOCOL_IP4,
798 session_rule_table_add_del_args_t args = {
801 .lcl_port = lcl_port,
802 .rmt_port = rmt_port,
803 .action_index = action_index++,
806 error = session_rules_table_add_del (srt, &args);
807 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
811 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
812 SESSION_TEST ((res == 1),
813 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 1: %d",
817 * 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
819 args.lcl.fp_addr.ip4 = lcl_ip;
820 args.lcl.fp_len = 24;
821 args.action_index = action_index++;
822 error = session_rules_table_add_del (srt, &args);
823 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/16 4321 action %d",
825 args.rmt.fp_addr.ip4 = rmt_ip;
826 args.rmt.fp_len = 24;
827 args.action_index = action_index++;
828 error = session_rules_table_add_del (srt, &args);
829 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/24 4321 action %d",
833 * 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
835 args.lcl.fp_addr.ip4 = lcl_ip2;
836 args.lcl.fp_len = 24;
837 args.rmt.fp_addr.ip4 = rmt_ip2;
838 args.rmt.fp_len = 16;
839 args.action_index = action_index++;
840 error = session_rules_table_add_del (srt, &args);
841 SESSION_TEST ((error == 0), "Add 2.2.2.2/24 1234 6.6.6.6/16 4321 action %d",
843 args.lcl.fp_addr.ip4 = lcl_ip3;
844 args.rmt.fp_addr.ip4 = rmt_ip3;
845 args.action_index = action_index++;
846 error = session_rules_table_add_del (srt, &args);
847 SESSION_TEST ((error == 0), "Add 3.3.3.3/24 1234 7.7.7.7/16 4321 action %d",
851 * Add again 3.3.3.3/24 1234 7.7.7.7/16 4321
853 args.lcl.fp_addr.ip4 = lcl_ip3;
854 args.rmt.fp_addr.ip4 = rmt_ip3;
855 args.action_index = action_index++;
856 error = session_rules_table_add_del (srt, &args);
857 SESSION_TEST ((error == 0), "overwrite 3.3.3.3/24 1234 7.7.7.7/16 4321 "
858 "action %d", action_index - 1);
861 * 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
862 * and 3.3.3.3 1234 7.7.7.7 4321
865 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
866 SESSION_TEST ((res == 3),
867 "Lookup 1.2.3.4 1234 5.6.7.8 4321 action " "should be 3: %d",
870 lcl_lkup.as_u32 = clib_host_to_net_u32 (0x01020204);
871 rmt_lkup.as_u32 = clib_host_to_net_u32 (0x05060709);
873 session_rules_table_lookup4 (srt, &lcl_lkup,
874 &rmt_lkup, lcl_port, rmt_port);
875 SESSION_TEST ((res == 1),
876 "Lookup 1.2.2.4 1234 5.6.7.9 4321, action " "should be 1: %d",
880 session_rules_table_lookup4 (srt, &lcl_ip3, &rmt_ip3, lcl_port, rmt_port);
881 SESSION_TEST ((res == 6),
882 "Lookup 3.3.3.3 1234 7.7.7.7 4321, action "
883 "should be 6 (updated): %d", res);
886 * Add 1.2.3.4/24 * 5.6.7.8/24 *
887 * Lookup 1.2.3.4 1234 5.6.7.8 4321 and 1.2.3.4 1235 5.6.7.8 4321
889 args.lcl.fp_addr.ip4 = lcl_ip;
890 args.rmt.fp_addr.ip4 = rmt_ip;
891 args.lcl.fp_len = 24;
892 args.rmt.fp_len = 24;
895 args.action_index = action_index++;
896 error = session_rules_table_add_del (srt, &args);
897 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 * 5.6.7.8/24 * action %d",
900 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
901 SESSION_TEST ((res == 7),
902 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should"
903 " be 7 (lpm dst): %d", res);
905 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
906 lcl_port + 1, rmt_port);
907 SESSION_TEST ((res == 7),
908 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 7: %d",
912 * Del 1.2.3.4/24 * 5.6.7.8/24 *
913 * Add 1.2.3.4/16 * 5.6.7.8/16 * and 1.2.3.4/24 1235 5.6.7.8/24 4321
914 * Lookup 1.2.3.4 1234 5.6.7.8 4321, 1.2.3.4 1235 5.6.7.8 4321 and
915 * 1.2.3.4 1235 5.6.7.8 4322
918 error = session_rules_table_add_del (srt, &args);
919 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 * 5.6.7.8/24 *");
921 args.lcl.fp_addr.ip4 = lcl_ip;
922 args.rmt.fp_addr.ip4 = rmt_ip;
923 args.lcl.fp_len = 16;
924 args.rmt.fp_len = 16;
927 args.action_index = action_index++;
929 error = session_rules_table_add_del (srt, &args);
930 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 * action %d",
933 args.lcl.fp_addr.ip4 = lcl_ip;
934 args.rmt.fp_addr.ip4 = rmt_ip;
935 args.lcl.fp_len = 24;
936 args.rmt.fp_len = 24;
937 args.lcl_port = lcl_port + 1;
938 args.rmt_port = rmt_port;
939 args.action_index = action_index++;
941 error = session_rules_table_add_del (srt, &args);
942 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1235 5.6.7.8/24 4321 action %d",
946 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
949 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
950 SESSION_TEST ((res == 3),
951 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
954 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
955 lcl_port + 1, rmt_port);
956 SESSION_TEST ((res == 9),
957 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 9: %d",
960 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
961 lcl_port + 1, rmt_port + 1);
962 SESSION_TEST ((res == 8),
963 "Lookup 1.2.3.4 1235 5.6.7.8 4322, action should " "be 8: %d",
967 * Delete 1.2.0.0/16 1234 5.6.0.0/16 4321 and 1.2.0.0/16 * 5.6.0.0/16 *
968 * Lookup 1.2.3.4 1234 5.6.7.8 4321
970 args.lcl_port = 1234;
971 args.rmt_port = 4321;
972 args.lcl.fp_len = 16;
973 args.rmt.fp_len = 16;
975 error = session_rules_table_add_del (srt, &args);
976 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 1234 5.6.0.0/16 4321");
978 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
979 SESSION_TEST ((res == 3),
980 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
986 error = session_rules_table_add_del (srt, &args);
987 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 * 5.6.0.0/16 *");
989 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
990 SESSION_TEST ((res == 3),
991 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
995 * Delete 1.2.3.4/24 1234 5.6.7.5/24
997 args.lcl.fp_addr.ip4 = lcl_ip;
998 args.rmt.fp_addr.ip4 = rmt_ip;
999 args.lcl.fp_len = 24;
1000 args.rmt.fp_len = 24;
1001 args.lcl_port = 1234;
1002 args.rmt_port = 4321;
1004 error = session_rules_table_add_del (srt, &args);
1005 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 1234 5.6.7.5/24");
1007 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1008 SESSION_TEST ((res == 2), "Action should be 2: %d", res);
1014 session_test_rules (vlib_main_t * vm, unformat_input_t * input)
1016 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
1017 u64 options[APP_OPTIONS_N_OPTIONS];
1018 u16 lcl_port = 1234, rmt_port = 4321;
1019 u32 server_index, server_index2;
1020 u32 dummy_server_api_index = ~0;
1021 transport_connection_t *tc;
1022 u32 dummy_port = 1111;
1023 u8 is_filtered = 0, *ns_id = format (0, "appns1");
1024 session_t *listener, *s;
1025 app_namespace_t *default_ns = app_namespace_get_default ();
1026 u32 local_ns_index = default_ns->local_table_index;
1028 app_namespace_t *app_ns;
1033 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1035 if (unformat (input, "verbose"))
1039 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1045 server_sep.is_ip4 = 1;
1046 server_sep.port = dummy_port;
1047 clib_memset (options, 0, sizeof (options));
1049 vnet_app_attach_args_t attach_args = {
1050 .api_client_index = ~0,
1053 .session_cb_vft = &dummy_session_cbs,
1054 .name = format (0, "session_test"),
1057 vnet_listen_args_t bind_args = {
1063 * Attach server with global and local default scope
1065 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1066 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1067 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1068 attach_args.namespace_id = 0;
1069 attach_args.api_client_index = dummy_server_api_index;
1070 error = vnet_application_attach (&attach_args);
1071 SESSION_TEST ((error == 0), "server attached");
1072 server_index = attach_args.app_index;
1074 bind_args.app_index = server_index;
1075 error = vnet_listen (&bind_args);
1076 SESSION_TEST ((error == 0), "server bound to %U/%d", format_ip46_address,
1077 &server_sep.ip, 1, server_sep.port);
1078 al = app_listener_get_w_handle (bind_args.handle);
1079 listener = app_listener_get_session (al);
1080 ip4_address_t lcl_ip = {
1081 .as_u32 = clib_host_to_net_u32 (0x01020304),
1083 ip4_address_t rmt_ip = {
1084 .as_u32 = clib_host_to_net_u32 (0x05060708),
1086 fib_prefix_t lcl_pref = {
1087 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
1089 .fp_proto = FIB_PROTOCOL_IP4,
1091 fib_prefix_t rmt_pref = {
1092 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1094 .fp_proto = FIB_PROTOCOL_IP4,
1097 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1098 &rmt_pref.fp_addr.ip4, lcl_port,
1099 rmt_port, TRANSPORT_PROTO_TCP, 0,
1101 SESSION_TEST ((tc == 0), "optimized lookup should not work (port)");
1104 * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
1106 session_rule_add_del_args_t args = {
1107 .table_args.lcl = lcl_pref,
1108 .table_args.rmt = rmt_pref,
1109 .table_args.lcl_port = lcl_port,
1110 .table_args.rmt_port = rmt_port,
1111 .table_args.action_index = server_index,
1112 .table_args.is_add = 1,
1115 error = vnet_session_rule_add_del (&args);
1116 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
1117 args.table_args.action_index);
1119 tc = session_lookup_connection4 (0, &lcl_pref.fp_addr.ip4,
1120 &rmt_pref.fp_addr.ip4, lcl_port, rmt_port,
1121 TRANSPORT_PROTO_TCP);
1122 SESSION_TEST ((tc->c_index == listener->connection_index),
1123 "optimized lookup should return the listener");
1124 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1125 &rmt_pref.fp_addr.ip4, lcl_port,
1126 rmt_port, TRANSPORT_PROTO_TCP, 0,
1128 SESSION_TEST ((tc->c_index == listener->connection_index),
1129 "lookup should return the listener");
1130 s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4,
1131 lcl_port, rmt_port, TRANSPORT_PROTO_TCP);
1132 SESSION_TEST ((s->connection_index == listener->connection_index),
1133 "safe lookup should return the listener");
1134 session_endpoint_t sep = {
1135 .ip = rmt_pref.fp_addr,
1138 .transport_proto = TRANSPORT_PROTO_TCP,
1140 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1141 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1142 "should not work (global scope)");
1144 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1145 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1146 rmt_port, TRANSPORT_PROTO_TCP, 0,
1148 SESSION_TEST ((tc == 0),
1149 "optimized lookup for wrong lcl port + 1 should not work");
1152 * Add 1.2.3.4/16 * 5.6.7.8/16 4321
1154 args.table_args.lcl_port = 0;
1155 args.scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1156 error = vnet_session_rule_add_del (&args);
1157 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 4321 action %d",
1158 args.table_args.action_index);
1159 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1160 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1161 rmt_port, TRANSPORT_PROTO_TCP, 0,
1163 SESSION_TEST ((tc->c_index == listener->connection_index),
1164 "optimized lookup for lcl port + 1 should work");
1165 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1166 SESSION_TEST ((handle == server_index), "local session endpoint lookup "
1167 "should work (lcl ip was zeroed)");
1170 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1172 args.table_args.lcl_port = 1234;
1173 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1174 args.table_args.lcl.fp_len = 30;
1175 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1176 args.table_args.rmt.fp_len = 30;
1177 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1178 error = vnet_session_rule_add_del (&args);
1179 SESSION_TEST ((error == 0), "Add 1.2.3.4/30 1234 5.6.7.8/30 4321 action %d",
1180 args.table_args.action_index);
1184 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1185 TRANSPORT_PROTO_TCP);
1186 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1187 TRANSPORT_PROTO_TCP);
1190 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1191 &rmt_pref.fp_addr.ip4, lcl_port,
1192 rmt_port, TRANSPORT_PROTO_TCP, 0,
1194 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1195 "should fail (deny rule)");
1196 SESSION_TEST ((is_filtered == SESSION_LOOKUP_RESULT_FILTERED),
1197 "lookup should be filtered (deny)");
1199 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1200 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1201 "5.6.7.8/16 4321 in local table should return deny");
1203 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1204 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1205 rmt_port, TRANSPORT_PROTO_TCP, 0,
1207 SESSION_TEST ((tc->c_index == listener->connection_index),
1208 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should work");
1211 * "Mask" deny rule with more specific allow:
1212 * Add allow rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -3 (allow)
1214 args.table_args.is_add = 1;
1215 args.table_args.lcl_port = 1234;
1216 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1217 args.table_args.lcl.fp_len = 32;
1218 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1219 args.table_args.rmt.fp_len = 32;
1220 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1221 error = vnet_session_rule_add_del (&args);
1222 SESSION_TEST ((error == 0), "Add masking rule 1.2.3.4/30 1234 5.6.7.8/32 "
1223 "4321 action %d", args.table_args.action_index);
1226 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1227 &rmt_pref.fp_addr.ip4, lcl_port,
1228 rmt_port, TRANSPORT_PROTO_TCP, 0,
1230 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1231 "should fail (allow without app)");
1232 SESSION_TEST ((is_filtered == 0), "lookup should NOT be filtered");
1234 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1235 SESSION_TEST ((handle == SESSION_INVALID_HANDLE), "lookup for 1.2.3.4/32 "
1236 "1234 5.6.7.8/32 4321 in local table should return invalid");
1240 vlib_cli_output (vm, "Local rules");
1241 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1242 TRANSPORT_PROTO_TCP);
1245 sep.ip.ip4.as_u32 += 1 << 24;
1246 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1247 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234"
1248 " 5.6.7.9/32 4321 in local table should return deny");
1250 vnet_connect_args_t connect_args = {
1251 .app_index = attach_args.app_index,
1254 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1256 /* Try connecting */
1257 error = vnet_connect (&connect_args);
1258 SESSION_TEST ((error != 0), "connect should fail");
1259 SESSION_TEST ((error == VNET_API_ERROR_APP_CONNECT_FILTERED),
1260 "connect should be filtered");
1262 sep.ip.ip4.as_u32 -= 1 << 24;
1265 * Delete masking rule: 1.2.3.4/32 1234 5.6.7.8/32 4321 allow
1267 args.table_args.is_add = 0;
1268 args.table_args.lcl_port = 1234;
1269 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1270 args.table_args.lcl.fp_len = 32;
1271 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1272 args.table_args.rmt.fp_len = 32;
1273 error = vnet_session_rule_add_del (&args);
1274 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 allow");
1278 * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
1280 args.table_args.is_add = 1;
1281 args.table_args.lcl_port = 0;
1282 args.table_args.lcl.fp_len = 0;
1283 args.table_args.rmt.fp_len = 16;
1284 args.table_args.action_index = -1;
1285 error = vnet_session_rule_add_del (&args);
1286 SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d",
1287 args.table_args.action_index);
1291 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1292 TRANSPORT_PROTO_TCP);
1293 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1294 TRANSPORT_PROTO_TCP);
1297 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1298 SESSION_TEST ((handle == SESSION_DROP_HANDLE),
1299 "local session endpoint lookup should return deny");
1302 * Delete 1.2.3.4/32 1234 5.6.7.8/32 4321 deny
1304 args.table_args.is_add = 0;
1305 args.table_args.lcl_port = 1234;
1306 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1307 args.table_args.lcl.fp_len = 30;
1308 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1309 args.table_args.rmt.fp_len = 30;
1310 error = vnet_session_rule_add_del (&args);
1311 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1313 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1314 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1315 "local session endpoint lookup should return invalid");
1318 * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and
1319 * 1.2.3.4/16 1234 5.6.7.8/16 4321
1321 args.table_args.is_add = 0;
1322 args.table_args.lcl_port = 0;
1323 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1324 args.table_args.lcl.fp_len = 0;
1325 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1326 args.table_args.rmt.fp_len = 16;
1327 args.table_args.rmt_port = 4321;
1328 error = vnet_session_rule_add_del (&args);
1329 SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
1330 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1331 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1332 "should not work (removed)");
1334 args.table_args.is_add = 0;
1335 args.table_args.lcl = lcl_pref;
1337 args.table_args.is_add = 0;
1338 args.table_args.lcl_port = 0;
1339 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1340 args.table_args.lcl.fp_len = 16;
1341 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1342 args.table_args.rmt.fp_len = 16;
1343 args.table_args.rmt_port = 4321;
1344 error = vnet_session_rule_add_del (&args);
1345 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321");
1346 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1347 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1348 rmt_port, TRANSPORT_PROTO_TCP, 0,
1350 SESSION_TEST ((tc == 0),
1351 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should not "
1354 args.table_args.is_add = 0;
1355 args.table_args.lcl_port = 1234;
1356 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1357 args.table_args.lcl.fp_len = 16;
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 1.2.3.4/16 1234 5.6.7.8/16 4321");
1363 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1364 &rmt_pref.fp_addr.ip4, lcl_port,
1365 rmt_port, TRANSPORT_PROTO_TCP, 0,
1367 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should "
1368 "not work (del + deny)");
1370 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1371 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1372 &rmt_pref.fp_addr.ip4, lcl_port,
1373 rmt_port, TRANSPORT_PROTO_TCP, 0,
1375 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should"
1376 " not work (no-rule)");
1379 * Test tags. Add/overwrite/del rule with tag
1381 args.table_args.is_add = 1;
1382 args.table_args.lcl_port = 1234;
1383 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1384 args.table_args.lcl.fp_len = 16;
1385 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1386 args.table_args.rmt.fp_len = 16;
1387 args.table_args.rmt_port = 4321;
1388 args.table_args.tag = format (0, "test_rule");
1389 args.table_args.action_index = server_index;
1390 error = vnet_session_rule_add_del (&args);
1391 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 deny "
1395 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1396 TRANSPORT_PROTO_TCP);
1397 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1398 TRANSPORT_PROTO_TCP);
1400 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1401 &rmt_pref.fp_addr.ip4, lcl_port,
1402 rmt_port, TRANSPORT_PROTO_TCP, 0,
1404 SESSION_TEST ((tc->c_index == listener->connection_index),
1405 "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should work");
1407 vec_free (args.table_args.tag);
1408 args.table_args.lcl_port = 1234;
1409 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1410 args.table_args.lcl.fp_len = 16;
1411 args.table_args.tag = format (0, "test_rule_overwrite");
1412 error = vnet_session_rule_add_del (&args);
1413 SESSION_TEST ((error == 0),
1414 "Overwrite 1.2.3.4/16 1234 5.6.7.8/16 4321 deny tag test_rule"
1418 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1419 TRANSPORT_PROTO_TCP);
1420 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1421 TRANSPORT_PROTO_TCP);
1424 args.table_args.is_add = 0;
1425 args.table_args.lcl_port += 1;
1426 error = vnet_session_rule_add_del (&args);
1427 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny "
1428 "tag %v", args.table_args.tag);
1431 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1432 TRANSPORT_PROTO_TCP);
1433 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1434 TRANSPORT_PROTO_TCP);
1436 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1437 &rmt_pref.fp_addr.ip4, lcl_port,
1438 rmt_port, TRANSPORT_PROTO_TCP, 0,
1440 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/32 4321 should not"
1445 * Test local rules with multiple namespaces
1449 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1451 args.table_args.is_add = 1;
1452 args.table_args.lcl_port = 1234;
1453 args.table_args.rmt_port = 0;
1454 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1455 args.table_args.lcl.fp_len = 32;
1456 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1457 args.table_args.rmt.fp_len = 32;
1458 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1459 args.table_args.tag = 0;
1460 args.scope = SESSION_RULE_SCOPE_LOCAL;
1461 error = vnet_session_rule_add_del (&args);
1462 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d",
1463 args.table_args.action_index);
1465 * Add 'white' rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1467 args.table_args.is_add = 1;
1468 args.table_args.lcl_port = 1234;
1469 args.table_args.rmt_port = 4321;
1470 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1471 args.table_args.lcl.fp_len = 32;
1472 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1473 args.table_args.rmt.fp_len = 32;
1474 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1475 error = vnet_session_rule_add_del (&args);
1479 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1480 TRANSPORT_PROTO_TCP);
1483 vnet_app_namespace_add_del_args_t ns_args = {
1486 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
1489 error = vnet_app_namespace_add_del (&ns_args);
1490 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
1491 app_ns = app_namespace_get_from_id (ns_id);
1493 attach_args.namespace_id = ns_id;
1494 attach_args.api_client_index = dummy_server_api_index;
1495 error = vnet_application_attach (&attach_args);
1496 SESSION_TEST ((error == 0), "server2 attached");
1497 server_index2 = attach_args.app_index;
1500 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1502 args.table_args.lcl_port = 1234;
1503 args.table_args.rmt_port = 0;
1504 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1505 args.table_args.lcl.fp_len = 32;
1506 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1507 args.table_args.rmt.fp_len = 32;
1508 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1509 args.appns_index = app_namespace_index (app_ns);
1511 error = vnet_session_rule_add_del (&args);
1512 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d "
1513 "in test namespace", args.table_args.action_index);
1515 * Lookup default namespace
1517 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1518 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1519 "lookup for 1.2.3.4/32 1234 5.6.7.8/32 4321 in local table "
1520 "should return allow (invalid)");
1523 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1524 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1525 "5.6.7.8/16 432*2* in local table should return deny");
1528 connect_args.app_index = server_index;
1529 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1531 error = vnet_connect (&connect_args);
1532 SESSION_TEST ((error != 0), "connect should fail");
1533 SESSION_TEST ((error == VNET_API_ERROR_APP_CONNECT_FILTERED),
1534 "connect should be filtered");
1537 * Lookup test namespace
1539 handle = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1540 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1541 "5.6.7.8/16 4321 in local table should return deny");
1543 connect_args.app_index = server_index;
1544 error = vnet_connect (&connect_args);
1545 SESSION_TEST ((error != 0), "connect should fail");
1546 SESSION_TEST ((error == VNET_API_ERROR_APP_CONNECT_FILTERED),
1547 "connect should be filtered");
1549 args.table_args.is_add = 0;
1550 vnet_session_rule_add_del (&args);
1552 args.appns_index = 0;
1553 args.table_args.is_add = 0;
1554 vnet_session_rule_add_del (&args);
1556 args.table_args.rmt_port = 4321;
1557 vnet_session_rule_add_del (&args);
1561 vec_free (args.table_args.tag);
1562 vnet_app_detach_args_t detach_args = {
1563 .app_index = server_index,
1564 .api_client_index = ~0,
1566 vnet_application_detach (&detach_args);
1568 detach_args.app_index = server_index2;
1569 vnet_application_detach (&detach_args);
1572 vec_free (attach_args.name);
1577 session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
1579 u64 options[APP_OPTIONS_N_OPTIONS];
1580 char *show_listeners = "sh session listeners tcp verbose";
1581 char *show_local_listeners = "sh app ns table default";
1582 unformat_input_t tmp_input;
1583 u32 server_index, app_index;
1584 u32 dummy_server_api_index = ~0, sw_if_index = 0;
1587 transport_connection_t *tc;
1588 u16 lcl_port = 1234, rmt_port = 4321;
1589 app_namespace_t *app_ns;
1590 int verbose = 0, error = 0;
1592 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1594 if (unformat (input, "verbose"))
1598 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1604 ip4_address_t lcl_ip = {
1605 .as_u32 = clib_host_to_net_u32 (0x01020304),
1607 ip4_address_t rmt_ip = {
1608 .as_u32 = clib_host_to_net_u32 (0x05060708),
1610 fib_prefix_t rmt_pref = {
1611 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1613 .fp_proto = FIB_PROTOCOL_IP4,
1615 session_endpoint_t sep = {
1616 .ip = rmt_pref.fp_addr,
1619 .transport_proto = TRANSPORT_PROTO_TCP,
1623 * Create loopback interface
1625 session_create_lookpback (0, &sw_if_index, &lcl_ip);
1627 app_ns = app_namespace_get_default ();
1628 app_ns->sw_if_index = sw_if_index;
1630 clib_memset (options, 0, sizeof (options));
1631 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1632 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
1633 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_PROXY;
1634 options[APP_OPTIONS_PROXY_TRANSPORT] = 1 << TRANSPORT_PROTO_TCP;
1635 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1636 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1637 vnet_app_attach_args_t attach_args = {
1638 .api_client_index = ~0,
1641 .session_cb_vft = &dummy_session_cbs,
1642 .name = format (0, "session_test"),
1645 attach_args.api_client_index = dummy_server_api_index;
1646 error = vnet_application_attach (&attach_args);
1647 SESSION_TEST ((error == 0), "server attachment should work");
1648 server_index = attach_args.app_index;
1652 unformat_init_string (&tmp_input, show_listeners,
1653 strlen (show_listeners));
1654 vlib_cli_input (vm, &tmp_input, 0, 0);
1655 unformat_init_string (&tmp_input, show_local_listeners,
1656 strlen (show_local_listeners));
1657 vlib_cli_input (vm, &tmp_input, 0, 0);
1660 tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port,
1661 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1662 SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be "
1664 s = listen_session_get (tc->s_index);
1665 SESSION_TEST ((s->app_index == server_index), "lookup should return"
1668 tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port,
1669 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1670 SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should"
1673 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1674 SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1677 vnet_app_detach_args_t detach_args = {
1678 .app_index = server_index,
1679 .api_client_index = ~0,
1681 vnet_application_detach (&detach_args);
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 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1694 SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX),
1695 "local session endpoint lookup should not work after detach");
1697 unformat_free (&tmp_input);
1698 vec_free (attach_args.name);
1699 session_delete_loopback (sw_if_index);
1704 wait_for_event (svm_msg_q_t * mq, int fd, int epfd, u8 use_eventfd)
1708 svm_msg_q_lock (mq);
1709 while (svm_msg_q_is_empty (mq))
1710 svm_msg_q_wait (mq);
1714 int __clib_unused n_read, rv;
1715 struct epoll_event ep_evt;
1720 rv = epoll_wait (epfd, &ep_evt, 1, -1);
1723 ST_DBG ("epoll error");
1726 else if (rv > 0 && (ep_evt.events & EPOLLIN))
1728 n_read = read (fd, &buf, sizeof (buf));
1733 if (!svm_msg_q_is_empty (mq))
1735 svm_msg_q_lock (mq);
1743 session_test_mq_speed (vlib_main_t * vm, unformat_input_t * input)
1745 int error, __clib_unused verbose, use_eventfd = 0;
1746 u64 i, n_test_msgs = 1 << 10, *counter;
1747 u64 options[APP_OPTIONS_N_OPTIONS];
1748 int epfd = -1, rv, prod_fd = -1;
1749 svm_fifo_t *rx_fifo, *tx_fifo;
1750 vl_api_registration_t *reg;
1751 struct epoll_event ep_evt;
1752 u32 app_index, api_index;
1753 app_worker_t *app_wrk;
1754 segment_manager_t *sm;
1755 svm_msg_q_msg_t msg;
1763 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1765 if (unformat (input, "verbose"))
1767 else if (unformat (input, "%d", &n_test_msgs))
1769 else if (unformat (input, "use-eventfd"))
1773 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1779 q = clib_mem_alloc (sizeof (*q));
1780 api_index = vl_api_memclnt_create_internal ("session_mq_test_api", q);
1782 clib_memset (options, 0, sizeof (options));
1783 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1784 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1785 options[APP_OPTIONS_EVT_QUEUE_SIZE] = 2048;
1787 reg = vl_api_client_index_to_registration (api_index);
1788 /* Shut up coverity */
1791 if (!session_main.evt_qs_use_memfd_seg)
1792 reg->clib_file_index = VL_API_INVALID_FI;
1794 vnet_app_attach_args_t attach_args = {
1795 .api_client_index = api_index,
1798 .session_cb_vft = &dummy_session_cbs,
1799 .name = format (0, "session_mq_test"),
1801 error = vnet_application_attach (&attach_args);
1802 SESSION_TEST ((error == 0), "server attachment should work");
1804 app_index = attach_args.app_index;
1806 app = application_get (app_index);
1807 app_wrk = application_get_worker (app, 0);
1808 mq = app_wrk->event_queue;
1811 svm_msg_q_alloc_producer_eventfd (mq);
1812 svm_msg_q_alloc_consumer_eventfd (mq);
1813 prod_fd = svm_msg_q_get_producer_eventfd (mq);
1814 SESSION_TEST (prod_fd != -1, "mq producer eventd valid %u", prod_fd);
1817 sm = app_worker_get_or_alloc_connect_segment_manager (app_wrk);
1818 segment_manager_alloc_session_fifos (sm, &rx_fifo, &tx_fifo);
1819 s.rx_fifo = rx_fifo;
1820 s.tx_fifo = tx_fifo;
1821 s.session_state = SESSION_STATE_READY;
1822 counter = (u64 *) rx_fifo->head_chunk->data;
1823 start = vlib_time_now (vm);
1827 SESSION_TEST (0, "fork failed");
1833 epfd = epoll_create1 (0);
1834 SESSION_TEST (epfd != -1, "epfd created");
1835 ep_evt.events = EPOLLIN;
1836 ep_evt.data.u64 = prod_fd;
1837 rv = epoll_ctl (epfd, EPOLL_CTL_ADD, prod_fd, &ep_evt);
1838 SESSION_TEST (rv == 0, "epoll returned %d", rv);
1841 for (i = 0; i < n_test_msgs; i++)
1843 wait_for_event (mq, prod_fd, epfd, use_eventfd);
1844 svm_msg_q_sub_w_lock (mq, &msg);
1845 svm_msg_q_free_msg (mq, &msg);
1846 svm_msg_q_unlock (mq);
1847 *counter = *counter + 1;
1848 svm_fifo_unset_event (rx_fifo);
1854 ST_DBG ("client pid %u", pid);
1855 for (i = 0; i < n_test_msgs; i++)
1857 while (svm_fifo_has_event (rx_fifo))
1859 app_worker_lock_and_send_event (app_wrk, &s, SESSION_IO_EVT_RX);
1863 diff = vlib_time_now (vm) - start;
1864 ST_DBG ("done %u events in %.2f sec: %f evts/s", *counter,
1865 diff, *counter / diff);
1867 vnet_app_detach_args_t detach_args = {
1868 .app_index = app_index,
1869 .api_client_index = ~0,
1871 vnet_application_detach (&detach_args);
1876 session_test_mq_basic (vlib_main_t * vm, unformat_input_t * input)
1878 svm_msg_q_cfg_t _cfg, *cfg = &_cfg;
1879 svm_msg_q_msg_t msg1, msg2, msg[12];
1880 int __clib_unused verbose, i, rv;
1882 svm_msg_q_ring_t *ring;
1885 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1887 if (unformat (input, "verbose"))
1891 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1897 svm_msg_q_ring_cfg_t rc[2] = { {8, 8, 0}
1900 cfg->consumer_pid = ~0;
1903 cfg->ring_cfgs = rc;
1905 mq = svm_msg_q_alloc (cfg);
1906 SESSION_TEST (mq != 0, "svm_msg_q_alloc");
1907 SESSION_TEST (vec_len (mq->rings) == 2, "ring allocation");
1908 rings_ptr = (u8 *) mq->rings + vec_bytes (mq->rings);
1909 vec_foreach (ring, mq->rings)
1911 SESSION_TEST (ring->data == rings_ptr, "ring data");
1912 rings_ptr += (uword) ring->nitems * ring->elsize;
1915 msg1 = svm_msg_q_alloc_msg (mq, 8);
1916 rv = (mq->rings[0].cursize != 1
1917 || msg1.ring_index != 0 || msg1.elt_index != 0);
1918 SESSION_TEST (rv == 0, "msg alloc1");
1920 msg2 = svm_msg_q_alloc_msg (mq, 15);
1921 rv = (mq->rings[1].cursize != 1
1922 || msg2.ring_index != 1 || msg2.elt_index != 0);
1923 SESSION_TEST (rv == 0, "msg alloc2");
1925 svm_msg_q_free_msg (mq, &msg1);
1926 SESSION_TEST (mq->rings[0].cursize == 0, "free msg");
1928 for (i = 0; i < 12; i++)
1930 msg[i] = svm_msg_q_alloc_msg (mq, 7);
1931 *(u32 *) svm_msg_q_msg_data (mq, &msg[i]) = i;
1934 rv = (mq->rings[0].cursize != 8 || mq->rings[1].cursize != 5);
1935 SESSION_TEST (rv == 0, "msg alloc3");
1937 *(u32 *) svm_msg_q_msg_data (mq, &msg2) = 123;
1938 svm_msg_q_add (mq, &msg2, SVM_Q_NOWAIT);
1939 for (i = 0; i < 12; i++)
1940 svm_msg_q_add (mq, &msg[i], SVM_Q_NOWAIT);
1942 rv = svm_msg_q_sub (mq, &msg2, SVM_Q_NOWAIT, 0);
1943 SESSION_TEST (rv == 0, "dequeue1");
1945 SESSION_TEST (msg2.ring_index == 1 && msg2.elt_index == 0,
1947 rv = (*(u32 *) svm_msg_q_msg_data (mq, &msg2) == 123);
1948 SESSION_TEST (rv, "dequeue 1 data");
1950 svm_msg_q_free_msg (mq, &msg2);
1952 for (i = 0; i < 12; i++)
1954 if (svm_msg_q_sub (mq, &msg[i], SVM_Q_NOWAIT, 0))
1955 SESSION_TEST (0, "dequeue2");
1958 if (msg[i].ring_index != 0 || msg[i].elt_index != (i + 1) % 8)
1959 SESSION_TEST (0, "dequeue2 result2");
1963 if (msg[i].ring_index != 1 || msg[i].elt_index != (i - 8) + 1)
1964 SESSION_TEST (0, "dequeue2 result3");
1966 if (*(u32 *) svm_msg_q_msg_data (mq, &msg[i]) != i)
1967 SESSION_TEST (0, "dequeue2 wrong data");
1968 svm_msg_q_free_msg (mq, &msg[i]);
1970 rv = (mq->rings[0].cursize == 0 && mq->rings[1].cursize == 0);
1971 SESSION_TEST (rv, "post dequeue");
1976 static clib_error_t *
1977 session_test (vlib_main_t * vm,
1978 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1982 vnet_session_enable_disable (vm, 1);
1984 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1986 if (unformat (input, "basic"))
1987 res = session_test_basic (vm, input);
1988 else if (unformat (input, "namespace"))
1989 res = session_test_namespace (vm, input);
1990 else if (unformat (input, "rules-table"))
1991 res = session_test_rule_table (vm, input);
1992 else if (unformat (input, "rules"))
1993 res = session_test_rules (vm, input);
1994 else if (unformat (input, "proxy"))
1995 res = session_test_proxy (vm, input);
1996 else if (unformat (input, "endpt-cfg"))
1997 res = session_test_endpoint_cfg (vm, input);
1998 else if (unformat (input, "mq-speed"))
1999 res = session_test_mq_speed (vm, input);
2000 else if (unformat (input, "mq-basic"))
2001 res = session_test_mq_basic (vm, input);
2002 else if (unformat (input, "all"))
2004 if ((res = session_test_basic (vm, input)))
2006 if ((res = session_test_namespace (vm, input)))
2008 if ((res = session_test_rule_table (vm, input)))
2010 if ((res = session_test_rules (vm, input)))
2012 if ((res = session_test_proxy (vm, input)))
2014 if ((res = session_test_endpoint_cfg (vm, input)))
2016 if ((res = session_test_mq_speed (vm, input)))
2018 if ((res = session_test_mq_basic (vm, input)))
2027 return clib_error_return (0, "Session unit test failed");
2032 VLIB_CLI_COMMAND (tcp_test_command, static) =
2034 .path = "test session",
2035 .short_help = "internal session unit tests",
2036 .function = session_test,
2041 * fd.io coding-style-patch-verification: ON
2044 * eval: (c-set-style "gnu")