2 *------------------------------------------------------------------
3 * cnat_db_v2.c - translation database definitions
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:
10 * http://www.apache.org/licenses/LICENSE-2.0
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 *------------------------------------------------------------------
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>
29 #include "cnat_config.h"
30 #include "cnat_global.h"
31 #include "cnat_v4_functions.h"
32 #include "cnat_log_api.h"
34 #include "spp_platform_trace_log.h"
35 #include "cnat_bulk_port.h"
37 #include "dslite_db.h"
38 #include "cnat_config_api.h"
40 #define HASH_TABLE_SIZE 8192 // hash table size
41 #define THROTTLE_TIME 180 // throttle time value for out of port msg/user
43 u8 cnat_db_init_done = 0;
46 u32 cached_next_index;
47 /* $$$$ add data here */
49 /* convenience variables */
50 vlib_main_t * vlib_main;
51 vnet_main_t * vnet_main;
54 cnat_db_v2_main_t cnat_db_v2_main;
57 /* TOBE_PORTED : Remove the following once fixed */
60 #define PREDICT_TRUE(x) (x)
61 #define PREDICT_FALSE(x) (x)
64 #define foreach_cnat_db_v2_error \
65 _(DROP, "error-drop packets")
68 #define _(sym,str) CNAT_DB_V2_##sym,
69 foreach_cnat_db_v2_error
74 static char * cnat_db_v2_error_strings[] __attribute__((unused)) = {
75 #define _(sym,string) string,
76 foreach_cnat_db_v2_error
81 void cnat_table_entry_fill_map(u32 start_addr, u32 end_addr,
82 cnat_portmap_v2_t **port_map_holder)
84 u32 this_start_addr, this_end_addr, this_addr, new;
87 cnat_portmap_v2_t *my_pm =0;
88 cnat_portmap_v2_t *pm = 0;
90 my_instance_number = 0;
92 this_start_addr = start_addr;
93 this_end_addr = end_addr;
96 * How many new addresses are getting added ??
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;
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);
109 /* Check whether the address pool add requested already exists */
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);
120 * For now give a warning message only....
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);
131 total_address_pool_allocated += new;
132 vec_add2(pm, my_pm, new);
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");
141 memset(my_pm, 0, new*sizeof(*my_pm));
142 this_addr = this_start_addr;
143 loop_count = 0; /* Sanity counter */
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);
149 my_pm->ipv4_address = this_addr;
151 * Set all bits to "1" indicating all ports are free
153 memset(my_pm->bm, 0xff,
154 (((BITS_PER_INST + BITS(uword)-1)/BITS(uword))*(sizeof(uword))));
155 //this_addr += MAX_CORES_PER_PARTITION;
161 * We should have loop_count same as the new value
163 if (loop_count != new) {
164 printf("Mismatch in loop_count (%d) != new (%d)\n",
168 *port_map_holder = pm;
170 #if DEBUG_NOT_COMMENTED
171 printf("revised pm len %d\n", vec_len(*port_map_holder));
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,
182 cnat_vrfmap_t *vrfmap);
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;
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;
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;
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;
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 */
210 * This is the pool of vrf map structures used by latest main-db functions
212 cnat_vrfmap_t *cnat_map_by_vrf;
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
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;
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; \
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); \
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); \
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
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) && \
265 udb->flags = udb->flags & (~CNAT_USER_DB_PORT_LIMIT_EXCEEDED); \
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*/
312 f64 port_log_timestamps[HASH_TABLE_SIZE]; /* 32 KB array per core */
314 void port_exceeded_msg_log (u32 src_addr, u16 i_vrf)
317 f64 current_timestamp;
318 vlib_main_t *vlib_main;
320 vlib_main = vlib_get_main();
321 current_timestamp = vlib_time_now((vlib_main_t *) vlib_main);
323 hash_value = ((src_addr >> 16) ^ ((src_addr & 0xffff) ^ i_vrf)) % (1024*8);
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);
335 static void log_port_alloc_error(cnat_errno_t error, cnat_key_t *k)
338 u32 arr[] = {k->k.vrf, k->k.ipv4, k->k.port};
341 case CNAT_NO_POOL_ANY:
342 error_code = CNAT_NO_POOL_FOR_ANY_ERROR;
344 case CNAT_NO_PORT_ANY:
345 error_code = CNAT_NO_PORT_FOR_ANY_ERROR;
347 case CNAT_ERR_PARSER:
348 error_code = CNAT_WRONG_PORT_ALLOC_TYPE;
350 case CNAT_BAD_INUSE_ANY:
351 error_code = CNAT_BAD_INUSE_ANY_ERROR;
353 case CNAT_BAD_INUSE_DIRECT:
354 error_code = CNAT_BAD_INUSE_DIRECT_ERROR;
356 case CNAT_NOT_FOUND_ANY:
357 error_code = CNAT_NOT_FOUND_ANY_ERROR;
359 case CNAT_NOT_FOUND_DIRECT:
360 error_code = CNAT_NOT_FOUND_DIRECT_ERROR;
362 case CNAT_INV_PORT_DIRECT:
363 error_code = CNAT_INV_PORT_FOR_DIRECT_ERROR;
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 */
370 spp_printf(error_code, 3, arr);
373 void cnat_db_debug_error(cnat_db_key_bucket_t *u_ki,
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);
386 u32 arg[] = {u_ki->k.k.vrf, u_ki->k.k.ipv4, u_ki->k.k.port};
387 spp_printf(error, 3, arg);
392 void dslite_db_debug_error(dslite_db_key_bucket_t *u_ki,
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);
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);
411 void cnat_db_debug_i2o_drop(cnat_db_key_bucket_t *ki)
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);
421 u32 arg[] = {ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port};
422 spp_printf(CNAT_PACKET_DROP_ERROR, 3, arg);
427 void cnat_db_in2out_hash_delete (cnat_main_db_entry_t *ep, cnat_user_db_entry_t *up)
431 cnat_main_db_entry_t *this, *prev;
434 if (PREDICT_FALSE(ep->flags & CNAT_DB_DSLITE_FLAG)) {
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}
439 DSLITE_V6_GET_HASH((&dk),
441 CNAT_MAIN_HASH_MASK);
442 DSLITE_PRINTF(1, "Delete1 DSL main hash bucket ..%u\n", bucket);
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);
449 CNAT_V4_GET_HASH(ep->in2out_key.key64,
450 bucket, CNAT_MAIN_HASH_MASK)
453 index = cnat_in2out_hash[bucket].next;
455 ASSERT(index != EMPTY);
459 this = cnat_main_db + index;
460 if (PREDICT_TRUE(this == ep)) {
462 cnat_in2out_hash[bucket].next = ep->in2out_hash.next;
465 prev->in2out_hash.next = ep->in2out_hash.next;
470 index = this->in2out_hash.next;
471 } while (index != EMPTY);
476 void cnat_db_out2in_hash_delete (cnat_main_db_entry_t *ep)
480 cnat_main_db_entry_t *this, *prev;
482 CNAT_V4_GET_HASH(ep->out2in_key.key64,
483 bucket, CNAT_MAIN_HASH_MASK)
485 index = cnat_out2in_hash[bucket].next;
487 ASSERT(index != EMPTY);
491 this = cnat_main_db + index;
492 if (PREDICT_TRUE(this == ep)) {
494 cnat_out2in_hash[bucket].next = ep->out2in_hash.next;
497 prev->out2in_hash.next = ep->out2in_hash.next;
502 index = this->out2in_hash.next;
503 } while (index != EMPTY);
508 cnat_main_db_entry_t*
509 cnat_main_db_lookup_entry(cnat_db_key_bucket_t *ki)
513 cnat_main_db_entry_t *db;
515 CNAT_V4_GET_HASH(ki->k.key64,
517 CNAT_MAIN_HASH_MASK);
519 index = cnat_in2out_hash[ki->bucket].next;
520 if (PREDICT_TRUE(index == EMPTY)) {
525 db = cnat_main_db + index;
526 if (PREDICT_TRUE(db->in2out_key.key64 == ki->k.key64)) {
529 index = db->in2out_hash.next;
530 } while (index != EMPTY);
535 void cnat_user_db_delete (cnat_user_db_entry_t *up)
539 cnat_user_db_entry_t *this, *prev;
541 if (PREDICT_FALSE(up->flags & CNAT_USER_DB_NAT64_FLAG) != 0) {
542 /* Preventive check - Not a NAT44 entry */
547 if(PREDICT_FALSE(up->flags & CNAT_USER_DB_DSLITE_FLAG)) {
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}}
553 DSLITE_V6_GET_HASH((&dk),
555 CNAT_USER_HASH_MASK);
556 DSLITE_PRINTF(1, "Delete1 DSL user hash bucket ..%u\n", bucket);
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);
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);
568 index = cnat_user_hash[bucket].next;
570 ASSERT(index != EMPTY);
574 this = cnat_user_db + index;
575 if (PREDICT_TRUE(this == up)) {
577 cnat_user_hash[bucket].next = up->user_hash.next;
580 prev->user_hash.next = up->user_hash.next;
585 index = this->user_hash.next;
586 } while (index != EMPTY);
591 pool_put(cnat_user_db, up);
594 cnat_user_db_entry_t*
595 cnat_user_db_lookup_entry(cnat_db_key_bucket_t *uki)
599 cnat_user_db_entry_t *udb=NULL;
601 CNAT_V4_GET_HASH(uki->k.key64,
605 /* now: index in user vector */
606 index = cnat_user_hash[uki->bucket].next;
607 if (PREDICT_TRUE(index != EMPTY)) {
609 udb = cnat_user_db + index;
610 if (PREDICT_FALSE(udb->key.key64 == uki->k.key64)) {
613 index = udb->user_hash.next;
614 } while (index != EMPTY);
619 cnat_user_db_entry_t*
620 cnat_user_db_create_entry(cnat_db_key_bucket_t *uki,
623 cnat_user_db_entry_t *udb = NULL;
625 pool_get(cnat_user_db, udb);
626 memset(udb, 0, sizeof(*udb));
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;
636 #ifndef NO_BULK_LOGGING
638 #endif /* NO_BULK_LOGGING */
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)
649 cnat_main_db_entry_t *db = NULL;
651 pool_get(cnat_main_db, db);
652 memset(db, 0, sizeof(*db));
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;
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)) {
669 * first port for this src vrf/src ip addr
671 udb->translation_list_head_index = db_index;
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),
682 CNAT_V4_GET_HASH(ko->k.key64,
685 db->out2in_hash.next = cnat_out2in_hash[ko->bucket].next;
686 cnat_out2in_hash[ko->bucket].next = db_index;
688 * setup i2o hash key, bucket is already calculate
690 db->in2out_hash.next = cnat_in2out_hash[ki->bucket].next;
691 cnat_in2out_hash[ki->bucket].next = db_index;
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);
704 NAT44_COMMON_STATS.active_translations++;
709 static inline void pptp_clear_all_channels(
710 cnat_main_db_entry_t *db)
712 u32 db_index, current_db_index;
713 cnat_main_db_entry_t *temp_db;
715 /* clear all channels */
717 db_index = db->proto_data.pptp_list.next;
718 current_db_index = db - cnat_main_db;
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;
730 db->proto_data.pptp_list.next = EMPTY;
733 void pptp_remove_channel_from_tunnel(cnat_main_db_entry_t *db) {
735 cnat_main_db_entry_t *prev_db, *next_db;
737 prev_db = cnat_main_db + db->proto_data.pptp_list.prev;
738 next_db = cnat_main_db + db->proto_data.pptp_list.next;
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 ;
746 if(db->proto_data.pptp_list.next != EMPTY) {
747 next_db->proto_data.pptp_list.prev
748 = db->proto_data.pptp_list.prev;
753 void cnat_delete_main_db_entry_v2 (cnat_main_db_entry_t *ep)
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;
766 pool_header_t *h = pool_header(cnat_user_db);
771 if (PREDICT_FALSE(ep->flags & CNAT_DB_NAT64_FLAG) != 0) {
772 /* Preventive check - Not a NAT44 entry */
776 if(PREDICT_FALSE(ep->flags &
777 CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE)) {
778 pptp_clear_all_channels(ep);
779 PPTP_DECR(active_tunnels);
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);
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
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);
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);
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
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);
816 spp_printf(CNAT_INV_UNUSED_USR_INDEX, 1, (u32 *) &(ep->user_index));
817 cnat_main_db_entry_dump(ep);
821 up = cnat_user_db + ep->user_index;
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);
834 STAT_PORT_RANGE_FROM_INST_PTR(&(dslite_table_db_ptr[instance]));
836 * Netflow logging API for delete event
839 BULKSIZE_FROM_VRFMAP(&(dslite_table_db_ptr[instance]));
841 if (PREDICT_FALSE(ep->vrfmap_index >= vrfmap_len)) {
842 #ifdef DEBUG_PRINTF_ENABLED
843 printf("invalid vrfmap index in db\n");
845 spp_printf(CNAT_INVALID_VRFMAP_INDEX, 0, NULL);
846 cnat_main_db_entry_dump(ep);
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);
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
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
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);
881 cnat_nfv9_log_mapping_delete(ep, my_vrfmap
882 #ifndef NO_BULK_LOGGING
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
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);
903 cnat_nfv9_ds_lite_mapping_delete(ep,
904 (dslite_table_db_ptr + instance)
905 #ifndef NO_BULK_LOGGING
911 cnat_syslog_ds_lite_mapping_delete(ep,
912 (dslite_table_db_ptr + instance), NULL
913 #ifndef NO_BULK_LOGGING
917 #endif /* TOBE_PORTED */
923 main_db_index = ep - cnat_main_db;
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
935 * reach max port limit, we can generate new icmp msg again
937 up->icmp_msg_count = 0;
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),
945 cnat_db_in2out_hash_delete(ep, up);
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);
961 cnat_user_db_delete(up);
965 /* Remove from main DB hashes */
966 //cnat_db_in2out_hash_delete(ep);
967 cnat_db_out2in_hash_delete(ep);
969 pool_put(cnat_main_db, ep);
971 if(PREDICT_FALSE(ep->flags & CNAT_DB_FLAG_STATIC_PORT)) {
972 nat44_dslite_common_stats[instance].num_static_translations--;
974 nat44_dslite_common_stats[instance].num_dynamic_translations--;
976 nat44_dslite_common_stats[instance].active_translations--;
977 nat44_dslite_global_stats[!!(instance - 1)].translation_delete_count ++;
980 cnat_main_db_entry_t*
981 cnat_main_db_lookup_entry_out2in (cnat_db_key_bucket_t *ko)
985 cnat_main_db_entry_t *db;
987 CNAT_V4_GET_HASH(ko->k.key64,
989 CNAT_MAIN_HASH_MASK);
991 index = cnat_out2in_hash[ko->bucket].next;
992 if (PREDICT_TRUE(index == EMPTY)) {
997 db = cnat_main_db + index;
998 if (PREDICT_TRUE(db->out2in_key.key64 == ko->k.key64)) {
1001 index = db->out2in_hash.next;
1002 } while (index != EMPTY);
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
1012 cnat_session_entry_t *cnat_handle_1to2_session(
1013 cnat_main_db_entry_t *mdb,
1014 cnat_key_t *dest_info)
1016 cnat_key_t old_dest_info;
1018 u32 free_session = 0;
1020 cnat_session_entry_t *session_db1 = NULL, *session_db2 = NULL;
1022 h = pool_header(cnat_session_db);
1023 free_session = vec_len(h->free_indices) - 1;
1025 if (PREDICT_FALSE(free_session < 2)) {
1026 if (mdb->flags & CNAT_DB_DSLITE_FLAG) {
1027 instance = mdb->dslite_nat44_inst_id;
1029 instance = NAT44_RESERVED_INST_ID;
1032 /* we need 2 sessions here, return NULL */
1033 nat44_dslite_common_stats[instance].drops_sessiondb_limit_exceeded++;
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;
1041 /* create 2 new sessions */
1042 session_db1 = cnat_create_session_db_entry(&old_dest_info,
1045 if(PREDICT_FALSE(session_db1 == NULL)) {
1049 /* update pkt info to session 2 */
1050 session_db2 = cnat_create_session_db_entry(dest_info,
1053 if(PREDICT_FALSE(session_db2 == NULL)) {
1054 cnat_delete_session_db_entry(session_db1, FALSE);
1057 /* update main db info to session 1 */
1058 cnat_dest_update_main2session(mdb, session_db1);
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
1068 void cnat_add_dest_n_log(
1069 cnat_main_db_entry_t *mdb,
1070 cnat_key_t *dest_info)
1073 if(PREDICT_FALSE(mdb->nsessions != 0)) {
1074 return; /* Should not have been called */
1077 mdb->dst_ipv4 = dest_info->k.ipv4;
1078 mdb->dst_port = dest_info->k.port;
1080 mdb->entry_expires = cnat_current_time;
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);
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);
1095 * this function is called by exception node
1096 * when lookup is fialed in i2o node
1098 * if reash per user port limit,
1099 * set user_db_entry pointer, and error == CNAT_OUT_LIMIT
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)
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;
1121 cnat_portmap_v2_t *my_pm = 0;
1123 #ifndef NO_BULK_LOGGING
1124 int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
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.
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
1141 if(PREDICT_FALSE((!dest_info->k.ipv4) && (!dest_info->k.port))) {
1142 return db; /* if dest_info is null don't create session */
1144 if(PREDICT_TRUE((db->dst_ipv4 == dest_info->k.ipv4) &&
1145 (db->dst_port == dest_info->k.port))) {
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);
1157 info->error = CNAT_ERR_NO_SESSION_DB;
1160 } else if(PREDICT_FALSE(db->nsessions == 0)) {
1161 /* Should be static entry.. should never happen
1163 if(PREDICT_TRUE(dest_info->k.ipv4 != 0)) {
1164 cnat_add_dest_n_log(db, dest_info);
1168 /* The src has already created multiple sessions.. very rare
1170 session_db2 = cnat_create_session_db_entry(dest_info,
1172 if(PREDICT_TRUE(session_db2 != NULL)) {
1173 CNAT_DB_TIMEOUT_RST(session_db2);
1176 info->error = CNAT_ERR_NO_SESSION_DB;
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
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;
1195 my_vrfmap_index = vrf_map_array[u_ki.k.k.vrf];
1196 my_vrfmap = cnat_map_by_vrf + my_vrfmap_index;
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));
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);
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);
1218 pm = my_vrfmap->portmap_list;
1220 port_limit = my_vrfmap->port_limit;
1221 if(PREDICT_FALSE(!port_limit)) {
1222 port_limit = cnat_main_db_max_ports_per_user;
1225 * set o2i key with protocl bits
1227 ko.k.k.vrf = my_vrfmap->o_vrf | protocol;
1230 * step 2. check if src vrf, src ip addr is alreay
1232 * if yes, use PORT_ALLOC_DIRECTED
1233 * if no, use PORT_ALLOC_ANY since it is first time
1235 udb = cnat_user_db_lookup_entry(&u_ki);
1236 if (PREDICT_TRUE(udb)) {
1238 * not first time allocate port for this user
1241 if (PREDICT_FALSE(udb->ntranslations >=
1243 /* Check for the port type here. If we are getting
1244 * a STATIC PORT, allow the config.
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);
1258 CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb,
1262 * check if main db has space to accomodate new entry
1264 h = pool_header(cnat_main_db);
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)
1273 current_timestamp = spp_trace_log_get_unix_time_in_seconds();
1274 if (PREDICT_FALSE((current_timestamp - last_log_timestamp) >
1276 spp_printf(CNAT_SESSION_THRESH_EXCEEDED, 0, NULL);
1277 last_log_timestamp = current_timestamp;
1281 printf("Limit reached : OLD USER");
1287 * allocate port, from existing mapping
1289 my_index = udb->portmap_index;
1291 if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
1292 rv = cnat_static_port_alloc_v2_bulk(pm,
1293 PORT_ALLOC_DIRECTED,
1300 cnat_static_port_range
1301 #ifndef NO_BULK_LOGGING
1303 udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1306 , my_vrfmap->ip_n_to_1
1309 } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP) ) {
1311 rv = cnat_dynamic_port_alloc_v2_bulk(pm,
1312 PORT_ALLOC_DIRECTED,
1317 cnat_static_port_range
1318 #ifndef NO_BULK_LOGGING
1320 udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1323 , my_vrfmap->ip_n_to_1,
1324 &(my_vrfmap->rseed_ip)
1329 * For RTSP, two translation entries are created,
1330 * check if main db has space to accomodate two new entry
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)
1341 rv = cnat_dynamic_port_alloc_rtsp_bulk(pm,
1342 PORT_ALLOC_DIRECTED,
1348 cnat_static_port_range
1349 #ifndef NO_BULK_LOGGING
1351 udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1354 , &(my_vrfmap->rseed_ip)
1360 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
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));
1369 * increment port in use for this user
1371 udb->ntranslations += 1;
1375 * first time allocate port for this user
1379 * Do not create entry if port limit is invalid
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)
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.
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;
1405 * If either main_db or user_db does not have entries
1406 * bail out, with appropriate error
1408 if (PREDICT_FALSE(!(free_main && free_user))) {
1411 info->error = CNAT_USER_DB_LIMIT;
1412 log_error = CNAT_USER_DB_LIMIT_ERROR;
1414 info->error = CNAT_MAIN_DB_LIMIT;
1415 log_error = CNAT_MAIN_DB_LIMIT_ERROR;
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);
1424 if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
1425 rv = cnat_static_port_alloc_v2_bulk(pm,
1433 cnat_static_port_range
1434 #ifndef NO_BULK_LOGGING
1436 udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1439 , my_vrfmap->ip_n_to_1
1442 } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP)) {
1443 rv = cnat_dynamic_port_alloc_v2_bulk(pm,
1449 cnat_static_port_range
1450 #ifndef NO_BULK_LOGGING
1451 , NULL, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1454 , my_vrfmap->ip_n_to_1,
1455 &(my_vrfmap->rseed_ip)
1459 * For RTSP, two translation entries are created,
1460 * check if main db has space to accomodate two new entry
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)
1472 rv = cnat_dynamic_port_alloc_rtsp_bulk(pm,
1479 cnat_static_port_range
1480 #ifndef NO_BULK_LOGGING
1481 , NULL, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1484 , &(my_vrfmap->rseed_ip)
1486 /* TODO: Add the port pair flag here */
1492 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
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));
1501 * create entry in user db
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);
1514 PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has "
1515 "reached MAX PORTS_PER_ADDR");
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));
1522 #endif /* #ifndef NO_BULK_LOGGING */
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
1533 db = cnat_create_main_db_entry_and_hash(ki, &ko, udb);
1535 translation_create_count ++;
1537 db->dslite_nat44_inst_id = NAT44_RESERVED_INST_ID;
1539 db->vrfmap_index = my_vrfmap - cnat_map_by_vrf;
1542 * don't forget logging
1543 * logging API is unconditional,
1544 * logging configuration check is done inside the inline function
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)) {
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);
1560 cnat_nfv9_log_mapping_create(db, my_vrfmap
1561 #ifndef NO_BULK_LOGGING
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
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;
1580 new_ki.k.k.port += 1;
1583 CNAT_V4_GET_HASH(new_ki.k.key64, new_ki.bucket,
1584 CNAT_MAIN_HASH_MASK);
1586 db2 = cnat_create_main_db_entry_and_hash(&new_ki, &ko, udb);
1588 translation_create_count ++;
1590 db2->dslite_nat44_inst_id = NAT44_RESERVED_INST_ID;
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 */
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);
1607 cnat_nfv9_log_mapping_create(db2, my_vrfmap
1608 #ifndef NO_BULK_LOGGING
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
1628 * this function is called from config handler only
1629 * to allocate a static port based db entry
1631 * the actual mapped address and port are already specified
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)
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;
1649 #ifndef NO_BULK_LOGGING
1650 int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
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.
1658 info->gen_icmp_msg = CNAT_NO_ICMP_MSG;
1659 info->error = CNAT_SUCCESS;
1660 db = cnat_main_db_lookup_entry(ki);
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
1667 if (PREDICT_FALSE(db)) {
1669 if (db->flags & CNAT_DB_FLAG_STATIC_PORT) {
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)) {
1675 #ifdef DEBUG_PRINTF_ENABLED
1676 printf("Same Static Port Exists ki 0x%16llx ko 0x%16llx",
1680 * We have already programmed this, return
1686 * We already have a static port with different mapping
1687 * Return an error for this case.
1689 info->error = CNAT_ERR_PARSER;
1691 #ifdef DEBUG_PRINTF_ENABLED
1692 printf("Static Port Existing and Diff ki 0x%16llx ko 0x%16llx",
1693 ki, db->out2in_key);
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);
1703 #ifdef DEBUG_PRINTF_ENABLED
1704 printf("Deleting Dynamic entry ki 0x%16llx ko 0x%16llx",
1705 ki, db->out2in_key);
1709 * If for some reason we have dynamic entries, just delete them
1712 cnat_delete_main_db_entry_v2(db);
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;
1722 pm = my_vrfmap->portmap_list;
1725 * check if src vrf, src ip addr is already
1727 * if yes, use PORT_ALLOC_DIRECTED
1728 * if no, use PORT_ALLOC_ANY since it is first time
1730 udb = cnat_user_db_lookup_entry(&u_ki);
1731 if (PREDICT_TRUE(udb)) {
1733 * check if main db has space to accomodate new entry
1735 h = pool_header(cnat_main_db);
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)
1744 printf("Limit reached : OLD USER");
1746 spp_printf(CNAT_MAIN_DB_LIMIT_ERROR, 0, 0);
1751 * allocate port, from existing mapping
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
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);
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));
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);
1778 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1780 in2out_drops_resource_depletion ++;
1781 CNAT_SET_ICMP_MSG_INFO
1782 CNAT_DEBUG_INSIDE_ERR(rv)
1786 * create entry in user db
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);
1798 PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has "
1799 "reached MAX PORTS_PER_ADDR");
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 */
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);
1813 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1815 CNAT_SET_ICMP_MSG_INFO
1816 CNAT_DEBUG_INSIDE_ERR(rv)
1817 log_port_alloc_error(rv, &(ki->k));
1822 * increment port in use for this user
1824 udb->ntranslations += 1;
1827 if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) {
1828 printf ("Static port alloc any\n");
1831 * first time allocate port for this user
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.
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;
1846 * If either main_db or user_db does not have entries
1847 * bail out, with appropriate error
1849 if (PREDICT_FALSE(!(free_main && free_user))) {
1852 info->error = CNAT_USER_DB_LIMIT;
1853 log_error = CNAT_USER_DB_LIMIT_ERROR;
1855 info->error = CNAT_MAIN_DB_LIMIT;
1856 log_error = CNAT_MAIN_DB_LIMIT_ERROR;
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);
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);
1870 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
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));
1879 * create entry in user db
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);
1891 PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has "
1892 "reached MAX PORTS_PER_ADDR");
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 */
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
1908 db = cnat_create_main_db_entry_and_hash(ki, ko, udb);
1910 translation_create_count ++;
1911 db->vrfmap_index = my_vrfmap - cnat_map_by_vrf;
1914 * don't forget logging
1915 * logging API is unconditional,
1916 * logging configuration check is done inside the inline function
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
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
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
1943 cnat_main_db_entry_t*
1944 dslite_main_db_lookup_entry(dslite_db_key_bucket_t *ki);
1946 cnat_user_db_entry_t*
1947 dslite_user_db_lookup_entry(dslite_db_key_bucket_t *uki);
1949 cnat_user_db_entry_t*
1950 dslite_user_db_create_entry(dslite_db_key_bucket_t *uki, u32 portmap_index);
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);
1959 * this function is called from config handler only
1960 * to allocate a static port based db entry
1962 * the actual mapped address and port are already specified
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)
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;
1980 u16 dslite_id = dslite_entry_ptr->dslite_id;
1981 #ifndef NO_BULK_LOGGING
1982 int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
1984 cnat_vrfmap_t *my_vrfmap =0;
1985 u16 my_vrfmap_index;
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.
1992 info->gen_icmp_msg = CNAT_NO_ICMP_MSG;
1993 info->error = CNAT_SUCCESS;
1994 db = dslite_main_db_lookup_entry(ki);
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
2001 if (PREDICT_FALSE(db)) {
2003 if (db->flags & CNAT_DB_FLAG_STATIC_PORT) {
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)) {
2009 #ifdef DEBUG_PRINTF_ENABLED
2010 printf("Same Static Port Exists ki 0x%16llx ko 0x%16llx",
2014 * We have already programmed this, return
2020 * We already have a static port with different mapping
2021 * Return an error for this case.
2023 info->error = CNAT_ERR_PARSER;
2025 #ifdef DEBUG_PRINTF_ENABLED
2026 printf("Static Port Existing and Diff ki 0x%16llx ko 0x%16llx",
2027 ki, db->out2in_key);
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);
2037 #ifdef DEBUG_PRINTF_ENABLED
2038 printf("Deleting Dynamic entry ki 0x%16llx ko 0x%16llx",
2039 ki, db->out2in_key);
2043 * If for some reason we have dynamic entries, just delete them
2046 cnat_delete_main_db_entry_v2(db);
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];
2061 my_vrfmap_index = vrf_map_array[u_ki.dk.ipv4_key.k.vrf];
2062 my_vrfmap = cnat_map_by_vrf + my_vrfmap_index;
2064 pm = dslite_entry_ptr->portmap_list;
2067 * check if src vrf, src ip addr is already
2069 * if yes, use PORT_ALLOC_DIRECTED
2070 * if no, use PORT_ALLOC_ANY since it is first time
2072 udb = dslite_user_db_lookup_entry(&u_ki);
2073 if (PREDICT_TRUE(udb)) {
2075 * check if main db has space to accomodate new entry
2077 h = pool_header(cnat_main_db);
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)
2085 printf("Limit reached : OLD USER");
2087 spp_printf(CNAT_MAIN_DB_LIMIT_ERROR, 0, 0);
2092 * allocate port, from existing mapping
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
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);
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));
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);
2119 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
2121 nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
2122 DSLITE_DEBUG_INSIDE_ERR(rv)
2126 * create entry in user db
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));
2135 #endif /* #ifndef NO_BULK_LOGGING */
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);
2143 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
2145 DSLITE_DEBUG_INSIDE_ERR(rv)
2146 log_port_alloc_error(rv, &(ki->dk.ipv4_key));
2151 * increment port in use for this user
2153 udb->ntranslations += 1;
2156 if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) {
2157 printf ("Static port alloc any\n");
2160 * first time allocate port for this user
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.
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;
2175 * If either main_db or user_db does not have entries
2176 * bail out, with appropriate error
2178 if (PREDICT_FALSE(!(free_main && free_user))) {
2181 info->error = CNAT_USER_DB_LIMIT;
2182 log_error = CNAT_USER_DB_LIMIT_ERROR;
2184 info->error = CNAT_MAIN_DB_LIMIT;
2185 log_error = CNAT_MAIN_DB_LIMIT_ERROR;
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);
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);
2198 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
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));
2206 * create entry in user db
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));
2215 #endif /* #ifndef NO_BULK_LOGGING */
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
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++;
2231 * don't forget logging
2232 * logging API is unconditional,
2233 * logging configuration check is done inside the inline function
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
2240 #endif /* #if 0 - this has to be removed later */
2244 #endif /* TOBE_PORTED */
2247 /* Per port/ip timeout related routines */
2249 u32 cnat_timeout_db_hash_lookup (cnat_key_t t_key)
2254 cnat_timeout_db_entry_t *db;
2256 key.k.ipv4 = t_key.k.ipv4;
2257 key.k.port = t_key.k.port;
2258 key.k.vrf = t_key.k.vrf;
2260 CNAT_V4_GET_HASH(key.key64,
2261 index, CNAT_TIMEOUT_HASH_MASK)
2264 index = cnat_timeout_hash[index].next;
2266 if (PREDICT_FALSE(index == EMPTY))
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)))
2274 index = db->t_hash.next;
2275 } while (index != EMPTY);
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
2285 query_and_update_db_timeout(void *db, u8 db_type)
2287 cnat_key_t t_search_key;
2289 cnat_timeout_db_entry_t *timeout_db_entry;
2293 cnat_main_db_entry_t *mdb = NULL;
2294 cnat_session_entry_t *sdb = NULL;
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;
2304 h = pool_header(cnat_timeout_db);
2305 free = vec_len(h->free_indices) - 1;
2307 if(free == CNAT_TIMEOUT_HASH_SIZE) {
2308 /* No timeout db configured */
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;
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;
2323 index = cnat_timeout_db_hash_lookup(t_search_key);
2325 if(index == EMPTY) {
2326 /* Search for port map */
2327 t_search_key.k.ipv4 = 0;
2329 index = cnat_timeout_db_hash_lookup(t_search_key);
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;
2336 t_search_key.k.ipv4 = sdb->v4_dest_key.k.ipv4;
2338 t_search_key.k.port = 0;
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");
2347 #ifdef DEBUG_PRINTF_ENABLED
2348 printf("%s: port only map sucess\n", "query_and_update_db_timeout");
2353 #ifdef DEBUG_PRINTF_ENABLED
2354 printf("%s: ip port map sucess\n","query_and_update_db_timeout");
2359 if(index == EMPTY) {
2360 /* No match found, clear timeout */
2361 if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) {
2366 #ifdef DEBUG_PRINTF_ENABLED
2367 printf("%s: No match\n","query_and_update_db_timeout");
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;
2375 sdb->timeout = timeout_db_entry->t_key.timeout_value;
2377 return timeout_db_entry->t_key.timeout_value;
2385 void cnat_timeout_db_hash_add (cnat_timeout_db_entry_t *t_entry)
2390 cnat_key_t t_key = t_entry->t_key.timeout_key;
2392 key.k.ipv4 = t_key.k.ipv4;
2393 key.k.port = t_key.k.port;
2394 key.k.vrf = t_key.k.vrf;
2396 CNAT_V4_GET_HASH(key.key64,
2397 bucket, CNAT_TIMEOUT_HASH_MASK)
2400 index = cnat_timeout_hash[bucket].next;
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;
2410 cnat_timeout_db_create (cnat_timeout_t t_entry)
2412 cnat_timeout_db_entry_t *db;
2413 cnat_key_t t_key = t_entry.timeout_key;
2419 db_index = cnat_timeout_db_hash_lookup(t_key);
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;
2428 h = pool_header(cnat_timeout_db);
2429 free = vec_len(h->free_indices) - 1;
2432 return CNAT_OUT_LIMIT;
2436 pool_get(cnat_timeout_db, db);
2439 memset(db, 0, sizeof(*db));
2441 db_index = db - cnat_timeout_db;
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;
2449 cnat_timeout_db_hash_add(db);
2450 return CNAT_SUCCESS;
2453 void cnat_timeout_db_delete(cnat_key_t t_key)
2458 cnat_timeout_db_entry_t *this, *prev;
2460 key.k.ipv4 = t_key.k.ipv4;
2461 key.k.port = t_key.k.port;
2462 key.k.vrf = t_key.k.vrf;
2465 CNAT_V4_GET_HASH(key.key64,
2466 bucket, CNAT_TIMEOUT_HASH_MASK)
2469 index = cnat_timeout_hash[bucket].next;
2471 if(index == EMPTY) return;
2475 this = cnat_timeout_db + index;
2477 (this->t_key.timeout_key.key64 & CNAT_TIMEOUT_FULL_MASK) ==
2478 (key.key64 & CNAT_TIMEOUT_FULL_MASK))) {
2480 cnat_timeout_hash[bucket].next = this->t_hash.next;
2483 prev->t_hash.next = this->t_hash.next;
2489 index = this->t_hash.next;
2490 } while (index != EMPTY);
2492 if(index == EMPTY) return;
2495 pool_put(cnat_timeout_db, this);
2499 void cnat_session_db_hash_delete (cnat_session_entry_t *ep)
2503 cnat_session_entry_t *this, *prev;
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)
2510 index = cnat_session_hash[bucket].next;
2512 ASSERT(index != EMPTY);
2516 this = cnat_session_db + index;
2517 if (PREDICT_TRUE(this == ep)) {
2519 cnat_session_hash[bucket].next =
2520 ep->cnat_session_hash.next;
2523 prev->cnat_session_hash.next =
2524 ep->cnat_session_hash.next;
2529 index = this->cnat_session_hash.next;
2530 } while (index != EMPTY);
2536 cnat_session_entry_t *
2537 cnat_session_db_edm_lookup_entry(cnat_key_t *ko,u32 session_head_index,
2541 cnat_session_entry_t *db;
2544 index = session_head_index;
2545 if (PREDICT_TRUE(index == EMPTY)) {
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))) {
2557 index = db->cnat_session_hash.next;
2558 } while (index != EMPTY);
2565 cnat_session_entry_t *
2566 cnat_session_db_lookup_entry(cnat_key_t *ko,u32 main_db_index)
2570 cnat_session_entry_t *db;
2572 CNAT_V4_GET_SESSION_HASH(main_db_index, ko->k.ipv4, ko->k.port,
2573 ko->k.vrf, bucket, CNAT_SESSION_HASH_MASK)
2576 index = cnat_session_hash[bucket].next;
2577 if (PREDICT_TRUE(index == EMPTY)) {
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))) {
2590 index = db->cnat_session_hash.next;
2591 } while (index != EMPTY);
2596 cnat_session_entry_t *
2597 cnat_create_session_db_entry(cnat_key_t *ko,
2598 cnat_main_db_entry_t *bdb, u8 log)
2601 u32 db_index, bucket_out;
2602 cnat_session_entry_t *db = NULL;
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");*/
2613 h = pool_header(cnat_session_db);
2614 free_session = vec_len(h->free_indices) - 1;
2616 if (bdb->flags & CNAT_DB_DSLITE_FLAG) {
2617 instance = bdb->dslite_nat44_inst_id;
2619 instance = NAT44_RESERVED_INST_ID;
2622 if (PREDICT_FALSE(!free_session)) {
2623 nat44_dslite_common_stats[instance].drops_sessiondb_limit_exceeded++;
2627 if( PREDICT_FALSE(bdb->nsessions == CNAT_MAX_SESSIONS_PER_BIB)) {
2628 /* printf("Create Session - Max sessions per BIB reached\n"); */
2632 pool_get(cnat_session_db, db);
2633 memset(db, 0, sizeof(*db));
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;
2640 db->main_list.next = db_index;
2641 db->main_list.prev = db_index;
2642 db->main_db_index = bdb - cnat_main_db;
2644 db->tcp_seq_num = 0;
2648 if(PREDICT_FALSE(log)) {
2650 query_and_update_db_timeout(db, SESSION_DB_TYPE);
2653 if (PREDICT_FALSE(bdb->nsessions == 1)) {
2655 * first port for this src vrf/src ip addr
2657 bdb->session_head_index = db_index;
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),
2666 * setup o2i hash key
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)
2672 db->cnat_session_hash.next =
2673 cnat_session_hash[bucket_out].next;
2674 cnat_session_hash[bucket_out].next = db_index;
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);
2682 cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + bdb->vrfmap_index;
2683 cnat_session_log_nat44_mapping_create(bdb, db, my_vrfmap);
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++;
2695 cnat_dest_update_main2session(cnat_main_db_entry_t *mdb,
2696 cnat_session_entry_t *sdb)
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;
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);
2710 mdb->entry_expires = 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;
2723 cnat_dest_update_session2main(cnat_main_db_entry_t *mdb,
2724 cnat_session_entry_t *sdb)
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;
2738 mdb->dst_ipv4 = sdb->v4_dest_key.k.ipv4;
2739 mdb->dst_port = sdb->v4_dest_key.k.port;
2742 void cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log)
2744 u32 session_db_index;
2746 cnat_main_db_entry_t *be =0;
2747 cnat_session_entry_t *sdb_last = NULL;
2750 if (PREDICT_FALSE(ep->flags & CNAT_DB_NAT64_FLAG) != 0) {
2751 /* Preventive check - Not a NAT44 entry */
2755 pool_header_t *h = pool_header(cnat_main_db);
2757 /* Validate .. just in case we are trying to delete a non existing one */
2758 bdb_len = vec_len(cnat_main_db);
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
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);
2769 spp_printf(CNAT_INV_UNUSED_USR_INDEX, 1, (u32 *) &(ep->main_db_index));
2773 be = cnat_main_db + ep->main_db_index;
2775 session_db_index = ep - cnat_session_db;
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),
2783 if (be->flags & CNAT_DB_DSLITE_FLAG) {
2784 instance = be->dslite_nat44_inst_id;
2786 instance = NAT44_RESERVED_INST_ID;
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);
2794 cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + be->vrfmap_index;
2795 cnat_session_log_nat44_mapping_delete(be, ep, my_vrfmap);
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
2806 sdb_last = cnat_session_db + be->session_head_index;
2807 ASSERT(sdb_last != NULL);
2809 cnat_dest_update_session2main(be, sdb_last);
2810 cnat_delete_session_db_entry(sdb_last, FALSE);
2813 /* Remove from session DB hashes */
2814 cnat_session_db_hash_delete(ep);
2815 nat44_dslite_common_stats[instance].sessions--;
2817 pool_put(cnat_session_db, ep);
2820 cnat_main_db_entry_t*
2821 dslite_main_db_lookup_entry(dslite_db_key_bucket_t *ki)
2825 cnat_main_db_entry_t *db;
2826 cnat_user_db_entry_t *userdb;
2828 DSLITE_V6_GET_HASH((&(ki->dk)),
2830 CNAT_MAIN_HASH_MASK);
2832 DSLITE_PRINTF(1,"MDBLU hash..%u\n", ki->bucket);
2834 index = cnat_in2out_hash[ki->bucket].next;
2835 if (PREDICT_TRUE(index == EMPTY)) {
2836 DSLITE_PRINTF(1,"MDBLU index MT..\n");
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
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);
2855 index = db->in2out_hash.next;
2856 } while (index != EMPTY);
2858 DSLITE_PRINTF(1,"MDBLU Entry does not exist..\n");
2862 cnat_user_db_entry_t*
2863 dslite_user_db_lookup_entry(dslite_db_key_bucket_t *uki)
2867 cnat_user_db_entry_t *udb=NULL;
2869 DSLITE_V6_GET_HASH((&(uki->dk)),
2871 CNAT_USER_HASH_MASK)
2873 DSLITE_PRINTF(1,"UDBLU hash..%u\n", uki->bucket);
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");
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);
2889 index = udb->user_hash.next;
2890 } while (index != EMPTY);
2892 DSLITE_PRINTF(1,"UDBLU Entry doesnt exist..\n");
2896 cnat_user_db_entry_t*
2897 dslite_user_db_create_entry(dslite_db_key_bucket_t *uki,
2900 cnat_user_db_entry_t *udb = NULL;
2902 pool_get(cnat_user_db, udb);
2903 memset(udb, 0, sizeof(*udb));
2905 udb->ntranslations = 1;
2906 udb->portmap_index = portmap_index;
2907 // udb->key.key64 = uki->k.key64;
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];
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;
2921 #ifndef NO_BULK_LOGGING
2922 INIT_BULK_CACHE(udb)
2923 #endif /* NO_BULK_LOGGING */
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)
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)
2944 cnat_main_db_entry_t *db = NULL;
2946 pool_get(cnat_main_db, db);
2947 memset(db, 0, sizeof(*db));
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;
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;
2963 if (PREDICT_FALSE(udb->ntranslations == 1)) {
2965 * first port for this src vrf/src ip addr
2967 udb->translation_list_head_index = db_index;
2968 DSLITE_PRINTF(1,"First translation of this user..\n");
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),
2977 * setup o2i hash key
2979 CNAT_V4_GET_HASH(ko->k.key64,
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;
2985 * setup i2o hash key, bucket is already calculate
2987 db->in2out_hash.next = cnat_in2out_hash[ki->bucket].next;
2988 cnat_in2out_hash[ki->bucket].next = db_index;
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);
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);
3005 //nat44_dslite_common_stats[DSLITE_COMMON_STATS].active_translations++;
3010 static inline void handle_dslite_port_exceeded_logging(
3011 cnat_user_db_entry_t *udb,
3013 dslite_table_entry_t *dslite_entry_ptr)
3016 if(PREDICT_TRUE(udb->flags & CNAT_USER_DB_PORT_LIMIT_EXCEEDED)) {
3017 /* Already logged ..*/
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);
3028 inline void handle_cnat_port_exceeded_logging(
3029 cnat_user_db_entry_t *udb,
3031 cnat_vrfmap_t *vrfmap)
3034 if(PREDICT_TRUE(udb->flags & CNAT_USER_DB_PORT_LIMIT_EXCEEDED)) {
3035 /* Already logged ..*/
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);
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)
3058 * this function is called by exception node
3059 * when lookup is fialed in i2o node
3061 * if reash per user port limit,
3062 * set user_db_entry pointer, and error == CNAT_OUT_LIMIT
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)
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;
3084 u16 dslite_id = dslite_entry_ptr->dslite_id;
3086 #ifndef NO_BULK_LOGGING
3087 int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
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.
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
3102 if(PREDICT_FALSE((!dest_info->k.ipv4) && (!dest_info->k.port))) {
3103 return db; /* if dest_info is null don't create session */
3106 if(PREDICT_TRUE((db->dst_ipv4 == dest_info->k.ipv4) &&
3107 (db->dst_port == dest_info->k.port))) {
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);
3119 info->error = CNAT_ERR_NO_SESSION_DB;
3122 } else if(PREDICT_FALSE(db->nsessions == 0)) {
3123 /* Should be static entry.. should never happen
3125 if(PREDICT_TRUE(dest_info->k.ipv4 != 0)) {
3126 cnat_add_dest_n_log(db, dest_info);
3130 /* The src has already created multiple sessions.. very rare
3132 session_db2 = cnat_create_session_db_entry(dest_info,
3134 if(PREDICT_TRUE(session_db2 != NULL)) {
3135 CNAT_DB_TIMEOUT_RST(session_db2);
3138 info->error = CNAT_ERR_NO_SESSION_DB;
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
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;
3158 * Inside ipv4 address should be masked, if port limit
3159 * need to be done at B4 element level.
3161 u_ki.dk.ipv4_key.k.ipv4 = 0;
3163 u_ki.dk.ipv4_key.k.port = 0;
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];
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
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));
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);
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);
3198 dslite_inst_ptr = dslite_nat44_config_table[dslite_inst_id];
3200 pm = dslite_entry_ptr->portmap_list;
3201 //pm = my_vrfmap->portmap_list;
3204 * set o2i key with protocl bits
3206 ko.k.k.vrf = dslite_entry_ptr->o_vrf | protocol;
3207 //ko.k.k.vrf = my_vrfmap->o_vrf | protocol;
3210 * step 2. check if src vrf, src ip addr is alreay
3212 * if yes, use PORT_ALLOC_DIRECTED
3213 * if no, use PORT_ALLOC_ANY since it is first time
3215 udb = dslite_user_db_lookup_entry(&u_ki);
3216 if (PREDICT_TRUE(udb)) {
3218 * not first time allocate port for this user
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))
3225 /* Check for the port type here. If we are getting
3226 * a STATIC PORT, allow the config.
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);
3240 CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb,
3241 dslite_entry_ptr->cnat_main_db_max_ports_per_user)
3244 * check if main db has space to accomodate new entry
3246 h = pool_header(cnat_main_db);
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)
3254 current_timestamp = spp_trace_log_get_unix_time_in_seconds();
3255 if (PREDICT_FALSE((current_timestamp - last_log_timestamp) >
3257 spp_printf(CNAT_SESSION_THRESH_EXCEEDED, 0, NULL);
3258 last_log_timestamp = current_timestamp;
3262 printf("Limit reached : OLD USER");
3268 * allocate port, from existing mapping
3270 my_index = udb->portmap_index;
3272 if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
3273 rv = cnat_static_port_alloc_v2_bulk(pm,
3274 PORT_ALLOC_DIRECTED,
3276 ki->dk.ipv4_key.k.ipv4,
3277 ki->dk.ipv4_key.k.port,
3281 STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3282 #ifndef NO_BULK_LOGGING
3284 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3287 , my_vrfmap->ip_n_to_1
3289 } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP) ) {
3291 rv = cnat_dynamic_port_alloc_v2_bulk(pm,
3292 PORT_ALLOC_DIRECTED,
3297 STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3298 #ifndef NO_BULK_LOGGING
3300 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3304 &(dslite_entry_ptr->rseed_ip)
3306 DSLITE_PRINTF(1,"D_PORT_ALLOC %x %u\n", ko.k.k.ipv4, ko.k.k.port);
3309 * For RTSP, two translation entries are created,
3310 * check if main db has space to accomodate two new entry
3312 free_main = free_main - 1;
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)
3322 rv = cnat_dynamic_port_alloc_rtsp_bulk(pm,
3323 PORT_ALLOC_DIRECTED,
3325 ki->dk.ipv4_key.k.port,
3329 STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3330 #ifndef NO_BULK_LOGGING
3332 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3335 , &(dslite_entry_ptr->rseed_ip)
3340 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
3341 DSLITE_PRINTF(1,"D_PORT_ALLOC port alloc error\n");
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));
3349 * increment port in use for this user
3351 udb->ntranslations += 1;
3354 * first time allocate port for this user
3358 * Do not create entry if port limit is invalid
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)
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.
3376 h = pool_header(cnat_main_db);
3377 free_main = vec_len(h->free_indices) - 1;
3379 h = pool_header(cnat_user_db);
3380 free_user = vec_len(h->free_indices) - 1;
3383 * If either main_db or user_db does not have entries
3384 * bail out, with appropriate error
3386 if (PREDICT_FALSE(!(free_main && free_user))) {
3389 info->error = CNAT_USER_DB_LIMIT;
3390 log_error = CNAT_USER_DB_LIMIT_ERROR;
3392 info->error = CNAT_MAIN_DB_LIMIT;
3393 log_error = CNAT_MAIN_DB_LIMIT_ERROR;
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);
3401 if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
3402 rv = cnat_static_port_alloc_v2_bulk(pm,
3405 ki->dk.ipv4_key.k.ipv4,
3406 ki->dk.ipv4_key.k.port,
3410 STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3411 #ifndef NO_BULK_LOGGING
3413 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3416 , my_vrfmap->ip_n_to_1
3419 } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP)) {
3420 rv = cnat_dynamic_port_alloc_v2_bulk(pm,
3426 STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3427 #ifndef NO_BULK_LOGGING
3429 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3433 &(dslite_entry_ptr->rseed_ip)
3435 DSLITE_PRINTF(1,"NU:D PORT ALLOC..%x %u\n", ko.k.k.ipv4,
3440 * For RTSP, two translation entries are created,
3441 * check if main db has space to accomodate two new entry
3443 free_main = free_main - 1;
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)
3453 rv = cnat_dynamic_port_alloc_rtsp_bulk(pm,
3454 PORT_ALLOC_DIRECTED,
3456 ki->dk.ipv4_key.k.port,
3460 STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3461 #ifndef NO_BULK_LOGGING
3463 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3466 , &(dslite_entry_ptr->rseed_ip)
3468 /* TODO: Add the port pair flag here */
3474 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
3475 DSLITE_PRINTF(1,"NU:D_PORT_ALLOC port alloc error\n");
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));
3483 * create entry in user db
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));
3493 #endif /* #ifndef NO_BULK_LOGGING */
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
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++;
3511 nat44_dslite_common_stats[dslite_id].num_dynamic_translations++;
3514 dslite_translation_create_count++;
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 */
3524 * don't forget logging
3525 * logging API is unconditional,
3526 * logging configuration check is done inside the inline function
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);
3536 cnat_nfv9_ds_lite_mapping_create(db,dslite_entry_ptr
3537 #ifndef NO_BULK_LOGGING
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
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;
3558 new_ki.k.k.port += 1;
3561 CNAT_V4_GET_HASH(new_ki.k.key64, new_ki.bucket,
3562 CNAT_MAIN_HASH_MASK);
3564 db2 = cnat_create_main_db_entry_and_hash(&new_ki, &ko, udb);
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);
3575 cnat_nfv9_log_mapping_create(db2, my_vrfmap);
3581 #endif /* TOBE_PORTED */
3586 cnat_db_v2_node_fn (vlib_main_t * vm,
3587 vlib_node_runtime_t * node,
3588 vlib_frame_t * frame)
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,
3598 .n_errors = ARRAY_LEN(cnat_db_v2_error_strings),
3599 .error_strings = cnat_db_v2_error_strings,
3601 .n_next_nodes = CNAT_DB_V2_DROP,
3603 /* edit / add dispositions here */
3605 [CNAT_DB_V2_DROP] = "error-drop",
3609 void cnat_db_v2_init (void)
3613 cnat_timeout_db_entry_t * tdb __attribute__((unused));
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));
3619 n = CNAT_DB_SIZE*1.15; /* add 15% LB margin */
3622 * We also make it multiple of NUM_BITS_IN_UWORD for better
3623 * DB scanning algorithm
3625 if (n % NUM_BITS_IN_UWORD)
3626 n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD));
3628 pool_alloc(cgse_nat_db,n);
3629 for(i=0; i< n; i++) {
3630 pool_get(cgse_nat_db, comb_db);
3633 for(i=0; i< n; i++) {
3634 pool_put(cgse_nat_db, cgse_nat_db + i);
3637 cnat_main_db = &cgse_nat_db->nat44_main_db;
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 */
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 */
3651 * We also make it multiple of NUM_BITS_IN_UWORD for better
3652 * DB scanning algorithm
3654 if (n % NUM_BITS_IN_UWORD)
3655 n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD));
3657 pool_alloc(cgse_session_db,n);
3658 for(i=0; i< n; i++) {
3659 pool_get(cgse_session_db, comb_session);
3662 for(i=0; i< n; i++) {
3663 pool_put(cgse_session_db, cgse_session_db + i);
3666 cnat_session_db = &cgse_session_db->nat44_session_db;
3668 vec_validate(cnat_out2in_hash, CNAT_MAIN_HASH_MASK);
3669 memset(cnat_out2in_hash, 0xff, CNAT_MAIN_HASH_SIZE*sizeof(index_slist_t));
3671 vec_validate(cnat_in2out_hash, CNAT_MAIN_HASH_MASK);
3672 memset(cnat_in2out_hash, 0xff, CNAT_MAIN_HASH_SIZE*sizeof(index_slist_t));
3674 vec_validate(cnat_session_hash, CNAT_SESSION_HASH_MASK);
3675 memset(cnat_session_hash, 0xff, CNAT_SESSION_HASH_SIZE*sizeof(index_slist_t));
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));
3681 pool_alloc(cgse_user_db,n);
3682 for(i=0; i< n; i++) {
3683 pool_get(cgse_user_db, comb_user);
3686 for(i=0; i< n; i++) {
3687 pool_put(cgse_user_db, cgse_user_db + i);
3690 cnat_user_db = &cgse_user_db->nat44_user_db;
3692 vec_validate(cnat_user_hash, CNAT_USER_HASH_MASK);
3693 memset(cnat_user_hash, 0xff, CNAT_USER_HASH_SIZE*sizeof(index_slist_t));
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);
3700 for(i=0; i< n; i++) {
3701 pool_put(cnat_timeout_db, cnat_timeout_db + i);
3704 vec_validate(cnat_timeout_hash, CNAT_TIMEOUT_HASH_MASK);
3705 memset(cnat_timeout_hash, 0xff, CNAT_TIMEOUT_HASH_SIZE*sizeof(index_slist_t));
3708 for (i=0;i<CNAT_MAX_VRFMAP_ENTRIES; i++) {
3709 svi_params_array[i].svi_type = CGSE_SVI_TYPE_INFRA;
3712 cnat_db_init_done = 1;
3713 printf("CNAT DB init is successful\n");