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, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
510 SESSION_TEST ((res == 1),
511 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 1: %d",
515 * 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
517 args.lcl.fp_addr.ip4 = lcl_ip;
518 args.lcl.fp_len = 24;
519 args.action_index = action_index++;
520 error = session_rules_table_add_del (srt, &args);
521 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/16 4321 action %d",
523 args.rmt.fp_addr.ip4 = rmt_ip;
524 args.rmt.fp_len = 24;
525 args.action_index = action_index++;
526 error = session_rules_table_add_del (srt, &args);
527 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/24 4321 action %d",
531 * 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
533 args.lcl.fp_addr.ip4 = lcl_ip2;
534 args.lcl.fp_len = 24;
535 args.rmt.fp_addr.ip4 = rmt_ip2;
536 args.rmt.fp_len = 16;
537 args.action_index = action_index++;
538 error = session_rules_table_add_del (srt, &args);
539 SESSION_TEST ((error == 0), "Add 2.2.2.2/24 1234 6.6.6.6/16 4321 action %d",
541 args.lcl.fp_addr.ip4 = lcl_ip3;
542 args.rmt.fp_addr.ip4 = rmt_ip3;
543 args.action_index = action_index++;
544 error = session_rules_table_add_del (srt, &args);
545 SESSION_TEST ((error == 0), "Add 3.3.3.3/24 1234 7.7.7.7/16 4321 action %d",
549 * Add again 3.3.3.3/24 1234 7.7.7.7/16 4321
551 args.lcl.fp_addr.ip4 = lcl_ip3;
552 args.rmt.fp_addr.ip4 = rmt_ip3;
553 args.action_index = action_index++;
554 error = session_rules_table_add_del (srt, &args);
555 SESSION_TEST ((error == 0), "overwrite 3.3.3.3/24 1234 7.7.7.7/16 4321 "
556 "action %d", action_index - 1);
559 * 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
560 * and 3.3.3.3 1234 7.7.7.7 4321
563 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
564 SESSION_TEST ((res == 3),
565 "Lookup 1.2.3.4 1234 5.6.7.8 4321 action " "should be 3: %d",
568 lcl_lkup.as_u32 = clib_host_to_net_u32 (0x01020204);
569 rmt_lkup.as_u32 = clib_host_to_net_u32 (0x05060709);
571 session_rules_table_lookup4 (srt, &lcl_lkup,
572 &rmt_lkup, lcl_port, rmt_port);
573 SESSION_TEST ((res == 1),
574 "Lookup 1.2.2.4 1234 5.6.7.9 4321, action " "should be 1: %d",
578 session_rules_table_lookup4 (srt, &lcl_ip3, &rmt_ip3, lcl_port, rmt_port);
579 SESSION_TEST ((res == 6),
580 "Lookup 3.3.3.3 1234 7.7.7.7 4321, action "
581 "should be 6 (updated): %d", res);
584 * Add 1.2.3.4/24 * 5.6.7.8/24 *
585 * Lookup 1.2.3.4 1234 5.6.7.8 4321 and 1.2.3.4 1235 5.6.7.8 4321
587 args.lcl.fp_addr.ip4 = lcl_ip;
588 args.rmt.fp_addr.ip4 = rmt_ip;
589 args.lcl.fp_len = 24;
590 args.rmt.fp_len = 24;
593 args.action_index = action_index++;
594 error = session_rules_table_add_del (srt, &args);
595 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 * 5.6.7.8/24 * action %d",
598 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
599 SESSION_TEST ((res == 7),
600 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should"
601 " be 7 (lpm dst): %d", res);
603 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
604 lcl_port + 1, rmt_port);
605 SESSION_TEST ((res == 7),
606 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 7: %d",
610 * Del 1.2.3.4/24 * 5.6.7.8/24 *
611 * Add 1.2.3.4/16 * 5.6.7.8/16 * and 1.2.3.4/24 1235 5.6.7.8/24 4321
612 * Lookup 1.2.3.4 1234 5.6.7.8 4321, 1.2.3.4 1235 5.6.7.8 4321 and
613 * 1.2.3.4 1235 5.6.7.8 4322
616 error = session_rules_table_add_del (srt, &args);
617 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 * 5.6.7.8/24 *");
619 args.lcl.fp_addr.ip4 = lcl_ip;
620 args.rmt.fp_addr.ip4 = rmt_ip;
621 args.lcl.fp_len = 16;
622 args.rmt.fp_len = 16;
625 args.action_index = action_index++;
627 error = session_rules_table_add_del (srt, &args);
628 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 * action %d",
631 args.lcl.fp_addr.ip4 = lcl_ip;
632 args.rmt.fp_addr.ip4 = rmt_ip;
633 args.lcl.fp_len = 24;
634 args.rmt.fp_len = 24;
635 args.lcl_port = lcl_port + 1;
636 args.rmt_port = rmt_port;
637 args.action_index = action_index++;
639 error = session_rules_table_add_del (srt, &args);
640 SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1235 5.6.7.8/24 4321 action %d",
644 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
647 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
648 SESSION_TEST ((res == 3),
649 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
652 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
653 lcl_port + 1, rmt_port);
654 SESSION_TEST ((res == 9),
655 "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 9: %d",
658 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip,
659 lcl_port + 1, rmt_port + 1);
660 SESSION_TEST ((res == 8),
661 "Lookup 1.2.3.4 1235 5.6.7.8 4322, action should " "be 8: %d",
665 * Delete 1.2.0.0/16 1234 5.6.0.0/16 4321 and 1.2.0.0/16 * 5.6.0.0/16 *
666 * Lookup 1.2.3.4 1234 5.6.7.8 4321
668 args.lcl_port = 1234;
669 args.rmt_port = 4321;
670 args.lcl.fp_len = 16;
671 args.rmt.fp_len = 16;
673 error = session_rules_table_add_del (srt, &args);
674 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 1234 5.6.0.0/16 4321");
676 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
677 SESSION_TEST ((res == 3),
678 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
684 error = session_rules_table_add_del (srt, &args);
685 SESSION_TEST ((error == 0), "Del 1.2.0.0/16 * 5.6.0.0/16 *");
687 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
688 SESSION_TEST ((res == 3),
689 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
693 * Delete 1.2.3.4/24 1234 5.6.7.5/24
695 args.lcl.fp_addr.ip4 = lcl_ip;
696 args.rmt.fp_addr.ip4 = rmt_ip;
697 args.lcl.fp_len = 24;
698 args.rmt.fp_len = 24;
699 args.lcl_port = 1234;
700 args.rmt_port = 4321;
702 error = session_rules_table_add_del (srt, &args);
703 SESSION_TEST ((error == 0), "Del 1.2.3.4/24 1234 5.6.7.5/24");
705 session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port);
706 SESSION_TEST ((res == 2), "Action should be 2: %d", res);
712 session_test_rules (vlib_main_t * vm, unformat_input_t * input)
714 session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
715 u64 options[SESSION_OPTIONS_N_OPTIONS];
716 u16 lcl_port = 1234, rmt_port = 4321;
717 u32 server_index, app_index;
718 u32 dummy_server_api_index = ~0;
719 transport_connection_t *tc;
720 u32 dummy_port = 1111;
721 clib_error_t *error = 0;
722 u8 segment_name[128];
723 stream_session_t *listener, *s;
724 app_namespace_t *default_ns = app_namespace_get_default ();
725 u32 local_ns_index = default_ns->local_table_index;
728 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
730 if (unformat (input, "verbose"))
734 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
740 server_sep.is_ip4 = 1;
741 server_sep.port = dummy_port;
742 memset (options, 0, sizeof (options));
744 vnet_app_attach_args_t attach_args = {
745 .api_client_index = ~0,
748 .session_cb_vft = &dummy_session_cbs,
749 .segment_name = segment_name,
752 vnet_bind_args_t bind_args = {
758 * Attach server with global and local default scope
760 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
761 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
762 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
763 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
764 attach_args.namespace_id = 0;
765 attach_args.api_client_index = dummy_server_api_index;
766 error = vnet_application_attach (&attach_args);
767 SESSION_TEST ((error == 0), "server attached");
768 server_index = attach_args.app_index;
770 bind_args.app_index = server_index;
771 error = vnet_bind (&bind_args);
772 SESSION_TEST ((error == 0), "server bound to %U/%d", format_ip46_address,
773 &server_sep.ip, 1, server_sep.port);
774 listener = listen_session_get_from_handle (bind_args.handle);
775 ip4_address_t lcl_ip = {
776 .as_u32 = clib_host_to_net_u32 (0x01020304),
778 ip4_address_t rmt_ip = {
779 .as_u32 = clib_host_to_net_u32 (0x05060708),
781 fib_prefix_t lcl_pref = {
782 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
784 .fp_proto = FIB_PROTOCOL_IP4,
786 fib_prefix_t rmt_pref = {
787 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
789 .fp_proto = FIB_PROTOCOL_IP4,
792 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
793 &rmt_pref.fp_addr.ip4, lcl_port,
794 rmt_port, TRANSPORT_PROTO_TCP, 0);
795 SESSION_TEST ((tc == 0), "optimized lookup should not work (port)");
798 * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
800 session_rule_add_del_args_t args = {
801 .table_args.lcl = lcl_pref,
802 .table_args.rmt = rmt_pref,
803 .table_args.lcl_port = lcl_port,
804 .table_args.rmt_port = rmt_port,
805 .table_args.action_index = server_index,
806 .table_args.is_add = 1,
809 error = vnet_session_rule_add_del (&args);
810 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
811 args.table_args.action_index);
813 tc = session_lookup_connection4 (0, &lcl_pref.fp_addr.ip4,
814 &rmt_pref.fp_addr.ip4, lcl_port, rmt_port,
815 TRANSPORT_PROTO_TCP);
816 SESSION_TEST ((tc->c_index == listener->connection_index),
817 "optimized lookup should return the listener");
818 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
819 &rmt_pref.fp_addr.ip4, lcl_port,
820 rmt_port, TRANSPORT_PROTO_TCP, 0);
821 SESSION_TEST ((tc->c_index == listener->connection_index),
822 "lookup should return the listener");
823 s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4,
824 lcl_port, rmt_port, TRANSPORT_PROTO_TCP);
825 SESSION_TEST ((s->connection_index == listener->connection_index),
826 "safe lookup should return the listener");
827 session_endpoint_t sep = {
828 .ip = rmt_pref.fp_addr,
831 .transport_proto = TRANSPORT_PROTO_TCP,
833 app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
834 SESSION_TEST ((app_index != server_index), "local session endpoint lookup "
835 "should not work (global scope)");
837 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
838 &rmt_pref.fp_addr.ip4, lcl_port + 1,
839 rmt_port, TRANSPORT_PROTO_TCP, 0);
840 SESSION_TEST ((tc == 0),
841 "optimized lookup for wrong lcl port + 1 should not work");
844 * Add 1.2.3.4/16 * 5.6.7.8/16 4321
846 args.table_args.lcl_port = 0;
847 args.scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
848 error = vnet_session_rule_add_del (&args);
849 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 4321 action %d",
850 args.table_args.action_index);
851 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
852 &rmt_pref.fp_addr.ip4, lcl_port + 1,
853 rmt_port, TRANSPORT_PROTO_TCP, 0);
854 SESSION_TEST ((tc->c_index == listener->connection_index),
855 "optimized lookup for lcl port + 1 should work");
856 app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
857 SESSION_TEST ((app_index != server_index), "local session endpoint lookup "
858 "should not work (constrained lcl ip)");
861 * Add drop rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
863 args.table_args.lcl_port = 1234;
864 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
865 args.table_args.lcl.fp_len = 32;
866 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
867 args.table_args.rmt.fp_len = 32;
868 args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
869 error = vnet_session_rule_add_del (&args);
870 SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d",
871 args.table_args.action_index);
875 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
876 TRANSPORT_PROTO_TCP);
877 session_lookup_dump_local_rules_table (0, FIB_PROTOCOL_IP4,
878 TRANSPORT_PROTO_TCP);
881 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
882 &rmt_pref.fp_addr.ip4, lcl_port,
883 rmt_port, TRANSPORT_PROTO_TCP, 0);
884 SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
885 "should fail (drop rule)");
888 * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
890 args.table_args.lcl_port = 0;
891 args.table_args.lcl.fp_len = 0;
892 args.table_args.rmt.fp_len = 16;
893 args.table_args.action_index = server_index;
894 error = vnet_session_rule_add_del (&args);
895 SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d",
896 args.table_args.action_index);
900 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
901 TRANSPORT_PROTO_TCP);
902 session_lookup_dump_local_rules_table (0, FIB_PROTOCOL_IP4,
903 TRANSPORT_PROTO_TCP);
906 app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
907 SESSION_TEST ((app_index == server_index), "local session endpoint lookup "
911 * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and
912 * 1.2.3.4/16 1234 5.6.7.8/16 4321
914 args.table_args.is_add = 0;
915 error = vnet_session_rule_add_del (&args);
916 SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
917 app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
918 SESSION_TEST ((app_index != server_index), "local session endpoint lookup "
919 "should not work (removed)");
921 args.table_args.is_add = 0;
922 args.table_args.lcl = lcl_pref;
923 error = vnet_session_rule_add_del (&args);
924 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321");
925 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
926 &rmt_pref.fp_addr.ip4, lcl_port + 1,
927 rmt_port, TRANSPORT_PROTO_TCP, 0);
928 SESSION_TEST ((tc == 0), "optimized lookup for lcl port + 1 should not "
931 args.table_args.is_add = 0;
932 args.table_args.lcl_port = 1234;
933 error = vnet_session_rule_add_del (&args);
934 SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321");
935 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
936 &rmt_pref.fp_addr.ip4, lcl_port,
937 rmt_port, TRANSPORT_PROTO_TCP, 0);
938 SESSION_TEST ((tc == 0),
939 "optimized lookup should not work (del + negative)");
941 args.table_args.is_add = 0;
942 args.table_args.lcl_port = 1234;
943 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
944 args.table_args.lcl.fp_len = 32;
945 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
946 args.table_args.rmt.fp_len = 32;
947 error = vnet_session_rule_add_del (&args);
948 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 drop");
949 tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
950 &rmt_pref.fp_addr.ip4, lcl_port,
951 rmt_port, TRANSPORT_PROTO_TCP, 0);
952 SESSION_TEST ((tc == 0), "optimized lookup should not work (no-rule)");
955 * Test tags. Add/del rule with tag
957 args.table_args.is_add = 1;
958 args.table_args.lcl_port = 1234;
959 args.table_args.lcl.fp_addr.ip4 = lcl_ip;
960 args.table_args.lcl.fp_len = 16;
961 args.table_args.rmt.fp_addr.ip4 = rmt_ip;
962 args.table_args.rmt.fp_len = 16;
963 args.table_args.tag = format (0, "test_rule");
964 error = vnet_session_rule_add_del (&args);
965 SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 drop "
969 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
970 TRANSPORT_PROTO_TCP);
971 session_lookup_dump_local_rules_table (0, FIB_PROTOCOL_IP4,
972 TRANSPORT_PROTO_TCP);
974 args.table_args.is_add = 0;
975 args.table_args.lcl_port += 1;
976 SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 drop "
983 session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
985 u64 options[SESSION_OPTIONS_N_OPTIONS];
986 u32 server_index, app_index;
987 u32 dummy_server_api_index = ~0, sw_if_index = 0;
988 clib_error_t *error = 0;
989 u8 segment_name[128], intf_mac[6], sst;
991 transport_connection_t *tc;
992 u16 lcl_port = 1234, rmt_port = 4321;
993 app_namespace_t *app_ns;
996 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
998 if (unformat (input, "verbose"))
1002 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1008 ip4_address_t lcl_ip = {
1009 .as_u32 = clib_host_to_net_u32 (0x01020304),
1011 ip4_address_t rmt_ip = {
1012 .as_u32 = clib_host_to_net_u32 (0x05060708),
1014 fib_prefix_t rmt_pref = {
1015 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1017 .fp_proto = FIB_PROTOCOL_IP4,
1019 session_endpoint_t sep = {
1020 .ip = rmt_pref.fp_addr,
1023 .transport_proto = TRANSPORT_PROTO_TCP,
1027 * Create loopback interface
1029 memset (intf_mac, 0, sizeof (intf_mac));
1030 if (vnet_create_loopback_interface (&sw_if_index, intf_mac, 0, 0))
1032 clib_warning ("couldn't create loopback. stopping the test!");
1035 vnet_sw_interface_set_flags (vnet_get_main (), sw_if_index,
1036 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1037 ip4_add_del_interface_address (vlib_get_main (), sw_if_index, &lcl_ip,
1040 app_ns = app_namespace_get_default ();
1041 app_ns->sw_if_index = sw_if_index;
1043 memset (options, 0, sizeof (options));
1044 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
1045 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_PROXY;
1046 options[APP_OPTIONS_PROXY_TRANSPORT] = 1 << TRANSPORT_PROTO_TCP;
1047 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1048 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1049 vnet_app_attach_args_t attach_args = {
1050 .api_client_index = ~0,
1053 .session_cb_vft = &dummy_session_cbs,
1054 .segment_name = segment_name,
1057 attach_args.api_client_index = dummy_server_api_index;
1058 error = vnet_application_attach (&attach_args);
1059 SESSION_TEST ((error == 0), "server attachment should work");
1060 server_index = attach_args.app_index;
1063 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1064 TRANSPORT_PROTO_TCP);
1066 tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port,
1067 TRANSPORT_PROTO_TCP, 0);
1068 SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be "
1070 sst = session_type_from_proto_and_ip (TRANSPORT_PROTO_TCP, 1);
1071 s = listen_session_get (sst, tc->s_index);
1072 SESSION_TEST ((s->app_index == server_index), "lookup should return the"
1075 tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port,
1076 TRANSPORT_PROTO_TCP, 0);
1077 SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should"
1081 session_lookup_dump_local_rules_table (app_ns->local_table_index,
1083 TRANSPORT_PROTO_TCP);
1085 session_lookup_local_session_endpoint (app_ns->local_table_index, &sep);
1086 SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1089 vnet_app_detach_args_t detach_args = {
1090 .app_index = server_index,
1092 vnet_application_detach (&detach_args);
1095 session_lookup_dump_local_rules_table (app_ns->local_table_index,
1097 TRANSPORT_PROTO_TCP);
1100 session_lookup_local_session_endpoint (app_ns->local_table_index, &sep);
1101 SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX),
1102 "local session endpoint lookup should not work after detach");
1107 static clib_error_t *
1108 session_test (vlib_main_t * vm,
1109 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1113 vnet_session_enable_disable (vm, 1);
1115 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1117 if (unformat (input, "namespace"))
1119 res = session_test_namespace (vm, input);
1121 else if (unformat (input, "rules-table"))
1122 res = session_test_rule_table (vm, input);
1123 else if (unformat (input, "rules"))
1124 res = session_test_rules (vm, input);
1125 else if (unformat (input, "proxy"))
1126 res = session_test_proxy (vm, input);
1132 return clib_error_return (0, "Session unit test failed");
1137 VLIB_CLI_COMMAND (tcp_test_command, static) =
1139 .path = "test session",
1140 .short_help = "internal session unit tests",
1141 .function = session_test,
1146 * fd.io coding-style-patch-verification: ON
1149 * eval: (c-set-style "gnu")