a3e76c25539da60b2803660e8ca07603cef640ed
[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, 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
720 static int
721 session_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   int verbose = 0;
736
737   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
738     {
739       if (unformat (input, "verbose"))
740         verbose = 1;
741       else
742         {
743           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
744                            input);
745           return -1;
746         }
747     }
748
749   server_sep.is_ip4 = 1;
750   server_sep.port = dummy_port;
751   memset (options, 0, sizeof (options));
752
753   vnet_app_attach_args_t attach_args = {
754     .api_client_index = ~0,
755     .options = options,
756     .namespace_id = 0,
757     .session_cb_vft = &dummy_session_cbs,
758     .segment_name = segment_name,
759   };
760
761   vnet_bind_args_t bind_args = {
762     .sep = server_sep,
763     .app_index = 0,
764   };
765
766   /*
767    * Attach server with global and local default scope
768    */
769   options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
770   options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
771   options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
772   options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
773   attach_args.namespace_id = 0;
774   attach_args.api_client_index = dummy_server_api_index;
775   error = vnet_application_attach (&attach_args);
776   SESSION_TEST ((error == 0), "server attached");
777   server_index = attach_args.app_index;
778
779   bind_args.app_index = server_index;
780   error = vnet_bind (&bind_args);
781   SESSION_TEST ((error == 0), "server bound to %U/%d", format_ip46_address,
782                 &server_sep.ip, 1, server_sep.port);
783   listener = listen_session_get_from_handle (bind_args.handle);
784   ip4_address_t lcl_ip = {
785     .as_u32 = clib_host_to_net_u32 (0x01020304),
786   };
787   ip4_address_t rmt_ip = {
788     .as_u32 = clib_host_to_net_u32 (0x05060708),
789   };
790   fib_prefix_t lcl_pref = {
791     .fp_addr.ip4.as_u32 = lcl_ip.as_u32,
792     .fp_len = 16,
793     .fp_proto = FIB_PROTOCOL_IP4,
794   };
795   fib_prefix_t rmt_pref = {
796     .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
797     .fp_len = 16,
798     .fp_proto = FIB_PROTOCOL_IP4,
799   };
800
801   tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
802                                       &rmt_pref.fp_addr.ip4, lcl_port,
803                                       rmt_port, TRANSPORT_PROTO_TCP, 0);
804   SESSION_TEST ((tc == 0), "optimized lookup should not work (port)");
805
806   /*
807    * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index
808    */
809   session_rule_add_del_args_t args = {
810     .table_args.lcl = lcl_pref,
811     .table_args.rmt = rmt_pref,
812     .table_args.lcl_port = lcl_port,
813     .table_args.rmt_port = rmt_port,
814     .table_args.action_index = server_index,
815     .table_args.is_add = 1,
816     .appns_index = 0,
817   };
818   error = vnet_session_rule_add_del (&args);
819   SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d",
820                 args.table_args.action_index);
821
822   tc = session_lookup_connection4 (0, &lcl_pref.fp_addr.ip4,
823                                    &rmt_pref.fp_addr.ip4, lcl_port, rmt_port,
824                                    TRANSPORT_PROTO_TCP);
825   SESSION_TEST ((tc->c_index == listener->connection_index),
826                 "optimized lookup should return the listener");
827   tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
828                                       &rmt_pref.fp_addr.ip4, lcl_port,
829                                       rmt_port, TRANSPORT_PROTO_TCP, 0);
830   SESSION_TEST ((tc->c_index == listener->connection_index),
831                 "lookup should return the listener");
832   s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4,
833                             lcl_port, rmt_port, TRANSPORT_PROTO_TCP);
834   SESSION_TEST ((s->connection_index == listener->connection_index),
835                 "safe lookup should return the listener");
836   session_endpoint_t sep = {
837     .ip = rmt_pref.fp_addr,
838     .is_ip4 = 1,
839     .port = rmt_port,
840     .transport_proto = TRANSPORT_PROTO_TCP,
841   };
842   app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
843   SESSION_TEST ((app_index != server_index), "local session endpoint lookup "
844                 "should not work (global scope)");
845
846   tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
847                                       &rmt_pref.fp_addr.ip4, lcl_port + 1,
848                                       rmt_port, TRANSPORT_PROTO_TCP, 0);
849   SESSION_TEST ((tc == 0),
850                 "optimized lookup for wrong lcl port + 1 should not work");
851
852   /*
853    * Add 1.2.3.4/16 * 5.6.7.8/16 4321
854    */
855   args.table_args.lcl_port = 0;
856   args.scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
857   error = vnet_session_rule_add_del (&args);
858   SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 4321 action %d",
859                 args.table_args.action_index);
860   tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
861                                       &rmt_pref.fp_addr.ip4, lcl_port + 1,
862                                       rmt_port, TRANSPORT_PROTO_TCP, 0);
863   SESSION_TEST ((tc->c_index == listener->connection_index),
864                 "optimized lookup for lcl port + 1 should work");
865   app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
866   SESSION_TEST ((app_index != server_index), "local session endpoint lookup "
867                 "should not work (constrained lcl ip)");
868
869   /*
870    * Add drop rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -2 (drop)
871    */
872   args.table_args.lcl_port = 1234;
873   args.table_args.lcl.fp_addr.ip4 = lcl_ip;
874   args.table_args.lcl.fp_len = 32;
875   args.table_args.rmt.fp_addr.ip4 = rmt_ip;
876   args.table_args.rmt.fp_len = 32;
877   args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP;
878   error = vnet_session_rule_add_del (&args);
879   SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d",
880                 args.table_args.action_index);
881
882   if (verbose)
883     {
884       session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
885                                        TRANSPORT_PROTO_TCP);
886       session_lookup_dump_local_rules_table (0, FIB_PROTOCOL_IP4,
887                                              TRANSPORT_PROTO_TCP);
888     }
889
890   tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
891                                       &rmt_pref.fp_addr.ip4, lcl_port,
892                                       rmt_port, TRANSPORT_PROTO_TCP, 0);
893   SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 "
894                 "should fail (drop rule)");
895
896   /*
897    * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index
898    */
899   args.table_args.lcl_port = 0;
900   args.table_args.lcl.fp_len = 0;
901   args.table_args.rmt.fp_len = 16;
902   args.table_args.action_index = server_index;
903   error = vnet_session_rule_add_del (&args);
904   SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d",
905                 args.table_args.action_index);
906
907   if (verbose)
908     {
909       session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
910                                        TRANSPORT_PROTO_TCP);
911       session_lookup_dump_local_rules_table (0, FIB_PROTOCOL_IP4,
912                                              TRANSPORT_PROTO_TCP);
913     }
914
915   app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
916   SESSION_TEST ((app_index == server_index), "local session endpoint lookup "
917                 "should work");
918
919   /*
920    * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and
921    * 1.2.3.4/16 1234 5.6.7.8/16 4321
922    */
923   args.table_args.is_add = 0;
924   error = vnet_session_rule_add_del (&args);
925   SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321");
926   app_index = session_lookup_local_session_endpoint (local_ns_index, &sep);
927   SESSION_TEST ((app_index != server_index), "local session endpoint lookup "
928                 "should not work (removed)");
929
930   args.table_args.is_add = 0;
931   args.table_args.lcl = lcl_pref;
932   error = vnet_session_rule_add_del (&args);
933   SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321");
934   tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
935                                       &rmt_pref.fp_addr.ip4, lcl_port + 1,
936                                       rmt_port, TRANSPORT_PROTO_TCP, 0);
937   SESSION_TEST ((tc == 0), "optimized lookup for lcl port + 1 should not "
938                 "work (del)");
939
940   args.table_args.is_add = 0;
941   args.table_args.lcl_port = 1234;
942   error = vnet_session_rule_add_del (&args);
943   SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321");
944   tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
945                                       &rmt_pref.fp_addr.ip4, lcl_port,
946                                       rmt_port, TRANSPORT_PROTO_TCP, 0);
947   SESSION_TEST ((tc == 0),
948                 "optimized lookup should not work (del + negative)");
949
950   args.table_args.is_add = 0;
951   args.table_args.lcl_port = 1234;
952   args.table_args.lcl.fp_addr.ip4 = lcl_ip;
953   args.table_args.lcl.fp_len = 32;
954   args.table_args.rmt.fp_addr.ip4 = rmt_ip;
955   args.table_args.rmt.fp_len = 32;
956   error = vnet_session_rule_add_del (&args);
957   SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 drop");
958   tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4,
959                                       &rmt_pref.fp_addr.ip4, lcl_port,
960                                       rmt_port, TRANSPORT_PROTO_TCP, 0);
961   SESSION_TEST ((tc == 0), "optimized lookup should not work (no-rule)");
962   return 0;
963 }
964
965 static int
966 session_test_proxy (vlib_main_t * vm, unformat_input_t * input)
967 {
968   u64 options[SESSION_OPTIONS_N_OPTIONS];
969   u32 server_index, app_index;
970   u32 dummy_server_api_index = ~0, sw_if_index = 0;
971   clib_error_t *error = 0;
972   u8 segment_name[128], intf_mac[6], sst;
973   stream_session_t *s;
974   transport_connection_t *tc;
975   u16 lcl_port = 1234, rmt_port = 4321;
976   app_namespace_t *app_ns;
977   int verbose = 0;
978
979   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
980     {
981       if (unformat (input, "verbose"))
982         verbose = 1;
983       else
984         {
985           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
986                            input);
987           return -1;
988         }
989     }
990
991   ip4_address_t lcl_ip = {
992     .as_u32 = clib_host_to_net_u32 (0x01020304),
993   };
994   ip4_address_t rmt_ip = {
995     .as_u32 = clib_host_to_net_u32 (0x05060708),
996   };
997   fib_prefix_t rmt_pref = {
998     .fp_addr.ip4.as_u32 = rmt_ip.as_u32,
999     .fp_len = 16,
1000     .fp_proto = FIB_PROTOCOL_IP4,
1001   };
1002   session_endpoint_t sep = {
1003     .ip = rmt_pref.fp_addr,
1004     .is_ip4 = 1,
1005     .port = rmt_port,
1006     .transport_proto = TRANSPORT_PROTO_TCP,
1007   };
1008
1009   /*
1010    * Create loopback interface
1011    */
1012   memset (intf_mac, 0, sizeof (intf_mac));
1013   if (vnet_create_loopback_interface (&sw_if_index, intf_mac, 0, 0))
1014     {
1015       clib_warning ("couldn't create loopback. stopping the test!");
1016       return 0;
1017     }
1018   vnet_sw_interface_set_flags (vnet_get_main (), sw_if_index,
1019                                VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1020   ip4_add_del_interface_address (vlib_get_main (), sw_if_index, &lcl_ip,
1021                                  24, 0);
1022
1023   app_ns = app_namespace_get_default ();
1024   app_ns->sw_if_index = sw_if_index;
1025
1026   memset (options, 0, sizeof (options));
1027   options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
1028   options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_IS_PROXY;
1029   options[APP_OPTIONS_PROXY_TRANSPORT] = 1 << TRANSPORT_PROTO_TCP;
1030   options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1031   options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1032   vnet_app_attach_args_t attach_args = {
1033     .api_client_index = ~0,
1034     .options = options,
1035     .namespace_id = 0,
1036     .session_cb_vft = &dummy_session_cbs,
1037     .segment_name = segment_name,
1038   };
1039
1040   attach_args.api_client_index = dummy_server_api_index;
1041   error = vnet_application_attach (&attach_args);
1042   SESSION_TEST ((error == 0), "server attachment should work");
1043   server_index = attach_args.app_index;
1044
1045   if (verbose)
1046     session_lookup_dump_rules_table (0, FIB_PROTOCOL_IP4,
1047                                      TRANSPORT_PROTO_TCP);
1048
1049   tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port,
1050                                       TRANSPORT_PROTO_TCP, 0);
1051   SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be "
1052                 "successful");
1053   sst = session_type_from_proto_and_ip (TRANSPORT_PROTO_TCP, 1);
1054   s = listen_session_get (sst, tc->s_index);
1055   SESSION_TEST ((s->app_index == server_index), "lookup should return the"
1056                 " server");
1057
1058   tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port,
1059                                       TRANSPORT_PROTO_TCP, 0);
1060   SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should"
1061                 " not work");
1062
1063   if (verbose)
1064     session_lookup_dump_local_rules_table (app_ns->local_table_index,
1065                                            FIB_PROTOCOL_IP4,
1066                                            TRANSPORT_PROTO_TCP);
1067   app_index =
1068     session_lookup_local_session_endpoint (app_ns->local_table_index, &sep);
1069   SESSION_TEST ((app_index == server_index), "local session endpoint lookup"
1070                 " should work");
1071
1072   vnet_app_detach_args_t detach_args = {
1073     .app_index = server_index,
1074   };
1075   vnet_application_detach (&detach_args);
1076
1077   if (verbose)
1078     session_lookup_dump_local_rules_table (app_ns->local_table_index,
1079                                            FIB_PROTOCOL_IP4,
1080                                            TRANSPORT_PROTO_TCP);
1081
1082   app_index =
1083     session_lookup_local_session_endpoint (app_ns->local_table_index, &sep);
1084   SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX),
1085                 "local session endpoint lookup should not work after detach");
1086
1087   return 0;
1088 }
1089
1090 static clib_error_t *
1091 session_test (vlib_main_t * vm,
1092               unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1093 {
1094   int res = 0;
1095
1096   vnet_session_enable_disable (vm, 1);
1097
1098   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1099     {
1100       if (unformat (input, "namespace"))
1101         {
1102           res = session_test_namespace (vm, input);
1103         }
1104       else if (unformat (input, "rules-table"))
1105         res = session_test_rule_table (vm, input);
1106       else if (unformat (input, "rules"))
1107         res = session_test_rules (vm, input);
1108       else if (unformat (input, "proxy"))
1109         res = session_test_proxy (vm, input);
1110       else
1111         break;
1112     }
1113
1114   if (res)
1115     return clib_error_return (0, "Session unit test failed");
1116   return 0;
1117 }
1118
1119 /* *INDENT-OFF* */
1120 VLIB_CLI_COMMAND (tcp_test_command, static) =
1121 {
1122   .path = "test session",
1123   .short_help = "internal session unit tests",
1124   .function = session_test,
1125 };
1126 /* *INDENT-ON* */
1127
1128 /*
1129  * fd.io coding-style-patch-verification: ON
1130  *
1131  * Local Variables:
1132  * eval: (c-set-style "gnu")
1133  * End:
1134  */