Initial commit of vpp code.
[vpp.git] / vnet / vnet / vcgn / cnat_db_v2.c
1 /* 
2  *------------------------------------------------------------------
3  * cnat_db_v2.c - translation database definitions
4  *
5  * Copyright (c) 2007-2013 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
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_v4_functions.h"
32 #include "cnat_log_api.h"
33 #include "cnat_cli.h"
34 #include "spp_platform_trace_log.h"
35 #include "cnat_bulk_port.h"
36 #include "nat64_db.h"
37 #include "dslite_db.h"
38 #include "cnat_config_api.h"
39
40 #define HASH_TABLE_SIZE  8192 // hash table size
41 #define THROTTLE_TIME  180 // throttle time value for out of port msg/user
42
43 u8 cnat_db_init_done = 0;
44
45 typedef struct {
46   u32 cached_next_index;
47   /* $$$$ add data here */
48
49   /* convenience variables */
50   vlib_main_t * vlib_main;
51   vnet_main_t * vnet_main;
52 } cnat_db_v2_main_t;
53
54 cnat_db_v2_main_t cnat_db_v2_main;
55
56 #if 1
57 /* TOBE_PORTED : Remove the following once fixed */
58 #undef PREDICT_TRUE
59 #undef PREDICT_FALSE
60 #define PREDICT_TRUE(x) (x)
61 #define PREDICT_FALSE(x) (x)
62 #endif
63
64 #define foreach_cnat_db_v2_error \
65 _(DROP, "error-drop packets")
66
67 typedef enum {
68 #define _(sym,str) CNAT_DB_V2_##sym,
69   foreach_cnat_db_v2_error
70 #undef _
71   CNAT_DB_V2_N_ERROR,
72 } cnat_db_v2_error_t;
73
74 static char * cnat_db_v2_error_strings[] __attribute__((unused)) = {
75 #define _(sym,string) string,
76   foreach_cnat_db_v2_error
77 #undef _
78 };
79
80
81 void cnat_table_entry_fill_map(u32 start_addr, u32 end_addr,
82         cnat_portmap_v2_t **port_map_holder)
83 {
84     u32 this_start_addr, this_end_addr, this_addr, new;
85     u32 loop_count;
86     u32 pm_len, i;
87     cnat_portmap_v2_t *my_pm =0;
88     cnat_portmap_v2_t *pm = 0;
89     
90     my_instance_number = 0; 
91
92     this_start_addr = start_addr;
93     this_end_addr   = end_addr;    
94
95     /*
96      * How many new addresses are getting added ??
97      */
98      /* commenting this. Right now end - start will be for this vCGN instance */
99     //new = ((this_end_addr - this_start_addr) / MAX_CORES_PER_PARTITION) + 1;
100     new = (this_end_addr - this_start_addr) + 1;
101
102     pm = *port_map_holder;
103     pm_len = vec_len(pm);
104 #if DEBUG_NOT_COMMENTED
105     printf("this_start_addr = 0x%08X, this_end_addr = 0x%08X, Num Addr = %d\n",
106         this_start_addr, this_end_addr, new);
107     printf("pm_len = %d\n", pm_len);
108 #endif
109     /* Check whether the address pool add requested already exists */
110     my_pm = pm;
111     for(i = 0; i< pm_len; i++) {
112         if(my_pm->ipv4_address == this_start_addr) {
113             printf("address pool with addr 0x%08X exists\n", this_start_addr);
114             return;
115         }
116         my_pm++;
117     }
118
119     /*
120      * For now give a warning message only....
121      */
122 #if 0
123     if ((total_address_pool_allocated + new) >
124         CNAT_MAX_ADDR_POOL_SIZE_PER_CORE) {
125         printf("address pool size (%d) would cross permissible limit (%u) \n",
126             (total_address_pool_allocated + new),
127             CNAT_MAX_ADDR_POOL_SIZE_PER_CORE);
128     }
129 #endif
130
131     total_address_pool_allocated += new;
132     vec_add2(pm, my_pm, new);
133
134 #if DEBUG_NOT_COMMENTED
135     printf("total_address_pool_allocated changed from %d to %d (added %d)",
136         (total_address_pool_allocated - new),
137         total_address_pool_allocated, new);
138     printf("vec add is ok\n");
139 #endif
140
141     memset(my_pm, 0, new*sizeof(*my_pm));
142     this_addr = this_start_addr;
143     loop_count = 0; /* Sanity counter */
144
145     while (this_addr <= this_end_addr) {
146 #if DEBUG_NOT_COMMENTED
147         printf("loop %d: this addr = 0x%08X\n", loop_count+1, this_addr);
148 #endif
149         my_pm->ipv4_address = this_addr;
150         /*
151          * Set all bits to "1" indicating all ports are free
152          */
153         memset(my_pm->bm, 0xff,
154             (((BITS_PER_INST + BITS(uword)-1)/BITS(uword))*(sizeof(uword))));
155         //this_addr += MAX_CORES_PER_PARTITION;
156         this_addr += 1;
157         my_pm++;
158         loop_count++;
159     }
160     /*
161      * We should have loop_count same as the new value
162      */
163     if (loop_count != new) {
164         printf("Mismatch in loop_count (%d) != new (%d)\n",
165             loop_count, new);
166     }
167
168     *port_map_holder = pm;
169
170 #if DEBUG_NOT_COMMENTED
171     printf("revised pm len %d\n", vec_len(*port_map_holder));
172 #endif
173
174     return;
175 }
176
177  
178 void cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log);
179 inline void handle_cnat_port_exceeded_logging(
180     cnat_user_db_entry_t *udb,
181     cnat_key_t   * key,
182     cnat_vrfmap_t *vrfmap);
183
184 cnat_global_counters_t cnat_global_counters;
185 u32  last_log_timestamp = 0;
186 u32  last_user_dyn_port_exc_timestamp = 0;
187 u32  last_user_stat_port_exc_timestamp = 0; 
188
189 index_slist_t *cnat_out2in_hash;
190 index_slist_t *cnat_in2out_hash;
191 index_slist_t *cnat_user_hash;
192 index_slist_t *cnat_timeout_hash;
193 index_slist_t *cnat_session_hash;
194
195 cnat_main_db_entry_t *cnat_main_db;
196 cnat_user_db_entry_t *cnat_user_db;
197 cnat_session_entry_t *cnat_session_db;
198 cnat_timeout_db_entry_t *cnat_timeout_db;
199
200 cgse_nat_db_entry_t   *cgse_nat_db;
201 cgse_nat_user_db_entry_t *cgse_user_db;
202 cgse_nat_session_db_entry_t *cgse_session_db;
203
204 nat44_dslite_common_stats_t nat44_dslite_common_stats[255]; /* 0 is for nat44 */
205 nat44_dslite_global_stats_t nat44_dslite_global_stats[2]; /* 0 for nat44 and 1 for dslite */
206 nat44_counters_stats_t      nat44_counters_stats[CNAT_MAX_VRFMAP_ENTRIES];
207 /*For displaying show cgn <cgn-name> inside-vrf <vrf-name> counters */
208
209 /*
210  * This is the pool of vrf map structures used by latest main-db functions
211  */
212 cnat_vrfmap_t *cnat_map_by_vrf;
213
214 /*
215  * Have a mapping table of vrf_id-->vrf_map_index
216  * This helps in easily getting the vrf_map structure during
217  * main-db create paths
218  */
219 u16 vrf_map_array[CNAT_MAX_VRFMAP_ENTRIES];
220 cnat_svi_params_entry svi_params_array[CNAT_MAX_VRFMAP_ENTRIES];
221 cnat_ingress_vrfid_name_entry vrfid_name_map[MAX_VRFID] = {{0}};
222 u64 in2out_drops_port_limit_exceeded;
223 u64 in2out_drops_system_limit_reached;
224 u64 in2out_drops_resource_depletion;
225 u64 no_translation_entry_drops;
226 u32 no_sessions;
227
228 #define CNAT_SET_ICMP_MSG_INFO \
229 if (PREDICT_TRUE((my_vrfmap->i_vrf < CNAT_MAX_VRFMAP_ENTRIES) &&             \
230     (svi_params_array[my_vrfmap->i_vrf].ipv4_addr))) {                       \
231     info->gen_icmp_msg = icmp_msg_gen_allowed();  \
232     info->svi_addr = svi_params_array[my_vrfmap->i_vrf].ipv4_addr;           \
233 }
234
235 #define CNAT_DEBUG_INSIDE_ERR(err) \
236 if (((protocol == CNAT_UDP) && \
237      (debug_i_flag & CNAT_DEBUG_ERR_UDP)) || \
238     ((protocol == CNAT_TCP) && \
239      (debug_i_flag & CNAT_DEBUG_ERR_TCP)) || \
240     ((protocol == CNAT_ICMP) && \
241      (debug_i_flag & CNAT_DEBUG_ERR_ICMP))) { \
242     cnat_db_debug_error(&u_ki, err); \
243 }
244
245 #define DSLITE_DEBUG_INSIDE_ERR(err) \
246 if (((protocol == CNAT_UDP) && \
247      (debug_i_flag & CNAT_DEBUG_ERR_UDP)) || \
248     ((protocol == CNAT_TCP) && \
249      (debug_i_flag & CNAT_DEBUG_ERR_TCP)) || \
250     ((protocol == CNAT_ICMP) && \
251      (debug_i_flag & CNAT_DEBUG_ERR_ICMP))) { \
252     dslite_db_debug_error(&u_ki, err); \
253 }
254
255 #define PORT_LIMIT_LOW_THRESHOLD_FOR_SYSLOG    7
256 /* If the max_limit is less than 10, no meaningful throttling can be 
257  * done.. so, log only once per user and never clear the flag 
258  * once the user exceeds limit
259  */
260 #define CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb, max_limit) \
261     if(PREDICT_FALSE(udb->flags & CNAT_USER_DB_PORT_LIMIT_EXCEEDED)) { \
262         if(udb->ntranslations < \
263             ((max_limit/10)*PORT_LIMIT_LOW_THRESHOLD_FOR_SYSLOG) && \
264             max_limit >= 10) { \
265             udb->flags = udb->flags & (~CNAT_USER_DB_PORT_LIMIT_EXCEEDED); \
266         } \
267     } 
268
269 #ifdef TOBE_PORTED
270 /* Commented to remove unused variable warning */
271 static char *debug_db_error[] = {
272     "no error", /* CNAT_SUCCESS */
273     "no config", /*CNAT_NO_CONFIG*/
274     "not in run state", /*CNAT_NO_VRF_RUN*/
275     "no pool for any", /*CNAT_NO_POOL_ANY*/
276     "no port for any", /*CNAT_NO_PORT_ANY*/
277     "bad in use for any", /*CNAT_BAD_INUSE_ANY*/
278     "not found for any", /*CNAT_NOT_FOUND_ANY*/
279     "invalid index for direct", /*CNAT_INV_PORT_DIRECT*/
280     "deleted addr for direct", /*CNAT_DEL_PORT_DIRECT*/
281     "bad in use for direct",/*CNAT_BAD_INUSE_DIRECT*/
282     "not found for direct",/*CNAT_NOT_FOUND_DIRECT*/
283     "out of port limit", /*CNAT_OUT_LIMIT*/
284     "main db limit", /*CNAT_MAIN_DB_LIMIT*/
285     "user db limit", /*CNAT_USER_DB_LIMIT*/
286     "not static port", /*CNAT_NOT_STATIC_PORT*/
287     "bad static port request", /*CNAT_BAD_STATIC_PORT_REQ*/
288     "not this core", /*CNAT_NOT_THIS_CORE*/
289     "parser error", /*CNAT_ERR_PARSER*/
290     "invalid msg id", /*CNAT_ERR_INVALID_MSG_ID*/
291     "invalid msg size", /*CNAT_ERR_INVALID_MSG_SIZE*/
292     "invalid payload size", /*CNAT_ERR_INVALID_PAYLOAD_SIZE*/
293     "bad tcp udp port", /*CNAT_ERR_BAD_TCP_UDP_PORT*/
294     "bulk single failure", /*CNAT_ERR_BULK_SINGLE_FAILURE*/
295     "xlat id invalid", /*CNAT_ERR_XLAT_ID_INVALID*/
296     "xlat v6 prefix invalid", /*CNAT_ERR_XLAT_V6_PREFIX_INVALID*/
297     "xlat v4 prefix invalid", /*CNAT_ERR_XLAT_V4_PREFIX_INVALID*/
298     "xlat tcp mss invalid", /*CNAT_ERR_XLAT_TCP_MSS_INVALID*/
299     "6rd id invalid", /*CNAT_ERR_6RD_ID_INVALID*/
300     "6rd v4 tunnel src invalid", /*CNAT_ERR_6RD_V4_TUNNEL_SRC_INVALID*/
301     "6rd v6 prefix invalid", /*CNAT_ERR_6RD_V6_PREFIX_INVALID*/
302     "6rd v6 BR unicast invalid", /*CNAT_ERR_6RD_V6_BR_UNICAST_INVALID*/
303     "6rd v4 prefix masklen invalid", /*CNAT_ERR_6RD_V4_PREFIX_MASK_LEN_INVALID*/
304     "6rd v4 suffix masklen invalid", /*CNAT_ERR_6RD_V4_SUFFIX_MASK_LEN_INVALID*/
305     "6rd v4 combo masklen invalid", /*CNAT_ERR_6RD_V4_COMBO_MASK_LEN_INVALID*/
306     "6rd tunnel mtu invalid", /*CNAT_ERR_6RD_TUNNEL_MTU_INVALID*/
307     "6rd tunnel ttl invalid", /*CNAT_ERR_6RD_TUNNEL_TTL_INVALID*/
308     "6rd tunnel tos invalid", /*CNAT_ERR_6RD_TUNNEL_TOS_INVALID*/
309 };
310 #endif
311
312 f64 port_log_timestamps[HASH_TABLE_SIZE]; /* 32 KB array per core */
313
314 void port_exceeded_msg_log (u32 src_addr, u16 i_vrf)
315 {
316     u32 hash_value;
317     f64 current_timestamp;
318     vlib_main_t  *vlib_main;
319
320     vlib_main = vlib_get_main();
321     current_timestamp = vlib_time_now((vlib_main_t *) vlib_main);
322
323     hash_value = ((src_addr >> 16) ^ ((src_addr & 0xffff) ^ i_vrf)) % (1024*8); 
324
325     if (PREDICT_FALSE((current_timestamp - port_log_timestamps[hash_value]) > THROTTLE_TIME)) {
326         u32 arg[2] = {i_vrf, src_addr};
327         /* update timestamp */
328         port_log_timestamps[hash_value] = current_timestamp;
329         spp_printf(CNAT_USER_OUT_OF_PORTS, 2, arg);
330     }
331
332     return ;
333 }
334
335 static void log_port_alloc_error(cnat_errno_t error, cnat_key_t *k)
336 {
337     u32 error_code;
338     u32 arr[] = {k->k.vrf, k->k.ipv4, k->k.port};
339     switch (error)
340     {
341     case CNAT_NO_POOL_ANY:
342         error_code = CNAT_NO_POOL_FOR_ANY_ERROR;
343         break;
344     case CNAT_NO_PORT_ANY:
345         error_code = CNAT_NO_PORT_FOR_ANY_ERROR;
346         break;
347     case CNAT_ERR_PARSER:
348         error_code = CNAT_WRONG_PORT_ALLOC_TYPE;
349         break;
350     case CNAT_BAD_INUSE_ANY:
351         error_code = CNAT_BAD_INUSE_ANY_ERROR;
352         break;
353     case CNAT_BAD_INUSE_DIRECT:
354         error_code = CNAT_BAD_INUSE_DIRECT_ERROR;
355         break;
356     case CNAT_NOT_FOUND_ANY:
357         error_code = CNAT_NOT_FOUND_ANY_ERROR;
358         break;
359     case CNAT_NOT_FOUND_DIRECT:
360         error_code = CNAT_NOT_FOUND_DIRECT_ERROR;
361         break;
362     case CNAT_INV_PORT_DIRECT:
363         error_code = CNAT_INV_PORT_FOR_DIRECT_ERROR;
364         break;
365     default:
366         error_code = CNAT_NEW_PORT_ALLOC_ERROR; /* If this code is seen in the log,
367        it means, new error codes are to be added here */
368        break;
369     }
370     spp_printf(error_code, 3, arr);
371 }
372
373 void cnat_db_debug_error(cnat_db_key_bucket_t *u_ki, 
374                          cnat_errno_t  error)
375 {
376     if (PREDICT_FALSE((u_ki->k.k.vrf == debug_i_vrf) &&
377         ((u_ki->k.k.ipv4 >= debug_i_addr_start) &&
378          (u_ki->k.k.ipv4 <= debug_i_addr_end)))) { 
379 #ifdef DEBUG_PRINTF_ENABLED
380             PLATFORM_DEBUG_PRINT("failed to allocate port due to %s "
381            "for i-vrf 0x%x addr 0x%x port 0x%x\n",
382             debug_db_error[error], u_ki->k.k.vrf,
383                u_ki->k.k.ipv4, u_ki->k.k.port);
384 #endif
385         {
386             u32 arg[] = {u_ki->k.k.vrf, u_ki->k.k.ipv4,  u_ki->k.k.port};
387             spp_printf(error, 3, arg);
388         }
389     }
390 }
391
392 void dslite_db_debug_error(dslite_db_key_bucket_t *u_ki,
393                          cnat_errno_t  error)
394 {
395     if (PREDICT_FALSE((u_ki->dk.ipv4_key.k.vrf == debug_i_vrf) &&
396         ((u_ki->dk.ipv4_key.k.ipv4 >= debug_i_addr_start) &&
397          (u_ki->dk.ipv4_key.k.ipv4 <= debug_i_addr_end)))) {
398 #ifdef DEBUG_PRINTF_ENABLED
399             PLATFORM_DEBUG_PRINT("failed to allocate port due to %s "
400            "for i-vrf 0x%x addr 0x%x port 0x%x\n",
401             debug_db_error[error], u_ki->dk.ipv4_key.k.vrf,
402                u_ki->dk.ipv4_key.k.ipv4, u_ki->dk.ipv4_key.k.port);
403 #endif
404         {
405             u32 arg[] = {u_ki->dk.ipv4_key.k.vrf, u_ki->dk.ipv4_key.k.ipv4,  u_ki->dk.ipv4_key.k.port};
406             spp_printf(error, 3, arg);
407         }
408     }
409 }
410
411 void cnat_db_debug_i2o_drop(cnat_db_key_bucket_t *ki)
412 {
413     if (PREDICT_FALSE(((ki->k.k.vrf & CNAT_VRF_MASK) == debug_i_vrf) && 
414         ((ki->k.k.ipv4 >= debug_i_addr_start) &&
415         (ki->k.k.ipv4 <= debug_i_addr_end)))) {
416 #ifdef DEBUG_PRINTF_ENABLED
417         PLATFORM_DEBUG_PRINT("pakcet[i-vrf 0x%x addr 0x%x port 0x%x] dropped\n", 
418            ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port);
419 #endif
420         {
421             u32 arg[] = {ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port};
422             spp_printf(CNAT_PACKET_DROP_ERROR, 3, arg);
423         }
424     }
425 }
426
427 void cnat_db_in2out_hash_delete (cnat_main_db_entry_t *ep, cnat_user_db_entry_t *up)
428 {
429     u64 a, b, c;
430     u32 index, bucket;
431     cnat_main_db_entry_t *this, *prev;
432
433 #ifdef DSLITE_DEF
434     if (PREDICT_FALSE(ep->flags & CNAT_DB_DSLITE_FLAG)) {
435         dslite_key_t dk = { 
436                               {up->ipv6[0], up->ipv6[1], up->ipv6[2], up->ipv6[3]} ,
437                               {ep->in2out_key.k.ipv4, ep->in2out_key.k.port, ep->in2out_key.k.vrf}
438                           };
439         DSLITE_V6_GET_HASH((&dk),
440                      bucket,
441                      CNAT_MAIN_HASH_MASK);
442         DSLITE_PRINTF(1, "Delete1 DSL main hash bucket ..%u\n", bucket);
443     } else {
444         CNAT_V4_GET_HASH(ep->in2out_key.key64,
445                          bucket, CNAT_MAIN_HASH_MASK)
446         DSLITE_PRINTF(1, "Delete1 NAT44 main hash bucket ..%u\n", bucket);
447     }
448 #else
449     CNAT_V4_GET_HASH(ep->in2out_key.key64,
450                      bucket, CNAT_MAIN_HASH_MASK)
451 #endif
452     
453     index = cnat_in2out_hash[bucket].next;
454
455     ASSERT(index != EMPTY);
456
457     prev = 0;
458     do {
459         this = cnat_main_db + index;
460         if (PREDICT_TRUE(this == ep)) {
461             if (prev == 0) {
462                 cnat_in2out_hash[bucket].next = ep->in2out_hash.next;
463                 return;
464             } else {
465                 prev->in2out_hash.next = ep->in2out_hash.next;
466                 return;
467             }
468         }
469         prev = this;
470         index = this->in2out_hash.next;
471     } while (index != EMPTY);
472
473     ASSERT(0);
474 }
475
476 void cnat_db_out2in_hash_delete (cnat_main_db_entry_t *ep)
477 {
478     u64 a, b, c;
479     u32 index, bucket;
480     cnat_main_db_entry_t *this, *prev;
481
482     CNAT_V4_GET_HASH(ep->out2in_key.key64,
483                         bucket, CNAT_MAIN_HASH_MASK)
484
485     index = cnat_out2in_hash[bucket].next;
486
487     ASSERT(index != EMPTY);
488
489     prev = 0;
490     do {
491         this = cnat_main_db + index;
492         if (PREDICT_TRUE(this == ep)) {
493             if (prev == 0) {
494                 cnat_out2in_hash[bucket].next = ep->out2in_hash.next;
495                 return;
496             } else {
497                 prev->out2in_hash.next = ep->out2in_hash.next;
498                 return;
499             }
500         }
501         prev = this;
502         index = this->out2in_hash.next;
503     } while (index != EMPTY);
504
505     ASSERT(0);
506 }
507
508 cnat_main_db_entry_t*
509 cnat_main_db_lookup_entry(cnat_db_key_bucket_t *ki)
510 {
511     u64 a, b, c;
512     u32 index;
513     cnat_main_db_entry_t *db;
514
515     CNAT_V4_GET_HASH(ki->k.key64, 
516                      ki->bucket,
517                      CNAT_MAIN_HASH_MASK);
518  
519     index = cnat_in2out_hash[ki->bucket].next;
520     if (PREDICT_TRUE(index == EMPTY)) {
521         return (NULL);
522     }
523
524     do {
525         db = cnat_main_db + index;
526         if (PREDICT_TRUE(db->in2out_key.key64 == ki->k.key64)) {
527             return db;
528         }
529         index = db->in2out_hash.next;
530     } while (index != EMPTY);
531
532     return (NULL);
533 }
534
535 void cnat_user_db_delete (cnat_user_db_entry_t *up)
536 {
537     u64 a, b, c;
538     u32 index, bucket;
539     cnat_user_db_entry_t *this, *prev;
540     
541     if (PREDICT_FALSE(up->flags & CNAT_USER_DB_NAT64_FLAG) != 0) {
542        /* Preventive check - Not a NAT44 entry */
543         return;
544     }
545
546 #if 1
547     if(PREDICT_FALSE(up->flags & CNAT_USER_DB_DSLITE_FLAG)) {
548         dslite_key_t dk = {
549                               {up->ipv6[0], up->ipv6[1], up->ipv6[2], up->ipv6[3]} ,
550                               {{up->key.k.ipv4, up->key.k.port, up->key.k.vrf}}
551                           };
552
553         DSLITE_V6_GET_HASH((&dk),
554                      bucket,
555                      CNAT_USER_HASH_MASK); 
556         DSLITE_PRINTF(1, "Delete1 DSL user hash bucket ..%u\n", bucket);
557     } else {
558         CNAT_V4_GET_HASH(up->key.key64,
559                        bucket, CNAT_USER_HASH_MASK)
560         DSLITE_PRINTF(1, "Delete1 NAT44 user hash bucket ..%u\n", bucket);
561     }
562 #else
563     CNAT_V4_GET_HASH(up->key.key64,
564                      bucket, CNAT_USER_HASH_MASK)
565     DSLITE_PRINTF(1, "Delete2 NAT44 user hash bucket ..%u\n", bucket);
566 #endif
567
568     index = cnat_user_hash[bucket].next;
569
570     ASSERT(index != EMPTY);
571
572     prev = 0;
573     do {
574         this = cnat_user_db + index;
575         if (PREDICT_TRUE(this == up)) {
576             if (prev == 0) {
577                 cnat_user_hash[bucket].next = up->user_hash.next;
578                 goto found;
579             } else {
580                 prev->user_hash.next = up->user_hash.next;
581                 goto found;
582             }
583         }
584         prev = this;
585         index = this->user_hash.next;
586     } while (index != EMPTY);
587
588     ASSERT(0);
589
590  found:
591     pool_put(cnat_user_db, up);    
592 }
593
594 cnat_user_db_entry_t*
595 cnat_user_db_lookup_entry(cnat_db_key_bucket_t *uki) 
596 {
597     u64 a, b, c;
598     u32 index;
599     cnat_user_db_entry_t *udb=NULL;
600
601     CNAT_V4_GET_HASH(uki->k.key64, 
602                      uki->bucket,
603                      CNAT_USER_HASH_MASK)
604
605     /* now: index in user vector */
606     index = cnat_user_hash[uki->bucket].next;
607     if (PREDICT_TRUE(index != EMPTY)) {
608         do {
609             udb = cnat_user_db + index;
610             if (PREDICT_FALSE(udb->key.key64 == uki->k.key64)) {
611                 return udb;
612             }
613             index = udb->user_hash.next;
614         } while (index != EMPTY);
615     }
616     return (NULL);
617 }
618
619 cnat_user_db_entry_t*
620 cnat_user_db_create_entry(cnat_db_key_bucket_t *uki,
621                           u32 portmap_index)
622 {
623     cnat_user_db_entry_t *udb = NULL;
624
625     pool_get(cnat_user_db, udb);
626     memset(udb, 0, sizeof(*udb));
627
628     udb->ntranslations = 1; 
629     udb->portmap_index = portmap_index;
630     udb->key.key64 = uki->k.key64;
631     /* Add this user to the head of the bucket chain */
632     udb->user_hash.next = 
633              cnat_user_hash[uki->bucket].next;
634     cnat_user_hash[uki->bucket].next = udb - cnat_user_db;
635
636 #ifndef NO_BULK_LOGGING
637     INIT_BULK_CACHE(udb)
638 #endif /* NO_BULK_LOGGING */
639     return udb;
640 }
641
642 cnat_main_db_entry_t*
643 cnat_create_main_db_entry_and_hash(cnat_db_key_bucket_t *ki,
644                                    cnat_db_key_bucket_t *ko,
645                                    cnat_user_db_entry_t *udb)
646 {
647     u64 a, b, c;
648     u32 db_index;
649     cnat_main_db_entry_t *db = NULL;
650
651     pool_get(cnat_main_db, db);
652     memset(db, 0, sizeof(*db));
653
654     db_index = db - cnat_main_db;
655     db->in2out_key.k.ipv4 = ki->k.k.ipv4;
656     db->in2out_key.k.port = ki->k.k.port;
657     db->in2out_key.k.vrf = ki->k.k.vrf;
658     db->out2in_key.k.ipv4 = ko->k.k.ipv4;
659     db->out2in_key.k.port = ko->k.k.port;
660     db->out2in_key.k.vrf = ko->k.k.vrf;
661
662     db->user_ports.next = db_index;
663     db->user_ports.prev = db_index;
664     db->user_index = udb - cnat_user_db;
665     //db->portmap_index = udb->portmap_index;
666     db->flags &= ~(CNAT_DB_DSLITE_FLAG); // Mark that it is not dslite
667     if (PREDICT_FALSE(udb->ntranslations == 1)) {
668         /*
669          * first port for this src vrf/src ip addr
670          */
671         udb->translation_list_head_index = db_index;
672     } else {
673         index_dlist_addtail(udb->translation_list_head_index,
674                             (u8 *)cnat_main_db, sizeof(cnat_main_db[0]),
675                             STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports),
676                             db_index);
677     }
678
679     /* 
680      * setup o2i hash key
681      */
682     CNAT_V4_GET_HASH(ko->k.key64, 
683                      ko->bucket,
684                      CNAT_MAIN_HASH_MASK)
685     db->out2in_hash.next = cnat_out2in_hash[ko->bucket].next;
686     cnat_out2in_hash[ko->bucket].next = db_index;
687     /*
688      * setup i2o hash key, bucket is already calculate
689      */
690     db->in2out_hash.next = cnat_in2out_hash[ki->bucket].next;
691     cnat_in2out_hash[ki->bucket].next = db_index;
692
693 #if DEBUG > 1
694     printf("\nMy_Instance_Number %d: Bucket %d, Db_Index %d",
695            my_instance_number, ki->bucket, db_index);
696     printf("\nInside (VRF 0x%x, IP 0x%x, PORT 0x%x)",
697            db->in2out_key.k.vrf, db->in2out_key.k.ipv4, db->in2out_key.k.port);
698     printf("\nOutside (VRF 0x%x, IP 0x%x, PORT 0x%x)",
699            db->out2in_key.k.vrf, db->out2in_key.k.ipv4, db->out2in_key.k.port);
700     printf("\nUser Index %d, IP 0x%x",
701            db->user_index, udb->key.k.ipv4);
702 #endif
703
704     NAT44_COMMON_STATS.active_translations++;
705
706     return db;
707 }
708
709 static inline void pptp_clear_all_channels(
710          cnat_main_db_entry_t *db)
711 {
712    u32 db_index, current_db_index;
713    cnat_main_db_entry_t *temp_db;
714
715    /* clear all channels */
716   
717    db_index = db->proto_data.pptp_list.next;
718    current_db_index  = db - cnat_main_db;
719
720    while( db_index != EMPTY) {
721        temp_db = cnat_main_db + db_index;
722        db_index = temp_db->proto_data.pptp_list.next;
723        temp_db->entry_expires = 0;
724        if(PREDICT_FALSE(temp_db->proto_data.pptp_list.prev 
725            == current_db_index)) { // Decouple child GREs from parent
726            temp_db->proto_data.pptp_list.prev = EMPTY; 
727        }
728    }
729
730    db->proto_data.pptp_list.next = EMPTY;
731 }
732
733 void pptp_remove_channel_from_tunnel(cnat_main_db_entry_t *db) {
734    
735     cnat_main_db_entry_t *prev_db, *next_db;
736     
737     prev_db = cnat_main_db + db->proto_data.pptp_list.prev;
738     next_db = cnat_main_db + db->proto_data.pptp_list.next;
739   
740     /* remove entry from the tunnel list */ 
741     if(PREDICT_TRUE(db->proto_data.pptp_list.prev != EMPTY)) {
742         prev_db->proto_data.pptp_list.next =
743                  db->proto_data.pptp_list.next ;  
744     }
745
746     if(db->proto_data.pptp_list.next != EMPTY) {
747        next_db->proto_data.pptp_list.prev
748                 = db->proto_data.pptp_list.prev;
749     }
750
751 }
752
753 void cnat_delete_main_db_entry_v2 (cnat_main_db_entry_t *ep)
754 {
755     u32 main_db_index;
756     u32 vrfmap_len, udb_len;
757     cnat_user_db_entry_t *up =0;
758     cnat_portmap_v2_t *pm =0;
759     cnat_portmap_v2_t *my_pm =0;
760     cnat_vrfmap_t       *my_vrfmap =0;
761     u16 static_port_range;
762 #ifndef NO_BULK_LOGGING
763     bulk_alloc_size_t bulk_size;
764     int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
765 #endif
766     pool_header_t *h = pool_header(cnat_user_db);
767     u16 instance = 0;
768     u32                 my_index;
769
770
771     if (PREDICT_FALSE(ep->flags & CNAT_DB_NAT64_FLAG) != 0) {
772         /* Preventive check - Not a NAT44 entry */
773         return;
774     }
775
776    if(PREDICT_FALSE(ep->flags & 
777         CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE)) {
778       pptp_clear_all_channels(ep);
779       PPTP_DECR(active_tunnels);
780    }
781
782    if(PREDICT_FALSE(ep->flags &
783         CNAT_DB_FLAG_PPTP_GRE_ENTRY)) {
784         pptp_remove_channel_from_tunnel(ep);
785         PPTP_DECR(active_channels);
786    }
787
788     /* This function gets called from various locations..
789      * many times from config handler.. so we
790      * to ensure that multiple sessions if any are
791      * released
792      */
793
794     if(PREDICT_FALSE(ep->nsessions > 1)) {
795         cnat_session_entry_t *sdb;
796         while(ep->nsessions > 1 &&
797             ep->session_head_index != EMPTY) {
798             sdb = cnat_session_db + ep->session_head_index;
799             cnat_delete_session_db_entry(sdb, TRUE);
800         }
801     }
802
803     /* Find the set of portmaps for the outside vrf */
804     vrfmap_len = vec_len(cnat_map_by_vrf);
805     udb_len = vec_len(cnat_user_db);
806
807     /* In case of invalid user just return, deleting only main db
808      * is not a good idea, since some valid user db entry might be pointing 
809      * to that main db and hence leave the dbs in a inconsistent state
810      */
811     if (PREDICT_FALSE((ep->user_index >= udb_len) || 
812                     (clib_bitmap_get(h->free_bitmap, ep->user_index)))) {
813 #ifdef DEBUG_PRINTF_ENABLED
814         printf("invalid/unused user index in db %d\n", ep->user_index);
815 #endif
816         spp_printf(CNAT_INV_UNUSED_USR_INDEX, 1, (u32 *) &(ep->user_index));
817         cnat_main_db_entry_dump(ep);
818         return;
819     }
820
821     up = cnat_user_db + ep->user_index;
822
823 /* Point to the right portmap list */
824 if (PREDICT_FALSE(ep->flags & CNAT_DB_DSLITE_FLAG)) {
825     instance = ep->dslite_nat44_inst_id;
826     pm = dslite_table_db_ptr[instance].portmap_list;
827     if(PREDICT_FALSE((pm == NULL))) {
828         DSLITE_PRINTF(3, "NULL portmap list for dslite_id %u, state %u\n",
829                       instance,  dslite_table_db_ptr[instance].state);
830         cnat_main_db_entry_dump(ep);
831         goto delete_entry;
832     }
833     static_port_range = 
834     STAT_PORT_RANGE_FROM_INST_PTR(&(dslite_table_db_ptr[instance]));
835     /*
836      * Netflow logging API for delete event 
837      */
838     bulk_size = 
839         BULKSIZE_FROM_VRFMAP(&(dslite_table_db_ptr[instance]));
840 } else {
841     if (PREDICT_FALSE(ep->vrfmap_index >= vrfmap_len)) {
842 #ifdef DEBUG_PRINTF_ENABLED
843         printf("invalid vrfmap index in db\n");
844 #endif
845         spp_printf(CNAT_INVALID_VRFMAP_INDEX, 0, NULL);
846         cnat_main_db_entry_dump(ep);
847         goto delete_entry;
848     }
849     instance = NAT44_RESERVED_INST_ID;
850     my_vrfmap = cnat_map_by_vrf + ep->vrfmap_index;
851     pm = my_vrfmap->portmap_list;
852     static_port_range = cnat_static_port_range;
853     bulk_size = BULKSIZE_FROM_VRFMAP(my_vrfmap);
854 }
855  
856     if (PREDICT_FALSE(ep->flags & CNAT_DB_FLAG_PORT_PAIR)) {
857         /* Give back the port(s) */
858         cnat_port_free_v2_bulk(pm, up->portmap_index,
859             PORT_PAIR, ep->out2in_key.k.port, up, static_port_range
860 #ifndef NO_BULK_LOGGING
861             , bulk_size, &nfv9_log_req
862 #endif
863             );
864     } else {
865         /* Give back the port(s) */
866         cnat_port_free_v2_bulk (pm, up->portmap_index,
867             PORT_SINGLE, ep->out2in_key.k.port, up, static_port_range
868 #ifndef NO_BULK_LOGGING
869             , bulk_size, &nfv9_log_req
870 #endif
871             );
872     }
873
874     if (PREDICT_TRUE(!(ep->flags & CNAT_DB_DSLITE_FLAG))) {
875         if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
876             if(PREDICT_FALSE(my_vrfmap->nf_logging_policy == SESSION_LOG_ENABLE)) {
877                 if(ep->nsessions != 0) {
878                     cnat_nfv9_nat44_log_session_delete(ep, NULL, my_vrfmap);
879                 }
880             } else {
881                 cnat_nfv9_log_mapping_delete(ep, my_vrfmap
882 #ifndef NO_BULK_LOGGING
883                 , nfv9_log_req
884 #endif
885                 );
886             }
887             if(PREDICT_TRUE((my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE) ||
888                             (ep->nsessions != 0))) {
889                 cnat_syslog_nat44_mapping_delete(ep, my_vrfmap, NULL
890 #ifndef NO_BULK_LOGGING
891                 , nfv9_log_req
892 #endif
893                 );
894             }
895         }
896     } else {
897         if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
898             if(PREDICT_FALSE( dslite_table_db_ptr[instance].nf_logging_policy ==
899                                       SESSION_LOG_ENABLE)) {
900                 cnat_nfv9_ds_lite_log_session_delete(ep, 
901                                 (dslite_table_db_ptr + instance),NULL);
902             } else {
903                 cnat_nfv9_ds_lite_mapping_delete(ep,
904                                 (dslite_table_db_ptr + instance)
905 #ifndef NO_BULK_LOGGING
906                 , nfv9_log_req
907 #endif
908                 );
909             }
910 #ifdef TOBE_PORTED
911             cnat_syslog_ds_lite_mapping_delete(ep,
912                                 (dslite_table_db_ptr + instance), NULL
913 #ifndef NO_BULK_LOGGING
914             , nfv9_log_req
915 #endif
916             );
917 #endif /* TOBE_PORTED */
918         }
919     }
920
921 delete_entry:
922
923     main_db_index = ep - cnat_main_db;
924
925     up->ntranslations--;
926
927     /*
928      * when user reaches max allowed port limit
929      * we generate icmp msg and inc the counter
930      * when counter reach the icmp msg rate limit
931      * we stop icmp msg gen
932      * when a user port is freed
933      * that means we need to clear the msg gen counter
934      * so that next time 
935      * reach max port limit, we can generate new icmp msg again
936      */
937     up->icmp_msg_count = 0;
938
939     up->translation_list_head_index = index_dlist_remelem (
940         up->translation_list_head_index, (u8 *)cnat_main_db,
941         sizeof (cnat_main_db[0]),
942         STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports),
943         main_db_index);
944
945     cnat_db_in2out_hash_delete(ep, up);
946
947     if (PREDICT_FALSE(up->ntranslations == 0)) {
948         ASSERT(up->translation_list_head_index == EMPTY);
949         nat44_dslite_common_stats[instance].num_subscribers--;
950         my_index = up->portmap_index;
951         my_pm = pm + my_index;
952         if(PREDICT_TRUE(my_pm->private_ip_users_count)) {
953             my_pm->private_ip_users_count--;
954 #ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED
955             PLATFORM_DEBUG_PRINT("\n cnat_delete_main_db_entry_v2 "
956                                  "private_ip_users_count = %d",
957                                  my_pm->private_ip_users_count);
958 #endif
959             
960         }
961         cnat_user_db_delete(up);
962         
963     }
964
965     /* Remove from main DB hashes */
966     //cnat_db_in2out_hash_delete(ep);
967     cnat_db_out2in_hash_delete(ep);
968
969     pool_put(cnat_main_db, ep);
970
971     if(PREDICT_FALSE(ep->flags & CNAT_DB_FLAG_STATIC_PORT)) {
972             nat44_dslite_common_stats[instance].num_static_translations--;
973     } else {
974             nat44_dslite_common_stats[instance].num_dynamic_translations--;
975     }
976     nat44_dslite_common_stats[instance].active_translations--;
977     nat44_dslite_global_stats[!!(instance - 1)].translation_delete_count ++;
978 }
979
980 cnat_main_db_entry_t*
981 cnat_main_db_lookup_entry_out2in (cnat_db_key_bucket_t *ko)
982 {
983     u64 a, b, c;
984     u32 index;
985     cnat_main_db_entry_t *db;
986
987     CNAT_V4_GET_HASH(ko->k.key64,
988                      ko->bucket,
989                      CNAT_MAIN_HASH_MASK);
990
991     index = cnat_out2in_hash[ko->bucket].next;
992     if (PREDICT_TRUE(index == EMPTY)) {
993         return (NULL);
994     }
995
996     do {
997         db = cnat_main_db + index;
998         if (PREDICT_TRUE(db->out2in_key.key64 == ko->k.key64)) {
999             return db;
1000         }
1001         index = db->out2in_hash.next;
1002     } while (index != EMPTY);
1003
1004     return (NULL);
1005 }
1006
1007 /* Creates 2 sessions.
1008  * Moves the default dest info from mdb to first session
1009  * Fills the dest_info details in to second session and
1010  * returns the pointer to second session
1011  */
1012 cnat_session_entry_t *cnat_handle_1to2_session(
1013     cnat_main_db_entry_t *mdb,
1014     cnat_key_t *dest_info)
1015 {
1016     cnat_key_t old_dest_info;
1017     pool_header_t        *h;
1018     u32 free_session = 0;
1019     u16 instance;
1020     cnat_session_entry_t *session_db1 = NULL, *session_db2 = NULL;
1021
1022     h = pool_header(cnat_session_db);
1023     free_session = vec_len(h->free_indices) - 1;
1024
1025     if (PREDICT_FALSE(free_session < 2)) {
1026        if (mdb->flags & CNAT_DB_DSLITE_FLAG) {
1027         instance = mdb->dslite_nat44_inst_id;
1028        } else {
1029         instance = NAT44_RESERVED_INST_ID;
1030        }
1031
1032         /* we need 2 sessions here, return NULL */
1033         nat44_dslite_common_stats[instance].drops_sessiondb_limit_exceeded++;
1034         return NULL;
1035     }
1036
1037     old_dest_info.k.ipv4 = mdb->dst_ipv4;
1038     old_dest_info.k.port = mdb->dst_port;
1039     old_dest_info.k.vrf = mdb->in2out_key.k.vrf;
1040
1041     /* create 2 new sessions */
1042     session_db1 = cnat_create_session_db_entry(&old_dest_info,
1043             mdb, FALSE);
1044
1045     if(PREDICT_FALSE(session_db1 == NULL)) {
1046         return NULL;
1047     }
1048
1049     /* update pkt info to session 2 */
1050     session_db2 = cnat_create_session_db_entry(dest_info,
1051             mdb, TRUE);
1052
1053     if(PREDICT_FALSE(session_db2 == NULL)) {
1054         cnat_delete_session_db_entry(session_db1, FALSE);
1055         return NULL;
1056     }
1057     /* update main db info to session 1 */
1058     cnat_dest_update_main2session(mdb, session_db1);
1059
1060     return session_db2;
1061 }
1062
1063 /* The below function shold be called only
1064  * when a NAT44 STATIC entry received traffic
1065  * for the first time. This is to ensure
1066  * the destination is noted and logged
1067  */
1068 void cnat_add_dest_n_log(
1069     cnat_main_db_entry_t *mdb,
1070     cnat_key_t *dest_info)
1071 {
1072
1073     if(PREDICT_FALSE(mdb->nsessions != 0)) {
1074         return; /* Should not have been called */
1075     }
1076
1077     mdb->dst_ipv4 = dest_info->k.ipv4;
1078     mdb->dst_port = dest_info->k.port;
1079     mdb->nsessions = 1;
1080     mdb->entry_expires = cnat_current_time;
1081     u16 instance;
1082
1083     if (mdb->flags & CNAT_DB_DSLITE_FLAG) {
1084         instance = mdb->dslite_nat44_inst_id;
1085         cnat_session_log_ds_lite_mapping_create(mdb,
1086              (dslite_table_db_ptr + instance),NULL);
1087     } else {
1088         instance = NAT44_RESERVED_INST_ID;
1089         cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + mdb->vrfmap_index;
1090         cnat_session_log_nat44_mapping_create(mdb, 0, my_vrfmap);
1091     }
1092 }
1093
1094 /*
1095  * this function is called by exception node
1096  * when lookup is fialed in i2o node
1097  *
1098  * if reash per user port limit, 
1099  * set user_db_entry pointer, and error == CNAT_OUT_LIMIT
1100  */
1101 cnat_main_db_entry_t*
1102 cnat_get_main_db_entry_v2(cnat_db_key_bucket_t *ki,
1103                           port_pair_t port_pair_type,
1104                           port_type_t port_type,
1105                           cnat_gen_icmp_info *info,
1106                           cnat_key_t *dest_info)
1107 {
1108     u16 protocol;
1109     cnat_errno_t rv;
1110     cnat_db_key_bucket_t u_ki, ko;
1111     u32                 my_index, free_main, free_user;
1112     u32                 current_timestamp;
1113     u16                 my_vrfmap_index;
1114     u16                 my_vrfmap_entry_found = 0;
1115     cnat_vrfmap_t       *my_vrfmap =0;
1116     cnat_portmap_v2_t   *pm =0;
1117     cnat_user_db_entry_t *udb = 0;
1118     cnat_main_db_entry_t *db = 0;
1119     pool_header_t        *h;
1120     u16                 port_limit;
1121     cnat_portmap_v2_t *my_pm = 0;
1122
1123 #ifndef NO_BULK_LOGGING
1124     int                 nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
1125 #endif
1126
1127
1128     /* 
1129      * need to try lookup again because 
1130      * second pkt may come here before the entry is created
1131      * by receiving first pkt due to high line rate.
1132      */
1133     info->gen_icmp_msg = CNAT_NO_ICMP_MSG;
1134     info->error = CNAT_SUCCESS;
1135     db = cnat_main_db_lookup_entry(ki);
1136     if (PREDICT_TRUE(db)) {
1137         /* what if the source is talking to a
1138          * new dest now? We will have to handle this case and
1139          * take care of - creating session db and logging
1140          */
1141         if(PREDICT_FALSE((!dest_info->k.ipv4) && (!dest_info->k.port))) {
1142             return db;  /* if dest_info is null don't create session */
1143         }
1144         if(PREDICT_TRUE((db->dst_ipv4 == dest_info->k.ipv4) &&
1145             (db->dst_port == dest_info->k.port))) {
1146             return db;
1147         }
1148         dest_info->k.vrf = db->in2out_key.k.vrf;
1149         /* Src is indeed talking to a different dest */
1150         cnat_session_entry_t *session_db2 = NULL;
1151         if(PREDICT_TRUE(db->nsessions == 1)) {
1152             session_db2 = cnat_handle_1to2_session(db, dest_info);
1153             if(PREDICT_TRUE(session_db2 != NULL)) {
1154                 CNAT_DB_TIMEOUT_RST(session_db2);
1155                 return db;
1156             } else {
1157                 info->error = CNAT_ERR_NO_SESSION_DB;
1158                 return NULL;
1159             }
1160         } else if(PREDICT_FALSE(db->nsessions == 0)) {
1161             /* Should be static entry.. should never happen
1162              */
1163             if(PREDICT_TRUE(dest_info->k.ipv4 != 0)) {
1164                 cnat_add_dest_n_log(db, dest_info);
1165             }
1166             return db;
1167         } else {
1168             /* The src has already created multiple sessions.. very rare
1169              */
1170             session_db2 = cnat_create_session_db_entry(dest_info,
1171                         db, TRUE);
1172             if(PREDICT_TRUE(session_db2 != NULL)) {
1173                 CNAT_DB_TIMEOUT_RST(session_db2);
1174                return db;
1175             } else {
1176                 info->error = CNAT_ERR_NO_SESSION_DB;
1177                 return NULL;
1178             }
1179         }
1180
1181     }
1182
1183     /* 
1184      * step 1. check if outside vrf is configured or not
1185      *         and Find the set of portmaps for the outside vrf
1186      * insider vrf is one to one mappted to outside vrf
1187      * key is vrf and ip only
1188      * ki.k.k.vrf has protocol bits, mask out 
1189      */
1190     protocol = ki->k.k.vrf & CNAT_PRO_MASK;
1191     u_ki.k.k.vrf = ki->k.k.vrf & CNAT_VRF_MASK;
1192     u_ki.k.k.ipv4 = ki->k.k.ipv4;
1193     u_ki.k.k.port = 0;
1194
1195     my_vrfmap_index = vrf_map_array[u_ki.k.k.vrf];
1196     my_vrfmap = cnat_map_by_vrf + my_vrfmap_index;
1197
1198     my_vrfmap_entry_found = ((my_vrfmap_index != VRF_MAP_ENTRY_EMPTY) &&
1199                              (my_vrfmap->status == S_RUN) &&
1200                              (my_vrfmap->i_vrf == u_ki.k.k.vrf));
1201
1202     if (PREDICT_FALSE(!my_vrfmap_entry_found)) {
1203         u32 arr[] = {ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port};
1204         if ((my_vrfmap_index == VRF_MAP_ENTRY_EMPTY) || 
1205             (my_vrfmap->i_vrf == u_ki.k.k.vrf)) {
1206             info->error = CNAT_NO_CONFIG;
1207             CNAT_DEBUG_INSIDE_ERR(CNAT_NO_CONFIG)
1208         spp_printf(CNAT_NO_CONFIG_ERROR, 3, arr);
1209         } else {
1210             info->error = CNAT_NO_VRF_RUN;
1211             CNAT_DEBUG_INSIDE_ERR(CNAT_NO_VRF_RUN)
1212         spp_printf(CNAT_NO_VRF_RUN_ERROR, 3, arr);
1213         }
1214
1215         return (NULL);
1216     }
1217
1218     pm = my_vrfmap->portmap_list;
1219
1220     port_limit = my_vrfmap->port_limit;
1221     if(PREDICT_FALSE(!port_limit)) {
1222       port_limit = cnat_main_db_max_ports_per_user;
1223     }
1224     /*
1225      * set o2i key with protocl bits
1226      */
1227     ko.k.k.vrf = my_vrfmap->o_vrf | protocol;
1228
1229     /*
1230      * step 2. check if src vrf, src ip addr is alreay 
1231      *         in the user db
1232      * if yes, use PORT_ALLOC_DIRECTED
1233      * if no, use PORT_ALLOC_ANY since it is first time
1234      */
1235     udb = cnat_user_db_lookup_entry(&u_ki);
1236     if (PREDICT_TRUE(udb)) {
1237         /*
1238          * not first time allocate port for this user
1239          * check limit
1240          */
1241           if (PREDICT_FALSE(udb->ntranslations >=
1242                 port_limit)) { 
1243             /* Check for the port type here. If we are getting
1244              * a STATIC PORT, allow the config.
1245              */
1246             if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) {
1247                info->error = CNAT_OUT_LIMIT;
1248                CNAT_SET_ICMP_MSG_INFO
1249                CNAT_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT)
1250                port_exceeded_msg_log(u_ki.k.k.ipv4, u_ki.k.k.vrf);
1251                in2out_drops_port_limit_exceeded ++;
1252                u_ki.k.k.port = ki->k.k.port;
1253                u_ki.k.k.vrf = ki->k.k.vrf;
1254                handle_cnat_port_exceeded_logging(udb, &u_ki.k, my_vrfmap);
1255                return (NULL);
1256             }
1257         }
1258         CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb,
1259                 port_limit)
1260
1261         /* 
1262          * check if main db has space to accomodate new entry
1263          */
1264         h = pool_header(cnat_main_db);
1265
1266         free_main = vec_len(h->free_indices) - 1;
1267         if (PREDICT_FALSE(!free_main)) {
1268             info->error = CNAT_MAIN_DB_LIMIT;
1269             CNAT_SET_ICMP_MSG_INFO
1270             in2out_drops_system_limit_reached ++;
1271             CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
1272
1273             current_timestamp = spp_trace_log_get_unix_time_in_seconds();
1274             if (PREDICT_FALSE((current_timestamp - last_log_timestamp) >
1275                     1800)) {
1276                 spp_printf(CNAT_SESSION_THRESH_EXCEEDED, 0, NULL);
1277                 last_log_timestamp = current_timestamp;
1278             }
1279
1280 #ifdef UT_TEST_CODE
1281             printf("Limit reached : OLD USER");
1282 #endif
1283             return NULL;
1284         }
1285
1286         /*
1287          * allocate port, from existing mapping 
1288          */
1289         my_index = udb->portmap_index;
1290
1291         if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
1292             rv = cnat_static_port_alloc_v2_bulk(pm,
1293                         PORT_ALLOC_DIRECTED,
1294                         port_pair_type,
1295                         ki->k.k.ipv4,
1296                         ki->k.k.port,
1297                         &my_index,
1298                         &(ko.k.k.ipv4),
1299                         &(ko.k.k.port),
1300                         cnat_static_port_range
1301 #ifndef NO_BULK_LOGGING
1302                         ,
1303                         udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1304                         &nfv9_log_req
1305 #endif
1306                         , my_vrfmap->ip_n_to_1
1307                         );
1308
1309         }  else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP) ) {
1310
1311             rv = cnat_dynamic_port_alloc_v2_bulk(pm,
1312                         PORT_ALLOC_DIRECTED,
1313                         port_pair_type,
1314                         &my_index,
1315                         &(ko.k.k.ipv4),
1316                         &(ko.k.k.port),
1317                         cnat_static_port_range
1318 #ifndef NO_BULK_LOGGING
1319                         ,
1320                         udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1321                         &nfv9_log_req
1322 #endif
1323                         , my_vrfmap->ip_n_to_1,
1324                         &(my_vrfmap->rseed_ip)
1325                         );
1326
1327         } else {
1328             /*
1329              * For RTSP, two translation entries are created, 
1330              * check if main db has space to accomodate two new entry
1331              */
1332             free_main =  free_main - 1;
1333             if (PREDICT_FALSE(!free_main)) {
1334                 info->error = CNAT_MAIN_DB_LIMIT;
1335                 CNAT_SET_ICMP_MSG_INFO
1336                 in2out_drops_system_limit_reached ++;
1337                 CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
1338
1339                 return NULL;
1340             } else {
1341                 rv = cnat_dynamic_port_alloc_rtsp_bulk(pm,
1342                             PORT_ALLOC_DIRECTED,
1343                             port_pair_type,
1344                             ki->k.k.port,
1345                             &my_index,
1346                             &(ko.k.k.ipv4),
1347                             &(ko.k.k.port),
1348                             cnat_static_port_range
1349 #ifndef NO_BULK_LOGGING
1350                             ,
1351                             udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1352                             &nfv9_log_req
1353 #endif
1354                             , &(my_vrfmap->rseed_ip)
1355                             );
1356             }
1357         }
1358
1359
1360         if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1361             info->error = rv;
1362             CNAT_SET_ICMP_MSG_INFO
1363             CNAT_DEBUG_INSIDE_ERR(rv)
1364             in2out_drops_resource_depletion++;
1365             log_port_alloc_error(rv, &(ki->k));
1366             return (NULL);
1367         }
1368         /*
1369          * increment port in use for this user
1370          */
1371         udb->ntranslations += 1;
1372         
1373     } else {
1374         /*
1375          * first time allocate port for this user
1376          */
1377      
1378         /*
1379          * Do not create entry if port limit is invalid
1380          */
1381         
1382         if (PREDICT_FALSE(!port_limit)) {
1383             if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) {
1384                 info->error = CNAT_OUT_LIMIT;
1385                 in2out_drops_port_limit_exceeded ++;
1386                 port_exceeded_msg_log(u_ki.k.k.ipv4, u_ki.k.k.vrf);
1387                 CNAT_SET_ICMP_MSG_INFO
1388                 CNAT_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT)
1389                 return (NULL);
1390             }
1391         }
1392
1393         /*
1394          * Check if main db has space for new entry
1395          * Allowing a user db entry to be created if main db is not free
1396          * will cause a port to be allocated to that user, which results in  
1397          * wastage of that port, hence the check is done here.
1398          */
1399         h = pool_header(cnat_main_db);
1400         free_main = vec_len(h->free_indices) - 1;
1401         h = pool_header(cnat_user_db);
1402             free_user = vec_len(h->free_indices) - 1;
1403
1404            /*
1405             * If either main_db or user_db does not have entries
1406             * bail out, with appropriate error
1407             */
1408         if (PREDICT_FALSE(!(free_main && free_user))) {
1409             u32 log_error;
1410             if(free_main) {
1411                 info->error = CNAT_USER_DB_LIMIT;
1412                 log_error = CNAT_USER_DB_LIMIT_ERROR;
1413             } else {
1414                    info->error = CNAT_MAIN_DB_LIMIT;
1415                    log_error = CNAT_MAIN_DB_LIMIT_ERROR;
1416             }
1417             in2out_drops_system_limit_reached ++;
1418             CNAT_SET_ICMP_MSG_INFO 
1419             CNAT_DEBUG_INSIDE_ERR(info->error)
1420             spp_printf(log_error, 0, 0);
1421             return NULL;
1422         }
1423
1424         if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
1425             rv = cnat_static_port_alloc_v2_bulk(pm,
1426                         PORT_ALLOC_ANY,
1427                         port_pair_type,
1428                         ki->k.k.ipv4,
1429                         ki->k.k.port,
1430                         &my_index,
1431                         &(ko.k.k.ipv4),
1432                         &(ko.k.k.port),
1433                         cnat_static_port_range
1434 #ifndef NO_BULK_LOGGING
1435                         ,
1436                         udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1437                         &nfv9_log_req
1438 #endif
1439                         , my_vrfmap->ip_n_to_1
1440                         );
1441
1442         }  else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP)) {
1443             rv = cnat_dynamic_port_alloc_v2_bulk(pm,
1444                         PORT_ALLOC_ANY,
1445                         port_pair_type,
1446                         &my_index,
1447                         &(ko.k.k.ipv4),
1448                         &(ko.k.k.port),
1449                         cnat_static_port_range
1450 #ifndef NO_BULK_LOGGING
1451                         , NULL, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1452                         &nfv9_log_req
1453 #endif
1454                         , my_vrfmap->ip_n_to_1,
1455                         &(my_vrfmap->rseed_ip)
1456                         );
1457         } else {
1458             /*
1459              * For RTSP, two translation entries are created,
1460              * check if main db has space to accomodate two new entry
1461              */
1462             free_main =  free_main - 1;
1463             if (PREDICT_FALSE(!free_main)) {
1464                 info->error = CNAT_MAIN_DB_LIMIT;
1465                 CNAT_SET_ICMP_MSG_INFO
1466                 in2out_drops_system_limit_reached ++;
1467                 CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
1468
1469                 return NULL;
1470             } else {
1471
1472                 rv = cnat_dynamic_port_alloc_rtsp_bulk(pm,
1473                             PORT_ALLOC_ANY,
1474                             port_pair_type,
1475                             ki->k.k.port,
1476                             &my_index,
1477                             &(ko.k.k.ipv4),
1478                             &(ko.k.k.port),
1479                             cnat_static_port_range
1480 #ifndef NO_BULK_LOGGING
1481                             , NULL, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1482                             &nfv9_log_req
1483 #endif
1484                             , &(my_vrfmap->rseed_ip)
1485                     );
1486                 /* TODO: Add the port pair flag here */
1487             }
1488         }
1489
1490
1491
1492         if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1493             info->error = rv;
1494             in2out_drops_resource_depletion ++;
1495             CNAT_SET_ICMP_MSG_INFO
1496             CNAT_DEBUG_INSIDE_ERR(rv) 
1497             log_port_alloc_error(rv, &(ki->k));
1498             return (NULL);
1499         }
1500         /* 
1501          * create entry in user db
1502          */
1503         udb = cnat_user_db_create_entry(&u_ki, my_index);
1504         NAT44_COMMON_STATS.num_subscribers++;
1505         my_pm = pm + my_index;
1506         if(PREDICT_TRUE(my_pm->private_ip_users_count < PORTS_PER_ADDR)) {
1507             my_pm->private_ip_users_count++;
1508 #ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED
1509             PLATFORM_DEBUG_PRINT("\n cnat_get_main_db_entry_v2 "
1510                                  "dynamic alloc private_ip_users_count = %d",
1511                                  my_pm->private_ip_users_count);
1512 #endif
1513         } else {
1514             PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has "
1515                                  "reached MAX PORTS_PER_ADDR");
1516         }
1517 #ifndef NO_BULK_LOGGING
1518         if(PREDICT_TRUE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) {
1519             cnat_update_bulk_range_cache(udb, ko.k.k.port,
1520                 BULKSIZE_FROM_VRFMAP(my_vrfmap));
1521         }
1522 #endif /*  #ifndef NO_BULK_LOGGING */
1523
1524     }
1525
1526     /*
1527      * step 3:
1528      * outside port is allocated for this src vrf/src ip addr
1529      * 1)create a new entry in main db
1530      * 2)setup cnat_out2in_hash key
1531      * 3)setup cnat_in2out_hash key
1532      */
1533     db = cnat_create_main_db_entry_and_hash(ki, &ko, udb);
1534
1535     translation_create_count ++;
1536 #ifdef DSLITE_DEF 
1537     db->dslite_nat44_inst_id = NAT44_RESERVED_INST_ID;
1538 #endif
1539     db->vrfmap_index = my_vrfmap - cnat_map_by_vrf;
1540
1541     /*
1542      * don't forget logging
1543      * logging API is unconditional, 
1544      * logging configuration check is done inside the inline function
1545      */
1546
1547     db->dst_ipv4 = dest_info->k.ipv4;
1548     db->dst_port = dest_info->k.port;
1549     if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) {
1550         db->nsessions++;
1551     }
1552
1553     if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
1554         if(PREDICT_FALSE(my_vrfmap->nf_logging_policy == SESSION_LOG_ENABLE)) {
1555                 /* do not log for static entries.. we will log when traffic flows */
1556                 if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) {
1557                         cnat_nfv9_nat44_log_session_create(db, 0, my_vrfmap);
1558                 }
1559         } else {
1560                 cnat_nfv9_log_mapping_create(db, my_vrfmap
1561 #ifndef NO_BULK_LOGGING
1562                 , nfv9_log_req
1563 #endif
1564                 );
1565         }
1566         if(PREDICT_TRUE((my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE) ||
1567                         (db->dst_ipv4 || db->dst_port))) {
1568             cnat_syslog_nat44_mapping_create(db, my_vrfmap, 0
1569 #ifndef NO_BULK_LOGGING
1570             , nfv9_log_req
1571 #endif
1572             );
1573         }
1574     }
1575     if (PREDICT_FALSE(port_pair_type == PORT_PAIR)) {
1576        cnat_main_db_entry_t *db2 = 0;
1577        cnat_db_key_bucket_t new_ki = *ki;
1578        u64 a, b, c;
1579
1580        new_ki.k.k.port += 1;
1581        ko.k.k.port += 1;
1582
1583        CNAT_V4_GET_HASH(new_ki.k.key64, new_ki.bucket, 
1584                         CNAT_MAIN_HASH_MASK);
1585
1586        db2 = cnat_create_main_db_entry_and_hash(&new_ki, &ko, udb);
1587
1588        translation_create_count ++;
1589 #ifdef DSLITE_DEF 
1590        db2->dslite_nat44_inst_id = NAT44_RESERVED_INST_ID;
1591 #endif
1592        db2->vrfmap_index = my_vrfmap - cnat_map_by_vrf;
1593        db2->entry_expires = cnat_current_time;
1594        db2->flags |= CNAT_DB_FLAG_ALG_ENTRY;
1595        udb->ntranslations += 1;
1596        db2->dst_ipv4 = dest_info->k.ipv4;
1597        db2->dst_port = dest_info->k.port;
1598        db2->nsessions = 0; /* For ALG db, set sessions to 0 - CSCuf78420 */
1599
1600        if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
1601            if(PREDICT_FALSE(my_vrfmap->nf_logging_policy == SESSION_LOG_ENABLE)) {
1602                /* do not log for static entries.. we will log when traffic flows */
1603                if(PREDICT_TRUE(db2->dst_ipv4 || db2->dst_port)) {
1604                    cnat_nfv9_nat44_log_session_create(db2, 0, my_vrfmap);
1605                }
1606            } else {
1607                cnat_nfv9_log_mapping_create(db2, my_vrfmap
1608 #ifndef NO_BULK_LOGGING
1609                , nfv9_log_req
1610 #endif
1611                );
1612            }
1613            if(PREDICT_TRUE((my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE) ||
1614                            (db2->dst_ipv4 || db2->dst_port))) {
1615                cnat_syslog_nat44_mapping_create(db2, my_vrfmap, 0
1616 #ifndef NO_BULK_LOGGING
1617                , nfv9_log_req
1618 #endif
1619                );
1620            }
1621        }
1622     }
1623
1624     return db;
1625 }
1626
1627 /*
1628  * this function is called from config handler only
1629  * to allocate a static port based db entry
1630  *
1631  * the actual mapped address and port are already specified
1632  */
1633 cnat_main_db_entry_t*
1634 cnat_create_static_main_db_entry_v2 (cnat_db_key_bucket_t *ki,
1635                                      cnat_db_key_bucket_t *ko,
1636                                      cnat_vrfmap_t        *my_vrfmap,
1637                                      cnat_gen_icmp_info   *info)
1638 {
1639     u16 protocol;
1640     u32 head;
1641     cnat_errno_t rv;
1642     cnat_db_key_bucket_t u_ki;
1643     u32                 my_index, free_main, free_user;
1644     cnat_portmap_v2_t   *pm =0;
1645     cnat_portmap_v2_t   *my_pm =0;
1646     cnat_user_db_entry_t *udb = 0;
1647     cnat_main_db_entry_t *db = 0;
1648     pool_header_t        *h;
1649 #ifndef NO_BULK_LOGGING
1650     int                 nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
1651 #endif
1652
1653     /* 
1654      * need to try lookup again because 
1655      * second pkt may come here before the entry is created
1656      * by receiving first pkt due to high line rate.
1657      */
1658     info->gen_icmp_msg = CNAT_NO_ICMP_MSG;
1659     info->error = CNAT_SUCCESS;
1660     db = cnat_main_db_lookup_entry(ki);
1661
1662     /*
1663      * If we already have an entry with this inside address, port
1664      * check delete the entry and proceed further.  This should
1665      * If yes, something is terribly wrong.  Bail out
1666      */
1667     if (PREDICT_FALSE(db)) {
1668
1669         if (db->flags & CNAT_DB_FLAG_STATIC_PORT) {
1670
1671             if ((db->out2in_key.k.ipv4 == ko->k.k.ipv4) &&
1672                 (db->out2in_key.k.port == ko->k.k.port) &&
1673                 (db->out2in_key.k.vrf  == ko->k.k.vrf)) {
1674
1675 #ifdef DEBUG_PRINTF_ENABLED
1676                 printf("Same Static Port Exists ki 0x%16llx ko 0x%16llx",
1677                        ki->k, ko->k);
1678 #endif
1679                 /*
1680                  * We have already programmed this, return
1681                  */
1682                 return (db);
1683             }
1684
1685             /*
1686              * We already have a static port with different mapping
1687              * Return an error for this case.
1688              */
1689             info->error = CNAT_ERR_PARSER;
1690
1691 #ifdef DEBUG_PRINTF_ENABLED
1692             printf("Static Port Existing and Diff ki 0x%16llx ko 0x%16llx",
1693                        ki, db->out2in_key);
1694 #endif
1695         {
1696             u32 arr[] = {STAT_PORT_CONFIG_IN_USE, (ki->k.k.vrf & CNAT_VRF_MASK),
1697                 ki->k.k.ipv4, ki->k.k.port, (ki->k.k.vrf & CNAT_PRO_MASK) };
1698             spp_printf(CNAT_CONFIG_ERROR, 5, arr);
1699         }
1700             return (db);
1701         }
1702
1703 #ifdef DEBUG_PRINTF_ENABLED
1704         printf("Deleting Dynamic entry  ki 0x%16llx ko 0x%16llx",
1705                        ki, db->out2in_key);
1706 #endif
1707
1708         /*
1709          * If for some reason we have dynamic entries, just delete them
1710          * and proceed.
1711          */
1712         cnat_delete_main_db_entry_v2(db);
1713         
1714         db = NULL;
1715     }
1716
1717     protocol = ki->k.k.vrf & CNAT_PRO_MASK;
1718     u_ki.k.k.vrf = ki->k.k.vrf & CNAT_VRF_MASK;
1719     u_ki.k.k.ipv4 = ki->k.k.ipv4;
1720     u_ki.k.k.port = 0;
1721
1722     pm = my_vrfmap->portmap_list;
1723
1724     /*
1725      * check if src vrf, src ip addr is already 
1726      *         in the user db
1727      * if yes, use PORT_ALLOC_DIRECTED
1728      * if no, use PORT_ALLOC_ANY since it is first time
1729      */
1730     udb = cnat_user_db_lookup_entry(&u_ki);
1731     if (PREDICT_TRUE(udb)) {
1732         /* 
1733          * check if main db has space to accomodate new entry
1734          */
1735         h = pool_header(cnat_main_db);
1736
1737         free_main = vec_len(h->free_indices) - 1;
1738         if (PREDICT_FALSE(!free_main)) {
1739             info->error = CNAT_MAIN_DB_LIMIT;
1740             CNAT_SET_ICMP_MSG_INFO
1741             in2out_drops_system_limit_reached ++;
1742             CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
1743 #ifdef UT_TEST_CODE
1744             printf("Limit reached : OLD USER");
1745 #endif
1746             spp_printf(CNAT_MAIN_DB_LIMIT_ERROR, 0, 0);
1747             return NULL;
1748         }
1749
1750         /*
1751          * allocate port, from existing mapping 
1752          */
1753         my_index = udb->portmap_index;
1754         my_pm = pm + my_index;
1755        /* It is quite possible that we hit the scenario of CSCtj17774.
1756         * Delete all the main db entries and add the ipv4 address sent by
1757         * CGN-MA as Static port alloc any
1758         */
1759
1760         if (PREDICT_FALSE(my_pm->ipv4_address != ko->k.k.ipv4)) {
1761             if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) {
1762                 printf("Delete Main db entry and check for"
1763                         " ipv4 address sanity pm add = 0x%x ip add = 0x%x\n",
1764                         my_pm->ipv4_address,  ko->k.k.ipv4);
1765             }
1766             do {
1767                  /* udb is not NULL when we begin with for sure */
1768                  head = udb->translation_list_head_index;
1769                  db = cnat_main_db + head;
1770                  cnat_delete_main_db_entry_v2(db);
1771             } while (!pool_is_free(cnat_user_db, udb));
1772
1773             rv = cnat_mapped_static_port_alloc_v2_bulk (pm,
1774                  PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port,
1775                  udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), &nfv9_log_req, 
1776                                                         my_vrfmap->ip_n_to_1);
1777
1778             if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1779              info->error = rv;
1780              in2out_drops_resource_depletion ++;
1781              CNAT_SET_ICMP_MSG_INFO
1782              CNAT_DEBUG_INSIDE_ERR(rv)
1783              return (NULL);
1784             }
1785          /*
1786          * create entry in user db
1787          */
1788         udb = cnat_user_db_create_entry(&u_ki, my_index);
1789         my_pm = pm + my_index;
1790         if(PREDICT_TRUE(my_pm->private_ip_users_count < PORTS_PER_ADDR)) {
1791             my_pm->private_ip_users_count++;
1792 #ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED
1793             PLATFORM_DEBUG_PRINT("\n cnat_create_static_main_db_entry_v2 "
1794                                  "static del n alloc private_ip_users_count = "
1795                                  "%d",my_pm->private_ip_users_count);
1796 #endif
1797         } else {
1798             PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has "
1799                                  "reached MAX PORTS_PER_ADDR");
1800         }
1801         NAT44_COMMON_STATS.num_subscribers++;
1802 #ifndef NO_BULK_LOGGING
1803         cnat_update_bulk_range_cache(udb, ko->k.k.port,
1804             BULKSIZE_FROM_VRFMAP(my_vrfmap));
1805 #endif /*  #ifndef NO_BULK_LOGGING */
1806       } else {
1807
1808         rv = cnat_mapped_static_port_alloc_v2_bulk (pm,
1809             PORT_ALLOC_DIRECTED, &my_index, ko->k.k.ipv4, ko->k.k.port,
1810             udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), &nfv9_log_req, 
1811                                                     my_vrfmap->ip_n_to_1);
1812
1813         if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1814             info->error = rv;
1815             CNAT_SET_ICMP_MSG_INFO
1816             CNAT_DEBUG_INSIDE_ERR(rv)
1817             log_port_alloc_error(rv, &(ki->k));
1818             return (NULL);
1819         }
1820
1821         /*
1822          * increment port in use for this user
1823          */
1824         udb->ntranslations += 1;
1825       }
1826     } else {
1827         if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) {
1828             printf ("Static port alloc any\n");
1829         }
1830         /*
1831          * first time allocate port for this user
1832          */
1833      
1834         /*
1835          * Check if main db has space for new entry
1836          * Allowing a user db entry to be created if main db is not free
1837          * will cause a port to be allocated to that user, which results in  
1838          * wastage of that port, hence the check is done here.
1839          */
1840         h = pool_header(cnat_main_db);
1841         free_main = vec_len(h->free_indices) - 1;
1842         h = pool_header(cnat_user_db);
1843             free_user = vec_len(h->free_indices) - 1;
1844
1845         /*
1846          * If either main_db or user_db does not have entries
1847          * bail out, with appropriate error
1848          */
1849         if (PREDICT_FALSE(!(free_main && free_user))) {
1850             u32 log_error;
1851             if(free_main) {
1852                 info->error = CNAT_USER_DB_LIMIT;
1853                 log_error = CNAT_USER_DB_LIMIT_ERROR;
1854             } else {
1855                 info->error = CNAT_MAIN_DB_LIMIT;
1856                 log_error = CNAT_MAIN_DB_LIMIT_ERROR;
1857             }
1858             in2out_drops_system_limit_reached ++;
1859             CNAT_SET_ICMP_MSG_INFO 
1860             CNAT_DEBUG_INSIDE_ERR(info->error)
1861             spp_printf(log_error, 0, 0);
1862             return NULL;
1863         }
1864
1865         rv = cnat_mapped_static_port_alloc_v2_bulk (pm,
1866             PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port,
1867             udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), &nfv9_log_req, 
1868                                                     my_vrfmap->ip_n_to_1);
1869
1870         if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1871             info->error = rv;
1872             in2out_drops_resource_depletion ++;
1873             CNAT_SET_ICMP_MSG_INFO
1874             CNAT_DEBUG_INSIDE_ERR(rv) 
1875             log_port_alloc_error(rv, &(ki->k));
1876             return (NULL);
1877         }
1878         /* 
1879          * create entry in user db
1880          */
1881         udb = cnat_user_db_create_entry(&u_ki, my_index);
1882         my_pm = pm + my_index;
1883         if(PREDICT_TRUE(my_pm->private_ip_users_count < PORTS_PER_ADDR)) {
1884             my_pm->private_ip_users_count++;
1885 #ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED
1886             PLATFORM_DEBUG_PRINT("\n cnat_create_static_main_db_entry_v2 "
1887                                  "static alloc private_ip_users_count = %d",
1888                                  my_pm->private_ip_users_count);
1889 #endif
1890         } else {
1891             PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has "
1892                                  "reached MAX PORTS_PER_ADDR");
1893         }
1894         NAT44_COMMON_STATS.num_subscribers++;
1895 #ifndef NO_BULK_LOGGING
1896         cnat_update_bulk_range_cache(udb, ko->k.k.port,
1897             BULKSIZE_FROM_VRFMAP(my_vrfmap));
1898 #endif /*  #ifndef NO_BULK_LOGGING */
1899     }
1900
1901     /*
1902      * step 3:
1903      * outside port is allocated for this src vrf/src ip addr
1904      * 1)create a new entry in main db
1905      * 2)setup cnat_out2in_hash key
1906      * 3)setup cnat_in2out_hash key
1907      */
1908     db = cnat_create_main_db_entry_and_hash(ki, ko, udb);
1909
1910     translation_create_count ++;
1911     db->vrfmap_index = my_vrfmap - cnat_map_by_vrf;
1912
1913     /*
1914      * don't forget logging
1915      * logging API is unconditional, 
1916      * logging configuration check is done inside the inline function
1917      */
1918
1919         if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
1920         /* if session logging is enabled .. do not log  as there is no
1921          * traffic yet
1922          */
1923             if(PREDICT_FALSE(my_vrfmap->nf_logging_policy != SESSION_LOG_ENABLE)) {
1924                 cnat_nfv9_log_mapping_create(db, my_vrfmap
1925 #ifndef NO_BULK_LOGGING
1926                 , nfv9_log_req
1927 #endif
1928                 );
1929             }
1930             if(PREDICT_FALSE(my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE)) {
1931                 cnat_syslog_nat44_mapping_create(db, my_vrfmap, 0
1932 #ifndef NO_BULK_LOGGING
1933                 , nfv9_log_req
1934 #endif
1935                 );
1936             }
1937         }
1938
1939     return db;
1940 }
1941
1942
1943 cnat_main_db_entry_t*
1944 dslite_main_db_lookup_entry(dslite_db_key_bucket_t *ki);
1945
1946 cnat_user_db_entry_t*
1947 dslite_user_db_lookup_entry(dslite_db_key_bucket_t *uki);
1948
1949 cnat_user_db_entry_t*
1950 dslite_user_db_create_entry(dslite_db_key_bucket_t *uki, u32 portmap_index);
1951
1952 cnat_main_db_entry_t*
1953 dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki,
1954                                    cnat_db_key_bucket_t *ko,
1955                                    cnat_user_db_entry_t *udb);
1956
1957 #ifdef TOBE_PORTED
1958 /*
1959  * this function is called from config handler only
1960  * to allocate a static port based db entry
1961  *
1962  * the actual mapped address and port are already specified
1963  */
1964 cnat_main_db_entry_t*
1965 dslite_create_static_main_db_entry_v2 (dslite_db_key_bucket_t *ki,
1966                                      cnat_db_key_bucket_t *ko,
1967                                      dslite_table_entry_t *dslite_entry_ptr,
1968                                      cnat_gen_icmp_info   *info)
1969 {
1970     u16 protocol;
1971     u32 head;
1972     cnat_errno_t rv;
1973     dslite_db_key_bucket_t u_ki;
1974     u32                 my_index, free_main, free_user;
1975     cnat_portmap_v2_t   *pm =0;
1976     cnat_portmap_v2_t   *my_pm =0;
1977     cnat_user_db_entry_t *udb = 0;
1978     cnat_main_db_entry_t *db = 0;
1979     pool_header_t        *h;
1980     u16 dslite_id = dslite_entry_ptr->dslite_id;
1981 #ifndef NO_BULK_LOGGING
1982     int                 nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
1983 #endif
1984     cnat_vrfmap_t       *my_vrfmap =0;
1985     u16                 my_vrfmap_index;    
1986
1987     /* 
1988      * need to try lookup again because 
1989      * second pkt may come here before the entry is created
1990      * by receiving first pkt due to high line rate.
1991      */
1992     info->gen_icmp_msg = CNAT_NO_ICMP_MSG;
1993     info->error = CNAT_SUCCESS;
1994     db = dslite_main_db_lookup_entry(ki);
1995
1996     /*
1997      * If we already have an entry with this inside address, port
1998      * check delete the entry and proceed further.  This should
1999      * If yes, something is terribly wrong.  Bail out
2000      */
2001     if (PREDICT_FALSE(db)) {
2002
2003         if (db->flags & CNAT_DB_FLAG_STATIC_PORT) {
2004
2005             if ((db->out2in_key.k.ipv4 == ko->k.k.ipv4) &&
2006                 (db->out2in_key.k.port == ko->k.k.port) &&
2007                 (db->out2in_key.k.vrf  == ko->k.k.vrf)) {
2008
2009 #ifdef DEBUG_PRINTF_ENABLED
2010                 printf("Same Static Port Exists ki 0x%16llx ko 0x%16llx",
2011                        ki->k, ko->k);
2012 #endif
2013                 /*
2014                  * We have already programmed this, return
2015                  */
2016                 return (db);
2017             }
2018
2019             /*
2020              * We already have a static port with different mapping
2021              * Return an error for this case.
2022              */
2023             info->error = CNAT_ERR_PARSER;
2024
2025 #ifdef DEBUG_PRINTF_ENABLED
2026             printf("Static Port Existing and Diff ki 0x%16llx ko 0x%16llx",
2027                        ki, db->out2in_key);
2028 #endif
2029         {
2030             u32 arr[] = {STAT_PORT_CONFIG_IN_USE, (ki->dk.ipv4_key.k.vrf & CNAT_VRF_MASK),
2031                 ki->dk.ipv4_key.k.ipv4, ki->dk.ipv4_key.k.port, (ki->dk.ipv4_key.k.vrf & CNAT_PRO_MASK) };
2032             spp_printf(CNAT_CONFIG_ERROR, 5, arr);
2033         }
2034             return (db);
2035         }
2036
2037 #ifdef DEBUG_PRINTF_ENABLED
2038         printf("Deleting Dynamic entry  ki 0x%16llx ko 0x%16llx",
2039                        ki, db->out2in_key);
2040 #endif
2041
2042         /*
2043          * If for some reason we have dynamic entries, just delete them
2044          * and proceed.
2045          */
2046         cnat_delete_main_db_entry_v2(db);
2047         
2048         db = NULL;
2049     }
2050     
2051
2052     protocol = ki->dk.ipv4_key.k.vrf & CNAT_PRO_MASK;
2053     u_ki.dk.ipv4_key.k.vrf = ki->dk.ipv4_key.k.vrf & CNAT_VRF_MASK;
2054     u_ki.dk.ipv4_key.k.ipv4 = ki->dk.ipv4_key.k.ipv4;
2055     u_ki.dk.ipv4_key.k.port = 0;
2056     u_ki.dk.ipv6[0] =       ki->dk.ipv6[0];
2057     u_ki.dk.ipv6[1] =       ki->dk.ipv6[1];
2058     u_ki.dk.ipv6[2] =       ki->dk.ipv6[2];
2059     u_ki.dk.ipv6[3] =       ki->dk.ipv6[3];
2060
2061     my_vrfmap_index = vrf_map_array[u_ki.dk.ipv4_key.k.vrf];
2062     my_vrfmap = cnat_map_by_vrf + my_vrfmap_index;
2063
2064     pm = dslite_entry_ptr->portmap_list;
2065
2066     /*
2067      * check if src vrf, src ip addr is already 
2068      *         in the user db
2069      * if yes, use PORT_ALLOC_DIRECTED
2070      * if no, use PORT_ALLOC_ANY since it is first time
2071      */
2072     udb = dslite_user_db_lookup_entry(&u_ki);
2073     if (PREDICT_TRUE(udb)) {
2074         /* 
2075          * check if main db has space to accomodate new entry
2076          */
2077         h = pool_header(cnat_main_db);
2078
2079         free_main = vec_len(h->free_indices) - 1;
2080         if (PREDICT_FALSE(!free_main)) {
2081             info->error = CNAT_MAIN_DB_LIMIT;
2082             nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
2083             DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
2084 #ifdef UT_TEST_CODE
2085             printf("Limit reached : OLD USER");
2086 #endif
2087             spp_printf(CNAT_MAIN_DB_LIMIT_ERROR, 0, 0);
2088             return NULL;
2089         }
2090
2091         /*
2092          * allocate port, from existing mapping 
2093          */
2094         my_index = udb->portmap_index;
2095         my_pm = pm + my_index;
2096        /* It is quite possible that we hit the scenario of CSCtj17774.
2097         * Delete all the main db entries and add the ipv4 address sent by
2098         * CGN-MA as Static port alloc any
2099         */
2100
2101         if (PREDICT_FALSE(my_pm->ipv4_address != ko->k.k.ipv4)) {
2102             if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) {
2103                 printf("Delete Main db entry and check for"
2104                         " ipv4 address sanity pm add = 0x%x ip add = 0x%x\n",
2105                         my_pm->ipv4_address,  ko->k.k.ipv4);
2106             }
2107             do {
2108                  /* udb is not NULL when we begin with for sure */
2109                  head = udb->translation_list_head_index;
2110                  db = cnat_main_db + head;
2111                  cnat_delete_main_db_entry_v2(db);
2112             } while (!pool_is_free(cnat_user_db, udb));
2113
2114             rv = cnat_mapped_static_port_alloc_v2_bulk (pm,
2115                  PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port,
2116                  udb, BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), &nfv9_log_req, 
2117                                                         my_vrfmap->ip_n_to_1);
2118
2119             if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
2120              info->error = rv;
2121              nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
2122              DSLITE_DEBUG_INSIDE_ERR(rv)
2123              return (NULL);
2124             }
2125         /*
2126          * create entry in user db
2127          */
2128         udb = dslite_user_db_create_entry(&u_ki, my_index);
2129         nat44_dslite_common_stats[dslite_id].num_subscribers++;
2130 #ifndef NO_BULK_LOGGING
2131         if(PREDICT_FALSE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) {
2132             cnat_update_bulk_range_cache(udb, ko->k.k.port,
2133             BULKSIZE_FROM_VRFMAP(dslite_entry_ptr));
2134         }
2135 #endif /*  #ifndef NO_BULK_LOGGING */
2136       } else {
2137
2138         rv = cnat_mapped_static_port_alloc_v2_bulk (pm,
2139             PORT_ALLOC_DIRECTED, &my_index, ko->k.k.ipv4, ko->k.k.port,
2140             udb, BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), &nfv9_log_req, 
2141             my_vrfmap->ip_n_to_1);
2142
2143         if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
2144             info->error = rv;
2145             DSLITE_DEBUG_INSIDE_ERR(rv)
2146             log_port_alloc_error(rv, &(ki->dk.ipv4_key));
2147             return (NULL);
2148         }
2149
2150         /*
2151          * increment port in use for this user
2152          */
2153         udb->ntranslations += 1;
2154       }
2155     } else {
2156         if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) {
2157             printf ("Static port alloc any\n");
2158         }
2159         /*
2160          * first time allocate port for this user
2161          */
2162      
2163         /*
2164          * Check if main db has space for new entry
2165          * Allowing a user db entry to be created if main db is not free
2166          * will cause a port to be allocated to that user, which results in  
2167          * wastage of that port, hence the check is done here.
2168          */
2169         h = pool_header(cnat_main_db);
2170         free_main = vec_len(h->free_indices) - 1;
2171         h = pool_header(cnat_user_db);
2172             free_user = vec_len(h->free_indices) - 1;
2173
2174         /*
2175          * If either main_db or user_db does not have entries
2176          * bail out, with appropriate error
2177          */
2178         if (PREDICT_FALSE(!(free_main && free_user))) {
2179             u32 log_error;
2180             if(free_main) {
2181                 info->error = CNAT_USER_DB_LIMIT;
2182                 log_error = CNAT_USER_DB_LIMIT_ERROR;
2183             } else {
2184                 info->error = CNAT_MAIN_DB_LIMIT;
2185                 log_error = CNAT_MAIN_DB_LIMIT_ERROR;
2186             }
2187             nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
2188             DSLITE_DEBUG_INSIDE_ERR(info->error)
2189             spp_printf(log_error, 0, 0);
2190             return NULL;
2191         }
2192
2193         rv = cnat_mapped_static_port_alloc_v2_bulk (pm,
2194             PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port,
2195             udb, BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), &nfv9_log_req,
2196             my_vrfmap->ip_n_to_1);
2197
2198         if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
2199             info->error = rv;
2200             nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
2201             DSLITE_DEBUG_INSIDE_ERR(rv) 
2202             log_port_alloc_error(rv, &(ki->dk.ipv4_key));
2203             return (NULL);
2204         }
2205         /* 
2206          * create entry in user db
2207          */
2208         udb = dslite_user_db_create_entry(&u_ki, my_index);
2209         nat44_dslite_common_stats[dslite_id].num_subscribers++;
2210 #ifndef NO_BULK_LOGGING
2211         if(PREDICT_FALSE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) {
2212             cnat_update_bulk_range_cache(udb, ko->k.k.port,
2213             BULKSIZE_FROM_VRFMAP(dslite_entry_ptr));
2214         }
2215 #endif /*  #ifndef NO_BULK_LOGGING */
2216     }
2217
2218     /*
2219      * step 3:
2220      * outside port is allocated for this src vrf/src ip addr
2221      * 1)create a new entry in main db
2222      * 2)setup cnat_out2in_hash key
2223      * 3)setup cnat_in2out_hash key
2224      */
2225     db = dslite_create_main_db_entry_and_hash(ki, ko, udb);
2226     db->dslite_nat44_inst_id = dslite_id;
2227     nat44_dslite_common_stats[dslite_id].active_translations++;
2228     dslite_translation_create_count++;
2229
2230     /*
2231      * don't forget logging
2232      * logging API is unconditional, 
2233      * logging configuration check is done inside the inline function
2234      */
2235 #if 0 /* TBD - NEED TO DECIDE ON LOGGING */
2236         if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
2237         /* if session logging is enabled .. do not log  as there is no
2238          * traffic yet
2239          */
2240 #endif /* #if 0 - this has to be removed later */
2241
2242     return db;
2243 }
2244 #endif /* TOBE_PORTED */
2245
2246
2247 /* Per port/ip timeout related routines */
2248 static
2249 u32 cnat_timeout_db_hash_lookup (cnat_key_t t_key)
2250 {
2251     cnat_key_t key;
2252     u64 a, b, c;
2253     u32 index;
2254     cnat_timeout_db_entry_t *db;
2255
2256     key.k.ipv4 = t_key.k.ipv4;
2257     key.k.port = t_key.k.port;
2258     key.k.vrf = t_key.k.vrf;
2259
2260     CNAT_V4_GET_HASH(key.key64,
2261                      index, CNAT_TIMEOUT_HASH_MASK)
2262
2263
2264     index = cnat_timeout_hash[index].next;
2265
2266     if (PREDICT_FALSE(index == EMPTY))
2267         return EMPTY;
2268
2269     do {
2270         db = cnat_timeout_db + index;
2271         if (PREDICT_TRUE((db->t_key.timeout_key.key64 & CNAT_TIMEOUT_FULL_MASK)
2272                == (key.key64 & CNAT_TIMEOUT_FULL_MASK)))
2273             break;
2274         index = db->t_hash.next;
2275     } while (index != EMPTY);
2276
2277     return index;
2278 }
2279
2280 /* Pass db_type as MAIN_DB_TYPE if you are passing
2281  * cnat_main_db_entry_t * casted as void * for db
2282  * else pass db_type as SESSION_DB_TYPE
2283  */
2284 u16
2285 query_and_update_db_timeout(void *db, u8 db_type)
2286 {
2287     cnat_key_t t_search_key;
2288     u32 index;
2289     cnat_timeout_db_entry_t *timeout_db_entry;
2290     pool_header_t     *h;
2291     u32  free;
2292
2293     cnat_main_db_entry_t *mdb = NULL;
2294     cnat_session_entry_t *sdb = NULL;
2295
2296     if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) {
2297         mdb = (cnat_main_db_entry_t *)db;
2298     } else if(db_type == SESSION_DB_TYPE) {
2299         sdb = (cnat_session_entry_t *)db;
2300     } else {
2301         return 0;
2302     }
2303
2304     h = pool_header(cnat_timeout_db);
2305     free = vec_len(h->free_indices) - 1;
2306
2307     if(free == CNAT_TIMEOUT_HASH_SIZE) {
2308         /* No timeout db configured */
2309         return 0; 
2310     }
2311
2312     /* First search for ip/port pair */
2313     if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) {
2314         t_search_key.k.ipv4 = mdb->dst_ipv4;
2315         t_search_key.k.port = mdb->dst_port;
2316         t_search_key.k.vrf = mdb->in2out_key.k.vrf;
2317     } else {
2318         t_search_key.k.ipv4 = sdb->v4_dest_key.k.ipv4;
2319         t_search_key.k.port = sdb->v4_dest_key.k.port;
2320         t_search_key.k.vrf = sdb->v4_dest_key.k.vrf;
2321     }
2322
2323     index = cnat_timeout_db_hash_lookup(t_search_key);
2324
2325     if(index == EMPTY) {
2326         /* Search for port map */
2327         t_search_key.k.ipv4 = 0;
2328
2329         index = cnat_timeout_db_hash_lookup(t_search_key);
2330
2331         if(index == EMPTY) {
2332             /* Search for ip only map */
2333             if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) {
2334                 t_search_key.k.ipv4 = mdb->dst_ipv4;
2335             } else {
2336                 t_search_key.k.ipv4 = sdb->v4_dest_key.k.ipv4;
2337             }
2338             t_search_key.k.port = 0; 
2339
2340             index = cnat_timeout_db_hash_lookup(t_search_key);
2341             if(index != EMPTY) {
2342 #ifdef DEBUG_PRINTF_ENABLED
2343               printf("%s: ip only map sucess\n","query_and_update_db_timeout");
2344 #endif
2345             }
2346         } else {
2347 #ifdef DEBUG_PRINTF_ENABLED
2348             printf("%s: port only map sucess\n", "query_and_update_db_timeout");
2349 #endif
2350         }
2351
2352     } else {
2353 #ifdef DEBUG_PRINTF_ENABLED
2354         printf("%s: ip  port map sucess\n","query_and_update_db_timeout");
2355 #endif
2356
2357     }
2358
2359     if(index == EMPTY) {
2360         /* No match found, clear timeout */
2361         if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) {
2362             mdb->timeout = 0;
2363         } else {
2364             sdb->timeout = 0;
2365         }
2366 #ifdef DEBUG_PRINTF_ENABLED
2367         printf("%s: No match\n","query_and_update_db_timeout");
2368 #endif
2369     } else {
2370         /* Match found, update timeout */
2371         timeout_db_entry = cnat_timeout_db + index;
2372         if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) {
2373             mdb->timeout = timeout_db_entry->t_key.timeout_value;
2374         } else {
2375             sdb->timeout =  timeout_db_entry->t_key.timeout_value;
2376         }
2377         return timeout_db_entry->t_key.timeout_value;
2378     }
2379     return 0;
2380 }
2381
2382
2383
2384 static
2385 void cnat_timeout_db_hash_add (cnat_timeout_db_entry_t *t_entry)
2386 {
2387     cnat_key_t key;
2388     u64 a, b, c;
2389     u32 index, bucket;
2390     cnat_key_t t_key = t_entry->t_key.timeout_key;
2391
2392     key.k.ipv4 = t_key.k.ipv4;
2393     key.k.port = t_key.k.port;
2394     key.k.vrf = t_key.k.vrf;
2395
2396     CNAT_V4_GET_HASH(key.key64,
2397                      bucket, CNAT_TIMEOUT_HASH_MASK)
2398
2399
2400     index = cnat_timeout_hash[bucket].next;
2401
2402     /* Add this db entry to the head of the bucket chain */
2403     t_entry->t_hash.next = index;
2404     cnat_timeout_hash[bucket].next = t_entry - cnat_timeout_db;
2405 }
2406
2407
2408
2409 u16
2410 cnat_timeout_db_create (cnat_timeout_t t_entry)
2411 {
2412     cnat_timeout_db_entry_t *db;
2413     cnat_key_t t_key = t_entry.timeout_key;
2414     u32 db_index;
2415
2416     pool_header_t        *h;
2417     u32                  free;
2418
2419     db_index = cnat_timeout_db_hash_lookup(t_key);
2420
2421     if(db_index != EMPTY) {
2422         /* Entry already exists. Check if it is replay or update */
2423         db = cnat_timeout_db + db_index;
2424         db->t_key.timeout_value = t_entry.timeout_value;
2425         return CNAT_SUCCESS;
2426     }
2427
2428     h = pool_header(cnat_timeout_db);
2429     free = vec_len(h->free_indices) - 1;
2430     
2431     if(free == 0) {
2432         return CNAT_OUT_LIMIT;
2433     }
2434
2435
2436     pool_get(cnat_timeout_db, db);
2437     ASSERT(db);
2438
2439     memset(db, 0, sizeof(*db));
2440
2441     db_index = db - cnat_timeout_db;
2442
2443     db->t_key.timeout_key.k.ipv4 = t_key.k.ipv4;
2444     db->t_key.timeout_key.k.port = t_key.k.port;
2445     db->t_key.timeout_key.k.vrf = t_key.k.vrf;
2446     db->t_key.timeout_value  = t_entry.timeout_value;
2447
2448
2449     cnat_timeout_db_hash_add(db);
2450     return CNAT_SUCCESS;
2451 }
2452
2453 void cnat_timeout_db_delete(cnat_key_t t_key)
2454 {
2455     cnat_key_t key;
2456     u64 a, b, c;
2457     u32 index, bucket;
2458     cnat_timeout_db_entry_t *this, *prev;
2459
2460     key.k.ipv4 = t_key.k.ipv4;
2461     key.k.port = t_key.k.port;
2462     key.k.vrf = t_key.k.vrf;
2463
2464
2465     CNAT_V4_GET_HASH(key.key64,
2466                      bucket, CNAT_TIMEOUT_HASH_MASK)
2467
2468
2469     index = cnat_timeout_hash[bucket].next;
2470
2471     if(index == EMPTY) return;
2472
2473     prev = 0;
2474     do {
2475         this = cnat_timeout_db + index;
2476         if (PREDICT_TRUE(
2477             (this->t_key.timeout_key.key64 & CNAT_TIMEOUT_FULL_MASK) ==
2478                   (key.key64 & CNAT_TIMEOUT_FULL_MASK))) {
2479             if (prev == 0) {
2480                 cnat_timeout_hash[bucket].next = this->t_hash.next;
2481                 goto found;
2482              } else {
2483                 prev->t_hash.next = this->t_hash.next;
2484                 goto found;
2485             }
2486         }
2487
2488         prev = this;
2489         index = this->t_hash.next;
2490     } while (index != EMPTY);
2491
2492     if(index == EMPTY) return;
2493
2494  found:
2495     pool_put(cnat_timeout_db, this);
2496
2497 }
2498
2499 void cnat_session_db_hash_delete (cnat_session_entry_t *ep)
2500 {
2501     u32 a, b, c;
2502     u32 index, bucket;
2503     cnat_session_entry_t *this, *prev;
2504
2505     CNAT_V4_GET_SESSION_HASH(ep->main_db_index, ep->v4_dest_key.k.ipv4,
2506                     ep->v4_dest_key.k.port, ep->v4_dest_key.k.vrf, bucket,
2507                     CNAT_SESSION_HASH_MASK)
2508
2509
2510     index = cnat_session_hash[bucket].next;
2511
2512     ASSERT(index != EMPTY);
2513
2514     prev = 0;
2515     do {
2516         this = cnat_session_db + index;
2517         if (PREDICT_TRUE(this == ep)) {
2518             if (prev == 0) {
2519                 cnat_session_hash[bucket].next =
2520                               ep->cnat_session_hash.next;
2521                 return;
2522             } else {
2523                 prev->cnat_session_hash.next =
2524                               ep->cnat_session_hash.next;
2525                 return;
2526             }
2527         }
2528         prev = this;
2529         index = this->cnat_session_hash.next;
2530     } while (index != EMPTY);
2531
2532     ASSERT(0);
2533
2534 }
2535
2536 cnat_session_entry_t *
2537 cnat_session_db_edm_lookup_entry(cnat_key_t *ko,u32 session_head_index, 
2538                                  u32 main_db_index)
2539 {
2540     u32 index;
2541     cnat_session_entry_t *db;
2542
2543
2544     index = session_head_index;
2545     if (PREDICT_TRUE(index == EMPTY)) {
2546         return (NULL);
2547     }
2548
2549     do {
2550         db = cnat_session_db + index;
2551         if(PREDICT_TRUE((db->main_db_index == main_db_index) &&
2552               (db->v4_dest_key.k.vrf == ko->k.vrf) &&
2553               (db->v4_dest_key.k.ipv4 == ko->k.ipv4))) {
2554
2555                 return db;
2556         }
2557         index = db->cnat_session_hash.next;
2558     } while (index != EMPTY);
2559  
2560     return (NULL);
2561 }
2562
2563
2564
2565 cnat_session_entry_t *
2566 cnat_session_db_lookup_entry(cnat_key_t *ko,u32 main_db_index)
2567 {
2568     u32 a, b, c;
2569     u32 index, bucket;
2570     cnat_session_entry_t *db;
2571
2572     CNAT_V4_GET_SESSION_HASH(main_db_index, ko->k.ipv4, ko->k.port,
2573                      ko->k.vrf, bucket, CNAT_SESSION_HASH_MASK)
2574
2575
2576     index = cnat_session_hash[bucket].next;
2577     if (PREDICT_TRUE(index == EMPTY)) {
2578         return (NULL);
2579     }
2580
2581     do {
2582         db = cnat_session_db + index;
2583         if(PREDICT_TRUE((db->main_db_index == main_db_index) &&
2584               (db->v4_dest_key.k.vrf == ko->k.vrf) &&
2585               (db->v4_dest_key.k.port == ko->k.port) &&
2586               (db->v4_dest_key.k.ipv4 == ko->k.ipv4))) {
2587
2588                 return db;
2589         }
2590         index = db->cnat_session_hash.next;
2591     } while (index != EMPTY);
2592
2593     return (NULL);
2594 }
2595
2596 cnat_session_entry_t *
2597 cnat_create_session_db_entry(cnat_key_t *ko,
2598                              cnat_main_db_entry_t *bdb, u8 log)
2599 {
2600     u32 a, b, c;
2601     u32 db_index, bucket_out;
2602     cnat_session_entry_t *db = NULL;
2603     pool_header_t        *h;
2604     u32 free_session;
2605     u16 instance;
2606
2607     db = cnat_session_db_lookup_entry(ko, bdb - cnat_main_db);
2608     if (PREDICT_FALSE(db != NULL)) {
2609         /*printf("Create Session - Entry already Exists\n");*/
2610         return db;
2611     }
2612
2613     h = pool_header(cnat_session_db);
2614     free_session = vec_len(h->free_indices) - 1;
2615
2616     if (bdb->flags & CNAT_DB_DSLITE_FLAG) {
2617         instance = bdb->dslite_nat44_inst_id;
2618     } else {
2619         instance = NAT44_RESERVED_INST_ID;
2620     }
2621
2622     if (PREDICT_FALSE(!free_session)) {
2623       nat44_dslite_common_stats[instance].drops_sessiondb_limit_exceeded++;
2624         return NULL;
2625     }
2626
2627     if( PREDICT_FALSE(bdb->nsessions == CNAT_MAX_SESSIONS_PER_BIB)) {
2628         /* printf("Create Session - Max sessions per BIB reached\n"); */
2629         return NULL;
2630     }
2631
2632     pool_get(cnat_session_db, db);
2633     memset(db, 0, sizeof(*db));
2634
2635     db_index = db - cnat_session_db;
2636     db->v4_dest_key.k.port = ko->k.port;
2637     db->v4_dest_key.k.ipv4 = ko->k.ipv4;
2638     db->v4_dest_key.k.vrf = ko->k.vrf;
2639
2640     db->main_list.next = db_index;
2641     db->main_list.prev = db_index;
2642     db->main_db_index = bdb - cnat_main_db;
2643
2644     db->tcp_seq_num = 0;
2645     db->ack_no      = 0;
2646     db->window      = 0;
2647
2648     if(PREDICT_FALSE(log)) {
2649         bdb->nsessions++;
2650         query_and_update_db_timeout(db, SESSION_DB_TYPE);
2651     }
2652
2653     if (PREDICT_FALSE(bdb->nsessions == 1)) {
2654         /*
2655          * first port for this src vrf/src ip addr
2656          */
2657         bdb->session_head_index = db_index;
2658     } else {
2659         index_dlist_addtail(bdb->session_head_index,
2660                             (u8 *)cnat_session_db, sizeof(cnat_session_db[0]),
2661                             STRUCT_OFFSET_OF(cnat_session_entry_t, main_list),
2662                             db_index);
2663     }
2664
2665     /*
2666      * setup o2i hash key
2667      */
2668     CNAT_V4_GET_SESSION_HASH(db->main_db_index, ko->k.ipv4, ko->k.port,
2669                      ko->k.vrf, bucket_out, CNAT_SESSION_HASH_MASK)
2670
2671
2672     db->cnat_session_hash.next =
2673                           cnat_session_hash[bucket_out].next;
2674     cnat_session_hash[bucket_out].next = db_index;
2675
2676
2677     if(PREDICT_FALSE(log)) {
2678         if (bdb->flags & CNAT_DB_DSLITE_FLAG) {
2679             cnat_session_log_ds_lite_mapping_create(bdb,
2680                                 (dslite_table_db_ptr + instance),db);
2681         } else {
2682             cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + bdb->vrfmap_index;
2683             cnat_session_log_nat44_mapping_create(bdb, db, my_vrfmap);
2684         }
2685     }
2686
2687     /* Need to set entry_expires here, as we need to override 0 check for
2688        newly established sessions */
2689     db->entry_expires = cnat_current_time;
2690     nat44_dslite_common_stats[instance].sessions++;
2691     return db;
2692 }
2693
2694 void
2695 cnat_dest_update_main2session(cnat_main_db_entry_t *mdb,
2696                  cnat_session_entry_t *sdb)
2697 {
2698
2699     sdb->flags = mdb->flags;
2700     sdb->timeout = mdb->timeout;
2701     sdb->entry_expires = mdb->entry_expires;
2702     sdb->alg.delta = mdb->alg.delta;
2703     sdb->tcp_seq_num = mdb->proto_data.seq_pcp.tcp_seq_num;
2704
2705     /* Reset Main db values to 0 */
2706     /* Reset only session specific flags */
2707     mdb->flags &= ~(CNAT_DB_FLAG_TCP_ACTIVE | CNAT_DB_FLAG_UDP_ACTIVE
2708                         | CNAT_DB_FLAG_ALG_ENTRY | CNAT_DB_FLAG_ALG_CTRL_FLOW);
2709     mdb->timeout = 0;
2710     mdb->entry_expires = 0;
2711     mdb->alg.delta = 0;
2712     if(PREDICT_FALSE(!((mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE) ||
2713             (mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_INIT)))) {
2714         mdb->proto_data.seq_pcp.tcp_seq_num = 0;
2715     }
2716
2717     mdb->dst_ipv4 = 0;
2718     mdb->dst_port = 0;
2719 }
2720
2721
2722 void
2723 cnat_dest_update_session2main(cnat_main_db_entry_t *mdb,
2724                  cnat_session_entry_t *sdb)
2725 {
2726
2727     u16 flags = sdb->flags & (CNAT_DB_FLAG_TCP_ACTIVE |
2728         CNAT_DB_FLAG_UDP_ACTIVE | CNAT_DB_FLAG_ALG_ENTRY |
2729         CNAT_DB_FLAG_ALG_CTRL_FLOW);
2730     mdb->flags |= flags;
2731     mdb->timeout = sdb->timeout;
2732     mdb->entry_expires = sdb->entry_expires;
2733     mdb->alg.delta = sdb->alg.delta;
2734     if(PREDICT_FALSE(!((mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE) ||
2735             (mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_INIT)))) {
2736             mdb->proto_data.seq_pcp.tcp_seq_num = sdb->tcp_seq_num;
2737     }
2738     mdb->dst_ipv4 = sdb->v4_dest_key.k.ipv4;
2739     mdb->dst_port = sdb->v4_dest_key.k.port;
2740 }
2741
2742 void cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log)
2743 {
2744     u32  session_db_index;
2745     u32  bdb_len;
2746     cnat_main_db_entry_t *be =0;
2747     cnat_session_entry_t *sdb_last = NULL;
2748     u16 instance;
2749
2750     if (PREDICT_FALSE(ep->flags & CNAT_DB_NAT64_FLAG) != 0) {
2751         /* Preventive check - Not a NAT44 entry */
2752         return;
2753     }
2754
2755     pool_header_t *h = pool_header(cnat_main_db);
2756
2757      /* Validate .. just in case we are trying to delete a non existing one */
2758     bdb_len = vec_len(cnat_main_db);
2759
2760     /* In case of invalid user just return, deleting only main db
2761      * is not a good idea, since some valid user db entry might be pointing
2762      * to that main db and hence leave the dbs in a inconsistent state
2763      */
2764     if (PREDICT_FALSE((ep->main_db_index >= bdb_len) ||
2765                     (clib_bitmap_get(h->free_bitmap, ep->main_db_index)))) {
2766 #ifdef DEBUG_PRINTF_ENABLED
2767         printf("invalid/unused user index in db %d\n", ep->main_db_index);
2768 #endif
2769         spp_printf(CNAT_INV_UNUSED_USR_INDEX, 1, (u32 *) &(ep->main_db_index));
2770         return;
2771     }
2772
2773     be = cnat_main_db + ep->main_db_index;
2774
2775     session_db_index = ep - cnat_session_db;
2776
2777     be->session_head_index = index_dlist_remelem (
2778         be->session_head_index, (u8 *)cnat_session_db,
2779         sizeof (cnat_session_db[0]),
2780         STRUCT_OFFSET_OF(cnat_session_entry_t, main_list),
2781         session_db_index);
2782
2783     if (be->flags & CNAT_DB_DSLITE_FLAG) {
2784         instance = be->dslite_nat44_inst_id;
2785     } else {
2786         instance = NAT44_RESERVED_INST_ID;
2787     }    
2788
2789     if(PREDICT_TRUE(log)) {
2790         if (be->flags & CNAT_DB_DSLITE_FLAG) {
2791             cnat_session_log_ds_lite_mapping_delete(be, 
2792                                 (dslite_table_db_ptr + instance),ep);
2793         } else {
2794             cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + be->vrfmap_index;
2795             cnat_session_log_nat44_mapping_delete(be, ep, my_vrfmap);
2796         }
2797         be->nsessions--;
2798     }
2799
2800     if (PREDICT_FALSE(be->nsessions == 1 && log)) {
2801         /* There is only 1 session left
2802          * Copy the info back to main db and release the last
2803          * existing session
2804          */
2805
2806         sdb_last = cnat_session_db + be->session_head_index;
2807         ASSERT(sdb_last != NULL);
2808
2809         cnat_dest_update_session2main(be, sdb_last);
2810         cnat_delete_session_db_entry(sdb_last, FALSE);
2811     }
2812
2813     /* Remove from session DB hashes */
2814     cnat_session_db_hash_delete(ep);
2815     nat44_dslite_common_stats[instance].sessions--;
2816
2817     pool_put(cnat_session_db, ep);
2818 }
2819
2820 cnat_main_db_entry_t*
2821 dslite_main_db_lookup_entry(dslite_db_key_bucket_t *ki)
2822 {
2823     u64 a, b, c;
2824     u32 index;
2825     cnat_main_db_entry_t *db;
2826     cnat_user_db_entry_t *userdb;
2827
2828     DSLITE_V6_GET_HASH((&(ki->dk)),
2829                      ki->bucket,
2830                      CNAT_MAIN_HASH_MASK);
2831
2832     DSLITE_PRINTF(1,"MDBLU hash..%u\n", ki->bucket);
2833  
2834     index = cnat_in2out_hash[ki->bucket].next;
2835     if (PREDICT_TRUE(index == EMPTY)) {
2836         DSLITE_PRINTF(1,"MDBLU index MT..\n");
2837         return (NULL);
2838     }
2839
2840     do {
2841 /* We can add a flag here to indicate if the db entry is for nat44 or 
2842  * dslite. If the db entry is for nat44 then we can simply move to the
2843  * one.
2844  */
2845         db = cnat_main_db + index;
2846         userdb = cnat_user_db + db->user_index;
2847         if (PREDICT_TRUE(db->in2out_key.key64 == ki->dk.ipv4_key.key64)
2848             && userdb->ipv6[0] == ki->dk.ipv6[0]
2849             && userdb->ipv6[1] == ki->dk.ipv6[1]
2850             && userdb->ipv6[2] == ki->dk.ipv6[2]
2851             && userdb->ipv6[3] == ki->dk.ipv6[3]) {
2852             DSLITE_PRINTF(1,"MDBLU success..%u\n", index);
2853             return db;
2854         }
2855         index = db->in2out_hash.next;
2856     } while (index != EMPTY);
2857
2858     DSLITE_PRINTF(1,"MDBLU Entry does not exist..\n");
2859     return (NULL);
2860 }
2861
2862 cnat_user_db_entry_t*
2863 dslite_user_db_lookup_entry(dslite_db_key_bucket_t *uki) 
2864 {
2865     u64 a, b, c;
2866     u32 index;
2867     cnat_user_db_entry_t *udb=NULL;
2868
2869     DSLITE_V6_GET_HASH((&(uki->dk)), 
2870                      uki->bucket,
2871                      CNAT_USER_HASH_MASK)
2872
2873     DSLITE_PRINTF(1,"UDBLU hash..%u\n", uki->bucket);
2874
2875     /* now: index in user vector */
2876     index = cnat_user_hash[uki->bucket].next;
2877     if (PREDICT_TRUE(index != EMPTY)) {
2878         DSLITE_PRINTF(1,"UDBLU hash table entry not MT..\n");
2879         do {
2880             udb = cnat_user_db + index;
2881             if (PREDICT_FALSE(udb->key.key64 == uki->dk.ipv4_key.key64)
2882              && udb->ipv6[0] == uki->dk.ipv6[0]
2883              && udb->ipv6[1] == uki->dk.ipv6[1]
2884              && udb->ipv6[2] == uki->dk.ipv6[2]
2885              && udb->ipv6[3] == uki->dk.ipv6[3]) {
2886                 DSLITE_PRINTF(1,"UDBLU success..%u\n", index);
2887                 return udb;
2888             }
2889             index = udb->user_hash.next;
2890         } while (index != EMPTY);
2891     }
2892     DSLITE_PRINTF(1,"UDBLU Entry doesnt exist..\n");
2893     return (NULL);
2894 }
2895
2896 cnat_user_db_entry_t*
2897 dslite_user_db_create_entry(dslite_db_key_bucket_t *uki,
2898                           u32 portmap_index)
2899 {
2900     cnat_user_db_entry_t *udb = NULL;
2901
2902     pool_get(cnat_user_db, udb);
2903     memset(udb, 0, sizeof(*udb));
2904
2905     udb->ntranslations = 1; 
2906     udb->portmap_index = portmap_index;
2907 //    udb->key.key64 = uki->k.key64;
2908
2909     udb->key.key64 = uki->dk.ipv4_key.key64;
2910     udb->ipv6[0] = uki->dk.ipv6[0];
2911     udb->ipv6[1] = uki->dk.ipv6[1];
2912     udb->ipv6[2] = uki->dk.ipv6[2];
2913     udb->ipv6[3] = uki->dk.ipv6[3];
2914  
2915     udb->flags |= CNAT_USER_DB_DSLITE_FLAG;
2916     /* Add this user to the head of the bucket chain */
2917     udb->user_hash.next = 
2918              cnat_user_hash[uki->bucket].next;
2919     cnat_user_hash[uki->bucket].next = udb - cnat_user_db;
2920
2921 #ifndef NO_BULK_LOGGING
2922     INIT_BULK_CACHE(udb)
2923 #endif /* NO_BULK_LOGGING */
2924
2925     return udb;
2926 }
2927
2928 #ifndef TOBE_PORTED
2929 cnat_main_db_entry_t*
2930 dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki,
2931                                    cnat_db_key_bucket_t *ko,
2932                                    cnat_user_db_entry_t *udb)
2933 {
2934     return 0;
2935 }
2936 #else
2937 cnat_main_db_entry_t*
2938 dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki,
2939                                    cnat_db_key_bucket_t *ko,
2940                                    cnat_user_db_entry_t *udb)
2941 {
2942     u64 a, b, c;
2943     u32 db_index;
2944     cnat_main_db_entry_t *db = NULL;
2945
2946     pool_get(cnat_main_db, db);
2947     memset(db, 0, sizeof(*db));
2948
2949     db_index = db - cnat_main_db;
2950     db->in2out_key.k.ipv4 = ki->dk.ipv4_key.k.ipv4;
2951     db->in2out_key.k.port = ki->dk.ipv4_key.k.port;
2952     db->in2out_key.k.vrf =  ki->dk.ipv4_key.k.vrf;
2953     db->out2in_key.k.ipv4 = ko->k.k.ipv4;
2954     db->out2in_key.k.port = ko->k.k.port;
2955     db->out2in_key.k.vrf = ko->k.k.vrf;
2956
2957     db->user_ports.next = db_index;
2958     db->user_ports.prev = db_index;
2959     db->user_index = udb - cnat_user_db;
2960     //db->portmap_index = udb->portmap_index;
2961    db->flags |= CNAT_DB_DSLITE_FLAG;
2962
2963     if (PREDICT_FALSE(udb->ntranslations == 1)) {
2964         /*
2965          * first port for this src vrf/src ip addr
2966          */
2967         udb->translation_list_head_index = db_index;
2968         DSLITE_PRINTF(1,"First translation of this user..\n");
2969     } else {
2970         index_dlist_addtail(udb->translation_list_head_index,
2971                             (u8 *)cnat_main_db, sizeof(cnat_main_db[0]),
2972                             STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports),
2973                             db_index);
2974     }
2975
2976     /* 
2977      * setup o2i hash key
2978      */
2979     CNAT_V4_GET_HASH(ko->k.key64, 
2980                      ko->bucket,
2981                      CNAT_MAIN_HASH_MASK)
2982     db->out2in_hash.next = cnat_out2in_hash[ko->bucket].next;
2983     cnat_out2in_hash[ko->bucket].next = db_index;
2984     /*
2985      * setup i2o hash key, bucket is already calculate
2986      */
2987     db->in2out_hash.next = cnat_in2out_hash[ki->bucket].next;
2988     cnat_in2out_hash[ki->bucket].next = db_index;
2989
2990     DSLITE_PRINTF(1,"Create main db and hash..%u %u %u %u %x\n", 
2991                   ki->bucket, ko->bucket, 
2992                   db_index, db->user_index, ko->k.key64);
2993
2994 #if DEBUG > 1
2995     printf("\nMy_Instance_Number %d: Bucket %d, Db_Index %d",
2996            my_instance_number, ki->bucket, db_index);
2997     printf("\nInside (VRF 0x%x, IP 0x%x, PORT 0x%x)",
2998            db->in2out_key.k.vrf, db->in2out_key.k.ipv4, db->in2out_key.k.port);
2999     printf("\nOutside (VRF 0x%x, IP 0x%x, PORT 0x%x)",
3000            db->out2in_key.k.vrf, db->out2in_key.k.ipv4, db->out2in_key.k.port);
3001     printf("\nUser Index %d, IP 0x%x",
3002            db->user_index, udb->key.k.ipv4);
3003 #endif
3004
3005     //nat44_dslite_common_stats[DSLITE_COMMON_STATS].active_translations++;
3006
3007     return db;
3008 }
3009
3010 static inline void handle_dslite_port_exceeded_logging(
3011     cnat_user_db_entry_t *udb, 
3012     dslite_key_t   * key,
3013     dslite_table_entry_t *dslite_entry_ptr)
3014 {
3015
3016     if(PREDICT_TRUE(udb->flags & CNAT_USER_DB_PORT_LIMIT_EXCEEDED)) {
3017         /* Already logged ..*/
3018         return;
3019     }
3020
3021     /* else, set the flag and call the log API */
3022     udb->flags = udb->flags | CNAT_USER_DB_PORT_LIMIT_EXCEEDED;
3023     cnat_log_ds_lite_port_limit_exceeded(key, dslite_entry_ptr);
3024     return;
3025 }
3026 #endif
3027
3028 inline void handle_cnat_port_exceeded_logging(
3029     cnat_user_db_entry_t *udb,
3030     cnat_key_t   * key,
3031     cnat_vrfmap_t *vrfmap)
3032 {
3033
3034     if(PREDICT_TRUE(udb->flags & CNAT_USER_DB_PORT_LIMIT_EXCEEDED)) {
3035         /* Already logged ..*/
3036         return;
3037     }
3038
3039     /* else, set the flag and call the log API */
3040     udb->flags = udb->flags | CNAT_USER_DB_PORT_LIMIT_EXCEEDED;
3041     cnat_log_nat44_port_limit_exceeded(key,vrfmap);
3042     return;
3043 }
3044
3045 #ifndef TOBE_PORTED
3046 cnat_main_db_entry_t*
3047 dslite_get_main_db_entry_v2(dslite_db_key_bucket_t *ki,
3048                           port_pair_t port_pair_type,
3049                           port_type_t port_type,
3050                           cnat_gen_icmp_info *info,
3051                           dslite_table_entry_t *dslite_entry_ptr,
3052                           cnat_key_t *dest_info)
3053 {
3054     return 0;
3055 }
3056 #else
3057 /*
3058  * this function is called by exception node
3059  * when lookup is fialed in i2o node
3060  *
3061  * if reash per user port limit, 
3062  * set user_db_entry pointer, and error == CNAT_OUT_LIMIT
3063  */
3064 cnat_main_db_entry_t*
3065 dslite_get_main_db_entry_v2(dslite_db_key_bucket_t *ki,
3066                           port_pair_t port_pair_type,
3067                           port_type_t port_type,
3068                           cnat_gen_icmp_info *info,
3069                           dslite_table_entry_t *dslite_entry_ptr,
3070                           cnat_key_t *dest_info)
3071 {
3072     u16 protocol;
3073     cnat_errno_t rv;
3074     dslite_db_key_bucket_t u_ki;
3075     cnat_db_key_bucket_t ko;
3076     u32                 my_index, free_main, free_user;
3077     u32                 current_timestamp;
3078     cnat_vrfmap_t       *my_vrfmap =0;
3079     u16                 my_vrfmap_index;
3080     cnat_portmap_v2_t   *pm =0;
3081     cnat_user_db_entry_t *udb = 0;
3082     cnat_main_db_entry_t *db = 0;
3083     pool_header_t        *h;
3084     u16 dslite_id = dslite_entry_ptr->dslite_id;
3085
3086 #ifndef NO_BULK_LOGGING
3087     int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
3088 #endif
3089     /* 
3090      * need to try lookup again because 
3091      * second pkt may come here before the entry is created
3092      * by receiving first pkt due to high line rate.
3093      */
3094     info->gen_icmp_msg = CNAT_NO_ICMP_MSG;
3095     info->error = CNAT_SUCCESS;
3096     db = dslite_main_db_lookup_entry(ki);
3097     if (PREDICT_TRUE(db)) {
3098         /* what if the source is talking to a
3099          * new dest now? We will have to handle this case and
3100          * take care of - creating session db and logging
3101          */
3102         if(PREDICT_FALSE((!dest_info->k.ipv4) && (!dest_info->k.port))) {
3103             return db;  /* if dest_info is null don't create session */
3104         }
3105
3106         if(PREDICT_TRUE((db->dst_ipv4 == dest_info->k.ipv4) &&
3107             (db->dst_port == dest_info->k.port))) {
3108             return db;
3109         }
3110         dest_info->k.vrf = db->in2out_key.k.vrf;
3111         /* Src is indeed talking to a different dest */
3112         cnat_session_entry_t *session_db2 = NULL;
3113         if(PREDICT_TRUE(db->nsessions == 1)) {
3114             session_db2 = cnat_handle_1to2_session(db, dest_info);
3115             if(PREDICT_TRUE(session_db2 != NULL)) {
3116                 CNAT_DB_TIMEOUT_RST(session_db2);
3117                 return db;
3118             } else {
3119                 info->error = CNAT_ERR_NO_SESSION_DB;
3120                 return NULL;
3121             }
3122         } else if(PREDICT_FALSE(db->nsessions == 0)) {
3123             /* Should be static entry.. should never happen
3124              */
3125             if(PREDICT_TRUE(dest_info->k.ipv4 != 0)) {
3126                 cnat_add_dest_n_log(db, dest_info);
3127             }
3128             return db;
3129         } else {
3130             /* The src has already created multiple sessions.. very rare
3131              */
3132             session_db2 = cnat_create_session_db_entry(dest_info,
3133                         db, TRUE);
3134             if(PREDICT_TRUE(session_db2 != NULL)) {
3135                 CNAT_DB_TIMEOUT_RST(session_db2);
3136                return db;
3137             } else {
3138                 info->error = CNAT_ERR_NO_SESSION_DB;
3139                 return NULL;
3140             }
3141         }
3142
3143     }
3144
3145     /* 
3146      * step 1. check if outside vrf is configured or not
3147      *         and Find the set of portmaps for the outside vrf
3148      * insider vrf is one to one mappted to outside vrf
3149      * key is vrf and ip only
3150      * ki.k.k.vrf has protocol bits, mask out 
3151      */
3152     protocol =              ki->dk.ipv4_key.k.vrf & CNAT_PRO_MASK;
3153     u_ki.dk.ipv4_key.k.vrf =  ki->dk.ipv4_key.k.vrf & CNAT_VRF_MASK;
3154 #ifdef DSLITE_USER_IPV4
3155     u_ki.dk.ipv4_key.k.ipv4 = ki->dk.ipv4_key.k.ipv4;
3156 #else
3157    /*
3158     * Inside ipv4 address should be masked, if port limit
3159     * need to be done at B4 element level.
3160     */ 
3161     u_ki.dk.ipv4_key.k.ipv4 = 0;
3162 #endif
3163     u_ki.dk.ipv4_key.k.port = 0;
3164
3165     u_ki.dk.ipv6[0] =       ki->dk.ipv6[0];
3166     u_ki.dk.ipv6[1] =       ki->dk.ipv6[1];
3167     u_ki.dk.ipv6[2] =       ki->dk.ipv6[2];
3168     u_ki.dk.ipv6[3] =       ki->dk.ipv6[3];
3169
3170     my_vrfmap_index = vrf_map_array[u_ki.dk.ipv4_key.k.vrf];
3171     my_vrfmap = cnat_map_by_vrf + my_vrfmap_index;
3172 /*  Checking if the inst entry is active or not is done much earlier
3173  */
3174 #if 0
3175     my_vrfmap_index = vrf_map_array[u_ki.k.k.vrf];
3176     my_vrfmap = cnat_map_by_vrf + my_vrfmap_index;
3177     my_vrfmap_entry_found = ((my_vrfmap_index != VRF_MAP_ENTRY_EMPTY) &&
3178                              (my_vrfmap->status == S_RUN) &&
3179                              (my_vrfmap->i_vrf == u_ki.k.k.vrf));
3180
3181     if (PREDICT_FALSE(!my_vrfmap_entry_found)) {
3182         u32 arr[] = {ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port};
3183         if ((my_vrfmap_index == VRF_MAP_ENTRY_EMPTY) || 
3184             (my_vrfmap->i_vrf == u_ki.k.k.vrf)) {
3185             info->error = CNAT_NO_CONFIG;
3186             CNAT_DEBUG_INSIDE_ERR(CNAT_NO_CONFIG)
3187         spp_printf(CNAT_NO_CONFIG_ERROR, 3, arr);
3188         } else {
3189             info->error = CNAT_NO_VRF_RUN;
3190             CNAT_DEBUG_INSIDE_ERR(CNAT_NO_VRF_RUN)
3191         spp_printf(CNAT_NO_VRF_RUN_ERROR, 3, arr);
3192         }
3193
3194         return (NULL);
3195     }
3196 #endif
3197 /*
3198     dslite_inst_ptr = dslite_nat44_config_table[dslite_inst_id];
3199 */
3200     pm = dslite_entry_ptr->portmap_list;
3201     //pm = my_vrfmap->portmap_list;
3202
3203     /*
3204      * set o2i key with protocl bits
3205      */
3206     ko.k.k.vrf = dslite_entry_ptr->o_vrf | protocol;
3207     //ko.k.k.vrf = my_vrfmap->o_vrf | protocol;
3208
3209     /*
3210      * step 2. check if src vrf, src ip addr is alreay 
3211      *         in the user db
3212      * if yes, use PORT_ALLOC_DIRECTED
3213      * if no, use PORT_ALLOC_ANY since it is first time
3214      */
3215     udb = dslite_user_db_lookup_entry(&u_ki);
3216     if (PREDICT_TRUE(udb)) {
3217         /*
3218          * not first time allocate port for this user
3219          * check limit
3220          */
3221         if (PREDICT_FALSE(udb->ntranslations >= 
3222              dslite_entry_ptr->cnat_main_db_max_ports_per_user)) {
3223              //cnat_main_db_max_ports_per_user)) 
3224
3225             /* Check for the port type here. If we are getting
3226              * a STATIC PORT, allow the config.
3227              */
3228             if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) {
3229                info->error = CNAT_OUT_LIMIT;
3230                DSLITE_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT)
3231                port_exceeded_msg_log(u_ki.dk.ipv4_key.k.ipv4, u_ki.dk.ipv4_key.k.vrf);
3232                nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
3233                u_ki.dk.ipv4_key.k.vrf =  ki->dk.ipv4_key.k.vrf;
3234                u_ki.dk.ipv4_key.k.port = ki->dk.ipv4_key.k.port;
3235                handle_dslite_port_exceeded_logging(udb, &u_ki.dk, dslite_entry_ptr); 
3236                return (NULL);
3237             }
3238         }
3239
3240         CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb, 
3241             dslite_entry_ptr->cnat_main_db_max_ports_per_user)
3242
3243         /* 
3244          * check if main db has space to accomodate new entry
3245          */
3246         h = pool_header(cnat_main_db);
3247
3248         free_main = vec_len(h->free_indices) - 1;
3249         if (PREDICT_FALSE(!free_main)) {
3250             info->error = CNAT_MAIN_DB_LIMIT;
3251             nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++;
3252             DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
3253
3254             current_timestamp = spp_trace_log_get_unix_time_in_seconds();
3255             if (PREDICT_FALSE((current_timestamp - last_log_timestamp) >
3256                     1800)) {
3257                 spp_printf(CNAT_SESSION_THRESH_EXCEEDED, 0, NULL);
3258                 last_log_timestamp = current_timestamp;
3259             }
3260
3261 #ifdef UT_TEST_CODE
3262             printf("Limit reached : OLD USER");
3263 #endif
3264             return NULL;
3265         }
3266
3267         /*
3268          * allocate port, from existing mapping 
3269          */
3270         my_index = udb->portmap_index;
3271
3272         if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
3273             rv = cnat_static_port_alloc_v2_bulk(pm,
3274                         PORT_ALLOC_DIRECTED,
3275                         port_pair_type,
3276                         ki->dk.ipv4_key.k.ipv4,
3277                         ki->dk.ipv4_key.k.port,
3278                         &my_index,
3279                         &(ko.k.k.ipv4),
3280                         &(ko.k.k.port),
3281                         STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3282 #ifndef NO_BULK_LOGGING
3283                         , udb,
3284                         BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3285                         &nfv9_log_req
3286 #endif
3287                         , my_vrfmap->ip_n_to_1
3288                         );
3289         }  else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP) ) {
3290
3291             rv = cnat_dynamic_port_alloc_v2_bulk(pm,
3292                         PORT_ALLOC_DIRECTED,
3293                         port_pair_type,
3294                         &my_index,
3295                         &(ko.k.k.ipv4),
3296                         &(ko.k.k.port), 
3297                         STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3298 #ifndef NO_BULK_LOGGING
3299                         , udb,
3300                         BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3301                         &nfv9_log_req
3302 #endif
3303                         , 0,
3304                         &(dslite_entry_ptr->rseed_ip)
3305                         );
3306             DSLITE_PRINTF(1,"D_PORT_ALLOC %x %u\n", ko.k.k.ipv4, ko.k.k.port);
3307         } else {
3308             /*
3309              * For RTSP, two translation entries are created, 
3310              * check if main db has space to accomodate two new entry
3311              */
3312             free_main = free_main  - 1; 
3313
3314             if (PREDICT_FALSE(!free_main)) {
3315                 info->error = CNAT_MAIN_DB_LIMIT;
3316                 nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++;
3317                 DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
3318
3319                 return NULL;
3320             } else {    
3321
3322                 rv = cnat_dynamic_port_alloc_rtsp_bulk(pm,
3323                             PORT_ALLOC_DIRECTED,
3324                             port_pair_type,
3325                             ki->dk.ipv4_key.k.port,
3326                             &my_index,
3327                             &(ko.k.k.ipv4),
3328                             &(ko.k.k.port),
3329                             STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3330 #ifndef NO_BULK_LOGGING
3331                             , udb,
3332                             BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3333                             &nfv9_log_req
3334 #endif
3335                          , &(dslite_entry_ptr->rseed_ip)
3336                         );
3337             }
3338         }
3339
3340         if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
3341             DSLITE_PRINTF(1,"D_PORT_ALLOC port alloc error\n");
3342             info->error = rv;
3343             DSLITE_DEBUG_INSIDE_ERR(rv)
3344             nat44_dslite_common_stats[dslite_id].in2out_drops_resource_depletion ++;
3345             log_port_alloc_error(rv, &(ki->dk.ipv4_key));
3346             return (NULL);
3347         }
3348         /*
3349          * increment port in use for this user
3350          */
3351         udb->ntranslations += 1;
3352     } else {
3353         /*
3354          * first time allocate port for this user
3355          */
3356      
3357         /*
3358          * Do not create entry if port limit is invalid
3359          */
3360         if (PREDICT_FALSE(!(dslite_entry_ptr->cnat_main_db_max_ports_per_user))) {
3361             if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) {
3362                 info->error = CNAT_OUT_LIMIT;
3363                 nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
3364                 port_exceeded_msg_log(u_ki.dk.ipv4_key.k.ipv4, u_ki.dk.ipv4_key.k.vrf);
3365                 DSLITE_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT)
3366                 return (NULL);
3367             }
3368         }
3369
3370         /*
3371          * Check if main db has space for new entry
3372          * Allowing a user db entry to be created if main db is not free
3373          * will cause a port to be allocated to that user, which results in  
3374          * wastage of that port, hence the check is done here.
3375          */
3376         h = pool_header(cnat_main_db);
3377         free_main = vec_len(h->free_indices) - 1;
3378
3379         h = pool_header(cnat_user_db);
3380             free_user = vec_len(h->free_indices) - 1;
3381
3382         /*
3383          * If either main_db or user_db does not have entries
3384          * bail out, with appropriate error
3385          */
3386         if (PREDICT_FALSE(!(free_main && free_user))) {
3387             u32 log_error;
3388             if(free_main) {
3389                 info->error = CNAT_USER_DB_LIMIT;
3390                 log_error = CNAT_USER_DB_LIMIT_ERROR;
3391             } else {
3392                    info->error = CNAT_MAIN_DB_LIMIT;
3393                    log_error = CNAT_MAIN_DB_LIMIT_ERROR;
3394             }
3395             nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++;
3396             DSLITE_DEBUG_INSIDE_ERR(info->error)
3397             spp_printf(log_error, 0, 0);
3398             return NULL;
3399         }
3400
3401         if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
3402             rv = cnat_static_port_alloc_v2_bulk(pm,
3403                         PORT_ALLOC_ANY,
3404                         port_pair_type,
3405                         ki->dk.ipv4_key.k.ipv4,
3406                         ki->dk.ipv4_key.k.port,
3407                         &my_index,
3408                         &(ko.k.k.ipv4),
3409                         &(ko.k.k.port),
3410                         STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3411 #ifndef NO_BULK_LOGGING
3412                         , NULL,
3413                         BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), 
3414                         &nfv9_log_req
3415 #endif
3416                         , my_vrfmap->ip_n_to_1
3417                       
3418                         );
3419         }  else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP)) {
3420             rv = cnat_dynamic_port_alloc_v2_bulk(pm,
3421                         PORT_ALLOC_ANY,
3422                         port_pair_type,
3423                         &my_index,
3424                         &(ko.k.k.ipv4),
3425                         &(ko.k.k.port),
3426                         STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3427 #ifndef NO_BULK_LOGGING
3428                         , NULL,
3429                         BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3430                         &nfv9_log_req
3431 #endif
3432                         , 0,
3433                         &(dslite_entry_ptr->rseed_ip)
3434                         );
3435             DSLITE_PRINTF(1,"NU:D PORT ALLOC..%x %u\n", ko.k.k.ipv4,
3436                              ko.k.k.port);
3437
3438         } else {
3439             /*
3440              * For RTSP, two translation entries are created,
3441              * check if main db has space to accomodate two new entry
3442              */
3443             free_main = free_main  - 1;
3444
3445             if (PREDICT_FALSE(!free_main)) {
3446                 info->error = CNAT_MAIN_DB_LIMIT;
3447                 nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++;
3448                 DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
3449
3450                 return NULL;
3451             } else {
3452
3453                 rv = cnat_dynamic_port_alloc_rtsp_bulk(pm,
3454                             PORT_ALLOC_DIRECTED,
3455                             port_pair_type,
3456                             ki->dk.ipv4_key.k.port,
3457                             &my_index,
3458                             &(ko.k.k.ipv4),
3459                             &(ko.k.k.port),
3460                             STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3461 #ifndef NO_BULK_LOGGING
3462                             , NULL,
3463                             BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3464                             &nfv9_log_req
3465 #endif
3466                             , &(dslite_entry_ptr->rseed_ip)
3467                         );
3468             /* TODO: Add the port pair flag here */
3469             }
3470         }
3471
3472
3473
3474         if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
3475             DSLITE_PRINTF(1,"NU:D_PORT_ALLOC port alloc error\n");
3476             info->error = rv;
3477             nat44_dslite_common_stats[dslite_id].in2out_drops_resource_depletion ++;
3478             DSLITE_DEBUG_INSIDE_ERR(rv) 
3479             log_port_alloc_error(rv, &(ki->dk.ipv4_key));
3480             return (NULL);
3481         }
3482         /* 
3483          * create entry in user db
3484          */
3485         udb = dslite_user_db_create_entry(&u_ki, my_index);
3486         nat44_dslite_common_stats[dslite_id].num_subscribers++;
3487         DSLITE_PRINTF(1,"UDB crete entry done..\n");
3488 #ifndef NO_BULK_LOGGING
3489         if(PREDICT_TRUE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) {
3490             cnat_update_bulk_range_cache(udb, ko.k.k.port,
3491             BULKSIZE_FROM_VRFMAP(dslite_entry_ptr));
3492         }
3493 #endif /*  #ifndef NO_BULK_LOGGING */
3494     }
3495
3496     /*
3497      * step 3:
3498      * outside port is allocated for this src vrf/src ip addr
3499      * 1)create a new entry in main db
3500      * 2)setup cnat_out2in_hash key
3501      * 3)setup cnat_in2out_hash key
3502      */
3503     db = dslite_create_main_db_entry_and_hash(ki, &ko, udb);
3504     DSLITE_PRINTF(1,"dslite_create_main_db_entry_and_hash done..\n");
3505     //db->vrfmap_index = my_vrfmap - cnat_map_by_vrf;
3506     db->dslite_nat44_inst_id = dslite_id;
3507     nat44_dslite_common_stats[dslite_id].active_translations++;
3508     if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
3509         nat44_dslite_common_stats[dslite_id].num_static_translations++;
3510     } else {
3511         nat44_dslite_common_stats[dslite_id].num_dynamic_translations++;
3512     }
3513
3514     dslite_translation_create_count++;
3515
3516     db->dst_ipv4 = dest_info->k.ipv4;
3517     db->dst_port = dest_info->k.port;
3518     if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) {
3519         /* for static fwding, let the nsessions remain zero */
3520         db->nsessions++;
3521     }
3522
3523     /*
3524      * don't forget logging
3525      * logging API is unconditional, 
3526      * logging configuration check is done inside the inline function
3527      */
3528     if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
3529         if(PREDICT_FALSE( dslite_entry_ptr->nf_logging_policy == 
3530             SESSION_LOG_ENABLE)) {
3531             if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) {
3532                 cnat_nfv9_ds_lite_log_session_create(db, 
3533                         dslite_entry_ptr,NULL);
3534             }
3535         } else {
3536                 cnat_nfv9_ds_lite_mapping_create(db,dslite_entry_ptr
3537 #ifndef NO_BULK_LOGGING
3538                 ,nfv9_log_req
3539 #endif
3540                 );
3541         }
3542         if(PREDICT_TRUE((dslite_entry_ptr->syslog_logging_policy != SESSION_LOG_ENABLE) ||
3543                         (db->dst_ipv4 || db->dst_port))) {
3544             cnat_syslog_ds_lite_mapping_create(db,dslite_entry_ptr,NULL
3545 #ifndef NO_BULK_LOGGING
3546             ,nfv9_log_req
3547 #endif
3548             );
3549         }
3550     }
3551
3552 #if 0
3553     if (PREDICT_FALSE(port_pair_type == PORT_PAIR)) {
3554        cnat_main_db_entry_t *db2 = 0;
3555        dslite_db_key_bucket_t new_ki = *ki;
3556        u64 a, b, c;
3557
3558        new_ki.k.k.port += 1;
3559        ko.k.k.port += 1;
3560
3561        CNAT_V4_GET_HASH(new_ki.k.key64, new_ki.bucket, 
3562                         CNAT_MAIN_HASH_MASK);
3563
3564        db2 = cnat_create_main_db_entry_and_hash(&new_ki, &ko, udb);
3565
3566        translation_create_count ++;
3567        db2->dslite_nat44_inst_id = dslite_id;
3568        db2->entry_expires = cnat_current_time;
3569        db2->flags |= CNAT_DB_FLAG_ALG_ENTRY;
3570        udb->ntranslations += 1;
3571 #ifndef NO_BULK_LOGGING
3572        if(PREDICT_FALSE(nfv9_log_req == BULK_ALLOC_NOT_ATTEMPTED))
3573            cnat_nfv9_log_mapping_create(db2, my_vrfmap, nfv9_log_req);
3574 #else 
3575         cnat_nfv9_log_mapping_create(db2, my_vrfmap);
3576 #endif
3577     }
3578 #endif
3579     return db;
3580 }
3581 #endif /* TOBE_PORTED */
3582
3583 #if 0
3584 /* TOBE_PORTED */
3585 uword
3586 cnat_db_v2_node_fn (vlib_main_t * vm,
3587                   vlib_node_runtime_t * node,
3588                   vlib_frame_t * frame)
3589 {
3590     return 0;
3591 }
3592 VLIB_REGISTER_NODE (cnat_db_v2_node) = {
3593     .function = cnat_db_v2_node_fn,
3594     .name = "vcgn-db-v2",
3595     .vector_size = sizeof (u32),
3596     .type = VLIB_NODE_TYPE_INTERNAL,
3597   
3598     .n_errors = ARRAY_LEN(cnat_db_v2_error_strings),
3599     .error_strings = cnat_db_v2_error_strings,
3600   
3601     .n_next_nodes = CNAT_DB_V2_DROP,
3602   
3603     /* edit / add dispositions here */
3604     .next_nodes = {
3605         [CNAT_DB_V2_DROP] = "error-drop",
3606     },
3607 };
3608 #endif
3609 void cnat_db_v2_init (void)
3610 {
3611
3612     u32 i, n;
3613     cnat_timeout_db_entry_t * tdb __attribute__((unused));
3614
3615     cgse_nat_db_entry_t *comb_db __attribute__((unused));
3616     cgse_nat_user_db_entry_t *comb_user __attribute__((unused));
3617     cgse_nat_session_db_entry_t *comb_session __attribute__((unused));
3618
3619     n = CNAT_DB_SIZE*1.15;    /* add 15% LB margin */
3620
3621     /*
3622      * We also make it multiple of NUM_BITS_IN_UWORD for better
3623      * DB scanning algorithm
3624      */
3625     if (n % NUM_BITS_IN_UWORD)
3626         n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD));
3627
3628     pool_alloc(cgse_nat_db,n);
3629     for(i=0; i< n; i++) {
3630          pool_get(cgse_nat_db, comb_db);
3631     }
3632
3633     for(i=0; i< n; i++) {
3634         pool_put(cgse_nat_db, cgse_nat_db + i);
3635     }
3636
3637     cnat_main_db = &cgse_nat_db->nat44_main_db; 
3638
3639     /* For Sessions */
3640     if(PLATFORM_DBL_SUPPORT) {
3641         /* create session table for NAT44 and NAT64 itself */
3642         printf("DBL Support exist %d\n", PLATFORM_DBL_SUPPORT);
3643         n = CNAT_SESSION_DB_SIZE * 1.15;    /* add 15% LB margin */
3644     } else {
3645         /* Create session table for NAT64 only */
3646         printf("DBL Support Not exist\n");
3647         n = NAT64_MAIN_DB_SIZE * 1.15;    /* add 15% LB margin */
3648     }
3649
3650     /*
3651      * We also make it multiple of NUM_BITS_IN_UWORD for better
3652      * DB scanning algorithm
3653      */
3654     if (n % NUM_BITS_IN_UWORD)
3655         n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD));
3656
3657     pool_alloc(cgse_session_db,n);
3658     for(i=0; i< n; i++) {
3659          pool_get(cgse_session_db, comb_session);
3660     }
3661
3662     for(i=0; i< n; i++) {
3663         pool_put(cgse_session_db, cgse_session_db + i);
3664     }
3665
3666     cnat_session_db = &cgse_session_db->nat44_session_db;
3667
3668     vec_validate(cnat_out2in_hash, CNAT_MAIN_HASH_MASK);
3669     memset(cnat_out2in_hash, 0xff, CNAT_MAIN_HASH_SIZE*sizeof(index_slist_t));
3670
3671     vec_validate(cnat_in2out_hash, CNAT_MAIN_HASH_MASK);
3672     memset(cnat_in2out_hash, 0xff, CNAT_MAIN_HASH_SIZE*sizeof(index_slist_t));
3673
3674     vec_validate(cnat_session_hash, CNAT_SESSION_HASH_MASK);
3675     memset(cnat_session_hash, 0xff, CNAT_SESSION_HASH_SIZE*sizeof(index_slist_t));
3676
3677     n = CNAT_USER_DB_SIZE * 1.15;  /* use hash size as db size for LB margin */
3678     if (n % NUM_BITS_IN_UWORD)
3679         n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD));
3680
3681     pool_alloc(cgse_user_db,n);
3682     for(i=0; i< n; i++) {
3683         pool_get(cgse_user_db, comb_user);
3684     }
3685
3686     for(i=0; i< n; i++) {
3687         pool_put(cgse_user_db, cgse_user_db + i);
3688     }
3689
3690     cnat_user_db = &cgse_user_db->nat44_user_db;
3691
3692     vec_validate(cnat_user_hash, CNAT_USER_HASH_MASK);
3693     memset(cnat_user_hash, 0xff, CNAT_USER_HASH_SIZE*sizeof(index_slist_t));
3694
3695     n = CNAT_TIMEOUT_HASH_SIZE;  /* use hash size as db size for LB margin */
3696     for(i=0; i< n; i++) {
3697         pool_get(cnat_timeout_db, tdb);
3698     }
3699
3700     for(i=0; i< n; i++) {
3701         pool_put(cnat_timeout_db, cnat_timeout_db + i);
3702     }
3703
3704     vec_validate(cnat_timeout_hash, CNAT_TIMEOUT_HASH_MASK);
3705     memset(cnat_timeout_hash, 0xff, CNAT_TIMEOUT_HASH_SIZE*sizeof(index_slist_t));
3706
3707 #ifdef TOBE_PORTED
3708     for (i=0;i<CNAT_MAX_VRFMAP_ENTRIES; i++) {
3709         svi_params_array[i].svi_type = CGSE_SVI_TYPE_INFRA;
3710     }
3711 #endif
3712     cnat_db_init_done = 1;
3713     printf("CNAT DB init is successful\n");
3714     return;
3715     //return 0;
3716 }