blob: 4b47754464dcd5ed33ead3a5fcc075af710d09c2 [file] [log] [blame]
Florin Corascea194d2017-10-02 00:18:51 -07001/*
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:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
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.
14 */
15
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>
Florin Coras1c710452017-10-17 00:03:13 -070020#include <vnet/session/session_rules_table.h>
Florin Corascea194d2017-10-02 00:18:51 -070021
22#define SESSION_TEST_I(_cond, _comment, _args...) \
23({ \
24 int _evald = (_cond); \
25 if (!(_evald)) { \
26 fformat(stderr, "FAIL:%d: " _comment "\n", \
27 __LINE__, ##_args); \
28 } else { \
29 fformat(stderr, "PASS:%d: " _comment "\n", \
30 __LINE__, ##_args); \
31 } \
32 _evald; \
33})
34
35#define SESSION_TEST(_cond, _comment, _args...) \
36{ \
37 if (!SESSION_TEST_I(_cond, _comment, ##_args)) { \
38 return 1; \
39 } \
40}
41
42void
43dummy_session_reset_callback (stream_session_t * s)
44{
45 clib_warning ("called...");
46}
47
48int
49dummy_session_connected_callback (u32 app_index, u32 api_context,
50 stream_session_t * s, u8 is_fail)
51{
52 clib_warning ("called...");
53 return -1;
54}
55
56int
57dummy_add_segment_callback (u32 client_index, const u8 * seg_name,
58 u32 seg_size)
59{
60 clib_warning ("called...");
61 return -1;
62}
63
64int
65dummy_redirect_connect_callback (u32 client_index, void *mp)
66{
67 return VNET_API_ERROR_SESSION_REDIRECT;
68}
69
70void
71dummy_session_disconnect_callback (stream_session_t * s)
72{
73 clib_warning ("called...");
74}
75
76int
77dummy_session_accept_callback (stream_session_t * s)
78{
79 clib_warning ("called...");
80 return -1;
81}
82
83int
84dummy_server_rx_callback (stream_session_t * s)
85{
86 clib_warning ("called...");
87 return -1;
88}
89
90/* *INDENT-OFF* */
91static 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,
98};
99/* *INDENT-ON* */
100
101static int
102session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
103{
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;
117 stream_session_t *s;
118 int code;
119
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));
126
Florin Coras7999e832017-10-31 01:51:04 -0700127 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
Florin Corascea194d2017-10-02 00:18:51 -0700128 options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
129 vnet_app_attach_args_t attach_args = {
130 .api_client_index = ~0,
131 .options = options,
132 .namespace_id = 0,
133 .session_cb_vft = &dummy_session_cbs,
134 .segment_name = segment_name,
135 };
136
137 vnet_bind_args_t bind_args = {
138 .sep = server_sep,
139 .app_index = 0,
140 };
141
142 vnet_connect_args_t connect_args = {
143 .sep = client_sep,
144 .app_index = 0,
145 .api_context = 0,
146 };
147
148 vnet_unbind_args_t unbind_args = {
149 .handle = bind_args.handle,
150 .app_index = 0,
151 };
152
153 vnet_app_detach_args_t detach_args = {
154 .app_index = 0,
155 };
156
157 ip4_address_t intf_addr = {
158 .as_u32 = clib_host_to_net_u32 (0x06000105),
159 };
160
161 intf_sep.ip.ip4 = intf_addr;
162 intf_sep.is_ip4 = 1;
163 intf_sep.port = dummy_port;
164
165 /*
166 * Insert namespace and lookup
167 */
168
169 vnet_app_namespace_add_del_args_t ns_args = {
170 .ns_id = ns_id,
171 .secret = dummy_secret,
172 .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
173 .is_add = 1
174 };
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));
178
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",
182 dummy_secret);
183 SESSION_TEST ((app_ns->sw_if_index == APP_NAMESPACE_INVALID_INDEX),
184 "sw_if_index should be invalid");
185
186 /*
187 * Try application attach with wrong secret
188 */
189
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;
195
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);
201
202 /*
203 * Attach server with global default scope
204 */
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");
216
217 bind_args.app_index = server_index;
218 error = vnet_bind (&bind_args);
219 SESSION_TEST ((error == 0), "server bind should work");
220
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 "
225 "the server");
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");
229
230 unbind_args.app_index = server_index;
Florin Corasfc1c6122017-10-26 14:25:12 -0700231 unbind_args.handle = bind_args.handle;
Florin Corascea194d2017-10-02 00:18:51 -0700232 error = vnet_unbind (&unbind_args);
233 SESSION_TEST ((error == 0), "unbind should work");
234
235 s = session_lookup_listener (server_st_index, &server_sep);
236 SESSION_TEST ((s == 0), "listener should not exist in global table");
237
238 detach_args.app_index = server_index;
239 vnet_application_detach (&detach_args);
240
241 /*
242 * Attach server with local and global scope
243 */
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");
255
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 "
263 "the server");
264 server_local_st_index = application_local_session_table (server);
Florin Coras3cbc04b2017-10-02 00:18:51 -0700265 local_listener =
266 session_lookup_local_session_endpoint (server_local_st_index,
267 &server_sep);
Florin Corascea194d2017-10-02 00:18:51 -0700268 SESSION_TEST ((local_listener != SESSION_INVALID_INDEX),
269 "listener should exist in local table");
270
271 /*
272 * Try client connect with 1) local scope 2) global scope
273 */
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);
294
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);
307
308 /*
309 * Unbind and detach server and then re-attach with local scope only
310 */
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");
315
316 s = session_lookup_listener (server_st_index, &server_sep);
317 SESSION_TEST ((s == 0), "listener should not exist in global table");
Florin Coras3cbc04b2017-10-02 00:18:51 -0700318 local_listener =
319 session_lookup_local_session_endpoint (server_local_st_index,
320 &server_sep);
Florin Corascea194d2017-10-02 00:18:51 -0700321 SESSION_TEST ((s == 0), "listener should not exist in local table");
322
323 detach_args.app_index = server_index;
324 vnet_application_detach (&detach_args);
325
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");
335
336 bind_args.app_index = server_index;
337 error = vnet_bind (&bind_args);
338 SESSION_TEST ((error == 0), "bind should work");
339
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);
Florin Coras3cbc04b2017-10-02 00:18:51 -0700344 local_listener =
345 session_lookup_local_session_endpoint (server_local_st_index,
346 &server_sep);
Florin Corascea194d2017-10-02 00:18:51 -0700347 SESSION_TEST ((local_listener != SESSION_INVALID_INDEX),
348 "listener should exist in local table");
349
350 unbind_args.handle = bind_args.handle;
351 error = vnet_unbind (&unbind_args);
352 SESSION_TEST ((error == 0), "unbind should work");
353
Florin Coras3cbc04b2017-10-02 00:18:51 -0700354 local_listener =
355 session_lookup_local_session_endpoint (server_local_st_index,
356 &server_sep);
Florin Corascea194d2017-10-02 00:18:51 -0700357 SESSION_TEST ((local_listener == SESSION_INVALID_INDEX),
358 "listener should not exist in local table");
359
360 /*
361 * Client attach + connect in default ns with local scope
362 */
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);
375
376 /*
377 * Detach server
378 */
379 detach_args.app_index = server_index;
380 vnet_application_detach (&detach_args);
381
382 /*
383 * Create loopback interface
384 */
385 if (vnet_create_loopback_interface (&sw_if_index, intf_mac, 0, 0))
386 {
387 clib_warning ("couldn't create loopback. stopping the test!");
388 return 0;
389 }
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,
393 24, 0);
394
395 /*
396 * Update namespace
397 */
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));
402
403 /*
404 * Attach server with local and global scope
405 */
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;
414
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");
420
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 "
424 "the server");
425 server_local_st_index = application_local_session_table (server);
Florin Coras3cbc04b2017-10-02 00:18:51 -0700426 local_listener =
427 session_lookup_local_session_endpoint (server_local_st_index,
428 &server_sep);
Florin Corascea194d2017-10-02 00:18:51 -0700429 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);
433
434 /*
435 * Cleanup
436 */
437 vec_free (ns_id);
438 vnet_delete_loopback_interface (sw_if_index);
439 return 0;
440}
441
Florin Coras1c710452017-10-17 00:03:13 -0700442static int
443session_test_rule_table (vlib_main_t * vm, unformat_input_t * input)
444{
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;
449 clib_error_t *error;
450 int verbose = 0;
451
452 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
453 {
454 if (unformat (input, "verbose"))
455 verbose = 1;
456 else
457 {
458 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
459 input);
460 return -1;
461 }
462 }
463
464 memset (srt, 0, sizeof (*srt));
465 session_rules_table_init (srt);
466
467 ip4_address_t lcl_ip = {
468 .as_u32 = clib_host_to_net_u32 (0x01020304),
469 };
470 ip4_address_t rmt_ip = {
471 .as_u32 = clib_host_to_net_u32 (0x05060708),
472 };
473 ip4_address_t lcl_ip2 = {
474 .as_u32 = clib_host_to_net_u32 (0x02020202),
475 };
476 ip4_address_t rmt_ip2 = {
477 .as_u32 = clib_host_to_net_u32 (0x06060606),
478 };
479 ip4_address_t lcl_ip3 = {
480 .as_u32 = clib_host_to_net_u32 (0x03030303),
481 };
482 ip4_address_t rmt_ip3 = {
483 .as_u32 = clib_host_to_net_u32 (0x07070707),
484 };
485 fib_prefix_t lcl_pref = {
486 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
487 .fp_len = 16,
488 .fp_proto = FIB_PROTOCOL_IP4,
489 };
490 fib_prefix_t rmt_pref = {
491 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
492 .fp_len = 16,
493 .fp_proto = FIB_PROTOCOL_IP4,
494 };
495
496 session_rule_table_add_del_args_t args = {
497 .lcl = lcl_pref,
498 .rmt = rmt_pref,
499 .lcl_port = lcl_port,
500 .rmt_port = rmt_port,
501 .action_index = action_index++,
502 .is_add = 1,
503 };
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",
506 action_index - 1);
507
508 res =
509 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
510 lcl_port, rmt_port);
511 SESSION_TEST ((res == 1),
512 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 1: %d",
513 res);
514
515 /*
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
517 */
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",
523 action_index - 1);
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",
529 action_index - 1);
530
531 /*
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
533 */
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",
541 action_index - 1);
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",
547 action_index - 1);
548
549 /*
550 * Add again 3.3.3.3/24 1234 7.7.7.7/16 4321
551 */
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);
558
559 /*
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
562 */
563 res =
564 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
565 lcl_port, rmt_port);
566 SESSION_TEST ((res == 3),
567 "Lookup 1.2.3.4 1234 5.6.7.8 4321 action " "should be 3: %d",
568 res);
569
570 lcl_lkup.as_u32 = clib_host_to_net_u32 (0x01020204);
571 rmt_lkup.as_u32 = clib_host_to_net_u32 (0x05060709);
572 res =
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",
577 res);
578
579 res =
580 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip3, &rmt_ip3,
581 lcl_port, rmt_port);
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);
585
586 /*
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
589 */
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;
594 args.lcl_port = 0;
595 args.rmt_port = 0;
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",
599 action_index - 1);
600 res =
601 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
602 lcl_port, rmt_port);
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);
606 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",
611 res);
612
613 /*
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
618 */
619 args.is_add = 0;
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 *");
622
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;
627 args.lcl_port = 0;
628 args.rmt_port = 0;
629 args.action_index = action_index++;
630 args.is_add = 1;
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",
633 action_index - 1);
634
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++;
642 args.is_add = 1;
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",
645 action_index - 1);
646
647 if (verbose)
648 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4,
649 TRANSPORT_PROTO_TCP);
650
651 res =
652 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
653 lcl_port, rmt_port);
654 SESSION_TEST ((res == 3),
655 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
656 res);
657 res =
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",
662 res);
663 res =
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",
668 res);
669
670 /*
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
673 */
674 args.lcl_port = 1234;
675 args.rmt_port = 4321;
676 args.lcl.fp_len = 16;
677 args.rmt.fp_len = 16;
678 args.is_add = 0;
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");
681 res =
682 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
683 lcl_port, rmt_port);
684 SESSION_TEST ((res == 3),
685 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
686 res);
687
688 args.lcl_port = 0;
689 args.rmt_port = 0;
690 args.is_add = 0;
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 *");
693 res =
694 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
695 lcl_port, rmt_port);
696 SESSION_TEST ((res == 3),
697 "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d",
698 res);
699
700 /*
701 * Delete 1.2.3.4/24 1234 5.6.7.5/24
702 */
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;
709 args.is_add = 0;
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");
712 res =
713 session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip,
714 lcl_port, rmt_port);
715 SESSION_TEST ((res == 2), "Action should be 2: %d", res);
716
717 return 0;
718}
719
720static int
721session_test_rules (vlib_main_t * vm, unformat_input_t * input)
722{
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;
735
736 server_sep.is_ip4 = 1;
737 server_sep.port = dummy_port;
738 memset (options, 0, sizeof (options));
739
740 vnet_app_attach_args_t attach_args = {
741 .api_client_index = ~0,
742 .options = options,
743 .namespace_id = 0,
744 .session_cb_vft = &dummy_session_cbs,
745 .segment_name = segment_name,
746 };
747
748 vnet_bind_args_t bind_args = {
749 .sep = server_sep,
750 .app_index = 0,
751 };
752
753 /*
754 * Attach server with global and local default scope
755 */
Florin Coras7999e832017-10-31 01:51:04 -0700756 options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
Florin Coras1c710452017-10-17 00:03:13 -0700757 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;
765
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),
773 };
774 ip4_address_t rmt_ip = {
775 .as_u32 = clib_host_to_net_u32 (0x05060708),
776 };
777 fib_prefix_t lcl_pref = {
778 .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
779 .fp_len = 16,
780 .fp_proto = FIB_PROTOCOL_IP4,
781 };
782 fib_prefix_t rmt_pref = {
783 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
784 .fp_len = 16,
785 .fp_proto = FIB_PROTOCOL_IP4,
786 };
787
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)");
792
793 /*
794 * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
795 */
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,
803 .appns_index = 0,
804 };
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);
808
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,
825 .is_ip4 = 1,
826 .port = rmt_port,
827 .transport_proto = TRANSPORT_PROTO_TCP,
828 };
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)");
832
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");
838
839 /*
840 * Add 1.2.3.4/16 * 5.6.7.8/16 4321
841 */
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)");
855
856 /*
857 * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
858 */
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 "
865 "should work");
866
867 /*
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
870 */
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)");
877
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 "
886 "work (del)");
887
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)");
896 return 0;
897}
898
Florin Coras7999e832017-10-31 01:51:04 -0700899static int
900session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
901{
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;
907 stream_session_t *s;
908 transport_connection_t *tc;
909 u16 lcl_port = 1234, rmt_port = 4321;
910 app_namespace_t *app_ns;
911 int verbose = 0;
912
913 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
914 {
915 if (unformat (input, "verbose"))
916 verbose = 1;
917 else
918 {
919 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
920 input);
921 return -1;
922 }
923 }
924
925 ip4_address_t lcl_ip = {
926 .as_u32 = clib_host_to_net_u32 (0x01020304),
927 };
928 ip4_address_t rmt_ip = {
929 .as_u32 = clib_host_to_net_u32 (0x05060708),
930 };
931 fib_prefix_t rmt_pref = {
932 .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
933 .fp_len = 16,
934 .fp_proto = FIB_PROTOCOL_IP4,
935 };
936 session_endpoint_t sep = {
937 .ip = rmt_pref.fp_addr,
938 .is_ip4 = 1,
939 .port = rmt_port,
940 .transport_proto = TRANSPORT_PROTO_TCP,
941 };
942
943 /*
944 * Create loopback interface
945 */
946 memset (intf_mac, 0, sizeof (intf_mac));
947 if (vnet_create_loopback_interface (&sw_if_index, intf_mac, 0, 0))
948 {
949 clib_warning ("couldn't create loopback. stopping the test!");
950 return 0;
951 }
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,
955 24, 0);
956
957 app_ns = app_namespace_get_default ();
958 app_ns->sw_if_index = sw_if_index;
959
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,
968 .options = options,
969 .namespace_id = 0,
970 .session_cb_vft = &dummy_session_cbs,
971 .segment_name = segment_name,
972 };
973
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;
978
979 if (verbose)
980 session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
981 TRANSPORT_PROTO_TCP);
982
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 "
986 "successful");
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"
990 " server");
991
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"
995 " not work");
996
997 if (verbose)
998 session_lookup_dump_local_rules_table (app_ns->local_table_index,
999 FIB_PROTOCOL_IP4,
1000 TRANSPORT_PROTO_TCP);
1001 app_index =
1002 session_lookup_local_session_endpoint (app_ns->local_table_index, &sep);
1003 SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1004 " should work");
1005
1006 vnet_app_detach_args_t detach_args = {
1007 .app_index = server_index,
1008 };
1009 vnet_application_detach (&detach_args);
1010
1011 if (verbose)
1012 session_lookup_dump_local_rules_table (app_ns->local_table_index,
1013 FIB_PROTOCOL_IP4,
1014 TRANSPORT_PROTO_TCP);
1015
1016 app_index =
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");
1020
1021 return 0;
1022}
1023
Florin Corascea194d2017-10-02 00:18:51 -07001024static clib_error_t *
1025session_test (vlib_main_t * vm,
1026 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1027{
1028 int res = 0;
1029
1030 vnet_session_enable_disable (vm, 1);
1031
1032 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1033 {
1034 if (unformat (input, "namespace"))
1035 {
1036 res = session_test_namespace (vm, input);
1037 }
Florin Coras1c710452017-10-17 00:03:13 -07001038 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);
Florin Coras7999e832017-10-31 01:51:04 -07001042 else if (unformat (input, "proxy"))
1043 res = session_test_proxy (vm, input);
Florin Corascea194d2017-10-02 00:18:51 -07001044 else
1045 break;
1046 }
1047
1048 if (res)
1049 return clib_error_return (0, "Session unit test failed");
1050 return 0;
1051}
1052
1053/* *INDENT-OFF* */
1054VLIB_CLI_COMMAND (tcp_test_command, static) =
1055{
1056 .path = "test session",
1057 .short_help = "internal session unit tests",
1058 .function = session_test,
1059};
1060/* *INDENT-ON* */
1061
1062/*
1063 * fd.io coding-style-patch-verification: ON
1064 *
1065 * Local Variables:
1066 * eval: (c-set-style "gnu")
1067 * End:
1068 */