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 (stream_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 stream_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 (stream_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 (stream_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 (stream_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;
164 clib_error_t *error = 0;
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_bind_args_t bind_args = {
190 bind_args.app_index = server_index;
191 error = vnet_bind (&bind_args);
192 SESSION_TEST ((error == 0), "server bind4 should work");
193 bind4_handle = bind_args.handle;
195 error = vnet_bind (&bind_args);
196 SESSION_TEST ((error != 0), "double server bind4 should not work");
198 bind_args.sep.is_ip4 = 0;
199 error = vnet_bind (&bind_args);
200 SESSION_TEST ((error == 0), "server bind6 should work");
201 bind6_handle = bind_args.handle;
203 error = vnet_bind (&bind_args);
204 SESSION_TEST ((error != 0), "double server bind6 should not work");
206 vnet_unbind_args_t unbind_args = {
207 .handle = bind4_handle,
208 .app_index = server_index,
210 error = vnet_unbind (&unbind_args);
211 SESSION_TEST ((error == 0), "unbind4 should work");
213 unbind_args.handle = bind6_handle;
214 error = vnet_unbind (&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",
310 clib_error_get_code (error));
313 * Attach client/server
315 clib_memset (options, 0, sizeof (options));
316 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
317 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
319 vnet_app_attach_args_t attach_args = {
320 .api_client_index = ~0,
323 .session_cb_vft = &dummy_session_cbs,
324 .name = format (0, "session_test_client"),
327 error = vnet_application_attach (&attach_args);
328 SESSION_TEST ((error == 0), "client app attached");
329 client_index = attach_args.app_index;
330 vec_free (attach_args.name);
332 attach_args.name = format (0, "session_test_server");
333 attach_args.namespace_id = appns_id;
334 attach_args.options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret;
335 error = vnet_application_attach (&attach_args);
336 SESSION_TEST ((error == 0), "server app attached: %U", format_clib_error,
338 vec_free (attach_args.name);
339 server_index = attach_args.app_index;
341 server_sep.is_ip4 = 1;
342 server_sep.port = dummy_server_port;
343 vnet_bind_args_t bind_args = {
345 .app_index = server_index,
347 error = vnet_bind (&bind_args);
348 SESSION_TEST ((error == 0), "server bind should work");
351 * Connect and force lcl ip
353 client_sep.is_ip4 = 1;
354 client_sep.ip.ip4.as_u32 = clib_host_to_net_u32 (0x02020202);
355 client_sep.port = dummy_server_port;
356 client_sep.peer.is_ip4 = 1;
357 client_sep.peer.ip.ip4.as_u32 = clib_host_to_net_u32 (0x01010101);
358 client_sep.peer.port = dummy_client_port;
359 client_sep.transport_proto = TRANSPORT_PROTO_TCP;
361 vnet_connect_args_t connect_args = {
362 .sep_ext = client_sep,
363 .app_index = client_index,
366 connected_session_index = connected_session_thread = ~0;
367 accepted_session_index = accepted_session_thread = ~0;
368 error = vnet_connect (&connect_args);
369 SESSION_TEST ((error == 0), "connect should work");
371 /* wait for stuff to happen */
372 while ((connected_session_index == ~0
373 || vec_len (tcp_main.wrk_ctx[0].pending_acks)) && ++tries < 100)
374 vlib_process_suspend (vm, 100e-3);
375 clib_warning ("waited %.1f seconds for connections", tries / 10.0);
376 SESSION_TEST ((connected_session_index != ~0), "session should exist");
377 SESSION_TEST ((connected_session_thread != ~0), "thread should exist");
378 SESSION_TEST ((accepted_session_index != ~0), "session should exist");
379 SESSION_TEST ((accepted_session_thread != ~0), "thread should exist");
380 s = session_get (connected_session_index, connected_session_thread);
381 tc = session_get_transport (s);
382 SESSION_TEST ((tc != 0), "transport should exist");
383 SESSION_TEST ((memcmp (&tc->lcl_ip, &client_sep.peer.ip,
384 sizeof (tc->lcl_ip)) == 0), "ips should be equal");
385 SESSION_TEST ((tc->lcl_port == dummy_client_port), "ports should be equal");
387 /* These sessions, because of the way they're established are pinned to
388 * main thread, even when we have workers and we avoid polling main thread,
389 * i.e., we can't cleanup pending disconnects, so force cleanup for both
391 session_transport_cleanup (s);
392 s = session_get (accepted_session_index, accepted_session_thread);
393 session_transport_cleanup (s);
395 vnet_app_detach_args_t detach_args = {
396 .app_index = server_index,
397 .api_client_index = ~0,
399 vnet_application_detach (&detach_args);
400 detach_args.app_index = client_index;
401 vnet_application_detach (&detach_args);
403 /* Allow the disconnects to finish before removing the routes. */
404 vlib_process_suspend (vm, 10e-3);
406 session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
408 session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
411 session_delete_loopback (sw_if_index[0]);
412 session_delete_loopback (sw_if_index[1]);
417 session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
419 u64 options[APP_OPTIONS_N_OPTIONS], dummy_secret = 1234;
420 u32 server_index, server_st_index, server_local_st_index;
421 u32 dummy_port = 1234, client_index, server_wrk_index;
422 u32 dummy_api_context = 4321, dummy_client_api_index = ~0;
423 u32 dummy_server_api_index = ~0, sw_if_index = 0;
424 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
425 session_endpoint_t client_sep = SESSION_ENDPOINT_NULL;
426 session_endpoint_t intf_sep = SESSION_ENDPOINT_NULL;
427 clib_error_t *error = 0;
428 u8 *ns_id = format (0, "appns1");
429 app_namespace_t *app_ns;
430 application_t *server;
435 server_sep.is_ip4 = 1;
436 server_sep.port = dummy_port;
437 client_sep.is_ip4 = 1;
438 client_sep.port = dummy_port;
439 clib_memset (options, 0, sizeof (options));
441 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
442 vnet_app_attach_args_t attach_args = {
443 .api_client_index = ~0,
446 .session_cb_vft = &dummy_session_cbs,
447 .name = format (0, "session_test"),
450 vnet_bind_args_t bind_args = {
455 vnet_connect_args_t connect_args = {
459 clib_memcpy (&connect_args.sep, &client_sep, sizeof (client_sep));
461 vnet_unbind_args_t unbind_args = {
462 .handle = bind_args.handle,
466 vnet_app_detach_args_t detach_args = {
468 .api_client_index = ~0,
471 ip4_address_t intf_addr = {
472 .as_u32 = clib_host_to_net_u32 (0x07000105),
475 intf_sep.ip.ip4 = intf_addr;
477 intf_sep.port = dummy_port;
480 * Insert namespace and lookup
483 vnet_app_namespace_add_del_args_t ns_args = {
485 .secret = dummy_secret,
486 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
489 error = vnet_app_namespace_add_del (&ns_args);
490 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
491 clib_error_get_code (error));
493 app_ns = app_namespace_get_from_id (ns_id);
494 SESSION_TEST ((app_ns != 0), "should find ns %v status", ns_id);
495 SESSION_TEST ((app_ns->ns_secret == dummy_secret), "secret should be %d",
497 SESSION_TEST ((app_ns->sw_if_index == APP_NAMESPACE_INVALID_INDEX),
498 "sw_if_index should be invalid");
501 * Try application attach with wrong secret
504 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
505 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
506 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret - 1;
507 attach_args.namespace_id = ns_id;
508 attach_args.api_client_index = dummy_server_api_index;
510 error = vnet_application_attach (&attach_args);
511 SESSION_TEST ((error != 0), "app attachment should fail");
512 code = clib_error_get_code (error);
513 SESSION_TEST ((code == VNET_API_ERROR_APP_WRONG_NS_SECRET),
514 "code should be wrong ns secret: %d", code);
517 * Attach server with global default scope
519 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
520 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
521 options[APP_OPTIONS_NAMESPACE_SECRET] = 0;
522 attach_args.namespace_id = 0;
523 attach_args.api_client_index = dummy_server_api_index;
524 error = vnet_application_attach (&attach_args);
525 SESSION_TEST ((error == 0), "server attachment should work");
526 server_index = attach_args.app_index;
527 server = application_get (server_index);
528 server_wrk_index = application_get_default_worker (server)->wrk_index;
529 SESSION_TEST ((server->ns_index == 0),
530 "server should be in the default ns");
532 bind_args.app_index = server_index;
533 error = vnet_bind (&bind_args);
534 SESSION_TEST ((error == 0), "server bind should work");
536 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
537 s = session_lookup_listener (server_st_index, &server_sep);
538 SESSION_TEST ((s != 0), "listener should exist in global table");
539 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
540 " that of the server");
541 server_local_st_index = application_local_session_table (server);
542 SESSION_TEST ((server_local_st_index == APP_INVALID_INDEX),
543 "server shouldn't have access to local table");
545 unbind_args.app_index = server_index;
546 unbind_args.handle = bind_args.handle;
547 error = vnet_unbind (&unbind_args);
548 SESSION_TEST ((error == 0), "unbind should work");
550 s = session_lookup_listener (server_st_index, &server_sep);
551 SESSION_TEST ((s == 0), "listener should not exist in global table");
553 detach_args.app_index = server_index;
554 vnet_application_detach (&detach_args);
557 * Attach server with local and global scope
559 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
560 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
561 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret;
562 attach_args.namespace_id = ns_id;
563 attach_args.api_client_index = dummy_server_api_index;
564 error = vnet_application_attach (&attach_args);
565 SESSION_TEST ((error == 0), "server attachment should work");
566 server_index = attach_args.app_index;
567 server = application_get (server_index);
568 server_wrk_index = application_get_default_worker (server)->wrk_index;
569 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
570 "server should be in the right ns");
572 bind_args.app_index = server_index;
573 error = vnet_bind (&bind_args);
574 SESSION_TEST ((error == 0), "bind should work");
575 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
576 s = session_lookup_listener (server_st_index, &server_sep);
577 SESSION_TEST ((s != 0), "listener should exist in global table");
578 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
579 " that of the server");
580 server_local_st_index = application_local_session_table (server);
581 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
582 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
583 "listener should exist in local table");
586 * Try client connect with 1) local scope 2) global scope
588 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
589 attach_args.api_client_index = dummy_client_api_index;
590 error = vnet_application_attach (&attach_args);
591 SESSION_TEST ((error == 0), "client attachment should work");
592 client_index = attach_args.app_index;
593 connect_args.api_context = dummy_api_context;
594 connect_args.app_index = client_index;
595 error = vnet_connect (&connect_args);
596 SESSION_TEST ((error != 0), "client connect should return error code");
597 code = clib_error_get_code (error);
598 SESSION_TEST ((code == VNET_API_ERROR_INVALID_VALUE),
599 "error code should be invalid value (zero ip)");
600 SESSION_TEST ((dummy_segment_count == 0),
601 "shouldn't have received request to map new segment");
602 connect_args.sep.ip.ip4.as_u8[0] = 127;
603 error = vnet_connect (&connect_args);
604 SESSION_TEST ((error == 0), "client connect should not return error code");
605 code = clib_error_get_code (error);
606 SESSION_TEST ((dummy_segment_count == 1),
607 "should've received request to map new segment");
608 SESSION_TEST ((dummy_accept == 1), "should've received accept request");
609 detach_args.app_index = client_index;
610 vnet_application_detach (&detach_args);
612 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
613 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
614 attach_args.api_client_index = dummy_client_api_index;
615 error = vnet_application_attach (&attach_args);
616 SESSION_TEST ((error == 0), "client attachment should work");
617 error = vnet_connect (&connect_args);
618 SESSION_TEST ((error != 0), "client connect should return error code");
619 code = clib_error_get_code (error);
620 SESSION_TEST ((code == 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_unbind (&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_bind (&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_unbind (&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 code = clib_error_get_code (error);
683 SESSION_TEST ((code == VNET_API_ERROR_SESSION_CONNECT),
684 "error code should be connect (not in same ns)");
685 detach_args.app_index = client_index;
686 vnet_application_detach (&detach_args);
691 detach_args.app_index = server_index;
692 vnet_application_detach (&detach_args);
695 * Create loopback interface
697 session_create_lookpback (0, &sw_if_index, &intf_addr);
702 ns_args.sw_if_index = sw_if_index;
703 error = vnet_app_namespace_add_del (&ns_args);
704 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
705 clib_error_get_code (error));
708 * Attach server with local and global scope
710 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
711 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
712 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret;
713 attach_args.namespace_id = ns_id;
714 attach_args.api_client_index = dummy_server_api_index;
715 error = vnet_application_attach (&attach_args);
716 SESSION_TEST ((error == 0), "server attachment should work");
717 server_index = attach_args.app_index;
718 server = application_get (server_index);
719 server_wrk_index = application_get_default_worker (server)->wrk_index;
721 bind_args.app_index = server_index;
722 error = vnet_bind (&bind_args);
723 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
724 s = session_lookup_listener (server_st_index, &server_sep);
725 SESSION_TEST ((s == 0), "zero listener should not exist in global table");
727 s = session_lookup_listener (server_st_index, &intf_sep);
728 SESSION_TEST ((s != 0), "intf listener should exist in global table");
729 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be "
730 "that of the server");
731 server_local_st_index = application_local_session_table (server);
732 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
733 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
734 "zero listener should exist in local table");
735 detach_args.app_index = server_index;
736 vnet_application_detach (&detach_args);
741 vec_free (attach_args.name);
743 session_delete_loopback (sw_if_index);
748 session_test_rule_table (vlib_main_t * vm, unformat_input_t * input)
750 session_rules_table_t _srt, *srt = &_srt;
751 u16 lcl_port = 1234, rmt_port = 4321;
752 u32 action_index = 1, res;
753 ip4_address_t lcl_lkup, rmt_lkup;
757 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
759 if (unformat (input, "verbose"))
763 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
769 clib_memset (srt, 0, sizeof (*srt));
770 session_rules_table_init (srt);
772 ip4_address_t lcl_ip = {
773 .as_u32 = clib_host_to_net_u32 (0x01020304),
775 ip4_address_t rmt_ip = {
776 .as_u32 = clib_host_to_net_u32 (0x05060708),
778 ip4_address_t lcl_ip2 = {
779 .as_u32 = clib_host_to_net_u32 (0x02020202),
781 ip4_address_t rmt_ip2 = {
782 .as_u32 = clib_host_to_net_u32 (0x06060606),
784 ip4_address_t lcl_ip3 = {
785 .as_u32 = clib_host_to_net_u32 (0x03030303),
787 ip4_address_t rmt_ip3 = {
788 .as_u32 = clib_host_to_net_u32 (0x07070707),
790 fib_prefix_t lcl_pref = {
791 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
793 .fp_proto = FIB_PROTOCOL_IP4,
795 fib_prefix_t rmt_pref = {
796 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
798 .fp_proto = FIB_PROTOCOL_IP4,
801 session_rule_table_add_del_args_t args = {
804 .lcl_port = lcl_port,
805 .rmt_port = rmt_port,
806 .action_index = action_index++,
809 error = session_rules_table_add_del (srt, &args);
810 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
814 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
815 SESSION_TEST ((res == 1),
816 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 1: %d",
820 * 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
822 args.lcl.fp_addr.ip4 = lcl_ip;
823 args.lcl.fp_len = 24;
824 args.action_index = action_index++;
825 error = session_rules_table_add_del (srt, &args);
826 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/16 4321 action %d",
828 args.rmt.fp_addr.ip4 = rmt_ip;
829 args.rmt.fp_len = 24;
830 args.action_index = action_index++;
831 error = session_rules_table_add_del (srt, &args);
832 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/24 4321 action %d",
836 * 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
838 args.lcl.fp_addr.ip4 = lcl_ip2;
839 args.lcl.fp_len = 24;
840 args.rmt.fp_addr.ip4 = rmt_ip2;
841 args.rmt.fp_len = 16;
842 args.action_index = action_index++;
843 error = session_rules_table_add_del (srt, &args);
844 SESSION_TEST ((error == 0), "Add 2.2.2.2/24 1234 6.6.6.6/16 4321 action %d",
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), "Add 3.3.3.3/24 1234 7.7.7.7/16 4321 action %d",
854 * Add again 3.3.3.3/24 1234 7.7.7.7/16 4321
856 args.lcl.fp_addr.ip4 = lcl_ip3;
857 args.rmt.fp_addr.ip4 = rmt_ip3;
858 args.action_index = action_index++;
859 error = session_rules_table_add_del (srt, &args);
860 SESSION_TEST ((error == 0), "overwrite 3.3.3.3/24 1234 7.7.7.7/16 4321 "
861 "action %d", action_index - 1);
864 * 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
865 * and 3.3.3.3 1234 7.7.7.7 4321
868 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
869 SESSION_TEST ((res == 3),
870 "Lookup 1.2.3.4 1234 5.6.7.8 4321 action " "should be 3: %d",
873 lcl_lkup.as_u32 = clib_host_to_net_u32 (0x01020204);
874 rmt_lkup.as_u32 = clib_host_to_net_u32 (0x05060709);
876 session_rules_table_lookup4 (srt, &lcl_lkup,
877 &rmt_lkup, lcl_port, rmt_port);
878 SESSION_TEST ((res == 1),
879 "Lookup 1.2.2.4 1234 5.6.7.9 4321, action " "should be 1: %d",
883 session_rules_table_lookup4 (srt, &lcl_ip3, &rmt_ip3, lcl_port, rmt_port);
884 SESSION_TEST ((res == 6),
885 "Lookup 3.3.3.3 1234 7.7.7.7 4321, action "
886 "should be 6 (updated): %d", res);
889 * Add 1.2.3.4/24 * 5.6.7.8/24 *
890 * Lookup 1.2.3.4 1234 5.6.7.8 4321 and 1.2.3.4 1235 5.6.7.8 4321
892 args.lcl.fp_addr.ip4 = lcl_ip;
893 args.rmt.fp_addr.ip4 = rmt_ip;
894 args.lcl.fp_len = 24;
895 args.rmt.fp_len = 24;
898 args.action_index = action_index++;
899 error = session_rules_table_add_del (srt, &args);
900 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 * 5.6.7.8/24 * action %d",
903 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
904 SESSION_TEST ((res == 7),
905 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should"
906 " be 7 (lpm dst): %d", res);
908 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
909 lcl_port + 1, rmt_port);
910 SESSION_TEST ((res == 7),
911 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 7: %d",
915 * Del 1.2.3.4/24 * 5.6.7.8/24 *
916 * Add 1.2.3.4/16 * 5.6.7.8/16 * and 1.2.3.4/24 1235 5.6.7.8/24 4321
917 * Lookup 1.2.3.4 1234 5.6.7.8 4321, 1.2.3.4 1235 5.6.7.8 4321 and
918 * 1.2.3.4 1235 5.6.7.8 4322
921 error = session_rules_table_add_del (srt, &args);
922 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 * 5.6.7.8/24 *");
924 args.lcl.fp_addr.ip4 = lcl_ip;
925 args.rmt.fp_addr.ip4 = rmt_ip;
926 args.lcl.fp_len = 16;
927 args.rmt.fp_len = 16;
930 args.action_index = action_index++;
932 error = session_rules_table_add_del (srt, &args);
933 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 * action %d",
936 args.lcl.fp_addr.ip4 = lcl_ip;
937 args.rmt.fp_addr.ip4 = rmt_ip;
938 args.lcl.fp_len = 24;
939 args.rmt.fp_len = 24;
940 args.lcl_port = lcl_port + 1;
941 args.rmt_port = rmt_port;
942 args.action_index = action_index++;
944 error = session_rules_table_add_del (srt, &args);
945 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1235 5.6.7.8/24 4321 action %d",
949 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
952 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
953 SESSION_TEST ((res == 3),
954 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
957 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
958 lcl_port + 1, rmt_port);
959 SESSION_TEST ((res == 9),
960 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 9: %d",
963 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
964 lcl_port + 1, rmt_port + 1);
965 SESSION_TEST ((res == 8),
966 "Lookup 1.2.3.4 1235 5.6.7.8 4322, action should " "be 8: %d",
970 * Delete 1.2.0.0/16 1234 5.6.0.0/16 4321 and 1.2.0.0/16 * 5.6.0.0/16 *
971 * Lookup 1.2.3.4 1234 5.6.7.8 4321
973 args.lcl_port = 1234;
974 args.rmt_port = 4321;
975 args.lcl.fp_len = 16;
976 args.rmt.fp_len = 16;
978 error = session_rules_table_add_del (srt, &args);
979 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 1234 5.6.0.0/16 4321");
981 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
982 SESSION_TEST ((res == 3),
983 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
989 error = session_rules_table_add_del (srt, &args);
990 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 * 5.6.0.0/16 *");
992 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
993 SESSION_TEST ((res == 3),
994 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
998 * Delete 1.2.3.4/24 1234 5.6.7.5/24
1000 args.lcl.fp_addr.ip4 = lcl_ip;
1001 args.rmt.fp_addr.ip4 = rmt_ip;
1002 args.lcl.fp_len = 24;
1003 args.rmt.fp_len = 24;
1004 args.lcl_port = 1234;
1005 args.rmt_port = 4321;
1007 error = session_rules_table_add_del (srt, &args);
1008 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 1234 5.6.7.5/24");
1010 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1011 SESSION_TEST ((res == 2), "Action should be 2: %d", res);
1017 session_test_rules (vlib_main_t * vm, unformat_input_t * input)
1019 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
1020 u64 options[APP_OPTIONS_N_OPTIONS];
1021 u16 lcl_port = 1234, rmt_port = 4321;
1022 u32 server_index, server_index2;
1023 u32 dummy_server_api_index = ~0;
1024 transport_connection_t *tc;
1025 u32 dummy_port = 1111;
1026 clib_error_t *error = 0;
1027 u8 is_filtered = 0, *ns_id = format (0, "appns1");
1028 stream_session_t *listener, *s;
1029 app_namespace_t *default_ns = app_namespace_get_default ();
1030 u32 local_ns_index = default_ns->local_table_index;
1031 int verbose = 0, rv;
1032 app_namespace_t *app_ns;
1035 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1037 if (unformat (input, "verbose"))
1041 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1047 server_sep.is_ip4 = 1;
1048 server_sep.port = dummy_port;
1049 clib_memset (options, 0, sizeof (options));
1051 vnet_app_attach_args_t attach_args = {
1052 .api_client_index = ~0,
1055 .session_cb_vft = &dummy_session_cbs,
1056 .name = format (0, "session_test"),
1059 vnet_bind_args_t bind_args = {
1065 * Attach server with global and local default scope
1067 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1068 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1069 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1070 attach_args.namespace_id = 0;
1071 attach_args.api_client_index = dummy_server_api_index;
1072 error = vnet_application_attach (&attach_args);
1073 SESSION_TEST ((error == 0), "server attached");
1074 server_index = attach_args.app_index;
1076 bind_args.app_index = server_index;
1077 error = vnet_bind (&bind_args);
1078 SESSION_TEST ((error == 0), "server bound to %U/%d", format_ip46_address,
1079 &server_sep.ip, 1, server_sep.port);
1080 listener = listen_session_get_from_handle (bind_args.handle);
1081 ip4_address_t lcl_ip = {
1082 .as_u32 = clib_host_to_net_u32 (0x01020304),
1084 ip4_address_t rmt_ip = {
1085 .as_u32 = clib_host_to_net_u32 (0x05060708),
1087 fib_prefix_t lcl_pref = {
1088 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
1090 .fp_proto = FIB_PROTOCOL_IP4,
1092 fib_prefix_t rmt_pref = {
1093 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1095 .fp_proto = FIB_PROTOCOL_IP4,
1098 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1099 &rmt_pref.fp_addr.ip4, lcl_port,
1100 rmt_port, TRANSPORT_PROTO_TCP, 0,
1102 SESSION_TEST ((tc == 0), "optimized lookup should not work (port)");
1105 * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
1107 session_rule_add_del_args_t args = {
1108 .table_args.lcl = lcl_pref,
1109 .table_args.rmt = rmt_pref,
1110 .table_args.lcl_port = lcl_port,
1111 .table_args.rmt_port = rmt_port,
1112 .table_args.action_index = server_index,
1113 .table_args.is_add = 1,
1116 error = vnet_session_rule_add_del (&args);
1117 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
1118 args.table_args.action_index);
1120 tc = session_lookup_connection4 (0, &lcl_pref.fp_addr.ip4,
1121 &rmt_pref.fp_addr.ip4, lcl_port, rmt_port,
1122 TRANSPORT_PROTO_TCP);
1123 SESSION_TEST ((tc->c_index == listener->connection_index),
1124 "optimized lookup should return the listener");
1125 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1126 &rmt_pref.fp_addr.ip4, lcl_port,
1127 rmt_port, TRANSPORT_PROTO_TCP, 0,
1129 SESSION_TEST ((tc->c_index == listener->connection_index),
1130 "lookup should return the listener");
1131 s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4,
1132 lcl_port, rmt_port, TRANSPORT_PROTO_TCP);
1133 SESSION_TEST ((s->connection_index == listener->connection_index),
1134 "safe lookup should return the listener");
1135 session_endpoint_t sep = {
1136 .ip = rmt_pref.fp_addr,
1139 .transport_proto = TRANSPORT_PROTO_TCP,
1141 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1142 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1143 "should not work (global scope)");
1145 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1146 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1147 rmt_port, TRANSPORT_PROTO_TCP, 0,
1149 SESSION_TEST ((tc == 0),
1150 "optimized lookup for wrong lcl port + 1 should not work");
1153 * Add 1.2.3.4/16 * 5.6.7.8/16 4321
1155 args.table_args.lcl_port = 0;
1156 args.scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1157 error = vnet_session_rule_add_del (&args);
1158 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 4321 action %d",
1159 args.table_args.action_index);
1160 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1161 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1162 rmt_port, TRANSPORT_PROTO_TCP, 0,
1164 SESSION_TEST ((tc->c_index == listener->connection_index),
1165 "optimized lookup for lcl port + 1 should work");
1166 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1167 SESSION_TEST ((handle == server_index), "local session endpoint lookup "
1168 "should work (lcl ip was zeroed)");
1171 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1173 args.table_args.lcl_port = 1234;
1174 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1175 args.table_args.lcl.fp_len = 30;
1176 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1177 args.table_args.rmt.fp_len = 30;
1178 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1179 error = vnet_session_rule_add_del (&args);
1180 SESSION_TEST ((error == 0), "Add 1.2.3.4/30 1234 5.6.7.8/30 4321 action %d",
1181 args.table_args.action_index);
1185 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1186 TRANSPORT_PROTO_TCP);
1187 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1188 TRANSPORT_PROTO_TCP);
1191 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1192 &rmt_pref.fp_addr.ip4, lcl_port,
1193 rmt_port, TRANSPORT_PROTO_TCP, 0,
1195 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1196 "should fail (deny rule)");
1197 SESSION_TEST ((is_filtered == 1), "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 rv = clib_error_get_code (error);
1260 SESSION_TEST ((rv == VNET_API_ERROR_APP_CONNECT_FILTERED),
1261 "connect should be filtered");
1263 sep.ip.ip4.as_u32 -= 1 << 24;
1266 * Delete masking rule: 1.2.3.4/32 1234 5.6.7.8/32 4321 allow
1268 args.table_args.is_add = 0;
1269 args.table_args.lcl_port = 1234;
1270 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1271 args.table_args.lcl.fp_len = 32;
1272 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1273 args.table_args.rmt.fp_len = 32;
1274 error = vnet_session_rule_add_del (&args);
1275 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 allow");
1279 * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
1281 args.table_args.is_add = 1;
1282 args.table_args.lcl_port = 0;
1283 args.table_args.lcl.fp_len = 0;
1284 args.table_args.rmt.fp_len = 16;
1285 args.table_args.action_index = -1;
1286 error = vnet_session_rule_add_del (&args);
1287 SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d",
1288 args.table_args.action_index);
1292 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1293 TRANSPORT_PROTO_TCP);
1294 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1295 TRANSPORT_PROTO_TCP);
1298 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1299 SESSION_TEST ((handle == SESSION_DROP_HANDLE),
1300 "local session endpoint lookup should return deny");
1303 * Delete 1.2.3.4/32 1234 5.6.7.8/32 4321 deny
1305 args.table_args.is_add = 0;
1306 args.table_args.lcl_port = 1234;
1307 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1308 args.table_args.lcl.fp_len = 30;
1309 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1310 args.table_args.rmt.fp_len = 30;
1311 error = vnet_session_rule_add_del (&args);
1312 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1314 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1315 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1316 "local session endpoint lookup should return invalid");
1319 * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and
1320 * 1.2.3.4/16 1234 5.6.7.8/16 4321
1322 args.table_args.is_add = 0;
1323 args.table_args.lcl_port = 0;
1324 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1325 args.table_args.lcl.fp_len = 0;
1326 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1327 args.table_args.rmt.fp_len = 16;
1328 args.table_args.rmt_port = 4321;
1329 error = vnet_session_rule_add_del (&args);
1330 SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
1331 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1332 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1333 "should not work (removed)");
1335 args.table_args.is_add = 0;
1336 args.table_args.lcl = lcl_pref;
1338 args.table_args.is_add = 0;
1339 args.table_args.lcl_port = 0;
1340 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1341 args.table_args.lcl.fp_len = 16;
1342 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1343 args.table_args.rmt.fp_len = 16;
1344 args.table_args.rmt_port = 4321;
1345 error = vnet_session_rule_add_del (&args);
1346 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321");
1347 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1348 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1349 rmt_port, TRANSPORT_PROTO_TCP, 0,
1351 SESSION_TEST ((tc == 0),
1352 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should not "
1355 args.table_args.is_add = 0;
1356 args.table_args.lcl_port = 1234;
1357 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1358 args.table_args.lcl.fp_len = 16;
1359 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1360 args.table_args.rmt.fp_len = 16;
1361 args.table_args.rmt_port = 4321;
1362 error = vnet_session_rule_add_del (&args);
1363 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321");
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 (del + deny)");
1371 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1372 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1373 &rmt_pref.fp_addr.ip4, lcl_port,
1374 rmt_port, TRANSPORT_PROTO_TCP, 0,
1376 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should"
1377 " not work (no-rule)");
1380 * Test tags. Add/overwrite/del rule with tag
1382 args.table_args.is_add = 1;
1383 args.table_args.lcl_port = 1234;
1384 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1385 args.table_args.lcl.fp_len = 16;
1386 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1387 args.table_args.rmt.fp_len = 16;
1388 args.table_args.rmt_port = 4321;
1389 args.table_args.tag = format (0, "test_rule");
1390 args.table_args.action_index = server_index;
1391 error = vnet_session_rule_add_del (&args);
1392 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 deny "
1396 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1397 TRANSPORT_PROTO_TCP);
1398 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1399 TRANSPORT_PROTO_TCP);
1401 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1402 &rmt_pref.fp_addr.ip4, lcl_port,
1403 rmt_port, TRANSPORT_PROTO_TCP, 0,
1405 SESSION_TEST ((tc->c_index == listener->connection_index),
1406 "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should work");
1408 vec_free (args.table_args.tag);
1409 args.table_args.lcl_port = 1234;
1410 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1411 args.table_args.lcl.fp_len = 16;
1412 args.table_args.tag = format (0, "test_rule_overwrite");
1413 error = vnet_session_rule_add_del (&args);
1414 SESSION_TEST ((error == 0),
1415 "Overwrite 1.2.3.4/16 1234 5.6.7.8/16 4321 deny tag test_rule"
1419 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1420 TRANSPORT_PROTO_TCP);
1421 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1422 TRANSPORT_PROTO_TCP);
1425 args.table_args.is_add = 0;
1426 args.table_args.lcl_port += 1;
1427 error = vnet_session_rule_add_del (&args);
1428 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny "
1429 "tag %v", args.table_args.tag);
1432 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1433 TRANSPORT_PROTO_TCP);
1434 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1435 TRANSPORT_PROTO_TCP);
1437 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1438 &rmt_pref.fp_addr.ip4, lcl_port,
1439 rmt_port, TRANSPORT_PROTO_TCP, 0,
1441 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/32 4321 should not"
1446 * Test local rules with multiple namespaces
1450 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1452 args.table_args.is_add = 1;
1453 args.table_args.lcl_port = 1234;
1454 args.table_args.rmt_port = 0;
1455 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1456 args.table_args.lcl.fp_len = 32;
1457 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1458 args.table_args.rmt.fp_len = 32;
1459 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1460 args.table_args.tag = 0;
1461 args.scope = SESSION_RULE_SCOPE_LOCAL;
1462 error = vnet_session_rule_add_del (&args);
1463 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d",
1464 args.table_args.action_index);
1466 * Add 'white' rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1468 args.table_args.is_add = 1;
1469 args.table_args.lcl_port = 1234;
1470 args.table_args.rmt_port = 4321;
1471 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1472 args.table_args.lcl.fp_len = 32;
1473 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1474 args.table_args.rmt.fp_len = 32;
1475 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1476 error = vnet_session_rule_add_del (&args);
1480 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1481 TRANSPORT_PROTO_TCP);
1484 vnet_app_namespace_add_del_args_t ns_args = {
1487 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
1490 error = vnet_app_namespace_add_del (&ns_args);
1491 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
1492 clib_error_get_code (error));
1493 app_ns = app_namespace_get_from_id (ns_id);
1495 attach_args.namespace_id = ns_id;
1496 attach_args.api_client_index = dummy_server_api_index;
1497 error = vnet_application_attach (&attach_args);
1498 SESSION_TEST ((error == 0), "server2 attached");
1499 server_index2 = attach_args.app_index;
1502 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1504 args.table_args.lcl_port = 1234;
1505 args.table_args.rmt_port = 0;
1506 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1507 args.table_args.lcl.fp_len = 32;
1508 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1509 args.table_args.rmt.fp_len = 32;
1510 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1511 args.appns_index = app_namespace_index (app_ns);
1513 error = vnet_session_rule_add_del (&args);
1514 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d "
1515 "in test namespace", args.table_args.action_index);
1517 * Lookup default namespace
1519 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1520 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1521 "lookup for 1.2.3.4/32 1234 5.6.7.8/32 4321 in local table "
1522 "should return allow (invalid)");
1525 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1526 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1527 "5.6.7.8/16 432*2* in local table should return deny");
1530 connect_args.app_index = server_index;
1531 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1533 error = vnet_connect (&connect_args);
1534 SESSION_TEST ((error != 0), "connect should fail");
1535 rv = clib_error_get_code (error);
1536 SESSION_TEST ((rv == VNET_API_ERROR_APP_CONNECT_FILTERED),
1537 "connect should be filtered");
1540 * Lookup test namespace
1542 handle = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1543 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1544 "5.6.7.8/16 4321 in local table should return deny");
1546 connect_args.app_index = server_index;
1547 error = vnet_connect (&connect_args);
1548 SESSION_TEST ((error != 0), "connect should fail");
1549 rv = clib_error_get_code (error);
1550 SESSION_TEST ((rv == VNET_API_ERROR_APP_CONNECT_FILTERED),
1551 "connect should be filtered");
1553 args.table_args.is_add = 0;
1554 vnet_session_rule_add_del (&args);
1556 args.appns_index = 0;
1557 args.table_args.is_add = 0;
1558 vnet_session_rule_add_del (&args);
1560 args.table_args.rmt_port = 4321;
1561 vnet_session_rule_add_del (&args);
1565 vec_free (args.table_args.tag);
1566 vnet_app_detach_args_t detach_args = {
1567 .app_index = server_index,
1568 .api_client_index = ~0,
1570 vnet_application_detach (&detach_args);
1572 detach_args.app_index = server_index2;
1573 vnet_application_detach (&detach_args);
1576 vec_free (attach_args.name);
1581 session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
1583 u64 options[APP_OPTIONS_N_OPTIONS];
1584 char *show_listeners = "sh session listeners tcp verbose";
1585 char *show_local_listeners = "sh app ns table default";
1586 unformat_input_t tmp_input;
1587 u32 server_index, app_index;
1588 u32 dummy_server_api_index = ~0, sw_if_index = 0;
1589 clib_error_t *error = 0;
1591 stream_session_t *s;
1592 transport_connection_t *tc;
1593 u16 lcl_port = 1234, rmt_port = 4321;
1594 app_namespace_t *app_ns;
1597 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1599 if (unformat (input, "verbose"))
1603 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1609 ip4_address_t lcl_ip = {
1610 .as_u32 = clib_host_to_net_u32 (0x01020304),
1612 ip4_address_t rmt_ip = {
1613 .as_u32 = clib_host_to_net_u32 (0x05060708),
1615 fib_prefix_t rmt_pref = {
1616 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1618 .fp_proto = FIB_PROTOCOL_IP4,
1620 session_endpoint_t sep = {
1621 .ip = rmt_pref.fp_addr,
1624 .transport_proto = TRANSPORT_PROTO_TCP,
1628 * Create loopback interface
1630 session_create_lookpback (0, &sw_if_index, &lcl_ip);
1632 app_ns = app_namespace_get_default ();
1633 app_ns->sw_if_index = sw_if_index;
1635 clib_memset (options, 0, sizeof (options));
1636 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1637 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
1638 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_PROXY;
1639 options[APP_OPTIONS_PROXY_TRANSPORT] = 1 << TRANSPORT_PROTO_TCP;
1640 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1641 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1642 vnet_app_attach_args_t attach_args = {
1643 .api_client_index = ~0,
1646 .session_cb_vft = &dummy_session_cbs,
1647 .name = format (0, "session_test"),
1650 attach_args.api_client_index = dummy_server_api_index;
1651 error = vnet_application_attach (&attach_args);
1652 SESSION_TEST ((error == 0), "server attachment should work");
1653 server_index = attach_args.app_index;
1657 unformat_init_string (&tmp_input, show_listeners,
1658 strlen (show_listeners));
1659 vlib_cli_input (vm, &tmp_input, 0, 0);
1660 unformat_init_string (&tmp_input, show_local_listeners,
1661 strlen (show_local_listeners));
1662 vlib_cli_input (vm, &tmp_input, 0, 0);
1665 tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port,
1666 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1667 SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be "
1669 s = listen_session_get (tc->s_index);
1670 SESSION_TEST ((s->app_index == server_index), "lookup should return"
1673 tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port,
1674 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1675 SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should"
1678 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1679 SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1682 vnet_app_detach_args_t detach_args = {
1683 .app_index = server_index,
1684 .api_client_index = ~0,
1686 vnet_application_detach (&detach_args);
1690 unformat_init_string (&tmp_input, show_listeners,
1691 strlen (show_listeners));
1692 vlib_cli_input (vm, &tmp_input, 0, 0);
1693 unformat_init_string (&tmp_input, show_local_listeners,
1694 strlen (show_local_listeners));
1695 vlib_cli_input (vm, &tmp_input, 0, 0);
1698 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1699 SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX),
1700 "local session endpoint lookup should not work after detach");
1702 unformat_free (&tmp_input);
1703 vec_free (attach_args.name);
1707 static clib_error_t *
1708 session_test (vlib_main_t * vm,
1709 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1713 vnet_session_enable_disable (vm, 1);
1715 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1717 if (unformat (input, "basic"))
1718 res = session_test_basic (vm, input);
1719 else if (unformat (input, "namespace"))
1720 res = session_test_namespace (vm, input);
1721 else if (unformat (input, "rules-table"))
1722 res = session_test_rule_table (vm, input);
1723 else if (unformat (input, "rules"))
1724 res = session_test_rules (vm, input);
1725 else if (unformat (input, "proxy"))
1726 res = session_test_proxy (vm, input);
1727 else if (unformat (input, "endpt-cfg"))
1728 res = session_test_endpoint_cfg (vm, input);
1729 else if (unformat (input, "all"))
1731 if ((res = session_test_basic (vm, input)))
1733 if ((res = session_test_namespace (vm, input)))
1735 if ((res = session_test_rule_table (vm, input)))
1737 if ((res = session_test_rules (vm, input)))
1739 if ((res = session_test_proxy (vm, input)))
1741 if ((res = session_test_endpoint_cfg (vm, input)))
1750 return clib_error_return (0, "Session unit test failed");
1755 VLIB_CLI_COMMAND (tcp_test_command, static) =
1757 .path = "test session",
1758 .short_help = "internal session unit tests",
1759 .function = session_test,
1764 * fd.io coding-style-patch-verification: ON
1767 * eval: (c-set-style "gnu")