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, const ssvm_private_t * fs)
68 dummy_segment_count = 1;
73 dummy_del_segment_callback (u32 client_index, const ssvm_private_t * fs)
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,
220 vnet_application_detach (&detach_args);
225 session_add_del_route_via_lookup_in_table (u32 in_table_id, u32 via_table_id,
226 ip4_address_t * ip, u8 mask,
229 fib_route_path_t *rpaths = 0, *rpath;
230 u32 in_fib_index, via_fib_index;
232 fib_prefix_t prefix = {
233 .fp_addr.ip4.as_u32 = ip->as_u32,
235 .fp_proto = FIB_PROTOCOL_IP4,
238 via_fib_index = fib_table_find (FIB_PROTOCOL_IP4, via_table_id);
239 if (via_fib_index == ~0)
241 clib_warning ("couldn't resolve via table id to index");
244 in_fib_index = fib_table_find (FIB_PROTOCOL_IP4, in_table_id);
245 if (in_fib_index == ~0)
247 clib_warning ("couldn't resolve in table id to index");
251 vec_add2 (rpaths, rpath, 1);
252 clib_memset (rpath, 0, sizeof (*rpath));
253 rpath->frp_weight = 1;
254 rpath->frp_fib_index = via_fib_index;
255 rpath->frp_proto = DPO_PROTO_IP4;
256 rpath->frp_sw_if_index = ~0;
257 rpath->frp_flags |= FIB_ROUTE_PATH_DEAG;
260 fib_table_entry_path_add2 (in_fib_index, &prefix, FIB_SOURCE_CLI,
261 FIB_ENTRY_FLAG_NONE, rpath);
263 fib_table_entry_path_remove2 (in_fib_index, &prefix, FIB_SOURCE_CLI,
269 session_test_endpoint_cfg (vlib_main_t * vm, unformat_input_t * input)
271 session_endpoint_cfg_t client_sep = SESSION_ENDPOINT_CFG_NULL;
272 u32 server_index, client_index, sw_if_index[2], tries = 0;
273 u64 options[APP_OPTIONS_N_OPTIONS], dummy_secret = 1234;
274 u16 dummy_server_port = 1234, dummy_client_port = 5678;
275 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
276 ip4_address_t intf_addr[3];
277 transport_connection_t *tc;
283 * Create the loopbacks
285 intf_addr[0].as_u32 = clib_host_to_net_u32 (0x01010101),
286 session_create_lookpback (0, &sw_if_index[0], &intf_addr[0]);
288 intf_addr[1].as_u32 = clib_host_to_net_u32 (0x02020202),
289 session_create_lookpback (1, &sw_if_index[1], &intf_addr[1]);
291 session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
293 session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
299 appns_id = format (0, "appns1");
300 vnet_app_namespace_add_del_args_t ns_args = {
302 .secret = dummy_secret,
303 .sw_if_index = sw_if_index[1],
307 error = vnet_app_namespace_add_del (&ns_args);
308 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
309 clib_error_get_code (error));
312 * Attach client/server
314 clib_memset (options, 0, sizeof (options));
315 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
316 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
318 vnet_app_attach_args_t attach_args = {
319 .api_client_index = ~0,
322 .session_cb_vft = &dummy_session_cbs,
323 .name = format (0, "session_test_client"),
326 error = vnet_application_attach (&attach_args);
327 SESSION_TEST ((error == 0), "client app attached");
328 client_index = attach_args.app_index;
329 vec_free (attach_args.name);
331 attach_args.name = format (0, "session_test_server");
332 attach_args.namespace_id = appns_id;
333 attach_args.options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret;
334 error = vnet_application_attach (&attach_args);
335 SESSION_TEST ((error == 0), "server app attached: %U", format_clib_error,
337 vec_free (attach_args.name);
338 server_index = attach_args.app_index;
340 server_sep.is_ip4 = 1;
341 server_sep.port = dummy_server_port;
342 vnet_bind_args_t bind_args = {
344 .app_index = server_index,
346 error = vnet_bind (&bind_args);
347 SESSION_TEST ((error == 0), "server bind should work");
350 * Connect and force lcl ip
352 client_sep.is_ip4 = 1;
353 client_sep.ip.ip4.as_u32 = clib_host_to_net_u32 (0x02020202);
354 client_sep.port = dummy_server_port;
355 client_sep.peer.is_ip4 = 1;
356 client_sep.peer.ip.ip4.as_u32 = clib_host_to_net_u32 (0x01010101);
357 client_sep.peer.port = dummy_client_port;
358 client_sep.transport_proto = TRANSPORT_PROTO_TCP;
360 vnet_connect_args_t connect_args = {
361 .sep_ext = client_sep,
362 .app_index = client_index,
365 connected_session_index = connected_session_thread = ~0;
366 accepted_session_index = accepted_session_thread = ~0;
367 error = vnet_connect (&connect_args);
368 SESSION_TEST ((error == 0), "connect should work");
370 /* wait for stuff to happen */
371 while ((connected_session_index == ~0
372 || vec_len (tcp_main.wrk_ctx[0].pending_acks)) && ++tries < 100)
373 vlib_process_suspend (vm, 100e-3);
374 clib_warning ("waited %.1f seconds for connections", tries / 10.0);
375 SESSION_TEST ((connected_session_index != ~0), "session should exist");
376 SESSION_TEST ((connected_session_thread != ~0), "thread should exist");
377 SESSION_TEST ((accepted_session_index != ~0), "session should exist");
378 SESSION_TEST ((accepted_session_thread != ~0), "thread should exist");
379 s = session_get (connected_session_index, connected_session_thread);
380 tc = session_get_transport (s);
381 SESSION_TEST ((tc != 0), "transport should exist");
382 SESSION_TEST ((memcmp (&tc->lcl_ip, &client_sep.peer.ip,
383 sizeof (tc->lcl_ip)) == 0), "ips should be equal");
384 SESSION_TEST ((tc->lcl_port == dummy_client_port), "ports should be equal");
386 /* These sessions, because of the way they're established are pinned to
387 * main thread, even when we have workers and we avoid polling main thread,
388 * i.e., we can't cleanup pending disconnects, so force cleanup for both
390 stream_session_cleanup (s);
391 s = session_get (accepted_session_index, accepted_session_thread);
392 stream_session_cleanup (s);
394 vnet_app_detach_args_t detach_args = {
395 .app_index = server_index,
397 vnet_application_detach (&detach_args);
398 detach_args.app_index = client_index;
399 vnet_application_detach (&detach_args);
401 /* Allow the disconnects to finish before removing the routes. */
402 vlib_process_suspend (vm, 10e-3);
404 session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
406 session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
409 session_delete_loopback (sw_if_index[0]);
410 session_delete_loopback (sw_if_index[1]);
415 session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
417 u64 options[APP_OPTIONS_N_OPTIONS], dummy_secret = 1234;
418 u32 server_index, server_st_index, server_local_st_index;
419 u32 dummy_port = 1234, client_index, server_wrk_index;
420 u32 dummy_api_context = 4321, dummy_client_api_index = 1234;
421 u32 dummy_server_api_index = ~0, sw_if_index = 0;
422 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
423 session_endpoint_t client_sep = SESSION_ENDPOINT_NULL;
424 session_endpoint_t intf_sep = SESSION_ENDPOINT_NULL;
425 clib_error_t *error = 0;
426 u8 *ns_id = format (0, "appns1");
427 app_namespace_t *app_ns;
428 application_t *server;
433 server_sep.is_ip4 = 1;
434 server_sep.port = dummy_port;
435 client_sep.is_ip4 = 1;
436 client_sep.port = dummy_port;
437 clib_memset (options, 0, sizeof (options));
439 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
440 vnet_app_attach_args_t attach_args = {
441 .api_client_index = ~0,
444 .session_cb_vft = &dummy_session_cbs,
445 .name = format (0, "session_test"),
448 vnet_bind_args_t bind_args = {
453 vnet_connect_args_t connect_args = {
457 clib_memcpy (&connect_args.sep, &client_sep, sizeof (client_sep));
459 vnet_unbind_args_t unbind_args = {
460 .handle = bind_args.handle,
464 vnet_app_detach_args_t detach_args = {
468 ip4_address_t intf_addr = {
469 .as_u32 = clib_host_to_net_u32 (0x07000105),
472 intf_sep.ip.ip4 = intf_addr;
474 intf_sep.port = dummy_port;
477 * Insert namespace and lookup
480 vnet_app_namespace_add_del_args_t ns_args = {
482 .secret = dummy_secret,
483 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
486 error = vnet_app_namespace_add_del (&ns_args);
487 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
488 clib_error_get_code (error));
490 app_ns = app_namespace_get_from_id (ns_id);
491 SESSION_TEST ((app_ns != 0), "should find ns %v status", ns_id);
492 SESSION_TEST ((app_ns->ns_secret == dummy_secret), "secret should be %d",
494 SESSION_TEST ((app_ns->sw_if_index == APP_NAMESPACE_INVALID_INDEX),
495 "sw_if_index should be invalid");
498 * Try application attach with wrong secret
501 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
502 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
503 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret - 1;
504 attach_args.namespace_id = ns_id;
505 attach_args.api_client_index = dummy_server_api_index;
507 error = vnet_application_attach (&attach_args);
508 SESSION_TEST ((error != 0), "app attachment should fail");
509 code = clib_error_get_code (error);
510 SESSION_TEST ((code == VNET_API_ERROR_APP_WRONG_NS_SECRET),
511 "code should be wrong ns secret: %d", code);
514 * Attach server with global default scope
516 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
517 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
518 options[APP_OPTIONS_NAMESPACE_SECRET] = 0;
519 attach_args.namespace_id = 0;
520 attach_args.api_client_index = dummy_server_api_index;
521 error = vnet_application_attach (&attach_args);
522 SESSION_TEST ((error == 0), "server attachment should work");
523 server_index = attach_args.app_index;
524 server = application_get (server_index);
525 server_wrk_index = application_get_default_worker (server)->wrk_index;
526 SESSION_TEST ((server->ns_index == 0),
527 "server should be in the default ns");
529 bind_args.app_index = server_index;
530 error = vnet_bind (&bind_args);
531 SESSION_TEST ((error == 0), "server bind should work");
533 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
534 s = session_lookup_listener (server_st_index, &server_sep);
535 SESSION_TEST ((s != 0), "listener should exist in global table");
536 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
537 " that of the server");
538 server_local_st_index = application_local_session_table (server);
539 SESSION_TEST ((server_local_st_index == APP_INVALID_INDEX),
540 "server shouldn't have access to local table");
542 unbind_args.app_index = server_index;
543 unbind_args.handle = bind_args.handle;
544 error = vnet_unbind (&unbind_args);
545 SESSION_TEST ((error == 0), "unbind should work");
547 s = session_lookup_listener (server_st_index, &server_sep);
548 SESSION_TEST ((s == 0), "listener should not exist in global table");
550 detach_args.app_index = server_index;
551 vnet_application_detach (&detach_args);
554 * Attach server with local and global scope
556 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
557 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
558 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret;
559 attach_args.namespace_id = ns_id;
560 attach_args.api_client_index = dummy_server_api_index;
561 error = vnet_application_attach (&attach_args);
562 SESSION_TEST ((error == 0), "server attachment should work");
563 server_index = attach_args.app_index;
564 server = application_get (server_index);
565 server_wrk_index = application_get_default_worker (server)->wrk_index;
566 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
567 "server should be in the right ns");
569 bind_args.app_index = server_index;
570 error = vnet_bind (&bind_args);
571 SESSION_TEST ((error == 0), "bind should work");
572 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
573 s = session_lookup_listener (server_st_index, &server_sep);
574 SESSION_TEST ((s != 0), "listener should exist in global table");
575 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be"
576 " that of the server");
577 server_local_st_index = application_local_session_table (server);
578 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
579 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
580 "listener should exist in local table");
583 * Try client connect with 1) local scope 2) global scope
585 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
586 attach_args.api_client_index = dummy_client_api_index;
587 error = vnet_application_attach (&attach_args);
588 SESSION_TEST ((error == 0), "client attachment should work");
589 client_index = attach_args.app_index;
590 connect_args.api_context = dummy_api_context;
591 connect_args.app_index = client_index;
592 error = vnet_connect (&connect_args);
593 SESSION_TEST ((error != 0), "client connect should return error code");
594 code = clib_error_get_code (error);
595 SESSION_TEST ((code == VNET_API_ERROR_INVALID_VALUE),
596 "error code should be invalid value (zero ip)");
597 SESSION_TEST ((dummy_segment_count == 0),
598 "shouldn't have received request to map new segment");
599 connect_args.sep.ip.ip4.as_u8[0] = 127;
600 error = vnet_connect (&connect_args);
601 SESSION_TEST ((error == 0), "client connect should not return error code");
602 code = clib_error_get_code (error);
603 SESSION_TEST ((dummy_segment_count == 1),
604 "should've received request to map new segment");
605 SESSION_TEST ((dummy_accept == 1), "should've received accept request");
606 detach_args.app_index = client_index;
607 vnet_application_detach (&detach_args);
609 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
610 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
611 attach_args.api_client_index = dummy_client_api_index;
612 error = vnet_application_attach (&attach_args);
613 SESSION_TEST ((error == 0), "client attachment should work");
614 error = vnet_connect (&connect_args);
615 SESSION_TEST ((error != 0), "client connect should return error code");
616 code = clib_error_get_code (error);
617 SESSION_TEST ((code == VNET_API_ERROR_SESSION_CONNECT),
618 "error code should be connect (nothing in local scope)");
619 detach_args.app_index = client_index;
620 vnet_application_detach (&detach_args);
623 * Unbind and detach server and then re-attach with local scope only
625 unbind_args.handle = bind_args.handle;
626 unbind_args.app_index = server_index;
627 error = vnet_unbind (&unbind_args);
628 SESSION_TEST ((error == 0), "unbind should work");
630 s = session_lookup_listener (server_st_index, &server_sep);
631 SESSION_TEST ((s == 0), "listener should not exist in global table");
632 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
633 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
634 "listener should not exist in local table");
636 detach_args.app_index = server_index;
637 vnet_application_detach (&detach_args);
639 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
640 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
641 attach_args.api_client_index = dummy_server_api_index;
642 error = vnet_application_attach (&attach_args);
643 SESSION_TEST ((error == 0), "app attachment should work");
644 server_index = attach_args.app_index;
645 server = application_get (server_index);
646 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
647 "app should be in the right ns");
649 bind_args.app_index = server_index;
650 error = vnet_bind (&bind_args);
651 SESSION_TEST ((error == 0), "bind should work");
653 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
654 s = session_lookup_listener (server_st_index, &server_sep);
655 SESSION_TEST ((s == 0), "listener should not exist in global table");
656 server_local_st_index = application_local_session_table (server);
657 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
658 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
659 "listener should exist in local table");
661 unbind_args.handle = bind_args.handle;
662 error = vnet_unbind (&unbind_args);
663 SESSION_TEST ((error == 0), "unbind should work");
665 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
666 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
667 "listener should not exist in local table");
670 * Client attach + connect in default ns with local scope
672 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
673 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
674 attach_args.namespace_id = 0;
675 attach_args.api_client_index = dummy_client_api_index;
676 vnet_application_attach (&attach_args);
677 error = vnet_connect (&connect_args);
678 SESSION_TEST ((error != 0), "client connect should return error code");
679 code = clib_error_get_code (error);
680 SESSION_TEST ((code == VNET_API_ERROR_SESSION_CONNECT),
681 "error code should be connect (not in same ns)");
682 detach_args.app_index = client_index;
683 vnet_application_detach (&detach_args);
688 detach_args.app_index = server_index;
689 vnet_application_detach (&detach_args);
692 * Create loopback interface
694 session_create_lookpback (0, &sw_if_index, &intf_addr);
699 ns_args.sw_if_index = sw_if_index;
700 error = vnet_app_namespace_add_del (&ns_args);
701 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
702 clib_error_get_code (error));
705 * Attach server with local and global scope
707 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
708 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
709 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret;
710 attach_args.namespace_id = ns_id;
711 attach_args.api_client_index = dummy_server_api_index;
712 error = vnet_application_attach (&attach_args);
713 SESSION_TEST ((error == 0), "server attachment should work");
714 server_index = attach_args.app_index;
715 server = application_get (server_index);
716 server_wrk_index = application_get_default_worker (server)->wrk_index;
718 bind_args.app_index = server_index;
719 error = vnet_bind (&bind_args);
720 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
721 s = session_lookup_listener (server_st_index, &server_sep);
722 SESSION_TEST ((s == 0), "zero listener should not exist in global table");
724 s = session_lookup_listener (server_st_index, &intf_sep);
725 SESSION_TEST ((s != 0), "intf listener should exist in global table");
726 SESSION_TEST ((s->app_wrk_index == server_wrk_index), "app_index should be "
727 "that of the server");
728 server_local_st_index = application_local_session_table (server);
729 handle = session_lookup_local_endpoint (server_local_st_index, &server_sep);
730 SESSION_TEST ((handle != SESSION_INVALID_HANDLE),
731 "zero listener should exist in local table");
732 detach_args.app_index = server_index;
733 vnet_application_detach (&detach_args);
738 vec_free (attach_args.name);
740 session_delete_loopback (sw_if_index);
745 session_test_rule_table (vlib_main_t * vm, unformat_input_t * input)
747 session_rules_table_t _srt, *srt = &_srt;
748 u16 lcl_port = 1234, rmt_port = 4321;
749 u32 action_index = 1, res;
750 ip4_address_t lcl_lkup, rmt_lkup;
754 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
756 if (unformat (input, "verbose"))
760 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
766 clib_memset (srt, 0, sizeof (*srt));
767 session_rules_table_init (srt);
769 ip4_address_t lcl_ip = {
770 .as_u32 = clib_host_to_net_u32 (0x01020304),
772 ip4_address_t rmt_ip = {
773 .as_u32 = clib_host_to_net_u32 (0x05060708),
775 ip4_address_t lcl_ip2 = {
776 .as_u32 = clib_host_to_net_u32 (0x02020202),
778 ip4_address_t rmt_ip2 = {
779 .as_u32 = clib_host_to_net_u32 (0x06060606),
781 ip4_address_t lcl_ip3 = {
782 .as_u32 = clib_host_to_net_u32 (0x03030303),
784 ip4_address_t rmt_ip3 = {
785 .as_u32 = clib_host_to_net_u32 (0x07070707),
787 fib_prefix_t lcl_pref = {
788 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
790 .fp_proto = FIB_PROTOCOL_IP4,
792 fib_prefix_t rmt_pref = {
793 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
795 .fp_proto = FIB_PROTOCOL_IP4,
798 session_rule_table_add_del_args_t args = {
801 .lcl_port = lcl_port,
802 .rmt_port = rmt_port,
803 .action_index = action_index++,
806 error = session_rules_table_add_del (srt, &args);
807 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
811 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
812 SESSION_TEST ((res == 1),
813 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 1: %d",
817 * Add 1.2.3.4/24 1234 5.6.7.8/16 4321 and 1.2.3.4/24 1234 5.6.7.8/24 4321
819 args.lcl.fp_addr.ip4 = lcl_ip;
820 args.lcl.fp_len = 24;
821 args.action_index = action_index++;
822 error = session_rules_table_add_del (srt, &args);
823 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/16 4321 action %d",
825 args.rmt.fp_addr.ip4 = rmt_ip;
826 args.rmt.fp_len = 24;
827 args.action_index = action_index++;
828 error = session_rules_table_add_del (srt, &args);
829 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/24 4321 action %d",
833 * Add 2.2.2.2/24 1234 6.6.6.6/16 4321 and 3.3.3.3/24 1234 7.7.7.7/16 4321
835 args.lcl.fp_addr.ip4 = lcl_ip2;
836 args.lcl.fp_len = 24;
837 args.rmt.fp_addr.ip4 = rmt_ip2;
838 args.rmt.fp_len = 16;
839 args.action_index = action_index++;
840 error = session_rules_table_add_del (srt, &args);
841 SESSION_TEST ((error == 0), "Add 2.2.2.2/24 1234 6.6.6.6/16 4321 action %d",
843 args.lcl.fp_addr.ip4 = lcl_ip3;
844 args.rmt.fp_addr.ip4 = rmt_ip3;
845 args.action_index = action_index++;
846 error = session_rules_table_add_del (srt, &args);
847 SESSION_TEST ((error == 0), "Add 3.3.3.3/24 1234 7.7.7.7/16 4321 action %d",
851 * Add again 3.3.3.3/24 1234 7.7.7.7/16 4321
853 args.lcl.fp_addr.ip4 = lcl_ip3;
854 args.rmt.fp_addr.ip4 = rmt_ip3;
855 args.action_index = action_index++;
856 error = session_rules_table_add_del (srt, &args);
857 SESSION_TEST ((error == 0), "overwrite 3.3.3.3/24 1234 7.7.7.7/16 4321 "
858 "action %d", action_index - 1);
861 * Lookup 1.2.3.4/32 1234 5.6.7.8/32 4321, 1.2.2.4/32 1234 5.6.7.9/32 4321
862 * and 3.3.3.3 1234 7.7.7.7 4321
865 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
866 SESSION_TEST ((res == 3),
867 "Lookup 1.2.3.4 1234 5.6.7.8 4321 action " "should be 3: %d",
870 lcl_lkup.as_u32 = clib_host_to_net_u32 (0x01020204);
871 rmt_lkup.as_u32 = clib_host_to_net_u32 (0x05060709);
873 session_rules_table_lookup4 (srt, &lcl_lkup,
874 &rmt_lkup, lcl_port, rmt_port);
875 SESSION_TEST ((res == 1),
876 "Lookup 1.2.2.4 1234 5.6.7.9 4321, action " "should be 1: %d",
880 session_rules_table_lookup4 (srt, &lcl_ip3, &rmt_ip3, lcl_port, rmt_port);
881 SESSION_TEST ((res == 6),
882 "Lookup 3.3.3.3 1234 7.7.7.7 4321, action "
883 "should be 6 (updated): %d", res);
886 * Add 1.2.3.4/24 * 5.6.7.8/24 *
887 * Lookup 1.2.3.4 1234 5.6.7.8 4321 and 1.2.3.4 1235 5.6.7.8 4321
889 args.lcl.fp_addr.ip4 = lcl_ip;
890 args.rmt.fp_addr.ip4 = rmt_ip;
891 args.lcl.fp_len = 24;
892 args.rmt.fp_len = 24;
895 args.action_index = action_index++;
896 error = session_rules_table_add_del (srt, &args);
897 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 * 5.6.7.8/24 * action %d",
900 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
901 SESSION_TEST ((res == 7),
902 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should"
903 " be 7 (lpm dst): %d", res);
905 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
906 lcl_port + 1, rmt_port);
907 SESSION_TEST ((res == 7),
908 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 7: %d",
912 * Del 1.2.3.4/24 * 5.6.7.8/24 *
913 * Add 1.2.3.4/16 * 5.6.7.8/16 * and 1.2.3.4/24 1235 5.6.7.8/24 4321
914 * Lookup 1.2.3.4 1234 5.6.7.8 4321, 1.2.3.4 1235 5.6.7.8 4321 and
915 * 1.2.3.4 1235 5.6.7.8 4322
918 error = session_rules_table_add_del (srt, &args);
919 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 * 5.6.7.8/24 *");
921 args.lcl.fp_addr.ip4 = lcl_ip;
922 args.rmt.fp_addr.ip4 = rmt_ip;
923 args.lcl.fp_len = 16;
924 args.rmt.fp_len = 16;
927 args.action_index = action_index++;
929 error = session_rules_table_add_del (srt, &args);
930 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 * action %d",
933 args.lcl.fp_addr.ip4 = lcl_ip;
934 args.rmt.fp_addr.ip4 = rmt_ip;
935 args.lcl.fp_len = 24;
936 args.rmt.fp_len = 24;
937 args.lcl_port = lcl_port + 1;
938 args.rmt_port = rmt_port;
939 args.action_index = action_index++;
941 error = session_rules_table_add_del (srt, &args);
942 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1235 5.6.7.8/24 4321 action %d",
946 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
949 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
950 SESSION_TEST ((res == 3),
951 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
954 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
955 lcl_port + 1, rmt_port);
956 SESSION_TEST ((res == 9),
957 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 9: %d",
960 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
961 lcl_port + 1, rmt_port + 1);
962 SESSION_TEST ((res == 8),
963 "Lookup 1.2.3.4 1235 5.6.7.8 4322, action should " "be 8: %d",
967 * Delete 1.2.0.0/16 1234 5.6.0.0/16 4321 and 1.2.0.0/16 * 5.6.0.0/16 *
968 * Lookup 1.2.3.4 1234 5.6.7.8 4321
970 args.lcl_port = 1234;
971 args.rmt_port = 4321;
972 args.lcl.fp_len = 16;
973 args.rmt.fp_len = 16;
975 error = session_rules_table_add_del (srt, &args);
976 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 1234 5.6.0.0/16 4321");
978 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
979 SESSION_TEST ((res == 3),
980 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
986 error = session_rules_table_add_del (srt, &args);
987 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 * 5.6.0.0/16 *");
989 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
990 SESSION_TEST ((res == 3),
991 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
995 * Delete 1.2.3.4/24 1234 5.6.7.5/24
997 args.lcl.fp_addr.ip4 = lcl_ip;
998 args.rmt.fp_addr.ip4 = rmt_ip;
999 args.lcl.fp_len = 24;
1000 args.rmt.fp_len = 24;
1001 args.lcl_port = 1234;
1002 args.rmt_port = 4321;
1004 error = session_rules_table_add_del (srt, &args);
1005 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 1234 5.6.7.5/24");
1007 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
1008 SESSION_TEST ((res == 2), "Action should be 2: %d", res);
1014 session_test_rules (vlib_main_t * vm, unformat_input_t * input)
1016 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
1017 u64 options[APP_OPTIONS_N_OPTIONS];
1018 u16 lcl_port = 1234, rmt_port = 4321;
1019 u32 server_index, server_index2;
1020 u32 dummy_server_api_index = ~0;
1021 transport_connection_t *tc;
1022 u32 dummy_port = 1111;
1023 clib_error_t *error = 0;
1024 u8 is_filtered = 0, *ns_id = format (0, "appns1");
1025 stream_session_t *listener, *s;
1026 app_namespace_t *default_ns = app_namespace_get_default ();
1027 u32 local_ns_index = default_ns->local_table_index;
1028 int verbose = 0, rv;
1029 app_namespace_t *app_ns;
1032 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1034 if (unformat (input, "verbose"))
1038 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1044 server_sep.is_ip4 = 1;
1045 server_sep.port = dummy_port;
1046 clib_memset (options, 0, sizeof (options));
1048 vnet_app_attach_args_t attach_args = {
1049 .api_client_index = ~0,
1052 .session_cb_vft = &dummy_session_cbs,
1053 .name = format (0, "session_test"),
1056 vnet_bind_args_t bind_args = {
1062 * Attach server with global and local default scope
1064 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1065 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1066 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1067 attach_args.namespace_id = 0;
1068 attach_args.api_client_index = dummy_server_api_index;
1069 error = vnet_application_attach (&attach_args);
1070 SESSION_TEST ((error == 0), "server attached");
1071 server_index = attach_args.app_index;
1073 bind_args.app_index = server_index;
1074 error = vnet_bind (&bind_args);
1075 SESSION_TEST ((error == 0), "server bound to %U/%d", format_ip46_address,
1076 &server_sep.ip, 1, server_sep.port);
1077 listener = listen_session_get_from_handle (bind_args.handle);
1078 ip4_address_t lcl_ip = {
1079 .as_u32 = clib_host_to_net_u32 (0x01020304),
1081 ip4_address_t rmt_ip = {
1082 .as_u32 = clib_host_to_net_u32 (0x05060708),
1084 fib_prefix_t lcl_pref = {
1085 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
1087 .fp_proto = FIB_PROTOCOL_IP4,
1089 fib_prefix_t rmt_pref = {
1090 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1092 .fp_proto = FIB_PROTOCOL_IP4,
1095 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1096 &rmt_pref.fp_addr.ip4, lcl_port,
1097 rmt_port, TRANSPORT_PROTO_TCP, 0,
1099 SESSION_TEST ((tc == 0), "optimized lookup should not work (port)");
1102 * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
1104 session_rule_add_del_args_t args = {
1105 .table_args.lcl = lcl_pref,
1106 .table_args.rmt = rmt_pref,
1107 .table_args.lcl_port = lcl_port,
1108 .table_args.rmt_port = rmt_port,
1109 .table_args.action_index = server_index,
1110 .table_args.is_add = 1,
1113 error = vnet_session_rule_add_del (&args);
1114 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
1115 args.table_args.action_index);
1117 tc = session_lookup_connection4 (0, &lcl_pref.fp_addr.ip4,
1118 &rmt_pref.fp_addr.ip4, lcl_port, rmt_port,
1119 TRANSPORT_PROTO_TCP);
1120 SESSION_TEST ((tc->c_index == listener->connection_index),
1121 "optimized lookup should return the listener");
1122 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1123 &rmt_pref.fp_addr.ip4, lcl_port,
1124 rmt_port, TRANSPORT_PROTO_TCP, 0,
1126 SESSION_TEST ((tc->c_index == listener->connection_index),
1127 "lookup should return the listener");
1128 s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4,
1129 lcl_port, rmt_port, TRANSPORT_PROTO_TCP);
1130 SESSION_TEST ((s->connection_index == listener->connection_index),
1131 "safe lookup should return the listener");
1132 session_endpoint_t sep = {
1133 .ip = rmt_pref.fp_addr,
1136 .transport_proto = TRANSPORT_PROTO_TCP,
1138 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1139 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1140 "should not work (global scope)");
1142 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1143 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1144 rmt_port, TRANSPORT_PROTO_TCP, 0,
1146 SESSION_TEST ((tc == 0),
1147 "optimized lookup for wrong lcl port + 1 should not work");
1150 * Add 1.2.3.4/16 * 5.6.7.8/16 4321
1152 args.table_args.lcl_port = 0;
1153 args.scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1154 error = vnet_session_rule_add_del (&args);
1155 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 4321 action %d",
1156 args.table_args.action_index);
1157 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1158 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1159 rmt_port, TRANSPORT_PROTO_TCP, 0,
1161 SESSION_TEST ((tc->c_index == listener->connection_index),
1162 "optimized lookup for lcl port + 1 should work");
1163 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1164 SESSION_TEST ((handle == server_index), "local session endpoint lookup "
1165 "should work (lcl ip was zeroed)");
1168 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1170 args.table_args.lcl_port = 1234;
1171 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1172 args.table_args.lcl.fp_len = 30;
1173 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1174 args.table_args.rmt.fp_len = 30;
1175 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1176 error = vnet_session_rule_add_del (&args);
1177 SESSION_TEST ((error == 0), "Add 1.2.3.4/30 1234 5.6.7.8/30 4321 action %d",
1178 args.table_args.action_index);
1182 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1183 TRANSPORT_PROTO_TCP);
1184 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1185 TRANSPORT_PROTO_TCP);
1188 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1189 &rmt_pref.fp_addr.ip4, lcl_port,
1190 rmt_port, TRANSPORT_PROTO_TCP, 0,
1192 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1193 "should fail (deny rule)");
1194 SESSION_TEST ((is_filtered == 1), "lookup should be filtered (deny)");
1196 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1197 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1198 "5.6.7.8/16 4321 in local table should return deny");
1200 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1201 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1202 rmt_port, TRANSPORT_PROTO_TCP, 0,
1204 SESSION_TEST ((tc->c_index == listener->connection_index),
1205 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should work");
1208 * "Mask" deny rule with more specific allow:
1209 * Add allow rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -3 (allow)
1211 args.table_args.is_add = 1;
1212 args.table_args.lcl_port = 1234;
1213 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1214 args.table_args.lcl.fp_len = 32;
1215 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1216 args.table_args.rmt.fp_len = 32;
1217 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1218 error = vnet_session_rule_add_del (&args);
1219 SESSION_TEST ((error == 0), "Add masking rule 1.2.3.4/30 1234 5.6.7.8/32 "
1220 "4321 action %d", args.table_args.action_index);
1223 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1224 &rmt_pref.fp_addr.ip4, lcl_port,
1225 rmt_port, TRANSPORT_PROTO_TCP, 0,
1227 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
1228 "should fail (allow without app)");
1229 SESSION_TEST ((is_filtered == 0), "lookup should NOT be filtered");
1231 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1232 SESSION_TEST ((handle == SESSION_INVALID_HANDLE), "lookup for 1.2.3.4/32 "
1233 "1234 5.6.7.8/32 4321 in local table should return invalid");
1237 vlib_cli_output (vm, "Local rules");
1238 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1239 TRANSPORT_PROTO_TCP);
1242 sep.ip.ip4.as_u32 += 1 << 24;
1243 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1244 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234"
1245 " 5.6.7.9/32 4321 in local table should return deny");
1247 vnet_connect_args_t connect_args = {
1248 .app_index = attach_args.app_index,
1251 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1253 /* Try connecting */
1254 error = vnet_connect (&connect_args);
1255 SESSION_TEST ((error != 0), "connect should fail");
1256 rv = clib_error_get_code (error);
1257 SESSION_TEST ((rv == VNET_API_ERROR_APP_CONNECT_FILTERED),
1258 "connect should be filtered");
1260 sep.ip.ip4.as_u32 -= 1 << 24;
1263 * Delete masking rule: 1.2.3.4/32 1234 5.6.7.8/32 4321 allow
1265 args.table_args.is_add = 0;
1266 args.table_args.lcl_port = 1234;
1267 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1268 args.table_args.lcl.fp_len = 32;
1269 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1270 args.table_args.rmt.fp_len = 32;
1271 error = vnet_session_rule_add_del (&args);
1272 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 allow");
1276 * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
1278 args.table_args.is_add = 1;
1279 args.table_args.lcl_port = 0;
1280 args.table_args.lcl.fp_len = 0;
1281 args.table_args.rmt.fp_len = 16;
1282 args.table_args.action_index = -1;
1283 error = vnet_session_rule_add_del (&args);
1284 SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d",
1285 args.table_args.action_index);
1289 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1290 TRANSPORT_PROTO_TCP);
1291 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1292 TRANSPORT_PROTO_TCP);
1295 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1296 SESSION_TEST ((handle == SESSION_DROP_HANDLE),
1297 "local session endpoint lookup should return deny");
1300 * Delete 1.2.3.4/32 1234 5.6.7.8/32 4321 deny
1302 args.table_args.is_add = 0;
1303 args.table_args.lcl_port = 1234;
1304 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1305 args.table_args.lcl.fp_len = 30;
1306 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1307 args.table_args.rmt.fp_len = 30;
1308 error = vnet_session_rule_add_del (&args);
1309 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1311 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1312 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1313 "local session endpoint lookup should return invalid");
1316 * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and
1317 * 1.2.3.4/16 1234 5.6.7.8/16 4321
1319 args.table_args.is_add = 0;
1320 args.table_args.lcl_port = 0;
1321 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1322 args.table_args.lcl.fp_len = 0;
1323 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1324 args.table_args.rmt.fp_len = 16;
1325 args.table_args.rmt_port = 4321;
1326 error = vnet_session_rule_add_del (&args);
1327 SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
1328 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1329 SESSION_TEST ((handle != server_index), "local session endpoint lookup "
1330 "should not work (removed)");
1332 args.table_args.is_add = 0;
1333 args.table_args.lcl = lcl_pref;
1335 args.table_args.is_add = 0;
1336 args.table_args.lcl_port = 0;
1337 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1338 args.table_args.lcl.fp_len = 16;
1339 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1340 args.table_args.rmt.fp_len = 16;
1341 args.table_args.rmt_port = 4321;
1342 error = vnet_session_rule_add_del (&args);
1343 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321");
1344 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1345 &rmt_pref.fp_addr.ip4, lcl_port + 1,
1346 rmt_port, TRANSPORT_PROTO_TCP, 0,
1348 SESSION_TEST ((tc == 0),
1349 "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should not "
1352 args.table_args.is_add = 0;
1353 args.table_args.lcl_port = 1234;
1354 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1355 args.table_args.lcl.fp_len = 16;
1356 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1357 args.table_args.rmt.fp_len = 16;
1358 args.table_args.rmt_port = 4321;
1359 error = vnet_session_rule_add_del (&args);
1360 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321");
1361 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1362 &rmt_pref.fp_addr.ip4, lcl_port,
1363 rmt_port, TRANSPORT_PROTO_TCP, 0,
1365 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should "
1366 "not work (del + deny)");
1368 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny");
1369 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1370 &rmt_pref.fp_addr.ip4, lcl_port,
1371 rmt_port, TRANSPORT_PROTO_TCP, 0,
1373 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should"
1374 " not work (no-rule)");
1377 * Test tags. Add/overwrite/del rule with tag
1379 args.table_args.is_add = 1;
1380 args.table_args.lcl_port = 1234;
1381 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1382 args.table_args.lcl.fp_len = 16;
1383 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1384 args.table_args.rmt.fp_len = 16;
1385 args.table_args.rmt_port = 4321;
1386 args.table_args.tag = format (0, "test_rule");
1387 args.table_args.action_index = server_index;
1388 error = vnet_session_rule_add_del (&args);
1389 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 deny "
1393 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1394 TRANSPORT_PROTO_TCP);
1395 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1396 TRANSPORT_PROTO_TCP);
1398 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1399 &rmt_pref.fp_addr.ip4, lcl_port,
1400 rmt_port, TRANSPORT_PROTO_TCP, 0,
1402 SESSION_TEST ((tc->c_index == listener->connection_index),
1403 "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should work");
1405 vec_free (args.table_args.tag);
1406 args.table_args.lcl_port = 1234;
1407 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1408 args.table_args.lcl.fp_len = 16;
1409 args.table_args.tag = format (0, "test_rule_overwrite");
1410 error = vnet_session_rule_add_del (&args);
1411 SESSION_TEST ((error == 0),
1412 "Overwrite 1.2.3.4/16 1234 5.6.7.8/16 4321 deny tag test_rule"
1416 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1417 TRANSPORT_PROTO_TCP);
1418 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1419 TRANSPORT_PROTO_TCP);
1422 args.table_args.is_add = 0;
1423 args.table_args.lcl_port += 1;
1424 error = vnet_session_rule_add_del (&args);
1425 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny "
1426 "tag %v", args.table_args.tag);
1429 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1430 TRANSPORT_PROTO_TCP);
1431 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1432 TRANSPORT_PROTO_TCP);
1434 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
1435 &rmt_pref.fp_addr.ip4, lcl_port,
1436 rmt_port, TRANSPORT_PROTO_TCP, 0,
1438 SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/32 4321 should not"
1443 * Test local rules with multiple namespaces
1447 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1449 args.table_args.is_add = 1;
1450 args.table_args.lcl_port = 1234;
1451 args.table_args.rmt_port = 0;
1452 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1453 args.table_args.lcl.fp_len = 32;
1454 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1455 args.table_args.rmt.fp_len = 32;
1456 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1457 args.table_args.tag = 0;
1458 args.scope = SESSION_RULE_SCOPE_LOCAL;
1459 error = vnet_session_rule_add_del (&args);
1460 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d",
1461 args.table_args.action_index);
1463 * Add 'white' rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
1465 args.table_args.is_add = 1;
1466 args.table_args.lcl_port = 1234;
1467 args.table_args.rmt_port = 4321;
1468 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1469 args.table_args.lcl.fp_len = 32;
1470 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1471 args.table_args.rmt.fp_len = 32;
1472 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW;
1473 error = vnet_session_rule_add_del (&args);
1477 session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4,
1478 TRANSPORT_PROTO_TCP);
1481 vnet_app_namespace_add_del_args_t ns_args = {
1484 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
1487 error = vnet_app_namespace_add_del (&ns_args);
1488 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
1489 clib_error_get_code (error));
1490 app_ns = app_namespace_get_from_id (ns_id);
1492 attach_args.namespace_id = ns_id;
1493 attach_args.api_client_index = dummy_server_api_index - 1;
1494 error = vnet_application_attach (&attach_args);
1495 SESSION_TEST ((error == 0), "server2 attached");
1496 server_index2 = attach_args.app_index;
1499 * Add deny rule 1.2.3.4/32 1234 5.6.7.8/32 0 action -2 (drop)
1501 args.table_args.lcl_port = 1234;
1502 args.table_args.rmt_port = 0;
1503 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
1504 args.table_args.lcl.fp_len = 32;
1505 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
1506 args.table_args.rmt.fp_len = 32;
1507 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
1508 args.appns_index = app_namespace_index (app_ns);
1510 error = vnet_session_rule_add_del (&args);
1511 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d "
1512 "in test namespace", args.table_args.action_index);
1514 * Lookup default namespace
1516 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1517 SESSION_TEST ((handle == SESSION_INVALID_HANDLE),
1518 "lookup for 1.2.3.4/32 1234 5.6.7.8/32 4321 in local table "
1519 "should return allow (invalid)");
1522 handle = session_lookup_local_endpoint (local_ns_index, &sep);
1523 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1524 "5.6.7.8/16 432*2* in local table should return deny");
1527 connect_args.app_index = server_index;
1528 clib_memcpy (&connect_args.sep, &sep, sizeof (sep));
1530 error = vnet_connect (&connect_args);
1531 SESSION_TEST ((error != 0), "connect should fail");
1532 rv = clib_error_get_code (error);
1533 SESSION_TEST ((rv == VNET_API_ERROR_APP_CONNECT_FILTERED),
1534 "connect should be filtered");
1537 * Lookup test namespace
1539 handle = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1540 SESSION_TEST ((handle == SESSION_DROP_HANDLE), "lookup for 1.2.3.4/32 1234 "
1541 "5.6.7.8/16 4321 in local table should return deny");
1543 connect_args.app_index = server_index;
1544 error = vnet_connect (&connect_args);
1545 SESSION_TEST ((error != 0), "connect should fail");
1546 rv = clib_error_get_code (error);
1547 SESSION_TEST ((rv == VNET_API_ERROR_APP_CONNECT_FILTERED),
1548 "connect should be filtered");
1550 args.table_args.is_add = 0;
1551 vnet_session_rule_add_del (&args);
1553 args.appns_index = 0;
1554 args.table_args.is_add = 0;
1555 vnet_session_rule_add_del (&args);
1557 args.table_args.rmt_port = 4321;
1558 vnet_session_rule_add_del (&args);
1562 vec_free (args.table_args.tag);
1563 vnet_app_detach_args_t detach_args = {
1564 .app_index = server_index,
1566 vnet_application_detach (&detach_args);
1568 detach_args.app_index = server_index2;
1569 vnet_application_detach (&detach_args);
1572 vec_free (attach_args.name);
1577 session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
1579 u64 options[APP_OPTIONS_N_OPTIONS];
1580 char *show_listeners = "sh session listeners tcp verbose";
1581 char *show_local_listeners = "sh app ns table default";
1582 unformat_input_t tmp_input;
1583 u32 server_index, app_index;
1584 u32 dummy_server_api_index = ~0, sw_if_index = 0;
1585 clib_error_t *error = 0;
1587 stream_session_t *s;
1588 transport_connection_t *tc;
1589 u16 lcl_port = 1234, rmt_port = 4321;
1590 app_namespace_t *app_ns;
1593 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1595 if (unformat (input, "verbose"))
1599 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1605 ip4_address_t lcl_ip = {
1606 .as_u32 = clib_host_to_net_u32 (0x01020304),
1608 ip4_address_t rmt_ip = {
1609 .as_u32 = clib_host_to_net_u32 (0x05060708),
1611 fib_prefix_t rmt_pref = {
1612 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1614 .fp_proto = FIB_PROTOCOL_IP4,
1616 session_endpoint_t sep = {
1617 .ip = rmt_pref.fp_addr,
1620 .transport_proto = TRANSPORT_PROTO_TCP,
1624 * Create loopback interface
1626 session_create_lookpback (0, &sw_if_index, &lcl_ip);
1628 app_ns = app_namespace_get_default ();
1629 app_ns->sw_if_index = sw_if_index;
1631 clib_memset (options, 0, sizeof (options));
1632 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
1633 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
1634 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_PROXY;
1635 options[APP_OPTIONS_PROXY_TRANSPORT] = 1 << TRANSPORT_PROTO_TCP;
1636 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1637 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1638 vnet_app_attach_args_t attach_args = {
1639 .api_client_index = ~0,
1642 .session_cb_vft = &dummy_session_cbs,
1643 .name = format (0, "session_test"),
1646 attach_args.api_client_index = dummy_server_api_index;
1647 error = vnet_application_attach (&attach_args);
1648 SESSION_TEST ((error == 0), "server attachment should work");
1649 server_index = attach_args.app_index;
1653 unformat_init_string (&tmp_input, show_listeners,
1654 strlen (show_listeners));
1655 vlib_cli_input (vm, &tmp_input, 0, 0);
1656 unformat_init_string (&tmp_input, show_local_listeners,
1657 strlen (show_local_listeners));
1658 vlib_cli_input (vm, &tmp_input, 0, 0);
1661 tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port,
1662 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1663 SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be "
1665 s = listen_session_get (tc->s_index);
1666 SESSION_TEST ((s->app_index == server_index), "lookup should return"
1669 tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port,
1670 TRANSPORT_PROTO_TCP, 0, &is_filtered);
1671 SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should"
1674 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1675 SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1678 vnet_app_detach_args_t detach_args = {
1679 .app_index = server_index,
1681 vnet_application_detach (&detach_args);
1685 unformat_init_string (&tmp_input, show_listeners,
1686 strlen (show_listeners));
1687 vlib_cli_input (vm, &tmp_input, 0, 0);
1688 unformat_init_string (&tmp_input, show_local_listeners,
1689 strlen (show_local_listeners));
1690 vlib_cli_input (vm, &tmp_input, 0, 0);
1693 app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep);
1694 SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX),
1695 "local session endpoint lookup should not work after detach");
1697 unformat_free (&tmp_input);
1698 vec_free (attach_args.name);
1702 static clib_error_t *
1703 session_test (vlib_main_t * vm,
1704 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1708 vnet_session_enable_disable (vm, 1);
1710 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1712 if (unformat (input, "basic"))
1713 res = session_test_basic (vm, input);
1714 else if (unformat (input, "namespace"))
1715 res = session_test_namespace (vm, input);
1716 else if (unformat (input, "rules-table"))
1717 res = session_test_rule_table (vm, input);
1718 else if (unformat (input, "rules"))
1719 res = session_test_rules (vm, input);
1720 else if (unformat (input, "proxy"))
1721 res = session_test_proxy (vm, input);
1722 else if (unformat (input, "endpt-cfg"))
1723 res = session_test_endpoint_cfg (vm, input);
1724 else if (unformat (input, "all"))
1726 if ((res = session_test_basic (vm, input)))
1728 if ((res = session_test_namespace (vm, input)))
1730 if ((res = session_test_rule_table (vm, input)))
1732 if ((res = session_test_rules (vm, input)))
1734 if ((res = session_test_proxy (vm, input)))
1736 if ((res = session_test_endpoint_cfg (vm, input)))
1745 return clib_error_return (0, "Session unit test failed");
1750 VLIB_CLI_COMMAND (tcp_test_command, static) =
1752 .path = "test session",
1753 .short_help = "internal session unit tests",
1754 .function = session_test,
1759 * fd.io coding-style-patch-verification: ON
1762 * eval: (c-set-style "gnu")