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;
737 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
739 if (unformat (input, "verbose"))
743 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
749 server_sep.is_ip4 = 1;
750 server_sep.port = dummy_port;
751 memset (options, 0, sizeof (options));
753 vnet_app_attach_args_t attach_args = {
754 .api_client_index = ~0,
757 .session_cb_vft = &dummy_session_cbs,
758 .segment_name = segment_name,
761 vnet_bind_args_t bind_args = {
767 * Attach server with global and local default scope
769 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
770 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
771 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
772 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
773 attach_args.namespace_id = 0;
774 attach_args.api_client_index = dummy_server_api_index;
775 error = vnet_application_attach (&attach_args);
776 SESSION_TEST ((error == 0), "server attached");
777 server_index = attach_args.app_index;
779 bind_args.app_index = server_index;
780 error = vnet_bind (&bind_args);
781 SESSION_TEST ((error == 0), "server bound to %U/%d", format_ip46_address,
782 &server_sep.ip, 1, server_sep.port);
783 listener = listen_session_get_from_handle (bind_args.handle);
784 ip4_address_t lcl_ip = {
785 .as_u32 = clib_host_to_net_u32 (0x01020304),
787 ip4_address_t rmt_ip = {
788 .as_u32 = clib_host_to_net_u32 (0x05060708),
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 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
802 &rmt_pref.fp_addr.ip4, lcl_port,
803 rmt_port, TRANSPORT_PROTO_TCP, 0);
804 SESSION_TEST ((tc == 0), "optimized lookup should not work (port)");
807 * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
809 session_rule_add_del_args_t args = {
810 .table_args.lcl = lcl_pref,
811 .table_args.rmt = rmt_pref,
812 .table_args.lcl_port = lcl_port,
813 .table_args.rmt_port = rmt_port,
814 .table_args.action_index = server_index,
815 .table_args.is_add = 1,
818 error = vnet_session_rule_add_del (&args);
819 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
820 args.table_args.action_index);
822 tc = session_lookup_connection4 (0, &lcl_pref.fp_addr.ip4,
823 &rmt_pref.fp_addr.ip4, lcl_port, rmt_port,
824 TRANSPORT_PROTO_TCP);
825 SESSION_TEST ((tc->c_index == listener->connection_index),
826 "optimized lookup should return the listener");
827 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
828 &rmt_pref.fp_addr.ip4, lcl_port,
829 rmt_port, TRANSPORT_PROTO_TCP, 0);
830 SESSION_TEST ((tc->c_index == listener->connection_index),
831 "lookup should return the listener");
832 s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4,
833 lcl_port, rmt_port, TRANSPORT_PROTO_TCP);
834 SESSION_TEST ((s->connection_index == listener->connection_index),
835 "safe lookup should return the listener");
836 session_endpoint_t sep = {
837 .ip = rmt_pref.fp_addr,
840 .transport_proto = TRANSPORT_PROTO_TCP,
842 app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
843 SESSION_TEST ((app_index != server_index), "local session endpoint lookup "
844 "should not work (global scope)");
846 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
847 &rmt_pref.fp_addr.ip4, lcl_port + 1,
848 rmt_port, TRANSPORT_PROTO_TCP, 0);
849 SESSION_TEST ((tc == 0),
850 "optimized lookup for wrong lcl port + 1 should not work");
853 * Add 1.2.3.4/16 * 5.6.7.8/16 4321
855 args.table_args.lcl_port = 0;
856 args.scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
857 error = vnet_session_rule_add_del (&args);
858 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 4321 action %d",
859 args.table_args.action_index);
860 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
861 &rmt_pref.fp_addr.ip4, lcl_port + 1,
862 rmt_port, TRANSPORT_PROTO_TCP, 0);
863 SESSION_TEST ((tc->c_index == listener->connection_index),
864 "optimized lookup for lcl port + 1 should work");
865 app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
866 SESSION_TEST ((app_index != server_index), "local session endpoint lookup "
867 "should not work (constrained lcl ip)");
870 * Add drop rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
872 args.table_args.lcl_port = 1234;
873 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
874 args.table_args.lcl.fp_len = 32;
875 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
876 args.table_args.rmt.fp_len = 32;
877 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
878 error = vnet_session_rule_add_del (&args);
879 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d",
880 args.table_args.action_index);
884 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
885 TRANSPORT_PROTO_TCP);
886 session_lookup_dump_local_rules_table (0, FIB_PROTOCOL_IP4,
887 TRANSPORT_PROTO_TCP);
890 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
891 &rmt_pref.fp_addr.ip4, lcl_port,
892 rmt_port, TRANSPORT_PROTO_TCP, 0);
893 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
894 "should fail (drop rule)");
897 * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
899 args.table_args.lcl_port = 0;
900 args.table_args.lcl.fp_len = 0;
901 args.table_args.rmt.fp_len = 16;
902 args.table_args.action_index = server_index;
903 error = vnet_session_rule_add_del (&args);
904 SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d",
905 args.table_args.action_index);
909 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
910 TRANSPORT_PROTO_TCP);
911 session_lookup_dump_local_rules_table (0, FIB_PROTOCOL_IP4,
912 TRANSPORT_PROTO_TCP);
915 app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
916 SESSION_TEST ((app_index == server_index), "local session endpoint lookup "
920 * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and
921 * 1.2.3.4/16 1234 5.6.7.8/16 4321
923 args.table_args.is_add = 0;
924 error = vnet_session_rule_add_del (&args);
925 SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
926 app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
927 SESSION_TEST ((app_index != server_index), "local session endpoint lookup "
928 "should not work (removed)");
930 args.table_args.is_add = 0;
931 args.table_args.lcl = lcl_pref;
932 error = vnet_session_rule_add_del (&args);
933 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321");
934 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
935 &rmt_pref.fp_addr.ip4, lcl_port + 1,
936 rmt_port, TRANSPORT_PROTO_TCP, 0);
937 SESSION_TEST ((tc == 0), "optimized lookup for lcl port + 1 should not "
940 args.table_args.is_add = 0;
941 args.table_args.lcl_port = 1234;
942 error = vnet_session_rule_add_del (&args);
943 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321");
944 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
945 &rmt_pref.fp_addr.ip4, lcl_port,
946 rmt_port, TRANSPORT_PROTO_TCP, 0);
947 SESSION_TEST ((tc == 0),
948 "optimized lookup should not work (del + negative)");
950 args.table_args.is_add = 0;
951 args.table_args.lcl_port = 1234;
952 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
953 args.table_args.lcl.fp_len = 32;
954 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
955 args.table_args.rmt.fp_len = 32;
956 error = vnet_session_rule_add_del (&args);
957 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 drop");
958 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
959 &rmt_pref.fp_addr.ip4, lcl_port,
960 rmt_port, TRANSPORT_PROTO_TCP, 0);
961 SESSION_TEST ((tc == 0), "optimized lookup should not work (no-rule)");
966 session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
968 u64 options[SESSION_OPTIONS_N_OPTIONS];
969 u32 server_index, app_index;
970 u32 dummy_server_api_index = ~0, sw_if_index = 0;
971 clib_error_t *error = 0;
972 u8 segment_name[128], intf_mac[6], sst;
974 transport_connection_t *tc;
975 u16 lcl_port = 1234, rmt_port = 4321;
976 app_namespace_t *app_ns;
979 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
981 if (unformat (input, "verbose"))
985 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
991 ip4_address_t lcl_ip = {
992 .as_u32 = clib_host_to_net_u32 (0x01020304),
994 ip4_address_t rmt_ip = {
995 .as_u32 = clib_host_to_net_u32 (0x05060708),
997 fib_prefix_t rmt_pref = {
998 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1000 .fp_proto = FIB_PROTOCOL_IP4,
1002 session_endpoint_t sep = {
1003 .ip = rmt_pref.fp_addr,
1006 .transport_proto = TRANSPORT_PROTO_TCP,
1010 * Create loopback interface
1012 memset (intf_mac, 0, sizeof (intf_mac));
1013 if (vnet_create_loopback_interface (&sw_if_index, intf_mac, 0, 0))
1015 clib_warning ("couldn't create loopback. stopping the test!");
1018 vnet_sw_interface_set_flags (vnet_get_main (), sw_if_index,
1019 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1020 ip4_add_del_interface_address (vlib_get_main (), sw_if_index, &lcl_ip,
1023 app_ns = app_namespace_get_default ();
1024 app_ns->sw_if_index = sw_if_index;
1026 memset (options, 0, sizeof (options));
1027 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
1028 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_PROXY;
1029 options[APP_OPTIONS_PROXY_TRANSPORT] = 1 << TRANSPORT_PROTO_TCP;
1030 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1031 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1032 vnet_app_attach_args_t attach_args = {
1033 .api_client_index = ~0,
1036 .session_cb_vft = &dummy_session_cbs,
1037 .segment_name = segment_name,
1040 attach_args.api_client_index = dummy_server_api_index;
1041 error = vnet_application_attach (&attach_args);
1042 SESSION_TEST ((error == 0), "server attachment should work");
1043 server_index = attach_args.app_index;
1046 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1047 TRANSPORT_PROTO_TCP);
1049 tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port,
1050 TRANSPORT_PROTO_TCP, 0);
1051 SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be "
1053 sst = session_type_from_proto_and_ip (TRANSPORT_PROTO_TCP, 1);
1054 s = listen_session_get (sst, tc->s_index);
1055 SESSION_TEST ((s->app_index == server_index), "lookup should return the"
1058 tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port,
1059 TRANSPORT_PROTO_TCP, 0);
1060 SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should"
1064 session_lookup_dump_local_rules_table (app_ns->local_table_index,
1066 TRANSPORT_PROTO_TCP);
1068 session_lookup_local_session_endpoint (app_ns->local_table_index, &sep);
1069 SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1072 vnet_app_detach_args_t detach_args = {
1073 .app_index = server_index,
1075 vnet_application_detach (&detach_args);
1078 session_lookup_dump_local_rules_table (app_ns->local_table_index,
1080 TRANSPORT_PROTO_TCP);
1083 session_lookup_local_session_endpoint (app_ns->local_table_index, &sep);
1084 SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX),
1085 "local session endpoint lookup should not work after detach");
1090 static clib_error_t *
1091 session_test (vlib_main_t * vm,
1092 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1096 vnet_session_enable_disable (vm, 1);
1098 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1100 if (unformat (input, "namespace"))
1102 res = session_test_namespace (vm, input);
1104 else if (unformat (input, "rules-table"))
1105 res = session_test_rule_table (vm, input);
1106 else if (unformat (input, "rules"))
1107 res = session_test_rules (vm, input);
1108 else if (unformat (input, "proxy"))
1109 res = session_test_proxy (vm, input);
1115 return clib_error_return (0, "Session unit test failed");
1120 VLIB_CLI_COMMAND (tcp_test_command, static) =
1122 .path = "test session",
1123 .short_help = "internal session unit tests",
1124 .function = session_test,
1129 * fd.io coding-style-patch-verification: ON
1132 * eval: (c-set-style "gnu")