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