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>
23 #define SESSION_TEST_I(_cond, _comment, _args...) \
25 int _evald = (_cond); \
27 fformat(stderr, "FAIL:%d: " _comment "\n", \
30 fformat(stderr, "PASS:%d: " _comment "\n", \
36 #define SESSION_TEST(_cond, _comment, _args...) \
38 if (!SESSION_TEST_I(_cond, _comment, ##_args)) { \
44 dummy_session_reset_callback (session_t * s)
46 clib_warning ("called...");
49 volatile u32 connected_session_index = ~0;
50 volatile u32 connected_session_thread = ~0;
52 dummy_session_connected_callback (u32 app_index, u32 api_context,
53 session_t * s, u8 is_fail)
57 connected_session_index = s->session_index;
58 connected_session_thread = s->thread_index;
63 static u32 dummy_segment_count;
66 dummy_add_segment_callback (u32 client_index, u64 segment_handle)
68 dummy_segment_count = 1;
73 dummy_del_segment_callback (u32 client_index, u64 segment_handle)
75 dummy_segment_count = 0;
80 dummy_session_disconnect_callback (session_t * s)
82 clib_warning ("called...");
85 static u32 dummy_accept;
86 volatile u32 accepted_session_index;
87 volatile u32 accepted_session_thread;
90 dummy_session_accept_callback (session_t * s)
93 accepted_session_index = s->session_index;
94 accepted_session_thread = s->thread_index;
95 s->session_state = SESSION_STATE_READY;
100 dummy_server_rx_callback (session_t * s)
102 clib_warning ("called...");
107 static session_cb_vft_t dummy_session_cbs = {
108 .session_reset_callback = dummy_session_reset_callback,
109 .session_connected_callback = dummy_session_connected_callback,
110 .session_accept_callback = dummy_session_accept_callback,
111 .session_disconnect_callback = dummy_session_disconnect_callback,
112 .builtin_app_rx_callback = dummy_server_rx_callback,
113 .add_segment_callback = dummy_add_segment_callback,
114 .del_segment_callback = dummy_del_segment_callback,
119 session_create_lookpback (u32 table_id, u32 * sw_if_index,
120 ip4_address_t * intf_addr)
124 clib_memset (intf_mac, 0, sizeof (intf_mac));
126 if (vnet_create_loopback_interface (sw_if_index, intf_mac, 0, 0))
128 clib_warning ("couldn't create loopback. stopping the test!");
134 ip_table_create (FIB_PROTOCOL_IP4, table_id, 0, 0);
135 ip_table_bind (FIB_PROTOCOL_IP4, *sw_if_index, table_id, 0);
138 vnet_sw_interface_set_flags (vnet_get_main (), *sw_if_index,
139 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
141 if (ip4_add_del_interface_address (vlib_get_main (), *sw_if_index,
144 clib_warning ("couldn't assign loopback ip %U", format_ip4_address,
153 session_delete_loopback (u32 sw_if_index)
155 /* fails spectacularly */
156 /* vnet_delete_loopback_interface (sw_if_index); */
160 session_test_basic (vlib_main_t * vm, unformat_input_t * input)
162 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
163 u64 options[APP_OPTIONS_N_OPTIONS], bind4_handle, bind6_handle;
167 clib_memset (options, 0, sizeof (options));
168 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
169 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
170 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
171 vnet_app_attach_args_t attach_args = {
172 .api_client_index = ~0,
175 .session_cb_vft = &dummy_session_cbs,
176 .name = format (0, "session_test"),
179 error = vnet_application_attach (&attach_args);
180 SESSION_TEST ((error == 0), "app attached");
181 server_index = attach_args.app_index;
182 vec_free (attach_args.name);
184 server_sep.is_ip4 = 1;
185 vnet_listen_args_t bind_args = {
190 bind_args.app_index = server_index;
191 error = vnet_listen (&bind_args);
192 SESSION_TEST ((error == 0), "server bind4 should work");
193 bind4_handle = bind_args.handle;
195 error = vnet_listen (&bind_args);
196 SESSION_TEST ((error != 0), "double server bind4 should not work");
198 bind_args.sep.is_ip4 = 0;
199 error = vnet_listen (&bind_args);
200 SESSION_TEST ((error == 0), "server bind6 should work");
201 bind6_handle = bind_args.handle;
203 error = vnet_listen (&bind_args);
204 SESSION_TEST ((error != 0), "double server bind6 should not work");
206 vnet_unlisten_args_t unbind_args = {
207 .handle = bind4_handle,
208 .app_index = server_index,
210 error = vnet_unlisten (&unbind_args);
211 SESSION_TEST ((error == 0), "unbind4 should work");
213 unbind_args.handle = bind6_handle;
214 error = vnet_unlisten (&unbind_args);
215 SESSION_TEST ((error == 0), "unbind6 should work");
217 vnet_app_detach_args_t detach_args = {
218 .app_index = server_index,
219 .api_client_index = ~0,
221 vnet_application_detach (&detach_args);
226 session_add_del_route_via_lookup_in_table (u32 in_table_id, u32 via_table_id,
227 ip4_address_t * ip, u8 mask,
230 fib_route_path_t *rpaths = 0, *rpath;
231 u32 in_fib_index, via_fib_index;
233 fib_prefix_t prefix = {
234 .fp_addr.ip4.as_u32 = ip->as_u32,
236 .fp_proto = FIB_PROTOCOL_IP4,
239 via_fib_index = fib_table_find (FIB_PROTOCOL_IP4, via_table_id);
240 if (via_fib_index == ~0)
242 clib_warning ("couldn't resolve via table id to index");
245 in_fib_index = fib_table_find (FIB_PROTOCOL_IP4, in_table_id);
246 if (in_fib_index == ~0)
248 clib_warning ("couldn't resolve in table id to index");
252 vec_add2 (rpaths, rpath, 1);
253 clib_memset (rpath, 0, sizeof (*rpath));
254 rpath->frp_weight = 1;
255 rpath->frp_fib_index = via_fib_index;
256 rpath->frp_proto = DPO_PROTO_IP4;
257 rpath->frp_sw_if_index = ~0;
258 rpath->frp_flags |= FIB_ROUTE_PATH_DEAG;
261 fib_table_entry_path_add2 (in_fib_index, &prefix, FIB_SOURCE_CLI,
262 FIB_ENTRY_FLAG_NONE, rpath);
264 fib_table_entry_path_remove2 (in_fib_index, &prefix, FIB_SOURCE_CLI,
270 session_test_endpoint_cfg (vlib_main_t * vm, unformat_input_t * input)
272 session_endpoint_cfg_t client_sep = SESSION_ENDPOINT_CFG_NULL;
273 u32 server_index, client_index, sw_if_index[2], tries = 0;
274 u64 options[APP_OPTIONS_N_OPTIONS], dummy_secret = 1234;
275 u16 dummy_server_port = 1234, dummy_client_port = 5678;
276 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
277 ip4_address_t intf_addr[3];
278 transport_connection_t *tc;
284 * Create the loopbacks
286 intf_addr[0].as_u32 = clib_host_to_net_u32 (0x01010101),
287 session_create_lookpback (0, &sw_if_index[0], &intf_addr[0]);
289 intf_addr[1].as_u32 = clib_host_to_net_u32 (0x02020202),
290 session_create_lookpback (1, &sw_if_index[1], &intf_addr[1]);
292 session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
294 session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
300 appns_id = format (0, "appns1");
301 vnet_app_namespace_add_del_args_t ns_args = {
303 .secret = dummy_secret,
304 .sw_if_index = sw_if_index[1],
308 error = vnet_app_namespace_add_del (&ns_args);
309 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
312 * Attach client/server
314 clib_memset (options, 0, sizeof (options));
315 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
316 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
318 vnet_app_attach_args_t attach_args = {
319 .api_client_index = ~0,
322 .session_cb_vft = &dummy_session_cbs,
323 .name = format (0, "session_test_client"),
326 error = vnet_application_attach (&attach_args);
327 SESSION_TEST ((error == 0), "client app attached");
328 client_index = attach_args.app_index;
329 vec_free (attach_args.name);
331 attach_args.name = format (0, "session_test_server");
332 attach_args.namespace_id = appns_id;
333 attach_args.options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret;
334 error = vnet_application_attach (&attach_args);
335 SESSION_TEST ((error == 0), "server app attached: %U", format_clib_error,
337 vec_free (attach_args.name);
338 server_index = attach_args.app_index;
340 server_sep.is_ip4 = 1;
341 server_sep.port = dummy_server_port;
342 vnet_listen_args_t bind_args = {
344 .app_index = server_index,
346 error = vnet_listen (&bind_args);
347 SESSION_TEST ((error == 0), "server bind should work");
350 * Connect and force lcl ip
352 client_sep.is_ip4 = 1;
353 client_sep.ip.ip4.as_u32 = clib_host_to_net_u32 (0x02020202);
354 client_sep.port = dummy_server_port;
355 client_sep.peer.is_ip4 = 1;
356 client_sep.peer.ip.ip4.as_u32 = clib_host_to_net_u32 (0x01010101);
357 client_sep.peer.port = dummy_client_port;
358 client_sep.transport_proto = TRANSPORT_PROTO_TCP;
360 vnet_connect_args_t connect_args = {
361 .sep_ext = client_sep,
362 .app_index = client_index,
365 connected_session_index = connected_session_thread = ~0;
366 accepted_session_index = accepted_session_thread = ~0;
367 error = vnet_connect (&connect_args);
368 SESSION_TEST ((error == 0), "connect should work");
370 /* wait for stuff to happen */
371 while ((connected_session_index == ~0
372 || vec_len (tcp_main.wrk_ctx[0].pending_acks)) && ++tries < 100)
373 vlib_process_suspend (vm, 100e-3);
374 clib_warning ("waited %.1f seconds for connections", tries / 10.0);
375 SESSION_TEST ((connected_session_index != ~0), "session should exist");
376 SESSION_TEST ((connected_session_thread != ~0), "thread should exist");
377 SESSION_TEST ((accepted_session_index != ~0), "session should exist");
378 SESSION_TEST ((accepted_session_thread != ~0), "thread should exist");
379 s = session_get (connected_session_index, connected_session_thread);
380 tc = session_get_transport (s);
381 SESSION_TEST ((tc != 0), "transport should exist");
382 SESSION_TEST ((memcmp (&tc->lcl_ip, &client_sep.peer.ip,
383 sizeof (tc->lcl_ip)) == 0), "ips should be equal");
384 SESSION_TEST ((tc->lcl_port == dummy_client_port), "ports should be equal");
386 /* These sessions, because of the way they're established are pinned to
387 * main thread, even when we have workers and we avoid polling main thread,
388 * i.e., we can't cleanup pending disconnects, so force cleanup for both
390 session_transport_cleanup (s);
391 s = session_get (accepted_session_index, accepted_session_thread);
392 session_transport_cleanup (s);
394 vnet_app_detach_args_t detach_args = {
395 .app_index = server_index,
396 .api_client_index = ~0,
398 vnet_application_detach (&detach_args);
399 detach_args.app_index = client_index;
400 vnet_application_detach (&detach_args);
402 /* Allow the disconnects to finish before removing the routes. */
403 vlib_process_suspend (vm, 10e-3);
405 session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
407 session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
410 session_delete_loopback (sw_if_index[0]);
411 session_delete_loopback (sw_if_index[1]);
416 session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
418 u64 options[APP_OPTIONS_N_OPTIONS], dummy_secret = 1234;
419 u32 server_index, server_st_index, server_local_st_index;
420 u32 dummy_port = 1234, client_index, server_wrk_index;
421 u32 dummy_api_context = 4321, dummy_client_api_index = ~0;
422 u32 dummy_server_api_index = ~0, sw_if_index = 0;
423 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
424 session_endpoint_t client_sep = SESSION_ENDPOINT_NULL;
425 session_endpoint_t intf_sep = SESSION_ENDPOINT_NULL;
426 u8 *ns_id = format (0, "appns1");
427 app_namespace_t *app_ns;
428 application_t *server;
433 server_sep.is_ip4 = 1;
434 server_sep.port = dummy_port;
435 client_sep.is_ip4 = 1;
436 client_sep.port = dummy_port;
437 clib_memset (options, 0, sizeof (options));
439 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
440 vnet_app_attach_args_t attach_args = {
441 .api_client_index = ~0,
444 .session_cb_vft = &dummy_session_cbs,
445 .name = format (0, "session_test"),
448 vnet_listen_args_t bind_args = {
453 vnet_connect_args_t connect_args = {
457 clib_memcpy (&connect_args.sep, &client_sep, sizeof (client_sep));
459 vnet_unlisten_args_t unbind_args = {
460 .handle = bind_args.handle,
464 vnet_app_detach_args_t detach_args = {
466 .api_client_index = ~0,
469 ip4_address_t intf_addr = {
470 .as_u32 = clib_host_to_net_u32 (0x07000105),
473 intf_sep.ip.ip4 = intf_addr;
475 intf_sep.port = dummy_port;
478 * Insert namespace and lookup
481 vnet_app_namespace_add_del_args_t ns_args = {
483 .secret = dummy_secret,
484 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
487 error = vnet_app_namespace_add_del (&ns_args);
488 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
490 app_ns = app_namespace_get_from_id (ns_id);
491 SESSION_TEST ((app_ns != 0), "should find ns %v status", ns_id);
492 SESSION_TEST ((app_ns->ns_secret == dummy_secret), "secret should be %d",
494 SESSION_TEST ((app_ns->sw_if_index == APP_NAMESPACE_INVALID_INDEX),
495 "sw_if_index should be invalid");
498 * Try application attach with wrong secret
501 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
502 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
503 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret - 1;
504 attach_args.namespace_id = ns_id;
505 attach_args.api_client_index = dummy_server_api_index;
507 error = vnet_application_attach (&attach_args);
508 SESSION_TEST ((error != 0), "app attachment should fail");
509 SESSION_TEST ((error == VNET_API_ERROR_APP_WRONG_NS_SECRET),
510 "code should be wrong ns secret: %d", error);
513 * Attach server with global default scope
515 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
516 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
517 options[APP_OPTIONS_NAMESPACE_SECRET] = 0;
518 attach_args.namespace_id = 0;
519 attach_args.api_client_index = dummy_server_api_index;
520 error = vnet_application_attach (&attach_args);
521 SESSION_TEST ((error == 0), "server attachment should work");
522 server_index = attach_args.app_index;
523 server = application_get (server_index);
524 server_wrk_index = application_get_default_worker (server)->wrk_index;
525 SESSION_TEST ((server->ns_index == 0),
526 "server should be in the default ns");
528 bind_args.app_index = server_index;
529 error = vnet_listen (&bind_args);
530 SESSION_TEST ((error == 0), "server bind should work");
532 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
533 s = session_lookup_listener (server_st_index, &server_sep);
534 SESSION_TEST ((s != 0), "listener should exist in global table");
535 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
536 " that of the server");
537 server_local_st_index = application_local_session_table (server);
538 SESSION_TEST ((server_local_st_index == APP_INVALID_INDEX),
539 "server shouldn't have access to local table");
541 unbind_args.app_index = server_index;
542 unbind_args.handle = bind_args.handle;
543 error = vnet_unlisten (&unbind_args);
544 SESSION_TEST ((error == 0), "unbind should work");
546 s = session_lookup_listener (server_st_index, &server_sep);
547 SESSION_TEST ((s == 0), "listener should not exist in global table");
549 detach_args.app_index = server_index;
550 vnet_application_detach (&detach_args);
553 * Attach server with local and global scope
555 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
556 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
557 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret;
558 attach_args.namespace_id = ns_id;
559 attach_args.api_client_index = dummy_server_api_index;
560 error = vnet_application_attach (&attach_args);
561 SESSION_TEST ((error == 0), "server attachment should work");
562 server_index = attach_args.app_index;
563 server = application_get (server_index);
564 server_wrk_index = application_get_default_worker (server)->wrk_index;
565 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
566 "server should be in the right ns");
568 bind_args.app_index = server_index;
569 error = vnet_listen (&bind_args);
570 SESSION_TEST ((error == 0), "bind should work");
571 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
572 s = session_lookup_listener (server_st_index, &server_sep);
573 SESSION_TEST ((s != 0), "listener should exist in global table");
574 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
575 " that of the server");
576 server_local_st_index = application_local_session_table (server);
577 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
578 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
579 "listener should exist in local table");
582 * Try client connect with 1) local scope 2) global scope
584 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
585 attach_args.api_client_index = dummy_client_api_index;
586 error = vnet_application_attach (&attach_args);
587 SESSION_TEST ((error == 0), "client attachment should work");
588 client_index = attach_args.app_index;
589 connect_args.api_context = dummy_api_context;
590 connect_args.app_index = client_index;
591 error = vnet_connect (&connect_args);
592 SESSION_TEST ((error != 0), "client connect should return error code");
593 SESSION_TEST ((error == VNET_API_ERROR_INVALID_VALUE),
594 "error code should be invalid value (zero ip)");
595 SESSION_TEST ((dummy_segment_count == 0),
596 "shouldn't have received request to map new segment");
597 connect_args.sep.ip.ip4.as_u8[0] = 127;
598 error = vnet_connect (&connect_args);
599 SESSION_TEST ((error == 0), "client connect should not return error code");
600 SESSION_TEST ((dummy_segment_count == 1),
601 "should've received request to map new segment");
602 SESSION_TEST ((dummy_accept == 1), "should've received accept request");
603 detach_args.app_index = client_index;
604 vnet_application_detach (&detach_args);
606 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
607 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
608 attach_args.api_client_index = dummy_client_api_index;
609 error = vnet_application_attach (&attach_args);
610 SESSION_TEST ((error == 0), "client attachment should work");
611 error = vnet_connect (&connect_args);
612 SESSION_TEST ((error != 0), "client connect should return error code");
613 SESSION_TEST ((error == VNET_API_ERROR_SESSION_CONNECT),
614 "error code should be connect (nothing in local scope)");
615 detach_args.app_index = client_index;
616 vnet_application_detach (&detach_args);
619 * Unbind and detach server and then re-attach with local scope only
621 unbind_args.handle = bind_args.handle;
622 unbind_args.app_index = server_index;
623 error = vnet_unlisten (&unbind_args);
624 SESSION_TEST ((error == 0), "unbind should work");
626 s = session_lookup_listener (server_st_index, &server_sep);
627 SESSION_TEST ((s == 0), "listener should not exist in global table");
628 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
629 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
630 "listener should not exist in local table");
632 detach_args.app_index = server_index;
633 vnet_application_detach (&detach_args);
635 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
636 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
637 attach_args.api_client_index = dummy_server_api_index;
638 error = vnet_application_attach (&attach_args);
639 SESSION_TEST ((error == 0), "app attachment should work");
640 server_index = attach_args.app_index;
641 server = application_get (server_index);
642 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
643 "app should be in the right ns");
645 bind_args.app_index = server_index;
646 error = vnet_listen (&bind_args);
647 SESSION_TEST ((error == 0), "bind should work");
649 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
650 s = session_lookup_listener (server_st_index, &server_sep);
651 SESSION_TEST ((s == 0), "listener should not exist in global table");
652 server_local_st_index = application_local_session_table (server);
653 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
654 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
655 "listener should exist in local table");
657 unbind_args.handle = bind_args.handle;
658 error = vnet_unlisten (&unbind_args);
659 SESSION_TEST ((error == 0), "unbind should work");
661 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
662 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
663 "listener should not exist in local table");
666 * Client attach + connect in default ns with local scope
668 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
669 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
670 attach_args.namespace_id = 0;
671 attach_args.api_client_index = dummy_client_api_index;
672 vnet_application_attach (&attach_args);
673 error = vnet_connect (&connect_args);
674 SESSION_TEST ((error != 0), "client connect should return error code");
675 SESSION_TEST ((error == VNET_API_ERROR_SESSION_CONNECT),
676 "error code should be connect (not in same ns)");
677 detach_args.app_index = client_index;
678 vnet_application_detach (&detach_args);
683 detach_args.app_index = server_index;
684 vnet_application_detach (&detach_args);
687 * Create loopback interface
689 session_create_lookpback (0, &sw_if_index, &intf_addr);
692 * Update namespace with interface
694 ns_args.sw_if_index = sw_if_index;
695 error = vnet_app_namespace_add_del (&ns_args);
696 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
699 * Attach server with local and global scope
701 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
702 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
703 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret;
704 attach_args.namespace_id = ns_id;
705 attach_args.api_client_index = dummy_server_api_index;
706 error = vnet_application_attach (&attach_args);
707 SESSION_TEST ((error == 0), "server attachment should work");
708 server_index = attach_args.app_index;
709 server = application_get (server_index);
710 server_wrk_index = application_get_default_worker (server)->wrk_index;
712 bind_args.app_index = server_index;
713 error = vnet_listen (&bind_args);
714 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
715 s = session_lookup_listener (server_st_index, &server_sep);
716 SESSION_TEST ((s == 0), "zero listener should not exist in global table");
718 s = session_lookup_listener (server_st_index, &intf_sep);
719 SESSION_TEST ((s != 0), "intf listener should exist in global table");
720 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be "
721 "that of the server");
722 server_local_st_index = application_local_session_table (server);
723 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
724 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
725 "zero listener should exist in local table");
726 detach_args.app_index = server_index;
727 vnet_application_detach (&detach_args);
732 vec_free (attach_args.name);
734 session_delete_loopback (sw_if_index);
739 session_test_rule_table (vlib_main_t * vm, unformat_input_t * input)
741 session_rules_table_t _srt, *srt = &_srt;
742 u16 lcl_port = 1234, rmt_port = 4321;
743 u32 action_index = 1, res;
744 ip4_address_t lcl_lkup, rmt_lkup;
745 int verbose = 0, error;
747 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
749 if (unformat (input, "verbose"))
753 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
759 clib_memset (srt, 0, sizeof (*srt));
760 session_rules_table_init (srt);
762 ip4_address_t lcl_ip = {
763 .as_u32 = clib_host_to_net_u32 (0x01020304),
765 ip4_address_t rmt_ip = {
766 .as_u32 = clib_host_to_net_u32 (0x05060708),
768 ip4_address_t lcl_ip2 = {
769 .as_u32 = clib_host_to_net_u32 (0x02020202),
771 ip4_address_t rmt_ip2 = {
772 .as_u32 = clib_host_to_net_u32 (0x06060606),
774 ip4_address_t lcl_ip3 = {
775 .as_u32 = clib_host_to_net_u32 (0x03030303),
777 ip4_address_t rmt_ip3 = {
778 .as_u32 = clib_host_to_net_u32 (0x07070707),
780 fib_prefix_t lcl_pref = {
781 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
783 .fp_proto = FIB_PROTOCOL_IP4,
785 fib_prefix_t rmt_pref = {
786 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
788 .fp_proto = FIB_PROTOCOL_IP4,
791 session_rule_table_add_del_args_t args = {
794 .lcl_port = lcl_port,
795 .rmt_port = rmt_port,
796 .action_index = action_index++,
799 error = session_rules_table_add_del (srt, &args);
800 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
804 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
805 SESSION_TEST ((res == 1),
806 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 1: %d",
810 * 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
812 args.lcl.fp_addr.ip4 = lcl_ip;
813 args.lcl.fp_len = 24;
814 args.action_index = action_index++;
815 error = session_rules_table_add_del (srt, &args);
816 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/16 4321 action %d",
818 args.rmt.fp_addr.ip4 = rmt_ip;
819 args.rmt.fp_len = 24;
820 args.action_index = action_index++;
821 error = session_rules_table_add_del (srt, &args);
822 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/24 4321 action %d",
826 * 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
828 args.lcl.fp_addr.ip4 = lcl_ip2;
829 args.lcl.fp_len = 24;
830 args.rmt.fp_addr.ip4 = rmt_ip2;
831 args.rmt.fp_len = 16;
832 args.action_index = action_index++;
833 error = session_rules_table_add_del (srt, &args);
834 SESSION_TEST ((error == 0), "Add 2.2.2.2/24 1234 6.6.6.6/16 4321 action %d",
836 args.lcl.fp_addr.ip4 = lcl_ip3;
837 args.rmt.fp_addr.ip4 = rmt_ip3;
838 args.action_index = action_index++;
839 error = session_rules_table_add_del (srt, &args);
840 SESSION_TEST ((error == 0), "Add 3.3.3.3/24 1234 7.7.7.7/16 4321 action %d",
844 * Add again 3.3.3.3/24 1234 7.7.7.7/16 4321
846 args.lcl.fp_addr.ip4 = lcl_ip3;
847 args.rmt.fp_addr.ip4 = rmt_ip3;
848 args.action_index = action_index++;
849 error = session_rules_table_add_del (srt, &args);
850 SESSION_TEST ((error == 0), "overwrite 3.3.3.3/24 1234 7.7.7.7/16 4321 "
851 "action %d", action_index - 1);
854 * 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
855 * and 3.3.3.3 1234 7.7.7.7 4321
858 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
859 SESSION_TEST ((res == 3),
860 "Lookup 1.2.3.4 1234 5.6.7.8 4321 action " "should be 3: %d",
863 lcl_lkup.as_u32 = clib_host_to_net_u32 (0x01020204);
864 rmt_lkup.as_u32 = clib_host_to_net_u32 (0x05060709);
866 session_rules_table_lookup4 (srt, &lcl_lkup,
867 &rmt_lkup, lcl_port, rmt_port);
868 SESSION_TEST ((res == 1),
869 "Lookup 1.2.2.4 1234 5.6.7.9 4321, action " "should be 1: %d",
873 session_rules_table_lookup4 (srt, &lcl_ip3, &rmt_ip3, lcl_port, rmt_port);
874 SESSION_TEST ((res == 6),
875 "Lookup 3.3.3.3 1234 7.7.7.7 4321, action "
876 "should be 6 (updated): %d", res);
879 * Add 1.2.3.4/24 * 5.6.7.8/24 *
880 * Lookup 1.2.3.4 1234 5.6.7.8 4321 and 1.2.3.4 1235 5.6.7.8 4321
882 args.lcl.fp_addr.ip4 = lcl_ip;
883 args.rmt.fp_addr.ip4 = rmt_ip;
884 args.lcl.fp_len = 24;
885 args.rmt.fp_len = 24;
888 args.action_index = action_index++;
889 error = session_rules_table_add_del (srt, &args);
890 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 * 5.6.7.8/24 * action %d",
893 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
894 SESSION_TEST ((res == 7),
895 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should"
896 " be 7 (lpm dst): %d", res);
898 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
899 lcl_port + 1, rmt_port);
900 SESSION_TEST ((res == 7),
901 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 7: %d",
905 * Del 1.2.3.4/24 * 5.6.7.8/24 *
906 * Add 1.2.3.4/16 * 5.6.7.8/16 * and 1.2.3.4/24 1235 5.6.7.8/24 4321
907 * Lookup 1.2.3.4 1234 5.6.7.8 4321, 1.2.3.4 1235 5.6.7.8 4321 and
908 * 1.2.3.4 1235 5.6.7.8 4322
911 error = session_rules_table_add_del (srt, &args);
912 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 * 5.6.7.8/24 *");
914 args.lcl.fp_addr.ip4 = lcl_ip;
915 args.rmt.fp_addr.ip4 = rmt_ip;
916 args.lcl.fp_len = 16;
917 args.rmt.fp_len = 16;
920 args.action_index = action_index++;
922 error = session_rules_table_add_del (srt, &args);
923 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 * action %d",
926 args.lcl.fp_addr.ip4 = lcl_ip;
927 args.rmt.fp_addr.ip4 = rmt_ip;
928 args.lcl.fp_len = 24;
929 args.rmt.fp_len = 24;
930 args.lcl_port = lcl_port + 1;
931 args.rmt_port = rmt_port;
932 args.action_index = action_index++;
934 error = session_rules_table_add_del (srt, &args);
935 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1235 5.6.7.8/24 4321 action %d",
939 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
942 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
943 SESSION_TEST ((res == 3),
944 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
947 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
948 lcl_port + 1, rmt_port);
949 SESSION_TEST ((res == 9),
950 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 9: %d",
953 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
954 lcl_port + 1, rmt_port + 1);
955 SESSION_TEST ((res == 8),
956 "Lookup 1.2.3.4 1235 5.6.7.8 4322, action should " "be 8: %d",
960 * Delete 1.2.0.0/16 1234 5.6.0.0/16 4321 and 1.2.0.0/16 * 5.6.0.0/16 *
961 * Lookup 1.2.3.4 1234 5.6.7.8 4321
963 args.lcl_port = 1234;
964 args.rmt_port = 4321;
965 args.lcl.fp_len = 16;
966 args.rmt.fp_len = 16;
968 error = session_rules_table_add_del (srt, &args);
969 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 1234 5.6.0.0/16 4321");
971 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
972 SESSION_TEST ((res == 3),
973 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
979 error = session_rules_table_add_del (srt, &args);
980 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 * 5.6.0.0/16 *");
982 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
983 SESSION_TEST ((res == 3),
984 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
988 * Delete 1.2.3.4/24 1234 5.6.7.5/24
990 args.lcl.fp_addr.ip4 = lcl_ip;
991 args.rmt.fp_addr.ip4 = rmt_ip;
992 args.lcl.fp_len = 24;
993 args.rmt.fp_len = 24;
994 args.lcl_port = 1234;
995 args.rmt_port = 4321;
997 error = session_rules_table_add_del (srt, &args);
998 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 1234 5.6.7.5/24");
1000 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1001 SESSION_TEST ((res == 2), "Action should be 2: %d", res);
1007 session_test_rules (vlib_main_t * vm, unformat_input_t * input)
1009 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
1010 u64 options[APP_OPTIONS_N_OPTIONS];
1011 u16 lcl_port = 1234, rmt_port = 4321;
1012 u32 server_index, server_index2;
1013 u32 dummy_server_api_index = ~0;
1014 transport_connection_t *tc;
1015 u32 dummy_port = 1111;
1016 u8 is_filtered = 0, *ns_id = format (0, "appns1");
1017 session_t *listener, *s;
1018 app_namespace_t *default_ns = app_namespace_get_default ();
1019 u32 local_ns_index = default_ns->local_table_index;
1021 app_namespace_t *app_ns;
1026 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1028 if (unformat (input, "verbose"))
1032 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1038 server_sep.is_ip4 = 1;
1039 server_sep.port = dummy_port;
1040 clib_memset (options, 0, sizeof (options));
1042 vnet_app_attach_args_t attach_args = {
1043 .api_client_index = ~0,
1046 .session_cb_vft = &dummy_session_cbs,
1047 .name = format (0, "session_test"),
1050 vnet_listen_args_t bind_args = {
1056 * Attach server with global and local default scope
1058 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1059 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1060 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1061 attach_args.namespace_id = 0;
1062 attach_args.api_client_index = dummy_server_api_index;
1063 error = vnet_application_attach (&attach_args);
1064 SESSION_TEST ((error == 0), "server attached");
1065 server_index = attach_args.app_index;
1067 bind_args.app_index = server_index;
1068 error = vnet_listen (&bind_args);
1069 SESSION_TEST ((error == 0), "server bound to %U/%d", format_ip46_address,
1070 &server_sep.ip, 1, server_sep.port);
1071 al = app_listener_get_w_handle (bind_args.handle);
1072 listener = app_listener_get_session (al);
1073 ip4_address_t lcl_ip = {
1074 .as_u32 = clib_host_to_net_u32 (0x01020304),
1076 ip4_address_t rmt_ip = {
1077 .as_u32 = clib_host_to_net_u32 (0x05060708),
1079 fib_prefix_t lcl_pref = {
1080 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
1082 .fp_proto = FIB_PROTOCOL_IP4,
1084 fib_prefix_t rmt_pref = {
1085 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1087 .fp_proto = FIB_PROTOCOL_IP4,
1090 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1091 &rmt_pref.fp_addr.ip4, lcl_port,
1092 rmt_port, TRANSPORT_PROTO_TCP, 0,
1094 SESSION_TEST ((tc == 0), "optimized lookup should not work (port)");
1097 * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
1099 session_rule_add_del_args_t args = {
1100 .table_args.lcl = lcl_pref,
1101 .table_args.rmt = rmt_pref,
1102 .table_args.lcl_port = lcl_port,
1103 .table_args.rmt_port = rmt_port,
1104 .table_args.action_index = server_index,
1105 .table_args.is_add = 1,
1108 error = vnet_session_rule_add_del (&args);
1109 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
1110 args.table_args.action_index);
1112 tc = session_lookup_connection4 (0, &lcl_pref.fp_addr.ip4,
1113 &rmt_pref.fp_addr.ip4, lcl_port, rmt_port,
1114 TRANSPORT_PROTO_TCP);
1115 SESSION_TEST ((tc->c_index == listener->connection_index),
1116 "optimized lookup should return the listener");
1117 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1118 &rmt_pref.fp_addr.ip4, lcl_port,
1119 rmt_port, TRANSPORT_PROTO_TCP, 0,
1121 SESSION_TEST ((tc->c_index == listener->connection_index),
1122 "lookup should return the listener");
1123 s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4,
1124 lcl_port, rmt_port, TRANSPORT_PROTO_TCP);
1125 SESSION_TEST ((s->connection_index == listener->connection_index),
1126 "safe lookup should return the listener");
1127 session_endpoint_t sep = {
1128 .ip = rmt_pref.fp_addr,
1131 .transport_proto = TRANSPORT_PROTO_TCP,
1133 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1134 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1135 "should not work (global scope)");
1137 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1138 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1139 rmt_port, TRANSPORT_PROTO_TCP, 0,
1141 SESSION_TEST ((tc == 0),
1142 "optimized lookup for wrong lcl port + 1 should not work");
1145 * Add 1.2.3.4/16 * 5.6.7.8/16 4321
1147 args.table_args.lcl_port = 0;
1148 args.scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1149 error = vnet_session_rule_add_del (&args);
1150 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 4321 action %d",
1151 args.table_args.action_index);
1152 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1153 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1154 rmt_port, TRANSPORT_PROTO_TCP, 0,
1156 SESSION_TEST ((tc->c_index == listener->connection_index),
1157 "optimized lookup for lcl port + 1 should work");
1158 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1159 SESSION_TEST ((handle == server_index), "local session endpoint lookup "
1160 "should work (lcl ip was zeroed)");
1163 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1165 args.table_args.lcl_port = 1234;
1166 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1167 args.table_args.lcl.fp_len = 30;
1168 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1169 args.table_args.rmt.fp_len = 30;
1170 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1171 error = vnet_session_rule_add_del (&args);
1172 SESSION_TEST ((error == 0), "Add 1.2.3.4/30 1234 5.6.7.8/30 4321 action %d",
1173 args.table_args.action_index);
1177 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1178 TRANSPORT_PROTO_TCP);
1179 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1180 TRANSPORT_PROTO_TCP);
1183 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1184 &rmt_pref.fp_addr.ip4, lcl_port,
1185 rmt_port, TRANSPORT_PROTO_TCP, 0,
1187 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1188 "should fail (deny rule)");
1189 SESSION_TEST ((is_filtered == SESSION_LOOKUP_RESULT_FILTERED),
1190 "lookup should be filtered (deny)");
1192 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1193 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1194 "5.6.7.8/16 4321 in local table should return deny");
1196 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1197 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1198 rmt_port, TRANSPORT_PROTO_TCP, 0,
1200 SESSION_TEST ((tc->c_index == listener->connection_index),
1201 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should work");
1204 * "Mask" deny rule with more specific allow:
1205 * Add allow rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -3 (allow)
1207 args.table_args.is_add = 1;
1208 args.table_args.lcl_port = 1234;
1209 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1210 args.table_args.lcl.fp_len = 32;
1211 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1212 args.table_args.rmt.fp_len = 32;
1213 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1214 error = vnet_session_rule_add_del (&args);
1215 SESSION_TEST ((error == 0), "Add masking rule 1.2.3.4/30 1234 5.6.7.8/32 "
1216 "4321 action %d", args.table_args.action_index);
1219 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1220 &rmt_pref.fp_addr.ip4, lcl_port,
1221 rmt_port, TRANSPORT_PROTO_TCP, 0,
1223 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1224 "should fail (allow without app)");
1225 SESSION_TEST ((is_filtered == 0), "lookup should NOT be filtered");
1227 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1228 SESSION_TEST ((handle == SESSION_INVALID_HANDLE), "lookup for 1.2.3.4/32 "
1229 "1234 5.6.7.8/32 4321 in local table should return invalid");
1233 vlib_cli_output (vm, "Local rules");
1234 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1235 TRANSPORT_PROTO_TCP);
1238 sep.ip.ip4.as_u32 += 1 << 24;
1239 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1240 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234"
1241 " 5.6.7.9/32 4321 in local table should return deny");
1243 vnet_connect_args_t connect_args = {
1244 .app_index = attach_args.app_index,
1247 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1249 /* Try connecting */
1250 error = vnet_connect (&connect_args);
1251 SESSION_TEST ((error != 0), "connect should fail");
1252 SESSION_TEST ((error == VNET_API_ERROR_APP_CONNECT_FILTERED),
1253 "connect should be filtered");
1255 sep.ip.ip4.as_u32 -= 1 << 24;
1258 * Delete masking rule: 1.2.3.4/32 1234 5.6.7.8/32 4321 allow
1260 args.table_args.is_add = 0;
1261 args.table_args.lcl_port = 1234;
1262 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1263 args.table_args.lcl.fp_len = 32;
1264 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1265 args.table_args.rmt.fp_len = 32;
1266 error = vnet_session_rule_add_del (&args);
1267 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 allow");
1271 * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
1273 args.table_args.is_add = 1;
1274 args.table_args.lcl_port = 0;
1275 args.table_args.lcl.fp_len = 0;
1276 args.table_args.rmt.fp_len = 16;
1277 args.table_args.action_index = -1;
1278 error = vnet_session_rule_add_del (&args);
1279 SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d",
1280 args.table_args.action_index);
1284 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1285 TRANSPORT_PROTO_TCP);
1286 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1287 TRANSPORT_PROTO_TCP);
1290 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1291 SESSION_TEST ((handle == SESSION_DROP_HANDLE),
1292 "local session endpoint lookup should return deny");
1295 * Delete 1.2.3.4/32 1234 5.6.7.8/32 4321 deny
1297 args.table_args.is_add = 0;
1298 args.table_args.lcl_port = 1234;
1299 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1300 args.table_args.lcl.fp_len = 30;
1301 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1302 args.table_args.rmt.fp_len = 30;
1303 error = vnet_session_rule_add_del (&args);
1304 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1306 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1307 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1308 "local session endpoint lookup should return invalid");
1311 * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and
1312 * 1.2.3.4/16 1234 5.6.7.8/16 4321
1314 args.table_args.is_add = 0;
1315 args.table_args.lcl_port = 0;
1316 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1317 args.table_args.lcl.fp_len = 0;
1318 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1319 args.table_args.rmt.fp_len = 16;
1320 args.table_args.rmt_port = 4321;
1321 error = vnet_session_rule_add_del (&args);
1322 SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
1323 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1324 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1325 "should not work (removed)");
1327 args.table_args.is_add = 0;
1328 args.table_args.lcl = lcl_pref;
1330 args.table_args.is_add = 0;
1331 args.table_args.lcl_port = 0;
1332 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1333 args.table_args.lcl.fp_len = 16;
1334 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1335 args.table_args.rmt.fp_len = 16;
1336 args.table_args.rmt_port = 4321;
1337 error = vnet_session_rule_add_del (&args);
1338 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321");
1339 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1340 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1341 rmt_port, TRANSPORT_PROTO_TCP, 0,
1343 SESSION_TEST ((tc == 0),
1344 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should not "
1347 args.table_args.is_add = 0;
1348 args.table_args.lcl_port = 1234;
1349 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1350 args.table_args.lcl.fp_len = 16;
1351 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1352 args.table_args.rmt.fp_len = 16;
1353 args.table_args.rmt_port = 4321;
1354 error = vnet_session_rule_add_del (&args);
1355 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321");
1356 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1357 &rmt_pref.fp_addr.ip4, lcl_port,
1358 rmt_port, TRANSPORT_PROTO_TCP, 0,
1360 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should "
1361 "not work (del + deny)");
1363 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1364 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1365 &rmt_pref.fp_addr.ip4, lcl_port,
1366 rmt_port, TRANSPORT_PROTO_TCP, 0,
1368 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should"
1369 " not work (no-rule)");
1372 * Test tags. Add/overwrite/del rule with tag
1374 args.table_args.is_add = 1;
1375 args.table_args.lcl_port = 1234;
1376 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1377 args.table_args.lcl.fp_len = 16;
1378 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1379 args.table_args.rmt.fp_len = 16;
1380 args.table_args.rmt_port = 4321;
1381 args.table_args.tag = format (0, "test_rule");
1382 args.table_args.action_index = server_index;
1383 error = vnet_session_rule_add_del (&args);
1384 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 deny "
1388 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1389 TRANSPORT_PROTO_TCP);
1390 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1391 TRANSPORT_PROTO_TCP);
1393 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1394 &rmt_pref.fp_addr.ip4, lcl_port,
1395 rmt_port, TRANSPORT_PROTO_TCP, 0,
1397 SESSION_TEST ((tc->c_index == listener->connection_index),
1398 "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should work");
1400 vec_free (args.table_args.tag);
1401 args.table_args.lcl_port = 1234;
1402 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1403 args.table_args.lcl.fp_len = 16;
1404 args.table_args.tag = format (0, "test_rule_overwrite");
1405 error = vnet_session_rule_add_del (&args);
1406 SESSION_TEST ((error == 0),
1407 "Overwrite 1.2.3.4/16 1234 5.6.7.8/16 4321 deny tag test_rule"
1411 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1412 TRANSPORT_PROTO_TCP);
1413 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1414 TRANSPORT_PROTO_TCP);
1417 args.table_args.is_add = 0;
1418 args.table_args.lcl_port += 1;
1419 error = vnet_session_rule_add_del (&args);
1420 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny "
1421 "tag %v", args.table_args.tag);
1424 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1425 TRANSPORT_PROTO_TCP);
1426 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1427 TRANSPORT_PROTO_TCP);
1429 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1430 &rmt_pref.fp_addr.ip4, lcl_port,
1431 rmt_port, TRANSPORT_PROTO_TCP, 0,
1433 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/32 4321 should not"
1438 * Test local rules with multiple namespaces
1442 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1444 args.table_args.is_add = 1;
1445 args.table_args.lcl_port = 1234;
1446 args.table_args.rmt_port = 0;
1447 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1448 args.table_args.lcl.fp_len = 32;
1449 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1450 args.table_args.rmt.fp_len = 32;
1451 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1452 args.table_args.tag = 0;
1453 args.scope = SESSION_RULE_SCOPE_LOCAL;
1454 error = vnet_session_rule_add_del (&args);
1455 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d",
1456 args.table_args.action_index);
1458 * Add 'white' rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1460 args.table_args.is_add = 1;
1461 args.table_args.lcl_port = 1234;
1462 args.table_args.rmt_port = 4321;
1463 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1464 args.table_args.lcl.fp_len = 32;
1465 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1466 args.table_args.rmt.fp_len = 32;
1467 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1468 error = vnet_session_rule_add_del (&args);
1472 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1473 TRANSPORT_PROTO_TCP);
1476 vnet_app_namespace_add_del_args_t ns_args = {
1479 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
1482 error = vnet_app_namespace_add_del (&ns_args);
1483 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d", error);
1484 app_ns = app_namespace_get_from_id (ns_id);
1486 attach_args.namespace_id = ns_id;
1487 attach_args.api_client_index = dummy_server_api_index;
1488 error = vnet_application_attach (&attach_args);
1489 SESSION_TEST ((error == 0), "server2 attached");
1490 server_index2 = attach_args.app_index;
1493 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1495 args.table_args.lcl_port = 1234;
1496 args.table_args.rmt_port = 0;
1497 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1498 args.table_args.lcl.fp_len = 32;
1499 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1500 args.table_args.rmt.fp_len = 32;
1501 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1502 args.appns_index = app_namespace_index (app_ns);
1504 error = vnet_session_rule_add_del (&args);
1505 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d "
1506 "in test namespace", args.table_args.action_index);
1508 * Lookup default namespace
1510 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1511 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1512 "lookup for 1.2.3.4/32 1234 5.6.7.8/32 4321 in local table "
1513 "should return allow (invalid)");
1516 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1517 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1518 "5.6.7.8/16 432*2* in local table should return deny");
1521 connect_args.app_index = server_index;
1522 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1524 error = vnet_connect (&connect_args);
1525 SESSION_TEST ((error != 0), "connect should fail");
1526 SESSION_TEST ((error == VNET_API_ERROR_APP_CONNECT_FILTERED),
1527 "connect should be filtered");
1530 * Lookup test namespace
1532 handle = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1533 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1534 "5.6.7.8/16 4321 in local table should return deny");
1536 connect_args.app_index = server_index;
1537 error = vnet_connect (&connect_args);
1538 SESSION_TEST ((error != 0), "connect should fail");
1539 SESSION_TEST ((error == VNET_API_ERROR_APP_CONNECT_FILTERED),
1540 "connect should be filtered");
1542 args.table_args.is_add = 0;
1543 vnet_session_rule_add_del (&args);
1545 args.appns_index = 0;
1546 args.table_args.is_add = 0;
1547 vnet_session_rule_add_del (&args);
1549 args.table_args.rmt_port = 4321;
1550 vnet_session_rule_add_del (&args);
1554 vec_free (args.table_args.tag);
1555 vnet_app_detach_args_t detach_args = {
1556 .app_index = server_index,
1557 .api_client_index = ~0,
1559 vnet_application_detach (&detach_args);
1561 detach_args.app_index = server_index2;
1562 vnet_application_detach (&detach_args);
1565 vec_free (attach_args.name);
1570 session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
1572 u64 options[APP_OPTIONS_N_OPTIONS];
1573 char *show_listeners = "sh session listeners tcp verbose";
1574 char *show_local_listeners = "sh app ns table default";
1575 unformat_input_t tmp_input;
1576 u32 server_index, app_index;
1577 u32 dummy_server_api_index = ~0, sw_if_index = 0;
1580 transport_connection_t *tc;
1581 u16 lcl_port = 1234, rmt_port = 4321;
1582 app_namespace_t *app_ns;
1583 int verbose = 0, error = 0;
1585 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1587 if (unformat (input, "verbose"))
1591 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1597 ip4_address_t lcl_ip = {
1598 .as_u32 = clib_host_to_net_u32 (0x01020304),
1600 ip4_address_t rmt_ip = {
1601 .as_u32 = clib_host_to_net_u32 (0x05060708),
1603 fib_prefix_t rmt_pref = {
1604 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1606 .fp_proto = FIB_PROTOCOL_IP4,
1608 session_endpoint_t sep = {
1609 .ip = rmt_pref.fp_addr,
1612 .transport_proto = TRANSPORT_PROTO_TCP,
1616 * Create loopback interface
1618 session_create_lookpback (0, &sw_if_index, &lcl_ip);
1620 app_ns = app_namespace_get_default ();
1621 app_ns->sw_if_index = sw_if_index;
1623 clib_memset (options, 0, sizeof (options));
1624 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1625 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
1626 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_PROXY;
1627 options[APP_OPTIONS_PROXY_TRANSPORT] = 1 << TRANSPORT_PROTO_TCP;
1628 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1629 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1630 vnet_app_attach_args_t attach_args = {
1631 .api_client_index = ~0,
1634 .session_cb_vft = &dummy_session_cbs,
1635 .name = format (0, "session_test"),
1638 attach_args.api_client_index = dummy_server_api_index;
1639 error = vnet_application_attach (&attach_args);
1640 SESSION_TEST ((error == 0), "server attachment should work");
1641 server_index = attach_args.app_index;
1645 unformat_init_string (&tmp_input, show_listeners,
1646 strlen (show_listeners));
1647 vlib_cli_input (vm, &tmp_input, 0, 0);
1648 unformat_init_string (&tmp_input, show_local_listeners,
1649 strlen (show_local_listeners));
1650 vlib_cli_input (vm, &tmp_input, 0, 0);
1653 tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port,
1654 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1655 SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be "
1657 s = listen_session_get (tc->s_index);
1658 SESSION_TEST ((s->app_index == server_index), "lookup should return"
1661 tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port,
1662 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1663 SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should"
1666 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1667 SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1670 vnet_app_detach_args_t detach_args = {
1671 .app_index = server_index,
1672 .api_client_index = ~0,
1674 vnet_application_detach (&detach_args);
1678 unformat_init_string (&tmp_input, show_listeners,
1679 strlen (show_listeners));
1680 vlib_cli_input (vm, &tmp_input, 0, 0);
1681 unformat_init_string (&tmp_input, show_local_listeners,
1682 strlen (show_local_listeners));
1683 vlib_cli_input (vm, &tmp_input, 0, 0);
1686 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1687 SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX),
1688 "local session endpoint lookup should not work after detach");
1690 unformat_free (&tmp_input);
1691 vec_free (attach_args.name);
1695 static clib_error_t *
1696 session_test (vlib_main_t * vm,
1697 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1701 vnet_session_enable_disable (vm, 1);
1703 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1705 if (unformat (input, "basic"))
1706 res = session_test_basic (vm, input);
1707 else if (unformat (input, "namespace"))
1708 res = session_test_namespace (vm, input);
1709 else if (unformat (input, "rules-table"))
1710 res = session_test_rule_table (vm, input);
1711 else if (unformat (input, "rules"))
1712 res = session_test_rules (vm, input);
1713 else if (unformat (input, "proxy"))
1714 res = session_test_proxy (vm, input);
1715 else if (unformat (input, "endpt-cfg"))
1716 res = session_test_endpoint_cfg (vm, input);
1717 else if (unformat (input, "all"))
1719 if ((res = session_test_basic (vm, input)))
1721 if ((res = session_test_namespace (vm, input)))
1723 if ((res = session_test_rule_table (vm, input)))
1725 if ((res = session_test_rules (vm, input)))
1727 if ((res = session_test_proxy (vm, input)))
1729 if ((res = session_test_endpoint_cfg (vm, input)))
1738 return clib_error_return (0, "Session unit test failed");
1743 VLIB_CLI_COMMAND (tcp_test_command, static) =
1745 .path = "test session",
1746 .short_help = "internal session unit tests",
1747 .function = session_test,
1752 * fd.io coding-style-patch-verification: ON
1755 * eval: (c-set-style "gnu")