session: add rule tags
[vpp.git] / src / vnet / session / session_test.c
1 /*
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>
20 #include <vnet/session/session_rules_table.h>
21
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
42 void
43 dummy_session_reset_callback (stream_session_t * s)
44 {
45   clib_warning ("called...");
46 }
47
48 int
49 dummy_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
56 int
57 dummy_add_segment_callback (u32 client_index, const u8 * seg_name,
58                             u32 seg_size)
59 {
60   clib_warning ("called...");
61   return -1;
62 }
63
64 int
65 dummy_redirect_connect_callback (u32 client_index, void *mp)
66 {
67   return VNET_API_ERROR_SESSION_REDIRECT;
68 }
69
70 void
71 dummy_session_disconnect_callback (stream_session_t * s)
72 {
73   clib_warning ("called...");
74 }
75
76 int
77 dummy_session_accept_callback (stream_session_t * s)
78 {
79   clib_warning ("called...");
80   return -1;
81 }
82
83 int
84 dummy_server_rx_callback (stream_session_t * s)
85 {
86   clib_warning ("called...");
87   return -1;
88 }
89
90 /* *INDENT-OFF* */
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,
98 };
99 /* *INDENT-ON* */
100
101 static int
102 session_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
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,
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;
231   unbind_args.handle = bind_args.handle;
232   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);
265   local_listener =
266     session_lookup_local_session_endpoint (server_local_st_index,
267                                            &server_sep);
268   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");
318   local_listener =
319     session_lookup_local_session_endpoint (server_local_st_index,
320                                            &server_sep);
321   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);
344   local_listener =
345     session_lookup_local_session_endpoint (server_local_st_index,
346                                            &server_sep);
347   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
354   local_listener =
355     session_lookup_local_session_endpoint (server_local_st_index,
356                                            &server_sep);
357   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);
426   local_listener =
427     session_lookup_local_session_endpoint (server_local_st_index,
428                                            &server_sep);
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);
433
434   /*
435    * Cleanup
436    */
437   vec_free (ns_id);
438   vnet_delete_loopback_interface (sw_if_index);
439   return 0;
440 }
441
442 static int
443 session_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, &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",
512                 res);
513
514   /*
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
516    */
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",
522                 action_index - 1);
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",
528                 action_index - 1);
529
530   /*
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
532    */
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",
540                 action_index - 1);
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",
546                 action_index - 1);
547
548   /*
549    * Add again 3.3.3.3/24 1234 7.7.7.7/16 4321
550    */
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);
557
558   /*
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
561    */
562   res =
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",
566                 res);
567
568   lcl_lkup.as_u32 = clib_host_to_net_u32 (0x01020204);
569   rmt_lkup.as_u32 = clib_host_to_net_u32 (0x05060709);
570   res =
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",
575                 res);
576
577   res =
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);
582
583   /*
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
586    */
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;
591   args.lcl_port = 0;
592   args.rmt_port = 0;
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",
596                 action_index - 1);
597   res =
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);
602   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",
607                 res);
608
609   /*
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
614    */
615   args.is_add = 0;
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 *");
618
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;
623   args.lcl_port = 0;
624   args.rmt_port = 0;
625   args.action_index = action_index++;
626   args.is_add = 1;
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",
629                 action_index - 1);
630
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++;
638   args.is_add = 1;
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",
641                 action_index - 1);
642
643   if (verbose)
644     session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
645
646   res =
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",
650                 res);
651   res =
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",
656                 res);
657   res =
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",
662                 res);
663
664   /*
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
667    */
668   args.lcl_port = 1234;
669   args.rmt_port = 4321;
670   args.lcl.fp_len = 16;
671   args.rmt.fp_len = 16;
672   args.is_add = 0;
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");
675   res =
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",
679                 res);
680
681   args.lcl_port = 0;
682   args.rmt_port = 0;
683   args.is_add = 0;
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 *");
686   res =
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",
690                 res);
691
692   /*
693    * Delete 1.2.3.4/24 1234 5.6.7.5/24
694    */
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;
701   args.is_add = 0;
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");
704   res =
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);
707
708   return 0;
709 }
710
711 static int
712 session_test_rules (vlib_main_t * vm, unformat_input_t * input)
713 {
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;
726   int verbose = 0;
727
728   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
729     {
730       if (unformat (input, "verbose"))
731         verbose = 1;
732       else
733         {
734           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
735                            input);
736           return -1;
737         }
738     }
739
740   server_sep.is_ip4 = 1;
741   server_sep.port = dummy_port;
742   memset (options, 0, sizeof (options));
743
744   vnet_app_attach_args_t attach_args = {
745     .api_client_index = ~0,
746     .options = options,
747     .namespace_id = 0,
748     .session_cb_vft = &dummy_session_cbs,
749     .segment_name = segment_name,
750   };
751
752   vnet_bind_args_t bind_args = {
753     .sep = server_sep,
754     .app_index = 0,
755   };
756
757   /*
758    * Attach server with global and local default scope
759    */
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;
769
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),
777   };
778   ip4_address_t rmt_ip = {
779     .as_u32 = clib_host_to_net_u32 (0x05060708),
780   };
781   fib_prefix_t lcl_pref = {
782     .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
783     .fp_len = 16,
784     .fp_proto = FIB_PROTOCOL_IP4,
785   };
786   fib_prefix_t rmt_pref = {
787     .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
788     .fp_len = 16,
789     .fp_proto = FIB_PROTOCOL_IP4,
790   };
791
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)");
796
797   /*
798    * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
799    */
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,
807     .appns_index = 0,
808   };
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);
812
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,
829     .is_ip4 = 1,
830     .port = rmt_port,
831     .transport_proto = TRANSPORT_PROTO_TCP,
832   };
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)");
836
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");
842
843   /*
844    * Add 1.2.3.4/16 * 5.6.7.8/16 4321
845    */
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)");
859
860   /*
861    * Add drop rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
862    */
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);
872
873   if (verbose)
874     {
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);
879     }
880
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)");
886
887   /*
888    * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
889    */
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);
897
898   if (verbose)
899     {
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);
904     }
905
906   app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
907   SESSION_TEST ((app_index == server_index), "local session endpoint lookup "
908                 "should work");
909
910   /*
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
913    */
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)");
920
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 "
929                 "work (del)");
930
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)");
940
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)");
953
954   /*
955    * Test tags. Add/del rule with tag
956    */
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 "
966                 "tag test_rule");
967   if (verbose)
968     {
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);
973     }
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 "
977                 "tag test_rule");
978
979   return 0;
980 }
981
982 static int
983 session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
984 {
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;
990   stream_session_t *s;
991   transport_connection_t *tc;
992   u16 lcl_port = 1234, rmt_port = 4321;
993   app_namespace_t *app_ns;
994   int verbose = 0;
995
996   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
997     {
998       if (unformat (input, "verbose"))
999         verbose = 1;
1000       else
1001         {
1002           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1003                            input);
1004           return -1;
1005         }
1006     }
1007
1008   ip4_address_t lcl_ip = {
1009     .as_u32 = clib_host_to_net_u32 (0x01020304),
1010   };
1011   ip4_address_t rmt_ip = {
1012     .as_u32 = clib_host_to_net_u32 (0x05060708),
1013   };
1014   fib_prefix_t rmt_pref = {
1015     .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
1016     .fp_len = 16,
1017     .fp_proto = FIB_PROTOCOL_IP4,
1018   };
1019   session_endpoint_t sep = {
1020     .ip = rmt_pref.fp_addr,
1021     .is_ip4 = 1,
1022     .port = rmt_port,
1023     .transport_proto = TRANSPORT_PROTO_TCP,
1024   };
1025
1026   /*
1027    * Create loopback interface
1028    */
1029   memset (intf_mac, 0, sizeof (intf_mac));
1030   if (vnet_create_loopback_interface (&sw_if_index, intf_mac, 0, 0))
1031     {
1032       clib_warning ("couldn't create loopback. stopping the test!");
1033       return 0;
1034     }
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,
1038                                  24, 0);
1039
1040   app_ns = app_namespace_get_default ();
1041   app_ns->sw_if_index = sw_if_index;
1042
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,
1051     .options = options,
1052     .namespace_id = 0,
1053     .session_cb_vft = &dummy_session_cbs,
1054     .segment_name = segment_name,
1055   };
1056
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;
1061
1062   if (verbose)
1063     session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1064                                      TRANSPORT_PROTO_TCP);
1065
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 "
1069                 "successful");
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"
1073                 " server");
1074
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"
1078                 " not work");
1079
1080   if (verbose)
1081     session_lookup_dump_local_rules_table (app_ns->local_table_index,
1082                                            FIB_PROTOCOL_IP4,
1083                                            TRANSPORT_PROTO_TCP);
1084   app_index =
1085     session_lookup_local_session_endpoint (app_ns->local_table_index, &sep);
1086   SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1087                 " should work");
1088
1089   vnet_app_detach_args_t detach_args = {
1090     .app_index = server_index,
1091   };
1092   vnet_application_detach (&detach_args);
1093
1094   if (verbose)
1095     session_lookup_dump_local_rules_table (app_ns->local_table_index,
1096                                            FIB_PROTOCOL_IP4,
1097                                            TRANSPORT_PROTO_TCP);
1098
1099   app_index =
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");
1103
1104   return 0;
1105 }
1106
1107 static clib_error_t *
1108 session_test (vlib_main_t * vm,
1109               unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1110 {
1111   int res = 0;
1112
1113   vnet_session_enable_disable (vm, 1);
1114
1115   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1116     {
1117       if (unformat (input, "namespace"))
1118         {
1119           res = session_test_namespace (vm, input);
1120         }
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);
1127       else
1128         break;
1129     }
1130
1131   if (res)
1132     return clib_error_return (0, "Session unit test failed");
1133   return 0;
1134 }
1135
1136 /* *INDENT-OFF* */
1137 VLIB_CLI_COMMAND (tcp_test_command, static) =
1138 {
1139   .path = "test session",
1140   .short_help = "internal session unit tests",
1141   .function = session_test,
1142 };
1143 /* *INDENT-ON* */
1144
1145 /*
1146  * fd.io coding-style-patch-verification: ON
1147  *
1148  * Local Variables:
1149  * eval: (c-set-style "gnu")
1150  * End:
1151  */