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>
22 #define SESSION_TEST_I(_cond, _comment, _args...) \
24 int _evald = (_cond); \
26 fformat(stderr, "FAIL:%d: " _comment "\n", \
29 fformat(stderr, "PASS:%d: " _comment "\n", \
35 #define SESSION_TEST(_cond, _comment, _args...) \
37 if (!SESSION_TEST_I(_cond, _comment, ##_args)) { \
43 dummy_session_reset_callback (stream_session_t * s)
45 clib_warning ("called...");
49 dummy_session_connected_callback (u32 app_index, u32 api_context,
50 stream_session_t * s, u8 is_fail)
52 clib_warning ("called...");
57 dummy_add_segment_callback (u32 client_index, const u8 * seg_name,
60 clib_warning ("called...");
65 dummy_redirect_connect_callback (u32 client_index, void *mp)
67 return VNET_API_ERROR_SESSION_REDIRECT;
71 dummy_session_disconnect_callback (stream_session_t * s)
73 clib_warning ("called...");
77 dummy_session_accept_callback (stream_session_t * s)
79 clib_warning ("called...");
84 dummy_server_rx_callback (stream_session_t * s)
86 clib_warning ("called...");
91 static session_cb_vft_t dummy_session_cbs = {
92 .session_reset_callback = dummy_session_reset_callback,
93 .session_connected_callback = dummy_session_connected_callback,
94 .session_accept_callback = dummy_session_accept_callback,
95 .session_disconnect_callback = dummy_session_disconnect_callback,
96 .builtin_server_rx_callback = dummy_server_rx_callback,
97 .redirect_connect_callback = dummy_redirect_connect_callback,
102 session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
104 u64 options[SESSION_OPTIONS_N_OPTIONS], dummy_secret = 1234;
105 u32 server_index, server_st_index, server_local_st_index;
106 u32 dummy_port = 1234, local_listener, client_index;
107 u32 dummy_api_context = 4321, dummy_client_api_index = 1234;
108 u32 dummy_server_api_index = ~0, sw_if_index = 0;
109 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
110 session_endpoint_t client_sep = SESSION_ENDPOINT_NULL;
111 session_endpoint_t intf_sep = SESSION_ENDPOINT_NULL;
112 clib_error_t *error = 0;
113 u8 *ns_id = format (0, "appns1"), intf_mac[6];
114 app_namespace_t *app_ns;
115 u8 segment_name[128];
116 application_t *server;
120 server_sep.is_ip4 = 1;
121 server_sep.port = dummy_port;
122 client_sep.is_ip4 = 1;
123 client_sep.port = dummy_port;
124 memset (options, 0, sizeof (options));
125 memset (intf_mac, 0, sizeof (intf_mac));
127 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
128 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
129 vnet_app_attach_args_t attach_args = {
130 .api_client_index = ~0,
133 .session_cb_vft = &dummy_session_cbs,
134 .segment_name = segment_name,
137 vnet_bind_args_t bind_args = {
142 vnet_connect_args_t connect_args = {
148 vnet_unbind_args_t unbind_args = {
149 .handle = bind_args.handle,
153 vnet_app_detach_args_t detach_args = {
157 ip4_address_t intf_addr = {
158 .as_u32 = clib_host_to_net_u32 (0x06000105),
161 intf_sep.ip.ip4 = intf_addr;
163 intf_sep.port = dummy_port;
166 * Insert namespace and lookup
169 vnet_app_namespace_add_del_args_t ns_args = {
171 .secret = dummy_secret,
172 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
175 error = vnet_app_namespace_add_del (&ns_args);
176 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
177 clib_error_get_code (error));
179 app_ns = app_namespace_get_from_id (ns_id);
180 SESSION_TEST ((app_ns != 0), "should find ns %v status", ns_id);
181 SESSION_TEST ((app_ns->ns_secret == dummy_secret), "secret should be %d",
183 SESSION_TEST ((app_ns->sw_if_index == APP_NAMESPACE_INVALID_INDEX),
184 "sw_if_index should be invalid");
187 * Try application attach with wrong secret
190 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
191 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
192 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret - 1;
193 attach_args.namespace_id = ns_id;
194 attach_args.api_client_index = dummy_server_api_index;
196 error = vnet_application_attach (&attach_args);
197 SESSION_TEST ((error != 0), "app attachment should fail");
198 code = clib_error_get_code (error);
199 SESSION_TEST ((code == VNET_API_ERROR_APP_WRONG_NS_SECRET),
200 "code should be wrong ns secret: %d", code);
203 * Attach server with global default scope
205 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
206 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
207 options[APP_OPTIONS_NAMESPACE_SECRET] = 0;
208 attach_args.namespace_id = 0;
209 attach_args.api_client_index = dummy_server_api_index;
210 error = vnet_application_attach (&attach_args);
211 SESSION_TEST ((error == 0), "server attachment should work");
212 server_index = attach_args.app_index;
213 server = application_get (server_index);
214 SESSION_TEST ((server->ns_index == 0),
215 "server should be in the default ns");
217 bind_args.app_index = server_index;
218 error = vnet_bind (&bind_args);
219 SESSION_TEST ((error == 0), "server bind should work");
221 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
222 s = session_lookup_listener (server_st_index, &server_sep);
223 SESSION_TEST ((s != 0), "listener should exist in global table");
224 SESSION_TEST ((s->app_index == server_index), "app_index should be that of "
226 server_local_st_index = application_local_session_table (server);
227 SESSION_TEST ((server_local_st_index == APP_INVALID_INDEX),
228 "server shouldn't have access to local table");
230 unbind_args.app_index = server_index;
231 unbind_args.handle = bind_args.handle;
232 error = vnet_unbind (&unbind_args);
233 SESSION_TEST ((error == 0), "unbind should work");
235 s = session_lookup_listener (server_st_index, &server_sep);
236 SESSION_TEST ((s == 0), "listener should not exist in global table");
238 detach_args.app_index = server_index;
239 vnet_application_detach (&detach_args);
242 * Attach server with local and global scope
244 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
245 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
246 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret;
247 attach_args.namespace_id = ns_id;
248 attach_args.api_client_index = dummy_server_api_index;
249 error = vnet_application_attach (&attach_args);
250 SESSION_TEST ((error == 0), "server attachment should work");
251 server_index = attach_args.app_index;
252 server = application_get (server_index);
253 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
254 "server should be in the right ns");
256 bind_args.app_index = server_index;
257 error = vnet_bind (&bind_args);
258 SESSION_TEST ((error == 0), "bind should work");
259 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
260 s = session_lookup_listener (server_st_index, &server_sep);
261 SESSION_TEST ((s != 0), "listener should exist in global table");
262 SESSION_TEST ((s->app_index == server_index), "app_index should be that of "
264 server_local_st_index = application_local_session_table (server);
266 session_lookup_local_session_endpoint (server_local_st_index,
268 SESSION_TEST ((local_listener != SESSION_INVALID_INDEX),
269 "listener should exist in local table");
272 * Try client connect with 1) local scope 2) global scope
274 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
275 attach_args.api_client_index = dummy_client_api_index;
276 error = vnet_application_attach (&attach_args);
277 SESSION_TEST ((error == 0), "client attachment should work");
278 client_index = attach_args.app_index;
279 connect_args.api_context = dummy_api_context;
280 connect_args.app_index = client_index;
281 error = vnet_connect (&connect_args);
282 SESSION_TEST ((error != 0), "client connect should return error code");
283 code = clib_error_get_code (error);
284 SESSION_TEST ((code == VNET_API_ERROR_INVALID_VALUE),
285 "error code should be invalid value (zero ip)");
286 connect_args.sep.ip.ip4.as_u8[0] = 127;
287 error = vnet_connect (&connect_args);
288 SESSION_TEST ((error != 0), "client connect should return error code");
289 code = clib_error_get_code (error);
290 SESSION_TEST ((code == VNET_API_ERROR_SESSION_REDIRECT),
291 "error code should be redirect");
292 detach_args.app_index = client_index;
293 vnet_application_detach (&detach_args);
295 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
296 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
297 attach_args.api_client_index = dummy_client_api_index;
298 error = vnet_application_attach (&attach_args);
299 SESSION_TEST ((error == 0), "client attachment should work");
300 error = vnet_connect (&connect_args);
301 SESSION_TEST ((error != 0), "client connect should return error code");
302 code = clib_error_get_code (error);
303 SESSION_TEST ((code == VNET_API_ERROR_SESSION_CONNECT),
304 "error code should be connect (nothing in local scope)");
305 detach_args.app_index = client_index;
306 vnet_application_detach (&detach_args);
309 * Unbind and detach server and then re-attach with local scope only
311 unbind_args.handle = bind_args.handle;
312 unbind_args.app_index = server_index;
313 error = vnet_unbind (&unbind_args);
314 SESSION_TEST ((error == 0), "unbind should work");
316 s = session_lookup_listener (server_st_index, &server_sep);
317 SESSION_TEST ((s == 0), "listener should not exist in global table");
319 session_lookup_local_session_endpoint (server_local_st_index,
321 SESSION_TEST ((s == 0), "listener should not exist in local table");
323 detach_args.app_index = server_index;
324 vnet_application_detach (&detach_args);
326 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
327 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
328 attach_args.api_client_index = dummy_server_api_index;
329 error = vnet_application_attach (&attach_args);
330 SESSION_TEST ((error == 0), "app attachment should work");
331 server_index = attach_args.app_index;
332 server = application_get (server_index);
333 SESSION_TEST ((server->ns_index == app_namespace_index (app_ns)),
334 "app should be in the right ns");
336 bind_args.app_index = server_index;
337 error = vnet_bind (&bind_args);
338 SESSION_TEST ((error == 0), "bind should work");
340 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
341 s = session_lookup_listener (server_st_index, &server_sep);
342 SESSION_TEST ((s == 0), "listener should not exist in global table");
343 server_local_st_index = application_local_session_table (server);
345 session_lookup_local_session_endpoint (server_local_st_index,
347 SESSION_TEST ((local_listener != SESSION_INVALID_INDEX),
348 "listener should exist in local table");
350 unbind_args.handle = bind_args.handle;
351 error = vnet_unbind (&unbind_args);
352 SESSION_TEST ((error == 0), "unbind should work");
355 session_lookup_local_session_endpoint (server_local_st_index,
357 SESSION_TEST ((local_listener == SESSION_INVALID_INDEX),
358 "listener should not exist in local table");
361 * Client attach + connect in default ns with local scope
363 options[APP_OPTIONS_FLAGS] &= ~APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
364 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
365 attach_args.namespace_id = 0;
366 attach_args.api_client_index = dummy_client_api_index;
367 vnet_application_attach (&attach_args);
368 error = vnet_connect (&connect_args);
369 SESSION_TEST ((error != 0), "client connect should return error code");
370 code = clib_error_get_code (error);
371 SESSION_TEST ((code == VNET_API_ERROR_SESSION_CONNECT),
372 "error code should be connect (not in same ns)");
373 detach_args.app_index = client_index;
374 vnet_application_detach (&detach_args);
379 detach_args.app_index = server_index;
380 vnet_application_detach (&detach_args);
383 * Create loopback interface
385 if (vnet_create_loopback_interface (&sw_if_index, intf_mac, 0, 0))
387 clib_warning ("couldn't create loopback. stopping the test!");
390 vnet_sw_interface_set_flags (vnet_get_main (), sw_if_index,
391 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
392 ip4_add_del_interface_address (vlib_get_main (), sw_if_index, &intf_addr,
398 ns_args.sw_if_index = sw_if_index;
399 error = vnet_app_namespace_add_del (&ns_args);
400 SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
401 clib_error_get_code (error));
404 * Attach server with local and global scope
406 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
407 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
408 options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret;
409 attach_args.namespace_id = ns_id;
410 attach_args.api_client_index = dummy_server_api_index;
411 error = vnet_application_attach (&attach_args);
412 SESSION_TEST ((error == 0), "server attachment should work");
413 server_index = attach_args.app_index;
415 bind_args.app_index = server_index;
416 error = vnet_bind (&bind_args);
417 server_st_index = application_session_table (server, FIB_PROTOCOL_IP4);
418 s = session_lookup_listener (server_st_index, &server_sep);
419 SESSION_TEST ((s == 0), "zero listener should not exist in global table");
421 s = session_lookup_listener (server_st_index, &intf_sep);
422 SESSION_TEST ((s != 0), "intf listener should exist in global table");
423 SESSION_TEST ((s->app_index == server_index), "app_index should be that of "
425 server_local_st_index = application_local_session_table (server);
427 session_lookup_local_session_endpoint (server_local_st_index,
429 SESSION_TEST ((local_listener != SESSION_INVALID_INDEX),
430 "zero listener should exist in local table");
431 detach_args.app_index = server_index;
432 vnet_application_detach (&detach_args);
438 vnet_delete_loopback_interface (sw_if_index);
443 session_test_rule_table (vlib_main_t * vm, unformat_input_t * input)
445 session_rules_table_t _srt, *srt = &_srt;
446 u16 lcl_port = 1234, rmt_port = 4321;
447 u32 action_index = 1, res;
448 ip4_address_t lcl_lkup, rmt_lkup;
452 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
454 if (unformat (input, "verbose"))
458 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
464 memset (srt, 0, sizeof (*srt));
465 session_rules_table_init (srt);
467 ip4_address_t lcl_ip = {
468 .as_u32 = clib_host_to_net_u32 (0x01020304),
470 ip4_address_t rmt_ip = {
471 .as_u32 = clib_host_to_net_u32 (0x05060708),
473 ip4_address_t lcl_ip2 = {
474 .as_u32 = clib_host_to_net_u32 (0x02020202),
476 ip4_address_t rmt_ip2 = {
477 .as_u32 = clib_host_to_net_u32 (0x06060606),
479 ip4_address_t lcl_ip3 = {
480 .as_u32 = clib_host_to_net_u32 (0x03030303),
482 ip4_address_t rmt_ip3 = {
483 .as_u32 = clib_host_to_net_u32 (0x07070707),
485 fib_prefix_t lcl_pref = {
486 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
488 .fp_proto = FIB_PROTOCOL_IP4,
490 fib_prefix_t rmt_pref = {
491 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
493 .fp_proto = FIB_PROTOCOL_IP4,
496 session_rule_table_add_del_args_t args = {
499 .lcl_port = lcl_port,
500 .rmt_port = rmt_port,
501 .action_index = action_index++,
504 error = session_rules_table_add_del (srt, &args);
505 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
509 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
511 SESSION_TEST ((res == 1),
512 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 1: %d",
516 * 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
518 args.lcl.fp_addr.ip4 = lcl_ip;
519 args.lcl.fp_len = 24;
520 args.action_index = action_index++;
521 error = session_rules_table_add_del (srt, &args);
522 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/16 4321 action %d",
524 args.rmt.fp_addr.ip4 = rmt_ip;
525 args.rmt.fp_len = 24;
526 args.action_index = action_index++;
527 error = session_rules_table_add_del (srt, &args);
528 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/24 4321 action %d",
532 * 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
534 args.lcl.fp_addr.ip4 = lcl_ip2;
535 args.lcl.fp_len = 24;
536 args.rmt.fp_addr.ip4 = rmt_ip2;
537 args.rmt.fp_len = 16;
538 args.action_index = action_index++;
539 error = session_rules_table_add_del (srt, &args);
540 SESSION_TEST ((error == 0), "Add 2.2.2.2/24 1234 6.6.6.6/16 4321 action %d",
542 args.lcl.fp_addr.ip4 = lcl_ip3;
543 args.rmt.fp_addr.ip4 = rmt_ip3;
544 args.action_index = action_index++;
545 error = session_rules_table_add_del (srt, &args);
546 SESSION_TEST ((error == 0), "Add 3.3.3.3/24 1234 7.7.7.7/16 4321 action %d",
550 * Add again 3.3.3.3/24 1234 7.7.7.7/16 4321
552 args.lcl.fp_addr.ip4 = lcl_ip3;
553 args.rmt.fp_addr.ip4 = rmt_ip3;
554 args.action_index = action_index++;
555 error = session_rules_table_add_del (srt, &args);
556 SESSION_TEST ((error == 0), "overwrite 3.3.3.3/24 1234 7.7.7.7/16 4321 "
557 "action %d", action_index - 1);
560 * 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
561 * and 3.3.3.3 1234 7.7.7.7 4321
564 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
566 SESSION_TEST ((res == 3),
567 "Lookup 1.2.3.4 1234 5.6.7.8 4321 action " "should be 3: %d",
570 lcl_lkup.as_u32 = clib_host_to_net_u32 (0x01020204);
571 rmt_lkup.as_u32 = clib_host_to_net_u32 (0x05060709);
573 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_lkup,
574 &rmt_lkup, lcl_port, rmt_port);
575 SESSION_TEST ((res == 1),
576 "Lookup 1.2.2.4 1234 5.6.7.9 4321, action " "should be 1: %d",
580 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip3, &rmt_ip3,
582 SESSION_TEST ((res == 6),
583 "Lookup 3.3.3.3 1234 7.7.7.7 4321, action "
584 "should be 6 (updated): %d", res);
587 * Add 1.2.3.4/24 * 5.6.7.8/24 *
588 * Lookup 1.2.3.4 1234 5.6.7.8 4321 and 1.2.3.4 1235 5.6.7.8 4321
590 args.lcl.fp_addr.ip4 = lcl_ip;
591 args.rmt.fp_addr.ip4 = rmt_ip;
592 args.lcl.fp_len = 24;
593 args.rmt.fp_len = 24;
596 args.action_index = action_index++;
597 error = session_rules_table_add_del (srt, &args);
598 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 * 5.6.7.8/24 * action %d",
601 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
603 SESSION_TEST ((res == 7),
604 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should"
605 " be 7 (lpm dst): %d", res);
607 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
608 lcl_port + 1, rmt_port);
609 SESSION_TEST ((res == 7),
610 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 7: %d",
614 * Del 1.2.3.4/24 * 5.6.7.8/24 *
615 * Add 1.2.3.4/16 * 5.6.7.8/16 * and 1.2.3.4/24 1235 5.6.7.8/24 4321
616 * Lookup 1.2.3.4 1234 5.6.7.8 4321, 1.2.3.4 1235 5.6.7.8 4321 and
617 * 1.2.3.4 1235 5.6.7.8 4322
620 error = session_rules_table_add_del (srt, &args);
621 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 * 5.6.7.8/24 *");
623 args.lcl.fp_addr.ip4 = lcl_ip;
624 args.rmt.fp_addr.ip4 = rmt_ip;
625 args.lcl.fp_len = 16;
626 args.rmt.fp_len = 16;
629 args.action_index = action_index++;
631 error = session_rules_table_add_del (srt, &args);
632 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 * action %d",
635 args.lcl.fp_addr.ip4 = lcl_ip;
636 args.rmt.fp_addr.ip4 = rmt_ip;
637 args.lcl.fp_len = 24;
638 args.rmt.fp_len = 24;
639 args.lcl_port = lcl_port + 1;
640 args.rmt_port = rmt_port;
641 args.action_index = action_index++;
643 error = session_rules_table_add_del (srt, &args);
644 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1235 5.6.7.8/24 4321 action %d",
648 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4,
649 TRANSPORT_PROTO_TCP);
652 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
654 SESSION_TEST ((res == 3),
655 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
658 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
659 lcl_port + 1, rmt_port);
660 SESSION_TEST ((res == 9),
661 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 9: %d",
664 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
665 lcl_port + 1, rmt_port + 1);
666 SESSION_TEST ((res == 8),
667 "Lookup 1.2.3.4 1235 5.6.7.8 4322, action should " "be 8: %d",
671 * Delete 1.2.0.0/16 1234 5.6.0.0/16 4321 and 1.2.0.0/16 * 5.6.0.0/16 *
672 * Lookup 1.2.3.4 1234 5.6.7.8 4321
674 args.lcl_port = 1234;
675 args.rmt_port = 4321;
676 args.lcl.fp_len = 16;
677 args.rmt.fp_len = 16;
679 error = session_rules_table_add_del (srt, &args);
680 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 1234 5.6.0.0/16 4321");
682 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
684 SESSION_TEST ((res == 3),
685 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
691 error = session_rules_table_add_del (srt, &args);
692 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 * 5.6.0.0/16 *");
694 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
696 SESSION_TEST ((res == 3),
697 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
701 * Delete 1.2.3.4/24 1234 5.6.7.5/24
703 args.lcl.fp_addr.ip4 = lcl_ip;
704 args.rmt.fp_addr.ip4 = rmt_ip;
705 args.lcl.fp_len = 24;
706 args.rmt.fp_len = 24;
707 args.lcl_port = 1234;
708 args.rmt_port = 4321;
710 error = session_rules_table_add_del (srt, &args);
711 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 1234 5.6.7.5/24");
713 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
715 SESSION_TEST ((res == 2), "Action should be 2: %d", res);
721 session_test_rules (vlib_main_t * vm, unformat_input_t * input)
723 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
724 u64 options[SESSION_OPTIONS_N_OPTIONS];
725 u16 lcl_port = 1234, rmt_port = 4321;
726 u32 server_index, app_index;
727 u32 dummy_server_api_index = ~0;
728 transport_connection_t *tc;
729 u32 dummy_port = 1111;
730 clib_error_t *error = 0;
731 u8 segment_name[128];
732 stream_session_t *listener, *s;
733 app_namespace_t *default_ns = app_namespace_get_default ();
734 u32 local_ns_index = default_ns->local_table_index;
736 server_sep.is_ip4 = 1;
737 server_sep.port = dummy_port;
738 memset (options, 0, sizeof (options));
740 vnet_app_attach_args_t attach_args = {
741 .api_client_index = ~0,
744 .session_cb_vft = &dummy_session_cbs,
745 .segment_name = segment_name,
748 vnet_bind_args_t bind_args = {
754 * Attach server with global and local default scope
756 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
757 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
758 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
759 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
760 attach_args.namespace_id = 0;
761 attach_args.api_client_index = dummy_server_api_index;
762 error = vnet_application_attach (&attach_args);
763 SESSION_TEST ((error == 0), "server attached");
764 server_index = attach_args.app_index;
766 bind_args.app_index = server_index;
767 error = vnet_bind (&bind_args);
768 SESSION_TEST ((error == 0), "server bound to %U/%d", format_ip46_address,
769 &server_sep.ip, 1, server_sep.port);
770 listener = listen_session_get_from_handle (bind_args.handle);
771 ip4_address_t lcl_ip = {
772 .as_u32 = clib_host_to_net_u32 (0x01020304),
774 ip4_address_t rmt_ip = {
775 .as_u32 = clib_host_to_net_u32 (0x05060708),
777 fib_prefix_t lcl_pref = {
778 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
780 .fp_proto = FIB_PROTOCOL_IP4,
782 fib_prefix_t rmt_pref = {
783 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
785 .fp_proto = FIB_PROTOCOL_IP4,
788 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
789 &rmt_pref.fp_addr.ip4, lcl_port,
790 rmt_port, TRANSPORT_PROTO_TCP, 0);
791 SESSION_TEST ((tc == 0), "optimized lookup should not work (port)");
794 * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
796 session_rule_add_del_args_t args = {
797 .table_args.lcl = lcl_pref,
798 .table_args.rmt = rmt_pref,
799 .table_args.lcl_port = lcl_port,
800 .table_args.rmt_port = rmt_port,
801 .table_args.action_index = server_index,
802 .table_args.is_add = 1,
805 error = vnet_session_rule_add_del (&args);
806 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
807 args.table_args.action_index);
809 tc = session_lookup_connection4 (0, &lcl_pref.fp_addr.ip4,
810 &rmt_pref.fp_addr.ip4, lcl_port, rmt_port,
811 TRANSPORT_PROTO_TCP);
812 SESSION_TEST ((tc->c_index == listener->connection_index),
813 "optimized lookup should return the listener");
814 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
815 &rmt_pref.fp_addr.ip4, lcl_port,
816 rmt_port, TRANSPORT_PROTO_TCP, 0);
817 SESSION_TEST ((tc->c_index == listener->connection_index),
818 "lookup should return the listener");
819 s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4,
820 lcl_port, rmt_port, TRANSPORT_PROTO_TCP);
821 SESSION_TEST ((s->connection_index == listener->connection_index),
822 "safe lookup should return the listener");
823 session_endpoint_t sep = {
824 .ip = rmt_pref.fp_addr,
827 .transport_proto = TRANSPORT_PROTO_TCP,
829 app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
830 SESSION_TEST ((app_index != server_index), "local session endpoint lookup "
831 "should not work (global scope)");
833 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
834 &rmt_pref.fp_addr.ip4, lcl_port + 1,
835 rmt_port, TRANSPORT_PROTO_TCP, 0);
836 SESSION_TEST ((tc == 0),
837 "optimized lookup for wrong lcl port + 1 should not" " work");
840 * Add 1.2.3.4/16 * 5.6.7.8/16 4321
842 args.table_args.lcl_port = 0;
843 args.scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
844 error = vnet_session_rule_add_del (&args);
845 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 4321 action %d",
846 args.table_args.action_index);
847 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
848 &rmt_pref.fp_addr.ip4, lcl_port + 1,
849 rmt_port, TRANSPORT_PROTO_TCP, 0);
850 SESSION_TEST ((tc->c_index == listener->connection_index),
851 "optimized lookup for lcl port + 1 should work");
852 app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
853 SESSION_TEST ((app_index != server_index), "local session endpoint lookup "
854 "should not work (constrained lcl ip)");
857 * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
859 args.table_args.lcl.fp_len = 0;
860 error = vnet_session_rule_add_del (&args);
861 SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d",
862 args.table_args.action_index);
863 app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
864 SESSION_TEST ((app_index == server_index), "local session endpoint lookup "
868 * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and
869 * 1.2.3.4/16 1234 5.6.7.8/16 4321
871 args.table_args.is_add = 0;
872 error = vnet_session_rule_add_del (&args);
873 SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
874 app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
875 SESSION_TEST ((app_index != server_index), "local session endpoint lookup "
876 "should not work (removed)");
878 args.table_args.is_add = 0;
879 args.table_args.lcl = lcl_pref;
880 error = vnet_session_rule_add_del (&args);
881 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321");
882 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
883 &rmt_pref.fp_addr.ip4, lcl_port + 1,
884 rmt_port, TRANSPORT_PROTO_TCP, 0);
885 SESSION_TEST ((tc == 0), "optimized lookup for lcl port + 1 should not "
888 args.table_args.is_add = 0;
889 args.table_args.lcl_port = 1234;
890 error = vnet_session_rule_add_del (&args);
891 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321");
892 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
893 &rmt_pref.fp_addr.ip4, lcl_port,
894 rmt_port, TRANSPORT_PROTO_TCP, 0);
895 SESSION_TEST ((tc == 0), "optimized lookup should not work (del)");
900 session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
902 u64 options[SESSION_OPTIONS_N_OPTIONS];
903 u32 server_index, app_index;
904 u32 dummy_server_api_index = ~0, sw_if_index = 0;
905 clib_error_t *error = 0;
906 u8 segment_name[128], intf_mac[6], sst;
908 transport_connection_t *tc;
909 u16 lcl_port = 1234, rmt_port = 4321;
910 app_namespace_t *app_ns;
913 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
915 if (unformat (input, "verbose"))
919 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
925 ip4_address_t lcl_ip = {
926 .as_u32 = clib_host_to_net_u32 (0x01020304),
928 ip4_address_t rmt_ip = {
929 .as_u32 = clib_host_to_net_u32 (0x05060708),
931 fib_prefix_t rmt_pref = {
932 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
934 .fp_proto = FIB_PROTOCOL_IP4,
936 session_endpoint_t sep = {
937 .ip = rmt_pref.fp_addr,
940 .transport_proto = TRANSPORT_PROTO_TCP,
944 * Create loopback interface
946 memset (intf_mac, 0, sizeof (intf_mac));
947 if (vnet_create_loopback_interface (&sw_if_index, intf_mac, 0, 0))
949 clib_warning ("couldn't create loopback. stopping the test!");
952 vnet_sw_interface_set_flags (vnet_get_main (), sw_if_index,
953 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
954 ip4_add_del_interface_address (vlib_get_main (), sw_if_index, &lcl_ip,
957 app_ns = app_namespace_get_default ();
958 app_ns->sw_if_index = sw_if_index;
960 memset (options, 0, sizeof (options));
961 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
962 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_PROXY;
963 options[APP_OPTIONS_PROXY_TRANSPORT] = 1 << TRANSPORT_PROTO_TCP;
964 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
965 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
966 vnet_app_attach_args_t attach_args = {
967 .api_client_index = ~0,
970 .session_cb_vft = &dummy_session_cbs,
971 .segment_name = segment_name,
974 attach_args.api_client_index = dummy_server_api_index;
975 error = vnet_application_attach (&attach_args);
976 SESSION_TEST ((error == 0), "server attachment should work");
977 server_index = attach_args.app_index;
980 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
981 TRANSPORT_PROTO_TCP);
983 tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port,
984 TRANSPORT_PROTO_TCP, 0);
985 SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be "
987 sst = session_type_from_proto_and_ip (TRANSPORT_PROTO_TCP, 1);
988 s = listen_session_get (sst, tc->s_index);
989 SESSION_TEST ((s->app_index == server_index), "lookup should return the"
992 tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port,
993 TRANSPORT_PROTO_TCP, 0);
994 SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should"
998 session_lookup_dump_local_rules_table (app_ns->local_table_index,
1000 TRANSPORT_PROTO_TCP);
1002 session_lookup_local_session_endpoint (app_ns->local_table_index, &sep);
1003 SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1006 vnet_app_detach_args_t detach_args = {
1007 .app_index = server_index,
1009 vnet_application_detach (&detach_args);
1012 session_lookup_dump_local_rules_table (app_ns->local_table_index,
1014 TRANSPORT_PROTO_TCP);
1017 session_lookup_local_session_endpoint (app_ns->local_table_index, &sep);
1018 SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX),
1019 "local session endpoint lookup should not work after detach");
1024 static clib_error_t *
1025 session_test (vlib_main_t * vm,
1026 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1030 vnet_session_enable_disable (vm, 1);
1032 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1034 if (unformat (input, "namespace"))
1036 res = session_test_namespace (vm, input);
1038 else if (unformat (input, "rules-table"))
1039 res = session_test_rule_table (vm, input);
1040 else if (unformat (input, "rules"))
1041 res = session_test_rules (vm, input);
1042 else if (unformat (input, "proxy"))
1043 res = session_test_proxy (vm, input);
1049 return clib_error_return (0, "Session unit test failed");
1054 VLIB_CLI_COMMAND (tcp_test_command, static) =
1056 .path = "test session",
1057 .short_help = "internal session unit tests",
1058 .function = session_test,
1063 * fd.io coding-style-patch-verification: ON
1066 * eval: (c-set-style "gnu")