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 == SESSION_LOOKUP_RESULT_FILTERED),
1198 "lookup should be filtered (deny)");
1200 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1201 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1202 "5.6.7.8/16 4321 in local table should return deny");
1204 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1205 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1206 rmt_port, TRANSPORT_PROTO_TCP, 0,
1208 SESSION_TEST ((tc->c_index == listener->connection_index),
1209 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should work");
1212 * "Mask" deny rule with more specific allow:
1213 * Add allow rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -3 (allow)
1215 args.table_args.is_add = 1;
1216 args.table_args.lcl_port = 1234;
1217 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1218 args.table_args.lcl.fp_len = 32;
1219 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1220 args.table_args.rmt.fp_len = 32;
1221 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1222 error = vnet_session_rule_add_del (&args);
1223 SESSION_TEST ((error == 0), "Add masking rule 1.2.3.4/30 1234 5.6.7.8/32 "
1224 "4321 action %d", args.table_args.action_index);
1227 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1228 &rmt_pref.fp_addr.ip4, lcl_port,
1229 rmt_port, TRANSPORT_PROTO_TCP, 0,
1231 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1232 "should fail (allow without app)");
1233 SESSION_TEST ((is_filtered == 0), "lookup should NOT be filtered");
1235 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1236 SESSION_TEST ((handle == SESSION_INVALID_HANDLE), "lookup for 1.2.3.4/32 "
1237 "1234 5.6.7.8/32 4321 in local table should return invalid");
1241 vlib_cli_output (vm, "Local rules");
1242 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1243 TRANSPORT_PROTO_TCP);
1246 sep.ip.ip4.as_u32 += 1 << 24;
1247 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1248 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234"
1249 " 5.6.7.9/32 4321 in local table should return deny");
1251 vnet_connect_args_t connect_args = {
1252 .app_index = attach_args.app_index,
1255 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1257 /* Try connecting */
1258 error = vnet_connect (&connect_args);
1259 SESSION_TEST ((error != 0), "connect should fail");
1260 rv = clib_error_get_code (error);
1261 SESSION_TEST ((rv == VNET_API_ERROR_APP_CONNECT_FILTERED),
1262 "connect should be filtered");
1264 sep.ip.ip4.as_u32 -= 1 << 24;
1267 * Delete masking rule: 1.2.3.4/32 1234 5.6.7.8/32 4321 allow
1269 args.table_args.is_add = 0;
1270 args.table_args.lcl_port = 1234;
1271 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1272 args.table_args.lcl.fp_len = 32;
1273 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1274 args.table_args.rmt.fp_len = 32;
1275 error = vnet_session_rule_add_del (&args);
1276 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 allow");
1280 * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
1282 args.table_args.is_add = 1;
1283 args.table_args.lcl_port = 0;
1284 args.table_args.lcl.fp_len = 0;
1285 args.table_args.rmt.fp_len = 16;
1286 args.table_args.action_index = -1;
1287 error = vnet_session_rule_add_del (&args);
1288 SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d",
1289 args.table_args.action_index);
1293 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1294 TRANSPORT_PROTO_TCP);
1295 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1296 TRANSPORT_PROTO_TCP);
1299 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1300 SESSION_TEST ((handle == SESSION_DROP_HANDLE),
1301 "local session endpoint lookup should return deny");
1304 * Delete 1.2.3.4/32 1234 5.6.7.8/32 4321 deny
1306 args.table_args.is_add = 0;
1307 args.table_args.lcl_port = 1234;
1308 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1309 args.table_args.lcl.fp_len = 30;
1310 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1311 args.table_args.rmt.fp_len = 30;
1312 error = vnet_session_rule_add_del (&args);
1313 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1315 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1316 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1317 "local session endpoint lookup should return invalid");
1320 * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and
1321 * 1.2.3.4/16 1234 5.6.7.8/16 4321
1323 args.table_args.is_add = 0;
1324 args.table_args.lcl_port = 0;
1325 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1326 args.table_args.lcl.fp_len = 0;
1327 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1328 args.table_args.rmt.fp_len = 16;
1329 args.table_args.rmt_port = 4321;
1330 error = vnet_session_rule_add_del (&args);
1331 SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
1332 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1333 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1334 "should not work (removed)");
1336 args.table_args.is_add = 0;
1337 args.table_args.lcl = lcl_pref;
1339 args.table_args.is_add = 0;
1340 args.table_args.lcl_port = 0;
1341 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1342 args.table_args.lcl.fp_len = 16;
1343 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1344 args.table_args.rmt.fp_len = 16;
1345 args.table_args.rmt_port = 4321;
1346 error = vnet_session_rule_add_del (&args);
1347 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321");
1348 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1349 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1350 rmt_port, TRANSPORT_PROTO_TCP, 0,
1352 SESSION_TEST ((tc == 0),
1353 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should not "
1356 args.table_args.is_add = 0;
1357 args.table_args.lcl_port = 1234;
1358 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1359 args.table_args.lcl.fp_len = 16;
1360 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1361 args.table_args.rmt.fp_len = 16;
1362 args.table_args.rmt_port = 4321;
1363 error = vnet_session_rule_add_del (&args);
1364 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321");
1365 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1366 &rmt_pref.fp_addr.ip4, lcl_port,
1367 rmt_port, TRANSPORT_PROTO_TCP, 0,
1369 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should "
1370 "not work (del + deny)");
1372 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1373 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1374 &rmt_pref.fp_addr.ip4, lcl_port,
1375 rmt_port, TRANSPORT_PROTO_TCP, 0,
1377 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should"
1378 " not work (no-rule)");
1381 * Test tags. Add/overwrite/del rule with tag
1383 args.table_args.is_add = 1;
1384 args.table_args.lcl_port = 1234;
1385 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1386 args.table_args.lcl.fp_len = 16;
1387 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1388 args.table_args.rmt.fp_len = 16;
1389 args.table_args.rmt_port = 4321;
1390 args.table_args.tag = format (0, "test_rule");
1391 args.table_args.action_index = server_index;
1392 error = vnet_session_rule_add_del (&args);
1393 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 deny "
1397 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1398 TRANSPORT_PROTO_TCP);
1399 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1400 TRANSPORT_PROTO_TCP);
1402 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1403 &rmt_pref.fp_addr.ip4, lcl_port,
1404 rmt_port, TRANSPORT_PROTO_TCP, 0,
1406 SESSION_TEST ((tc->c_index == listener->connection_index),
1407 "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should work");
1409 vec_free (args.table_args.tag);
1410 args.table_args.lcl_port = 1234;
1411 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1412 args.table_args.lcl.fp_len = 16;
1413 args.table_args.tag = format (0, "test_rule_overwrite");
1414 error = vnet_session_rule_add_del (&args);
1415 SESSION_TEST ((error == 0),
1416 "Overwrite 1.2.3.4/16 1234 5.6.7.8/16 4321 deny tag test_rule"
1420 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1421 TRANSPORT_PROTO_TCP);
1422 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1423 TRANSPORT_PROTO_TCP);
1426 args.table_args.is_add = 0;
1427 args.table_args.lcl_port += 1;
1428 error = vnet_session_rule_add_del (&args);
1429 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny "
1430 "tag %v", args.table_args.tag);
1433 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1434 TRANSPORT_PROTO_TCP);
1435 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1436 TRANSPORT_PROTO_TCP);
1438 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1439 &rmt_pref.fp_addr.ip4, lcl_port,
1440 rmt_port, TRANSPORT_PROTO_TCP, 0,
1442 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/32 4321 should not"
1447 * Test local rules with multiple namespaces
1451 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1453 args.table_args.is_add = 1;
1454 args.table_args.lcl_port = 1234;
1455 args.table_args.rmt_port = 0;
1456 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1457 args.table_args.lcl.fp_len = 32;
1458 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1459 args.table_args.rmt.fp_len = 32;
1460 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1461 args.table_args.tag = 0;
1462 args.scope = SESSION_RULE_SCOPE_LOCAL;
1463 error = vnet_session_rule_add_del (&args);
1464 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d",
1465 args.table_args.action_index);
1467 * Add 'white' rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1469 args.table_args.is_add = 1;
1470 args.table_args.lcl_port = 1234;
1471 args.table_args.rmt_port = 4321;
1472 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1473 args.table_args.lcl.fp_len = 32;
1474 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1475 args.table_args.rmt.fp_len = 32;
1476 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1477 error = vnet_session_rule_add_del (&args);
1481 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1482 TRANSPORT_PROTO_TCP);
1485 vnet_app_namespace_add_del_args_t ns_args = {
1488 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
1491 error = vnet_app_namespace_add_del (&ns_args);
1492 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
1493 clib_error_get_code (error));
1494 app_ns = app_namespace_get_from_id (ns_id);
1496 attach_args.namespace_id = ns_id;
1497 attach_args.api_client_index = dummy_server_api_index;
1498 error = vnet_application_attach (&attach_args);
1499 SESSION_TEST ((error == 0), "server2 attached");
1500 server_index2 = attach_args.app_index;
1503 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1505 args.table_args.lcl_port = 1234;
1506 args.table_args.rmt_port = 0;
1507 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1508 args.table_args.lcl.fp_len = 32;
1509 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1510 args.table_args.rmt.fp_len = 32;
1511 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1512 args.appns_index = app_namespace_index (app_ns);
1514 error = vnet_session_rule_add_del (&args);
1515 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d "
1516 "in test namespace", args.table_args.action_index);
1518 * Lookup default namespace
1520 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1521 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1522 "lookup for 1.2.3.4/32 1234 5.6.7.8/32 4321 in local table "
1523 "should return allow (invalid)");
1526 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1527 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1528 "5.6.7.8/16 432*2* in local table should return deny");
1531 connect_args.app_index = server_index;
1532 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1534 error = vnet_connect (&connect_args);
1535 SESSION_TEST ((error != 0), "connect should fail");
1536 rv = clib_error_get_code (error);
1537 SESSION_TEST ((rv == VNET_API_ERROR_APP_CONNECT_FILTERED),
1538 "connect should be filtered");
1541 * Lookup test namespace
1543 handle = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1544 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1545 "5.6.7.8/16 4321 in local table should return deny");
1547 connect_args.app_index = server_index;
1548 error = vnet_connect (&connect_args);
1549 SESSION_TEST ((error != 0), "connect should fail");
1550 rv = clib_error_get_code (error);
1551 SESSION_TEST ((rv == VNET_API_ERROR_APP_CONNECT_FILTERED),
1552 "connect should be filtered");
1554 args.table_args.is_add = 0;
1555 vnet_session_rule_add_del (&args);
1557 args.appns_index = 0;
1558 args.table_args.is_add = 0;
1559 vnet_session_rule_add_del (&args);
1561 args.table_args.rmt_port = 4321;
1562 vnet_session_rule_add_del (&args);
1566 vec_free (args.table_args.tag);
1567 vnet_app_detach_args_t detach_args = {
1568 .app_index = server_index,
1569 .api_client_index = ~0,
1571 vnet_application_detach (&detach_args);
1573 detach_args.app_index = server_index2;
1574 vnet_application_detach (&detach_args);
1577 vec_free (attach_args.name);
1582 session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
1584 u64 options[APP_OPTIONS_N_OPTIONS];
1585 char *show_listeners = "sh session listeners tcp verbose";
1586 char *show_local_listeners = "sh app ns table default";
1587 unformat_input_t tmp_input;
1588 u32 server_index, app_index;
1589 u32 dummy_server_api_index = ~0, sw_if_index = 0;
1590 clib_error_t *error = 0;
1592 stream_session_t *s;
1593 transport_connection_t *tc;
1594 u16 lcl_port = 1234, rmt_port = 4321;
1595 app_namespace_t *app_ns;
1598 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1600 if (unformat (input, "verbose"))
1604 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1610 ip4_address_t lcl_ip = {
1611 .as_u32 = clib_host_to_net_u32 (0x01020304),
1613 ip4_address_t rmt_ip = {
1614 .as_u32 = clib_host_to_net_u32 (0x05060708),
1616 fib_prefix_t rmt_pref = {
1617 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1619 .fp_proto = FIB_PROTOCOL_IP4,
1621 session_endpoint_t sep = {
1622 .ip = rmt_pref.fp_addr,
1625 .transport_proto = TRANSPORT_PROTO_TCP,
1629 * Create loopback interface
1631 session_create_lookpback (0, &sw_if_index, &lcl_ip);
1633 app_ns = app_namespace_get_default ();
1634 app_ns->sw_if_index = sw_if_index;
1636 clib_memset (options, 0, sizeof (options));
1637 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1638 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
1639 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_PROXY;
1640 options[APP_OPTIONS_PROXY_TRANSPORT] = 1 << TRANSPORT_PROTO_TCP;
1641 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1642 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1643 vnet_app_attach_args_t attach_args = {
1644 .api_client_index = ~0,
1647 .session_cb_vft = &dummy_session_cbs,
1648 .name = format (0, "session_test"),
1651 attach_args.api_client_index = dummy_server_api_index;
1652 error = vnet_application_attach (&attach_args);
1653 SESSION_TEST ((error == 0), "server attachment should work");
1654 server_index = attach_args.app_index;
1658 unformat_init_string (&tmp_input, show_listeners,
1659 strlen (show_listeners));
1660 vlib_cli_input (vm, &tmp_input, 0, 0);
1661 unformat_init_string (&tmp_input, show_local_listeners,
1662 strlen (show_local_listeners));
1663 vlib_cli_input (vm, &tmp_input, 0, 0);
1666 tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port,
1667 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1668 SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be "
1670 s = listen_session_get (tc->s_index);
1671 SESSION_TEST ((s->app_index == server_index), "lookup should return"
1674 tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port,
1675 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1676 SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should"
1679 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1680 SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1683 vnet_app_detach_args_t detach_args = {
1684 .app_index = server_index,
1685 .api_client_index = ~0,
1687 vnet_application_detach (&detach_args);
1691 unformat_init_string (&tmp_input, show_listeners,
1692 strlen (show_listeners));
1693 vlib_cli_input (vm, &tmp_input, 0, 0);
1694 unformat_init_string (&tmp_input, show_local_listeners,
1695 strlen (show_local_listeners));
1696 vlib_cli_input (vm, &tmp_input, 0, 0);
1699 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1700 SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX),
1701 "local session endpoint lookup should not work after detach");
1703 unformat_free (&tmp_input);
1704 vec_free (attach_args.name);
1708 static clib_error_t *
1709 session_test (vlib_main_t * vm,
1710 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1714 vnet_session_enable_disable (vm, 1);
1716 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1718 if (unformat (input, "basic"))
1719 res = session_test_basic (vm, input);
1720 else if (unformat (input, "namespace"))
1721 res = session_test_namespace (vm, input);
1722 else if (unformat (input, "rules-table"))
1723 res = session_test_rule_table (vm, input);
1724 else if (unformat (input, "rules"))
1725 res = session_test_rules (vm, input);
1726 else if (unformat (input, "proxy"))
1727 res = session_test_proxy (vm, input);
1728 else if (unformat (input, "endpt-cfg"))
1729 res = session_test_endpoint_cfg (vm, input);
1730 else if (unformat (input, "all"))
1732 if ((res = session_test_basic (vm, input)))
1734 if ((res = session_test_namespace (vm, input)))
1736 if ((res = session_test_rule_table (vm, input)))
1738 if ((res = session_test_rules (vm, input)))
1740 if ((res = session_test_proxy (vm, input)))
1742 if ((res = session_test_endpoint_cfg (vm, input)))
1751 return clib_error_return (0, "Session unit test failed");
1756 VLIB_CLI_COMMAND (tcp_test_command, static) =
1758 .path = "test session",
1759 .short_help = "internal session unit tests",
1760 .function = session_test,
1765 * fd.io coding-style-patch-verification: ON
1768 * eval: (c-set-style "gnu")