Plugins: Clean up the plugin directory so that each plugin has its own
[vpp.git] / plugins / vcgn-plugin / vcgn / cnat_cli_handler.c
1 /* *------------------------------------------------------------------
2  * cnat_cli_handler.c - CLI handler definitions
3  *
4  * Copyright (c) 2007-2015 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *------------------------------------------------------------------
17  */
18
19 #include <vlib/vlib.h>
20 #include <vnet/vnet.h>
21 #include <vppinfra/vec.h>
22 #include <vppinfra/bitmap.h>
23 #include <vppinfra/hash.h>
24 #include <vppinfra/pool.h>
25 #include <vppinfra/clib.h>
26 #include <vppinfra/error.h>
27
28 #include "cnat_db.h"
29 #include "cnat_config.h"
30 #include "cnat_global.h"
31 #include "cnat_cli.h"
32 #include "cnat_logging.h"
33 #include "cnat_syslog.h"
34 #include "cnat_config_api.h"
35 #include "cnat_show_api.h"
36 #include "cnat_show_response.h"
37
38 #include <arpa/inet.h>
39
40 #if DPDK
41 #include <vnet/devices/dpdk/dpdk.h>
42 #endif
43
44 u32 show_debug_level = 0;
45
46 u32
47 cnat_get_vrfmap_nfv9_logging_index (u32 i_vrf_id)
48 {
49     cnat_nfv9_logging_info_t *my_nfv9_logging_info = 0;
50     u32 logging_index = EMPTY;
51
52     /*
53      * Start with global logging index if available
54      */
55     if (cnat_nfv9_global_info.cnat_nfv9_init_done) {
56         logging_index = cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
57
58         pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({
59             if (my_nfv9_logging_info->i_vrf_id == i_vrf_id) {
60                 logging_index = my_nfv9_logging_info -
61                                     cnat_nfv9_logging_info_pool;
62                 break;
63             }
64         }));
65     }
66     return (logging_index);
67 }
68
69 u32
70 cnat_get_vrfmap_syslog_logging_index (u32 i_vrf_id)
71 {
72     cnat_syslog_logging_info_t *my_syslog_info = NULL;
73     u32 logging_index = EMPTY;
74
75     /*
76      * Start with global logging index if available
77      */
78     if(PREDICT_TRUE(cnat_syslog_global_info.cnat_syslog_init_done)) {
79
80         pool_foreach (my_syslog_info, cnat_syslog_logging_info_pool, ({
81             if (my_syslog_info->i_vrf_id == i_vrf_id) {
82             logging_index = my_syslog_info -
83                                     cnat_syslog_logging_info_pool;
84                 break;
85             }
86         }));
87     }
88     return (logging_index);
89 }
90
91 void
92 cnat_set_vrf_params_with_default(cnat_vrfmap_t *my_vrfmap, u32 i_vrf, u32 i_vrf_id)
93 {
94
95     my_vrfmap->status   = S_WAO;
96
97     my_vrfmap->i_vrf    = i_vrf;
98     my_vrfmap->i_vrf_id = i_vrf_id;
99
100     my_vrfmap->o_vrf    = INVALID_UIDX;
101     my_vrfmap->o_vrf_id = INVALID_VRFID;
102
103 #ifndef NO_BULK_LOGGING
104     BULKSIZE_FROM_VRFMAP(my_vrfmap) = BULK_ALLOC_SIZE_NONE;
105 #endif /* #ifndef NO_BULK_LOGGING */
106     my_vrfmap->tcp_mss  = V4_TCP_MSS_NOT_CONFIGURED_VALUE;
107     my_vrfmap->frag_tout = CNAT_IPV4_FRAG_TIMEOUT_DEF;
108     my_vrfmap->port_limit = V4_DEF_VRF_MAX_PORTS;
109     my_vrfmap->nfv9_logging_index =
110         cnat_get_vrfmap_nfv9_logging_index(i_vrf_id);
111     my_vrfmap->syslog_logging_index =
112         cnat_get_vrfmap_syslog_logging_index(i_vrf_id);
113
114      /* Copy logging policy from nfv9 info. */
115     if(my_vrfmap->nfv9_logging_index != EMPTY) {
116         cnat_nfv9_logging_info_t *nfv9_logging_info =
117             cnat_nfv9_logging_info_pool + my_vrfmap->nfv9_logging_index;
118         my_vrfmap->nf_logging_policy = nfv9_logging_info->logging_policy;
119     }
120     if(my_vrfmap->syslog_logging_index != EMPTY) {
121         cnat_syslog_logging_info_t *syslog_logging_info =
122             cnat_syslog_logging_info_pool + my_vrfmap->syslog_logging_index;
123         my_vrfmap->syslog_logging_policy = syslog_logging_info->logging_policy;
124     }
125     #if 0
126     printf("Initializing params in cnat_set_vrf_params_with_default\n"
127                                   "my_vrfmap->status = %u\n"
128                                   "my_vrfmap->tcp_mss = %u\n"
129                                   "my_vrfmap->i_vrf   = %u\n"
130                                   "my_vrfmap->i_vrf_id = %u\n"
131                                   "my_vrfmap->o_vrf    = %u\n"
132                                   "my_vrfmap->o_vrf_id = %u\n"
133                                   "my_vrfmap->bulk_size = %u\n"
134                                   "my_vrfmap->nfv9_logging_index = %u\n"
135                                   "my_vrfmap->syslog_logging_index = %u\n"
136                                   "my_vrfmap->frag_tout = %u\n"
137                                   "my_vrfmap->port_limit = %u\n"
138                                   "my_vrfmap->nf_logging_policy = %u\n"
139                                   "my_vrfmap->syslog_logging_policy = %u\n",
140                                    my_vrfmap->status,
141                                    my_vrfmap->tcp_mss,
142                                    my_vrfmap->i_vrf,
143                                    my_vrfmap->i_vrf_id,
144                                    my_vrfmap->o_vrf,
145                                    my_vrfmap->o_vrf_id,
146                                    my_vrfmap->bulk_size,
147                                    my_vrfmap->nfv9_logging_index,
148                                    my_vrfmap->syslog_logging_index,
149                                    my_vrfmap->frag_tout,
150                                    my_vrfmap->port_limit,
151                                    my_vrfmap->nf_logging_policy,
152                                    my_vrfmap->syslog_logging_policy);
153     #endif /* if 0 */
154 }
155
156 /* config command handlers */
157 void cnat_nat44_add_vrf_map_t_handler(spp_api_cnat_v4_add_vrf_map_t *mp,
158                             vlib_main_t *vm)
159 {
160     void cnat_table_entry_fill_map(u32 start_addr, u32 end_addr,
161                                    cnat_portmap_v2_t **port_map_holder);
162     u32 start_addr, end_addr;
163     u32 pm_len __attribute__((unused));
164     cnat_vrfmap_t       *my_vrfmap = 0;
165     cnat_portmap_v2_t   *pm = 0;
166     u16   i_vrf, o_vrf;
167     u32   ivrf_id, ovrf_id; 
168     u16   my_vrfmap_index;
169     u8    i = 0;
170
171     start_addr = mp->start_addr[0]; 
172     end_addr   = mp->end_addr[0];
173     i_vrf      = mp->i_vrf; 
174     o_vrf      = mp->o_vrf;
175     ovrf_id    = mp->o_vrf_id;
176     ivrf_id    = mp->i_vrf_id;
177
178 #if DEBUG_NOT_COMMENTED
179     vlib_cli_output(vm, "%s: saddr[0x%x], eaddr[0x%x], i_vrf[0x%x], o_vrf[0x%x], "
180            "ovrf_id[0x%x], ivrf_id[0x%x]\n", __func__, start_addr, end_addr,
181             i_vrf, o_vrf, ovrf_id, ivrf_id);
182 #endif
183     if (start_addr > end_addr) {
184         vlib_cli_output(vm, "Add VRF Map failed start addr 0x%x > end addr 0x%x\n", 
185                                                 start_addr, end_addr);
186         return;
187     }
188     if ((end_addr - start_addr) > CNAT_MAX_ADDR_POOL_SIZE) {
189         vlib_cli_output(vm, "Add VRF Map failed start addr 0x%x - end addr "
190                         "0x%x range > 65536\n", start_addr, end_addr);
191         return;
192     }   
193     my_vrfmap_index = vrf_map_array[i_vrf];
194
195     if (my_vrfmap_index != VRF_MAP_ENTRY_EMPTY) {
196
197         my_vrfmap = cnat_map_by_vrf + my_vrfmap_index;
198
199         my_vrfmap->o_vrf = o_vrf;
200         my_vrfmap->i_vrf_id = ivrf_id;
201         my_vrfmap->o_vrf_id = ovrf_id;
202     } else {
203         /*
204          * first time add 
205          */
206         pool_get(cnat_map_by_vrf, my_vrfmap);
207         memset(my_vrfmap, 0, sizeof(*my_vrfmap));
208         /* waiting for outside vrf */
209         cnat_set_vrf_params_with_default(my_vrfmap, i_vrf, ivrf_id);
210         my_vrfmap->i_vrf = i_vrf;
211         my_vrfmap->o_vrf = o_vrf;
212         my_vrfmap->i_vrf_id = ivrf_id;
213         my_vrfmap->o_vrf_id = ovrf_id;
214 #ifndef NO_BULK_LOGGING
215         BULKSIZE_FROM_VRFMAP(my_vrfmap) = BULK_ALLOC_SIZE_NONE;
216 #endif /* #ifndef NO_BULK_LOGGING */
217
218         my_vrfmap->tcp_mss = V4_TCP_MSS_NOT_CONFIGURED_VALUE;
219         my_vrfmap->status = S_WA;
220         my_vrfmap->frag_tout = 0; /* currently setting it to 0 */
221         my_vrfmap->port_limit = V4_DEF_VRF_MAX_PORTS;
222         vrf_map_array[i_vrf] = (my_vrfmap - cnat_map_by_vrf);
223     }
224     pm = my_vrfmap->portmap_list;
225     pm_len = vec_len(pm);
226     for(i=0; i < 1 ; i++) {
227         start_addr = mp->start_addr[i];
228         end_addr   = mp->end_addr[i];
229         if((start_addr == 0) || (end_addr == 0))
230             break;
231         
232         cnat_table_entry_fill_map(start_addr, end_addr,
233                            &(my_vrfmap->portmap_list));
234     }
235     my_vrfmap->status = S_RUN;
236     vlib_cli_output(vm, "Address Pool Config Successful !!\n");
237     return;
238 }
239
240 void cnat_nat44_set_protocol_timeout_value(u16 active, 
241           u16 init, u8 *proto, u8 reset, vlib_main_t *vm)
242 {
243     if (!strncmp((char *) proto, "tcp", 3)) {
244         tcp_initial_setup_timeout = (reset) ? V4_DEF_TCP_IS_TO : init;
245         tcp_active_timeout = (reset) ? V4_DEF_TCP_AS_TO : active;
246
247     } else if (!strncmp((char *) proto, "udp", 3)) {
248         udp_init_session_timeout = (reset) ? V4_DEF_UDP_IS_TO : init;
249         udp_act_session_timeout = (reset) ? V4_DEF_UDP_AS_TO : active;
250
251     } else if (!strncmp((char *) proto, "icmp", 4)) {
252         icmp_session_timeout = (reset) ? V4_DEF_ICMP_S_TO : active;
253
254     } else {
255         vlib_cli_output(vm, "Error !! Unsupported protocol %s\n", proto);
256     }
257     return; 
258 }
259
260
261
262
263 /* Show command handlers */
264 void cnat_nat44_handle_show_stats(vlib_main_t *vm)
265 {
266     pool_header_t     *h;
267     u32               used, free;
268     cnat_vrfmap_t     *my_vrfmap =0;
269     cnat_portmap_v2_t *pm =0, *my_pm = 0;
270     u32 i, pm_len;
271     struct in_addr ip;
272     void cnat_nfv9_show_collector 
273         (vlib_main_t *vm, cnat_nfv9_logging_info_t *my_nfv9_logging_info);
274
275     /* active translations */
276     h = pool_header(cnat_main_db);
277     free = vec_len(h->free_indices);
278     used = vec_len(cnat_main_db) - free;
279
280     vlib_cli_output(vm, "vCGN NAT44 Statistics :\n");
281     vlib_cli_output(vm, "\tActive Translations : %u\n", 
282             NAT44_COMMON_STATS.active_translations);
283     vlib_cli_output(vm, "\tTotal free translation entries : %u\n", free);
284     vlib_cli_output(vm, "\tTotal used translation entries : %u\n", used);
285     vlib_cli_output(vm, "\ti2o drops due to port limit exceeded : %lu\n", 
286             in2out_drops_port_limit_exceeded);
287     vlib_cli_output(vm, "\ti2o drops due to system limit reached : %lu\n", 
288             in2out_drops_system_limit_reached);
289     vlib_cli_output(vm, "\ti2o drops due to resource depletion : %lu\n", 
290             in2out_drops_resource_depletion);
291     vlib_cli_output(vm, "\to2i drops due to no translations : %lu\n", 
292             NAT44_COMMON_STATS.no_translation_entry_drops);
293
294     vlib_cli_output(vm, "\tPool address usage:\n");
295     vlib_cli_output(vm, "\t-------------------------------------------------\n");
296     vlib_cli_output(vm, "\tExternal Address \tPorts Used\n");
297     vlib_cli_output(vm, "\t-------------------------------------------------\n");
298
299     used = 0;
300     pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
301                 pm = my_vrfmap->portmap_list;
302                 pm_len = vec_len(pm);
303                 for (i = 0; i < pm_len; i++) {
304                 my_pm = pm + i;
305                 if (my_pm->inuse) {
306                 used++;
307                 /* maximum of 200 addresses to be returned */
308                 if (used <= 200) {
309                 ip.s_addr = ntohl(my_pm->ipv4_address);    
310                 vlib_cli_output(vm, "\t%s   \t\t%u\n", inet_ntoa(ip), my_pm->inuse);
311                 }
312                 }
313                 }
314                 }));
315     return;
316 }
317
318 void cnat_nat44_handle_show_config(vlib_main_t *vm)
319 {
320     cnat_vrfmap_t * my_vrfmap;
321     cnat_portmap_v2_t *pm = 0;
322     cnat_portmap_v2_t *my_pm = 0;
323     u32 pm_len;
324     struct in_addr ip_addr;
325     u8  status_str[20]; 
326     cnat_nfv9_logging_info_t *my_nfv9_logging_info, 
327         *global_nfv9_logging_info = 0;
328
329     vnet_hw_interface_t * hw;
330     vnet_main_t * vnm = vnet_get_main();
331
332     void cnat_nfv9_show_collector 
333         (vlib_main_t *vm, cnat_nfv9_logging_info_t *my_nfv9_logging_info);
334
335     vlib_cli_output(vm, "vCGN NAT44 Config:\n");
336     vlib_cli_output(vm, "\tPort Limit : %u\n", cnat_main_db_max_ports_per_user);
337     vlib_cli_output(vm, "\ttotal address pool : %u\n", total_address_pool_allocated);
338     vlib_cli_output(vm, "\tdynamic port start range : %u\n", cnat_static_port_range);
339
340     pool_foreach(my_vrfmap, cnat_map_by_vrf, ({
341                 hw = vnet_get_hw_interface (vnm, my_vrfmap->i_vrf);
342                 vlib_cli_output(vm, "\tInside Interface  : %v\n", hw->name);
343                 hw = vnet_get_hw_interface (vnm, my_vrfmap->o_vrf);
344                 vlib_cli_output(vm, "\tOutside Interface : %v\n", hw->name);
345
346                 memset(status_str, 0x00, sizeof(status_str));
347                 switch(my_vrfmap->status) {
348                 case S_WAO: clib_memcpy(status_str, "S_WAO", 5); break;
349                 case S_WA:  clib_memcpy(status_str, "S_WA",  4); break;
350                 case S_WO:  clib_memcpy(status_str, "S_WO",  4); break;
351                 case S_RUN: clib_memcpy(status_str, "ONLINE", 6); break;
352                 case S_DEL: clib_memcpy(status_str, "S_DEL", 5); break;
353                 default: clib_memcpy(status_str, "Invalid state", 13); 
354
355                 } 
356                 vlib_cli_output(vm, 
357                               "\tAddress pool map table status : %s\n", status_str);
358
359                 pm = my_vrfmap->portmap_list;
360                 pm_len = vec_len(pm);
361                 my_pm = pm;
362                 ip_addr.s_addr = clib_net_to_host_u32(my_pm->ipv4_address);
363                 vlib_cli_output(vm, 
364                              "\tStart Address : %s\n", inet_ntoa(ip_addr));
365                 my_pm = pm + (pm_len - 1);
366                 ip_addr.s_addr = clib_net_to_host_u32(my_pm->ipv4_address);
367                 vlib_cli_output(vm, 
368                                "\tEnd Address : %s\n", inet_ntoa(ip_addr));
369
370     }));
371     vlib_cli_output(vm, 
372             "\ttcp init timeout    : %u sec\n", tcp_initial_setup_timeout);
373     vlib_cli_output(vm, 
374             "\ttcp active timeout  : %u sec\n", tcp_active_timeout);
375     vlib_cli_output(vm, 
376             "\tudp init timeout    : %u sec\n", udp_init_session_timeout);
377     vlib_cli_output(vm, 
378             "\tudp active timeout  : %u sec\n", udp_act_session_timeout);
379     vlib_cli_output(vm, 
380             "\ticmp session timeout: %u sec\n", icmp_session_timeout);
381
382 #if 0
383     if (cnat_nfv9_global_info.cnat_nfv9_global_collector_index != EMPTY) {
384         vlib_cli_output(vm,"\nGloabal NFV9 Collector :");
385         global_nfv9_logging_info = cnat_nfv9_logging_info_pool +
386             cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
387         cnat_nfv9_show_collector(vm, global_nfv9_logging_info);
388     }
389 #endif
390
391     vlib_cli_output(vm, "\nNFV9 Collector :");
392     if (cnat_nfv9_logging_info_pool !=NULL) { 
393         pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({
394             if (my_nfv9_logging_info != global_nfv9_logging_info) {
395                 cnat_nfv9_show_collector(vm, my_nfv9_logging_info);
396                 vlib_cli_output(vm, "\n");
397             }
398         }));
399     } else {
400         vlib_cli_output(vm, "\n");
401     }
402
403     return;
404 }
405
406 /*
407  * Check if the request flag matches the entry flags and
408  * if so return "1"
409  *
410  * entry_flag_ptr is an output parameter - it returns the flags
411  * corresponding to the translation entry
412  */
413 static u8 cnat_v4_show_verify_display_entry (
414                                         u16                  request_flag,
415                                         cnat_main_db_entry_t *db,
416                                         u16                  *entry_flag_ptr)
417 {
418     u8  display_entry = 0;
419
420     /*
421      * This should never happen
422      */
423     if (!entry_flag_ptr) {
424         return (display_entry);
425     }
426
427     *entry_flag_ptr = 0;
428
429     if ((db->flags & CNAT_DB_FLAG_STATIC_PORT)
430         &&(db->flags & CNAT_DB_FLAG_ALG_ENTRY)) {
431         *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_STATIC;
432         *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_ALG;
433     } else if (db->flags & CNAT_DB_FLAG_STATIC_PORT) {
434         *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_STATIC;
435     } else if ((db->flags & CNAT_DB_FLAG_ALG_ENTRY) || 
436         (db->flags & CNAT_DB_FLAG_PPTP_GRE_ENTRY)) {
437         *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_ALG;
438     } else if (db->flags & CNAT_DB_FLAG_PCPI) {
439         *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC;
440     } else if (db->flags & CNAT_DB_FLAG_PCPE) {
441         *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC; 
442     } else {
443         *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_DYNAMIC;
444     } 
445    
446     if (request_flag == CNAT_TRANSLATION_ENTRY_ALL) {
447         display_entry = 1;
448     } else {
449         /*
450          * Check if the request_flag is STATIC or ALG
451          * and the entry is STATIC or ALG as well
452          */
453         if ((request_flag & CNAT_TRANSLATION_ENTRY_STATIC) &&
454             (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_STATIC)) {
455             display_entry = 1;
456         }
457
458         if ((request_flag & CNAT_TRANSLATION_ENTRY_ALG) &&
459             (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_ALG)) {
460             display_entry = 1;
461         }
462
463         if ((request_flag & CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC) &&
464             (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC)) {
465             display_entry = 1;
466         }
467
468         if ((request_flag & CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC) &&
469             (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC)) {
470             display_entry = 1;
471         }
472
473         /*
474          * For dynamic entry case, check if flags field is 0
475          */
476         if ((request_flag & CNAT_TRANSLATION_ENTRY_DYNAMIC) && 
477             (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_DYNAMIC)) {
478             display_entry = 1;
479         }
480     }
481
482     if (PREDICT_FALSE(show_debug_level > 2)) {
483         PLATFORM_DEBUG_PRINT("Entry (0x%x, %d) -> (0x%x, %d) request_flag 0x%x, entry_flag 0x%x, display_entry %d\n", db->in2out_key.k.ipv4, db->in2out_key.k.port, db->out2in_key.k.ipv4, db->out2in_key.k.port, request_flag, *entry_flag_ptr, display_entry);
484     }
485
486     return (display_entry);
487 }
488 void cnat_v4_show_inside_entry_req_t_handler
489 (spp_api_cnat_v4_show_inside_entry_req_t *mp, vlib_main_t * vm)
490 {
491     cnat_user_db_entry_t *udb = NULL;
492     cnat_main_db_entry_t *db = NULL;
493     cnat_db_key_bucket_t u_ki, ki;
494     u64 a, b, c;
495     u32 index;
496     u16 start_port, end_port, port;
497     u16 request_flag = 0;
498     u16 entry_flag   = 0;
499     u8  num_entries = 0;
500     u8 proto, all;
501     u8 done = 0;
502     cnat_v4_show_translation_entry *entry_list; 
503     cnat_v4_show_translation_entry entry[PLATFORM_MAX_TRANSLATION_ENTRIES];
504     u8 display_entry;
505     u8 flag_str[11];
506     vnet_hw_interface_t * hw;
507     vnet_main_t * vnm = vnet_get_main();
508
509     ki.k.k.ipv4 = mp->ipv4_addr;
510     ki.k.k.vrf = mp->vrf_id;
511     start_port = mp->start_port;
512     end_port = mp->end_port;
513 #if DEBUG
514     vlib_cli_output(vm, "## proto %d, inside-addr 0x%x, start_port %u, "
515                 "end_port %u, vrf 0x%x, flag 0x%x\n",
516                 mp->protocol, 
517                 mp->ipv4_addr,
518                 mp->start_port,
519                 mp->end_port,
520                 mp->vrf_id,
521                 mp->flags);
522 #endif
523
524     proto = mp->protocol;
525     ki.k.k.vrf |= ((u16)proto << CNAT_PRO_SHIFT);
526
527     all = mp->all_entries;  /* for no port range case */
528     request_flag = mp->flags; /* for all, alg, static entries case */
529     entry_list = entry; 
530
531     /* 
532      * check if the address is belonging to this core
533      */
534         
535
536     /*
537      * first we check if the user exists in the udb, if he is not then
538      * it does not make sense to check the main db for translations
539      */
540     u_ki.k.k.vrf = ki.k.k.vrf & CNAT_VRF_MASK;
541     u_ki.k.k.ipv4 = ki.k.k.ipv4;
542     u_ki.k.k.port = 0;
543
544     if (PREDICT_FALSE(show_debug_level > 0)) {
545         vlib_cli_output(vm, "\nI_TRANS_CORE %d: IPv4 0x%x, VRF 0x%x, "
546                 "start_port %d, end_port %d", 
547                 my_instance_number, ki.k.k.ipv4, 
548                 ki.k.k.vrf, start_port, end_port);
549     }
550
551     udb = cnat_user_db_lookup_entry(&u_ki);
552     if (!udb) {
553         if (PREDICT_FALSE(show_debug_level > 0)) {
554             vlib_cli_output(vm, "\nReturning %d entries", 
555                     num_entries); 
556         }
557         return;
558     }
559
560     if (all) {
561     #if 0
562         if (PREDICT_FALSE(show_debug_level > 0)) {
563             PLATFORM_DEBUG_PRINT("\nI_TRANS: Printing ALL\n");
564         }
565
566         /* 
567          * get the head of list of translation entries for that user 
568          * from the user db 
569          */
570         head = udb->translation_list_head_index;
571         db = cnat_main_db + head;
572
573         while (num_entries < PLATFORM_MAX_TRANSLATION_ENTRIES) {
574
575             if (((db->in2out_key.k.vrf & CNAT_PRO_MASK) >> CNAT_PRO_SHIFT)
576                                                             != proto) {
577                 goto next_entry;
578             }
579
580             display_entry = 
581                 spp_api_cnat_v4_show_verify_display_entry(request_flag, db,
582                                                           &entry_flag);
583
584             if (display_entry) {
585                 entry_list->ipv4_addr = 
586                     spp_host_to_net_byte_order_32(db->out2in_key.k.ipv4);
587                 entry_list->cnat_port = 
588                     spp_host_to_net_byte_order_16(db->out2in_key.k.port);
589                 entry_list->src_port = 
590                     spp_host_to_net_byte_order_16(db->in2out_key.k.port);   
591
592                 entry_list->protocol = proto;
593
594                 /* incase of gre - in2out is not accounted */
595                 if(proto != CNAT_PPTP) {
596                     
597                     entry_list->in2out_packets =
598                        spp_host_to_net_byte_order_32(db->in2out_pkts);
599                 } else {
600                     entry_list->in2out_packets = 0;
601                 }
602                 entry_list->out2in_packets =
603                     spp_host_to_net_byte_order_32(db->out2in_pkts);
604
605                 entry_list->flags = 
606                     spp_host_to_net_byte_order_16(entry_flag);
607
608                 num_entries++;
609                 entry_list = entry_list + 1;
610             }
611 next_entry: 
612             db = cnat_main_db + db->user_ports.next;
613             /*
614              * its a circular list, so if we have reached the head again
615              * all the entries for that user have been read
616              */
617             if (db == (cnat_main_db + head)) { 
618                 break;
619             }
620         }
621         resp->num_entries = num_entries;
622     #endif /* if 0 */
623     } else {
624         if (PREDICT_FALSE(show_debug_level > 0)) {
625             vlib_cli_output(vm, "\nI_TRANS: Printing range %d .. %d\n",
626                     start_port, end_port);
627         }
628         /*
629          * port range is specified so for each port calculate the hash and
630          * check if the entry is present in main db
631          */
632         port = start_port;
633         done = 0;
634         while ((!done) && (num_entries < PLATFORM_MAX_TRANSLATION_ENTRIES)) {
635
636             ki.k.k.port = port;
637             if (port >= end_port) {
638                 done = 1;
639             } else {
640                 port++;
641             }
642             CNAT_V4_GET_HASH(ki.k.key64,
643                     ki.bucket,
644                     CNAT_MAIN_HASH_MASK);
645             index = cnat_in2out_hash[ki.bucket].next;
646             if (PREDICT_TRUE(index == EMPTY)) {
647                 continue;
648             }
649
650             do {
651                 db = cnat_main_db + index;
652                 if (db->in2out_key.key64 == ki.k.key64) {
653                     break;
654                 }
655                 index = db->in2out_hash.next;
656             } while (index != EMPTY);
657
658             if (index == EMPTY) {
659                 continue;
660             } else {
661
662                 display_entry = 
663                     cnat_v4_show_verify_display_entry(request_flag, db,
664                             &entry_flag);
665                 if (display_entry) {
666
667                     entry_list->ipv4_addr =
668                         clib_host_to_net_u32(db->out2in_key.k.ipv4);
669                     entry_list->cnat_port =
670                         clib_host_to_net_u16(db->out2in_key.k.port);
671                     entry_list->src_port =
672                         clib_host_to_net_u16(db->in2out_key.k.port);
673
674                     entry_list->protocol = proto;
675                     entry_list->nsessions = db->nsessions; 
676                     entry_list->flags = ((db->flags & CNAT_DB_FLAG_TCP_ACTIVE) ||
677                                          (db->flags & CNAT_DB_FLAG_UDP_ACTIVE)) ? 1:0;
678                     /* incase of gre - in2out is not accounted */
679                     if(proto != CNAT_PPTP) {
680                         entry_list->in2out_packets =
681                             clib_host_to_net_u32(db->in2out_pkts);
682                     } else {
683                         entry_list->in2out_packets = 0;
684                     }
685
686                     entry_list->out2in_packets =
687                         clib_host_to_net_u32(db->out2in_pkts);
688                
689                     if (PREDICT_FALSE(show_debug_level > 3)) {
690                         vlib_cli_output(vm, "\n1. Entry: Addr 0x%x, port %d, num_entries %d",
691                                 clib_net_to_host_u32(entry_list->ipv4_addr), 
692                                 clib_net_to_host_u16(entry_list->cnat_port), 
693                                 num_entries);
694                     } 
695
696                     entry_list = entry_list + 1;
697                     num_entries++;
698                 } 
699             } /* if (index == EMPTY) */
700         } /* while() */
701     }
702
703     if (PREDICT_FALSE(show_debug_level > 0)) {
704         if (num_entries) {
705             vlib_cli_output(vm, "\nReturning %d entries\n", 
706                     num_entries); 
707         }
708     }
709
710     entry_list = entry;
711     u8 i = 0;
712     struct in_addr ip;
713     u8 proto_str[10];
714     u8 transl_str[10];
715     memset(proto_str, 0x00, 10);
716     memset(transl_str, 0x00, 10);
717
718     if      (proto == 1) strncpy((char *)proto_str, "udp", 3);
719     else if (proto == 2) strncpy((char *)proto_str, "tcp", 3);
720     else if (proto == 3) strncpy((char *)proto_str, "icmp", 4);
721     else                 strncpy((char *)proto_str, "unknown", 7);
722
723     if (request_flag == 0x04) strncpy((char *)transl_str, "Dynamic", 7);
724     else strncpy((char *)transl_str, "Unknown", 7); /* currently we are not supporting static/alg entries */
725
726     ip.s_addr = clib_net_to_host_u32(u_ki.k.k.ipv4);
727     hw = vnet_get_hw_interface (vnm, u_ki.k.k.vrf);
728
729     vlib_cli_output (vm, "Inside-translation details\n");
730     vlib_cli_output (vm, "--------------------------\n");
731
732     vlib_cli_output (vm, "Inside interface       : %s\n", hw->name);
733     vlib_cli_output (vm, "Inside address         : %s\n", inet_ntoa(ip));
734     vlib_cli_output (vm, "Start port             : %u\n", start_port);
735     vlib_cli_output (vm, "End port               : %u\n", end_port);
736
737     vlib_cli_output (vm, "--------------------------------------------------------------------------------------"
738             "-----------------------\n");
739     vlib_cli_output (vm, "Outside          Protocol  Inside      Outside    Translation"
740             "      I2O       O2I           Flag      Num\n");
741     vlib_cli_output (vm, "Address                    Src Port    Src Port   Type       "
742             "      Pkts      Pkts                    Sessions\n");
743     vlib_cli_output (vm, "--------------------------------------------------------------------------------------"
744             "-----------------------\n");
745
746     while ((num_entries) && (entry_list) && (i < 50)) {
747
748         ip.s_addr = entry_list->ipv4_addr;
749         memset(flag_str,0x00,11);
750         if((proto == 1) || (proto == 2)) {
751           if(entry_list->flags == 1) {
752             strncpy((char *)flag_str,"Active",6);
753           }
754           else {
755             strncpy((char *) flag_str,"Non Active",10);
756           }
757         } else {
758             strncpy((char *) flag_str, "NA", 2);
759         } 
760         vlib_cli_output(vm, "%s %10s %11u %12u %13s %10u %10u %14s %6u\n",
761                 inet_ntoa(ip), proto_str,
762                 clib_net_to_host_u16(entry_list->src_port),
763                 clib_net_to_host_u16(entry_list->cnat_port),
764                 transl_str, 
765                 clib_net_to_host_u32(entry_list->in2out_packets), 
766                 clib_net_to_host_u32(entry_list->out2in_packets),
767                 flag_str, 
768                 entry_list->nsessions);
769         entry_list++;
770         num_entries--; i++;
771     }
772
773     return; 
774 }
775
776 void cnat_v4_show_outside_entry_req_t_handler
777 (spp_api_cnat_v4_show_outside_entry_req_t *mp, vlib_main_t *vm)
778 {
779     cnat_main_db_entry_t *db = NULL;
780     cnat_db_key_bucket_t ko;
781     u64 a, b, c;
782     u32 index;
783     u16 start_port, end_port, port;
784     u16 request_flag = 0;
785     u16 entry_flag   = 0;
786     u8  num_entries = 0;
787     u8 proto;
788     cnat_v4_show_translation_entry *entry_list;
789     cnat_v4_show_translation_entry entry[PLATFORM_MAX_TRANSLATION_ENTRIES];
790     u8 done = 0;
791     u8 display_entry;
792     u8 flag_str[11];
793     vnet_hw_interface_t * hw;
794     vnet_main_t * vnm = vnet_get_main();
795
796     ko.k.k.ipv4 = mp->ipv4_addr;
797     ko.k.k.vrf = mp->vrf_id;
798     start_port = mp->start_port;
799     end_port = mp->end_port;
800
801     proto = mp->protocol;
802     request_flag = mp->flags;
803
804     ko.k.k.vrf |= ((u16)proto << CNAT_PRO_SHIFT);
805
806     entry_list = entry;
807
808     if (PREDICT_FALSE(show_debug_level > 0)) {
809         vlib_cli_output(vm, "\nO_TRANS_CORE %d: IPv4 0x%x, VRF 0x%x, "
810                         "start_port %d, end_port %d", my_instance_number, 
811                         ko.k.k.ipv4, ko.k.k.vrf, start_port, end_port);
812     }
813
814     /*
815      * for each ip and port combination we need to scan the main db 
816      * and check if the entry is present in main db
817      */
818     port = start_port;
819     done = 0;
820     while ((!done) && (num_entries < PLATFORM_MAX_TRANSLATION_ENTRIES)) {
821         ko.k.k.port = port;
822
823         /*
824          * If we have reached the end_port, we are DONE
825          */
826         if (port >= end_port) {
827             done = 1;
828         } else {
829             port++;
830         }
831
832         CNAT_V4_GET_HASH(ko.k.key64,
833                 ko.bucket,
834                 CNAT_MAIN_HASH_MASK);
835
836         index = cnat_out2in_hash[ko.bucket].next;
837         if (PREDICT_TRUE(index == EMPTY)) {
838             continue;
839         }
840
841         do {
842             db = cnat_main_db + index;
843             if (db->out2in_key.key64 == ko.k.key64) {
844                 break;
845             }
846             index = db->out2in_hash.next;
847         } while (index != EMPTY);
848
849         if (index == EMPTY) {
850             continue;
851         } else {
852             display_entry = 
853                 cnat_v4_show_verify_display_entry(request_flag, db,
854                                                           &entry_flag);
855
856             if (display_entry) {
857                 entry_list->ipv4_addr =
858                     clib_host_to_net_u32(db->in2out_key.k.ipv4);
859                 entry_list->cnat_port =
860                     clib_host_to_net_u16(db->out2in_key.k.port);
861                 entry_list->src_port =
862                     clib_host_to_net_u16(db->in2out_key.k.port);
863                 entry_list->protocol = proto;
864                 entry_list->nsessions = db->nsessions;
865                 entry_list->flags = ((db->flags & CNAT_DB_FLAG_TCP_ACTIVE) || 
866                                      (db->flags & CNAT_DB_FLAG_UDP_ACTIVE)) ? 1:0;
867                 /* incase of gre - in2out is not accounted */
868                 if(proto != CNAT_PPTP) {
869                    entry_list->in2out_packets =
870                     clib_host_to_net_u32(db->in2out_pkts);
871                 } else {
872                    entry_list->in2out_packets = 0 ;
873                 }
874                 entry_list->out2in_packets =
875                     clib_host_to_net_u32(db->out2in_pkts);
876                 #if 0
877                 entry_list->flags =
878                     clib_host_to_net_u16(entry_flag); 
879                 #endif
880                 entry_list = entry_list + 1;
881                 num_entries++;
882             }
883         }
884     }
885     
886     if (num_entries == 0) {
887         /* No point proceeding further */
888         return;
889     }
890
891     if (PREDICT_FALSE(show_debug_level > 0)) {
892         if (num_entries) {
893             vlib_cli_output(vm, "\nO_TRANS: Core %d returning %d entries", 
894                     num_entries); 
895         }
896     }
897
898         entry_list = entry;
899         u8 i = 0;
900     struct in_addr ip;
901     u8 proto_str[10];
902     u8 transl_str[10];
903     memset(proto_str, 0x00, 10);
904     memset(transl_str, 0x00, 10);
905
906     if      (proto == 1) strncpy((char *) proto_str, "udp", 3);
907     else if (proto == 2) strncpy((char *) proto_str, "tcp", 3);
908     else if (proto == 3) strncpy((char *) proto_str, "icmp", 4);
909     else                 strncpy((char *) proto_str, "unknown", 7);
910
911     if (request_flag == 0x04) strncpy((char *) transl_str, "Dynamic", 7);
912     else strncpy((char *)transl_str, "Unknown", 7); /* currently we are not supporting static/alg entries */
913
914     ip.s_addr = clib_net_to_host_u32(ko.k.k.ipv4);
915     hw = vnet_get_hw_interface (vnm, (ko.k.k.vrf & CNAT_VRF_MASK));
916
917     vlib_cli_output (vm, "Outside-translation details\n");
918     vlib_cli_output (vm, "--------------------------\n");
919
920     vlib_cli_output (vm, "Outside interface       : %s\n", hw->name);
921     vlib_cli_output (vm, "Outside address         : %s\n", inet_ntoa(ip));
922     vlib_cli_output (vm, "Start port              : %u\n", start_port);
923     vlib_cli_output (vm, "End port                : %u\n", end_port);
924
925     vlib_cli_output (vm, "--------------------------------------------------------------------------------------"
926             "-----------------------\n");
927     vlib_cli_output (vm, "Inside           Protocol  Outside     Inside     Translation"
928             "      I2O       O2I       Flag          Num\n");
929     vlib_cli_output (vm, "Address                    Dst Port    Dst Port   Type       "
930             "      Pkts      Pkts                    Sessions\n");
931     vlib_cli_output (vm, "--------------------------------------------------------------------------------------"
932             "-----------------------\n");
933
934         while ((num_entries) && (entry_list) && (i < 50)) {
935         ip.s_addr = entry_list->ipv4_addr;
936         memset(flag_str,0x00,11);
937         if((proto == 1) || (proto == 2)) {
938           if(entry_list->flags == 1) {
939             strncpy((char *) flag_str,"Active",6);
940           }
941           else {
942             strncpy((char *) flag_str,"Non Active",10);
943           }
944         } else {
945             strncpy((char *) flag_str, "NA", 2);
946         } 
947         vlib_cli_output(vm, "%s %10s %11u %12u %13s %10u %10u %14s %6u\n",
948                 inet_ntoa(ip), proto_str,
949                 clib_net_to_host_u16(entry_list->cnat_port),
950                 clib_net_to_host_u16(entry_list->src_port),
951                 transl_str, 
952                 clib_net_to_host_u32(entry_list->in2out_packets), 
953                 clib_net_to_host_u32(entry_list->out2in_packets),
954                 flag_str,
955                 entry_list->nsessions);
956         entry_list++;
957         num_entries--; i++;
958
959         }
960     return;
961 }