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 /* Locks for multi thread support */
47 CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
48 pthread_spinlock_t *main_db_lockp;
49 pthread_spinlock_t *user_db_lockp;
50 pthread_spinlock_t *session_db_lockp;
52 u32 cached_next_index;
53 /* $$$$ add data here */
55 /* convenience variables */
56 vlib_main_t * vlib_main;
57 vnet_main_t * vnet_main;
60 cnat_db_v2_main_t cnat_db_v2_main;
63 /* TOBE_PORTED : Remove the following once fixed */
66 #define PREDICT_TRUE(x) (x)
67 #define PREDICT_FALSE(x) (x)
70 #define foreach_cnat_db_v2_error \
71 _(DROP, "error-drop packets")
74 #define _(sym,str) CNAT_DB_V2_##sym,
75 foreach_cnat_db_v2_error
80 static char * cnat_db_v2_error_strings[] __attribute__((unused)) = {
81 #define _(sym,string) string,
82 foreach_cnat_db_v2_error
87 void cnat_table_entry_fill_map(u32 start_addr, u32 end_addr,
88 cnat_portmap_v2_t **port_map_holder)
90 u32 this_start_addr, this_end_addr, this_addr, new;
93 cnat_portmap_v2_t *my_pm =0;
94 cnat_portmap_v2_t *pm = 0;
96 my_instance_number = 0;
98 this_start_addr = start_addr;
99 this_end_addr = end_addr;
102 * How many new addresses are getting added ??
104 /* commenting this. Right now end - start will be for this vCGN instance */
105 //new = ((this_end_addr - this_start_addr) / MAX_CORES_PER_PARTITION) + 1;
106 new = (this_end_addr - this_start_addr) + 1;
108 pm = *port_map_holder;
109 pm_len = vec_len(pm);
110 #if DEBUG_NOT_COMMENTED
111 printf("this_start_addr = 0x%08X, this_end_addr = 0x%08X, Num Addr = %d\n",
112 this_start_addr, this_end_addr, new);
113 printf("pm_len = %d\n", pm_len);
115 /* Check whether the address pool add requested already exists */
117 for(i = 0; i< pm_len; i++) {
118 if(my_pm->ipv4_address == this_start_addr) {
119 printf("address pool with addr 0x%08X exists\n", this_start_addr);
126 * For now give a warning message only....
129 if ((total_address_pool_allocated + new) >
130 CNAT_MAX_ADDR_POOL_SIZE_PER_CORE) {
131 printf("address pool size (%d) would cross permissible limit (%u) \n",
132 (total_address_pool_allocated + new),
133 CNAT_MAX_ADDR_POOL_SIZE_PER_CORE);
137 total_address_pool_allocated += new;
138 vec_add2(pm, my_pm, new);
140 #if DEBUG_NOT_COMMENTED
141 printf("total_address_pool_allocated changed from %d to %d (added %d)",
142 (total_address_pool_allocated - new),
143 total_address_pool_allocated, new);
144 printf("vec add is ok\n");
147 memset(my_pm, 0, new*sizeof(*my_pm));
148 this_addr = this_start_addr;
149 loop_count = 0; /* Sanity counter */
151 while (this_addr <= this_end_addr) {
152 #if DEBUG_NOT_COMMENTED
153 printf("loop %d: this addr = 0x%08X\n", loop_count+1, this_addr);
155 my_pm->ipv4_address = this_addr;
157 * Set all bits to "1" indicating all ports are free
159 memset(my_pm->bm, 0xff,
160 (((BITS_PER_INST + BITS(uword)-1)/BITS(uword))*(sizeof(uword))));
161 //this_addr += MAX_CORES_PER_PARTITION;
167 * We should have loop_count same as the new value
169 if (loop_count != new) {
170 printf("Mismatch in loop_count (%d) != new (%d)\n",
174 *port_map_holder = pm;
176 #if DEBUG_NOT_COMMENTED
177 printf("revised pm len %d\n", vec_len(*port_map_holder));
184 void cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log);
185 void handle_cnat_port_exceeded_logging(
186 cnat_user_db_entry_t *udb,
188 cnat_vrfmap_t *vrfmap);
190 cnat_global_counters_t cnat_global_counters;
191 u32 last_log_timestamp = 0;
192 u32 last_user_dyn_port_exc_timestamp = 0;
193 u32 last_user_stat_port_exc_timestamp = 0;
195 index_slist_t *cnat_out2in_hash;
196 index_slist_t *cnat_in2out_hash;
197 index_slist_t *cnat_user_hash;
198 index_slist_t *cnat_timeout_hash;
199 index_slist_t *cnat_session_hash;
201 cnat_main_db_entry_t *cnat_main_db;
202 cnat_user_db_entry_t *cnat_user_db;
203 cnat_session_entry_t *cnat_session_db;
204 cnat_timeout_db_entry_t *cnat_timeout_db;
206 cgse_nat_db_entry_t *cgse_nat_db;
207 cgse_nat_user_db_entry_t *cgse_user_db;
208 cgse_nat_session_db_entry_t *cgse_session_db;
210 nat44_dslite_common_stats_t nat44_dslite_common_stats[255]; /* 0 is for nat44 */
211 nat44_dslite_global_stats_t nat44_dslite_global_stats[2]; /* 0 for nat44 and 1 for dslite */
212 nat44_counters_stats_t nat44_counters_stats[CNAT_MAX_VRFMAP_ENTRIES];
213 /*For displaying show cgn <cgn-name> inside-vrf <vrf-name> counters */
216 * This is the pool of vrf map structures used by latest main-db functions
218 cnat_vrfmap_t *cnat_map_by_vrf;
221 * Have a mapping table of vrf_id-->vrf_map_index
222 * This helps in easily getting the vrf_map structure during
223 * main-db create paths
225 u16 vrf_map_array[CNAT_MAX_VRFMAP_ENTRIES];
226 cnat_svi_params_entry svi_params_array[CNAT_MAX_VRFMAP_ENTRIES];
227 cnat_ingress_vrfid_name_entry vrfid_name_map[MAX_VRFID] = {{0}};
228 u64 in2out_drops_port_limit_exceeded;
229 u64 in2out_drops_system_limit_reached;
230 u64 in2out_drops_resource_depletion;
231 u64 no_translation_entry_drops;
234 #define CNAT_SET_ICMP_MSG_INFO \
235 if (PREDICT_TRUE((my_vrfmap->i_vrf < CNAT_MAX_VRFMAP_ENTRIES) && \
236 (svi_params_array[my_vrfmap->i_vrf].ipv4_addr))) { \
237 info->gen_icmp_msg = icmp_msg_gen_allowed(); \
238 info->svi_addr = svi_params_array[my_vrfmap->i_vrf].ipv4_addr; \
241 #define CNAT_DEBUG_INSIDE_ERR(err) \
242 if (((protocol == CNAT_UDP) && \
243 (debug_i_flag & CNAT_DEBUG_ERR_UDP)) || \
244 ((protocol == CNAT_TCP) && \
245 (debug_i_flag & CNAT_DEBUG_ERR_TCP)) || \
246 ((protocol == CNAT_ICMP) && \
247 (debug_i_flag & CNAT_DEBUG_ERR_ICMP))) { \
248 cnat_db_debug_error(&u_ki, err); \
251 #define DSLITE_DEBUG_INSIDE_ERR(err) \
252 if (((protocol == CNAT_UDP) && \
253 (debug_i_flag & CNAT_DEBUG_ERR_UDP)) || \
254 ((protocol == CNAT_TCP) && \
255 (debug_i_flag & CNAT_DEBUG_ERR_TCP)) || \
256 ((protocol == CNAT_ICMP) && \
257 (debug_i_flag & CNAT_DEBUG_ERR_ICMP))) { \
258 dslite_db_debug_error(&u_ki, err); \
261 #define PORT_LIMIT_LOW_THRESHOLD_FOR_SYSLOG 7
262 /* If the max_limit is less than 10, no meaningful throttling can be
263 * done.. so, log only once per user and never clear the flag
264 * once the user exceeds limit
266 #define CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb, max_limit) \
267 if(PREDICT_FALSE(udb->flags & CNAT_USER_DB_PORT_LIMIT_EXCEEDED)) { \
268 if(udb->ntranslations < \
269 ((max_limit/10)*PORT_LIMIT_LOW_THRESHOLD_FOR_SYSLOG) && \
271 udb->flags = udb->flags & (~CNAT_USER_DB_PORT_LIMIT_EXCEEDED); \
276 /* Commented to remove unused variable warning */
277 static char *debug_db_error[] = {
278 "no error", /* CNAT_SUCCESS */
279 "no config", /*CNAT_NO_CONFIG*/
280 "not in run state", /*CNAT_NO_VRF_RUN*/
281 "no pool for any", /*CNAT_NO_POOL_ANY*/
282 "no port for any", /*CNAT_NO_PORT_ANY*/
283 "bad in use for any", /*CNAT_BAD_INUSE_ANY*/
284 "not found for any", /*CNAT_NOT_FOUND_ANY*/
285 "invalid index for direct", /*CNAT_INV_PORT_DIRECT*/
286 "deleted addr for direct", /*CNAT_DEL_PORT_DIRECT*/
287 "bad in use for direct",/*CNAT_BAD_INUSE_DIRECT*/
288 "not found for direct",/*CNAT_NOT_FOUND_DIRECT*/
289 "out of port limit", /*CNAT_OUT_LIMIT*/
290 "main db limit", /*CNAT_MAIN_DB_LIMIT*/
291 "user db limit", /*CNAT_USER_DB_LIMIT*/
292 "not static port", /*CNAT_NOT_STATIC_PORT*/
293 "bad static port request", /*CNAT_BAD_STATIC_PORT_REQ*/
294 "not this core", /*CNAT_NOT_THIS_CORE*/
295 "parser error", /*CNAT_ERR_PARSER*/
296 "invalid msg id", /*CNAT_ERR_INVALID_MSG_ID*/
297 "invalid msg size", /*CNAT_ERR_INVALID_MSG_SIZE*/
298 "invalid payload size", /*CNAT_ERR_INVALID_PAYLOAD_SIZE*/
299 "bad tcp udp port", /*CNAT_ERR_BAD_TCP_UDP_PORT*/
300 "bulk single failure", /*CNAT_ERR_BULK_SINGLE_FAILURE*/
301 "xlat id invalid", /*CNAT_ERR_XLAT_ID_INVALID*/
302 "xlat v6 prefix invalid", /*CNAT_ERR_XLAT_V6_PREFIX_INVALID*/
303 "xlat v4 prefix invalid", /*CNAT_ERR_XLAT_V4_PREFIX_INVALID*/
304 "xlat tcp mss invalid", /*CNAT_ERR_XLAT_TCP_MSS_INVALID*/
305 "6rd id invalid", /*CNAT_ERR_6RD_ID_INVALID*/
306 "6rd v4 tunnel src invalid", /*CNAT_ERR_6RD_V4_TUNNEL_SRC_INVALID*/
307 "6rd v6 prefix invalid", /*CNAT_ERR_6RD_V6_PREFIX_INVALID*/
308 "6rd v6 BR unicast invalid", /*CNAT_ERR_6RD_V6_BR_UNICAST_INVALID*/
309 "6rd v4 prefix masklen invalid", /*CNAT_ERR_6RD_V4_PREFIX_MASK_LEN_INVALID*/
310 "6rd v4 suffix masklen invalid", /*CNAT_ERR_6RD_V4_SUFFIX_MASK_LEN_INVALID*/
311 "6rd v4 combo masklen invalid", /*CNAT_ERR_6RD_V4_COMBO_MASK_LEN_INVALID*/
312 "6rd tunnel mtu invalid", /*CNAT_ERR_6RD_TUNNEL_MTU_INVALID*/
313 "6rd tunnel ttl invalid", /*CNAT_ERR_6RD_TUNNEL_TTL_INVALID*/
314 "6rd tunnel tos invalid", /*CNAT_ERR_6RD_TUNNEL_TOS_INVALID*/
318 f64 port_log_timestamps[HASH_TABLE_SIZE]; /* 32 KB array per core */
320 void port_exceeded_msg_log (u32 src_addr, u16 i_vrf)
323 f64 current_timestamp;
324 vlib_main_t *vlib_main;
326 vlib_main = vlib_get_main();
327 current_timestamp = vlib_time_now((vlib_main_t *) vlib_main);
329 hash_value = ((src_addr >> 16) ^ ((src_addr & 0xffff) ^ i_vrf)) % (1024*8);
331 if (PREDICT_FALSE((current_timestamp - port_log_timestamps[hash_value]) > THROTTLE_TIME)) {
332 u32 arg[2] = {i_vrf, src_addr};
333 /* update timestamp */
334 port_log_timestamps[hash_value] = current_timestamp;
335 spp_printf(CNAT_USER_OUT_OF_PORTS, 2, arg);
341 static void log_port_alloc_error(cnat_errno_t error, cnat_key_t *k)
344 u32 arr[] = {k->k.vrf, k->k.ipv4, k->k.port};
347 case CNAT_NO_POOL_ANY:
348 error_code = CNAT_NO_POOL_FOR_ANY_ERROR;
350 case CNAT_NO_PORT_ANY:
351 error_code = CNAT_NO_PORT_FOR_ANY_ERROR;
353 case CNAT_ERR_PARSER:
354 error_code = CNAT_WRONG_PORT_ALLOC_TYPE;
356 case CNAT_BAD_INUSE_ANY:
357 error_code = CNAT_BAD_INUSE_ANY_ERROR;
359 case CNAT_BAD_INUSE_DIRECT:
360 error_code = CNAT_BAD_INUSE_DIRECT_ERROR;
362 case CNAT_NOT_FOUND_ANY:
363 error_code = CNAT_NOT_FOUND_ANY_ERROR;
365 case CNAT_NOT_FOUND_DIRECT:
366 error_code = CNAT_NOT_FOUND_DIRECT_ERROR;
368 case CNAT_INV_PORT_DIRECT:
369 error_code = CNAT_INV_PORT_FOR_DIRECT_ERROR;
372 error_code = CNAT_NEW_PORT_ALLOC_ERROR; /* If this code is seen in the log,
373 it means, new error codes are to be added here */
376 spp_printf(error_code, 3, arr);
379 void cnat_db_debug_error(cnat_db_key_bucket_t *u_ki,
382 if (PREDICT_FALSE((u_ki->k.k.vrf == debug_i_vrf) &&
383 ((u_ki->k.k.ipv4 >= debug_i_addr_start) &&
384 (u_ki->k.k.ipv4 <= debug_i_addr_end)))) {
385 #ifdef DEBUG_PRINTF_ENABLED
386 PLATFORM_DEBUG_PRINT("failed to allocate port due to %s "
387 "for i-vrf 0x%x addr 0x%x port 0x%x\n",
388 debug_db_error[error], u_ki->k.k.vrf,
389 u_ki->k.k.ipv4, u_ki->k.k.port);
392 u32 arg[] = {u_ki->k.k.vrf, u_ki->k.k.ipv4, u_ki->k.k.port};
393 spp_printf(error, 3, arg);
398 void dslite_db_debug_error(dslite_db_key_bucket_t *u_ki,
401 if (PREDICT_FALSE((u_ki->dk.ipv4_key.k.vrf == debug_i_vrf) &&
402 ((u_ki->dk.ipv4_key.k.ipv4 >= debug_i_addr_start) &&
403 (u_ki->dk.ipv4_key.k.ipv4 <= debug_i_addr_end)))) {
404 #ifdef DEBUG_PRINTF_ENABLED
405 PLATFORM_DEBUG_PRINT("failed to allocate port due to %s "
406 "for i-vrf 0x%x addr 0x%x port 0x%x\n",
407 debug_db_error[error], u_ki->dk.ipv4_key.k.vrf,
408 u_ki->dk.ipv4_key.k.ipv4, u_ki->dk.ipv4_key.k.port);
411 u32 arg[] = {u_ki->dk.ipv4_key.k.vrf, u_ki->dk.ipv4_key.k.ipv4, u_ki->dk.ipv4_key.k.port};
412 spp_printf(error, 3, arg);
417 void cnat_db_debug_i2o_drop(cnat_db_key_bucket_t *ki)
419 if (PREDICT_FALSE(((ki->k.k.vrf & CNAT_VRF_MASK) == debug_i_vrf) &&
420 ((ki->k.k.ipv4 >= debug_i_addr_start) &&
421 (ki->k.k.ipv4 <= debug_i_addr_end)))) {
422 #ifdef DEBUG_PRINTF_ENABLED
423 PLATFORM_DEBUG_PRINT("pakcet[i-vrf 0x%x addr 0x%x port 0x%x] dropped\n",
424 ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port);
427 u32 arg[] = {ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port};
428 spp_printf(CNAT_PACKET_DROP_ERROR, 3, arg);
433 void cnat_db_in2out_hash_delete (cnat_main_db_entry_t *ep, cnat_user_db_entry_t *up)
437 cnat_main_db_entry_t *this, *prev;
440 if (PREDICT_FALSE(ep->flags & CNAT_DB_DSLITE_FLAG)) {
442 {up->ipv6[0], up->ipv6[1], up->ipv6[2], up->ipv6[3]} ,
443 {ep->in2out_key.k.ipv4, ep->in2out_key.k.port, ep->in2out_key.k.vrf}
445 DSLITE_V6_GET_HASH((&dk),
447 CNAT_MAIN_HASH_MASK);
448 DSLITE_PRINTF(1, "Delete1 DSL main hash bucket ..%u\n", bucket);
450 CNAT_V4_GET_HASH(ep->in2out_key.key64,
451 bucket, CNAT_MAIN_HASH_MASK)
452 DSLITE_PRINTF(1, "Delete1 NAT44 main hash bucket ..%u\n", bucket);
455 CNAT_V4_GET_HASH(ep->in2out_key.key64,
456 bucket, CNAT_MAIN_HASH_MASK)
459 index = cnat_in2out_hash[bucket].next;
461 ASSERT(index != EMPTY);
465 this = cnat_main_db + index;
466 if (PREDICT_TRUE(this == ep)) {
468 cnat_in2out_hash[bucket].next = ep->in2out_hash.next;
471 prev->in2out_hash.next = ep->in2out_hash.next;
476 index = this->in2out_hash.next;
477 } while (index != EMPTY);
482 void cnat_db_out2in_hash_delete (cnat_main_db_entry_t *ep)
486 cnat_main_db_entry_t *this, *prev;
488 CNAT_V4_GET_HASH(ep->out2in_key.key64,
489 bucket, CNAT_MAIN_HASH_MASK)
491 index = cnat_out2in_hash[bucket].next;
493 ASSERT(index != EMPTY);
497 this = cnat_main_db + index;
498 if (PREDICT_TRUE(this == ep)) {
500 cnat_out2in_hash[bucket].next = ep->out2in_hash.next;
503 prev->out2in_hash.next = ep->out2in_hash.next;
508 index = this->out2in_hash.next;
509 } while (index != EMPTY);
514 cnat_main_db_entry_t*
515 cnat_main_db_lookup_entry(cnat_db_key_bucket_t *ki)
519 cnat_main_db_entry_t *db;
521 CNAT_V4_GET_HASH(ki->k.key64,
523 CNAT_MAIN_HASH_MASK);
525 index = cnat_in2out_hash[ki->bucket].next;
526 if (PREDICT_TRUE(index == EMPTY)) {
531 db = cnat_main_db + index;
532 if (PREDICT_TRUE(db->in2out_key.key64 == ki->k.key64)) {
535 index = db->in2out_hash.next;
536 } while (index != EMPTY);
541 void cnat_user_db_delete (cnat_user_db_entry_t *up)
545 cnat_user_db_entry_t *this, *prev;
547 if (PREDICT_FALSE(up->flags & CNAT_USER_DB_NAT64_FLAG) != 0) {
548 /* Preventive check - Not a NAT44 entry */
552 pthread_spin_lock(cnat_db_v2_main.user_db_lockp);
554 if(PREDICT_FALSE(up->flags & CNAT_USER_DB_DSLITE_FLAG)) {
556 {up->ipv6[0], up->ipv6[1], up->ipv6[2], up->ipv6[3]} ,
557 {{up->key.k.ipv4, up->key.k.port, up->key.k.vrf}}
560 DSLITE_V6_GET_HASH((&dk),
562 CNAT_USER_HASH_MASK);
563 DSLITE_PRINTF(1, "Delete1 DSL user hash bucket ..%u\n", bucket);
565 CNAT_V4_GET_HASH(up->key.key64,
566 bucket, CNAT_USER_HASH_MASK)
567 DSLITE_PRINTF(1, "Delete1 NAT44 user hash bucket ..%u\n", bucket);
570 CNAT_V4_GET_HASH(up->key.key64,
571 bucket, CNAT_USER_HASH_MASK)
572 DSLITE_PRINTF(1, "Delete2 NAT44 user hash bucket ..%u\n", bucket);
575 index = cnat_user_hash[bucket].next;
577 ASSERT(index != EMPTY);
581 this = cnat_user_db + index;
582 if (PREDICT_TRUE(this == up)) {
584 cnat_user_hash[bucket].next = up->user_hash.next;
587 prev->user_hash.next = up->user_hash.next;
592 index = this->user_hash.next;
593 } while (index != EMPTY);
598 pool_put(cnat_user_db, up);
599 pthread_spin_unlock(cnat_db_v2_main.user_db_lockp);
602 cnat_user_db_entry_t*
603 cnat_user_db_lookup_entry(cnat_db_key_bucket_t *uki)
607 cnat_user_db_entry_t *udb=NULL;
609 CNAT_V4_GET_HASH(uki->k.key64,
613 /* now: index in user vector */
614 index = cnat_user_hash[uki->bucket].next;
615 if (PREDICT_TRUE(index != EMPTY)) {
617 udb = cnat_user_db + index;
618 if (PREDICT_FALSE(udb->key.key64 == uki->k.key64)) {
621 index = udb->user_hash.next;
622 } while (index != EMPTY);
627 cnat_user_db_entry_t*
628 cnat_user_db_create_entry(cnat_db_key_bucket_t *uki,
631 cnat_user_db_entry_t *udb = NULL;
633 pthread_spin_lock(cnat_db_v2_main.user_db_lockp);
634 pool_get(cnat_user_db, udb);
635 memset(udb, 0, sizeof(*udb));
637 udb->ntranslations = 1;
638 udb->portmap_index = portmap_index;
639 udb->key.key64 = uki->k.key64;
640 /* Add this user to the head of the bucket chain */
641 udb->user_hash.next =
642 cnat_user_hash[uki->bucket].next;
643 cnat_user_hash[uki->bucket].next = udb - cnat_user_db;
645 #ifndef NO_BULK_LOGGING
647 #endif /* NO_BULK_LOGGING */
648 pthread_spin_unlock(cnat_db_v2_main.user_db_lockp);
652 cnat_main_db_entry_t*
653 cnat_create_main_db_entry_and_hash(cnat_db_key_bucket_t *ki,
654 cnat_db_key_bucket_t *ko,
655 cnat_user_db_entry_t *udb)
659 cnat_main_db_entry_t *db = NULL;
661 pool_get(cnat_main_db, db);
662 memset(db, 0, sizeof(*db));
664 db_index = db - cnat_main_db;
665 db->in2out_key.k.ipv4 = ki->k.k.ipv4;
666 db->in2out_key.k.port = ki->k.k.port;
667 db->in2out_key.k.vrf = ki->k.k.vrf;
668 db->out2in_key.k.ipv4 = ko->k.k.ipv4;
669 db->out2in_key.k.port = ko->k.k.port;
670 db->out2in_key.k.vrf = ko->k.k.vrf;
672 db->user_ports.next = db_index;
673 db->user_ports.prev = db_index;
674 db->user_index = udb - cnat_user_db;
675 //db->portmap_index = udb->portmap_index;
676 db->flags &= ~(CNAT_DB_DSLITE_FLAG); // Mark that it is not dslite
677 if (PREDICT_FALSE(udb->ntranslations == 1)) {
679 * first port for this src vrf/src ip addr
681 udb->translation_list_head_index = db_index;
683 index_dlist_addtail(udb->translation_list_head_index,
684 (u8 *)cnat_main_db, sizeof(cnat_main_db[0]),
685 STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports),
692 CNAT_V4_GET_HASH(ko->k.key64,
695 db->out2in_hash.next = cnat_out2in_hash[ko->bucket].next;
696 cnat_out2in_hash[ko->bucket].next = db_index;
698 * setup i2o hash key, bucket is already calculate
700 db->in2out_hash.next = cnat_in2out_hash[ki->bucket].next;
701 cnat_in2out_hash[ki->bucket].next = db_index;
704 printf("\nMy_Instance_Number %d: Bucket %d, Db_Index %d",
705 my_instance_number, ki->bucket, db_index);
706 printf("\nInside (VRF 0x%x, IP 0x%x, PORT 0x%x)",
707 db->in2out_key.k.vrf, db->in2out_key.k.ipv4, db->in2out_key.k.port);
708 printf("\nOutside (VRF 0x%x, IP 0x%x, PORT 0x%x)",
709 db->out2in_key.k.vrf, db->out2in_key.k.ipv4, db->out2in_key.k.port);
710 printf("\nUser Index %d, IP 0x%x",
711 db->user_index, udb->key.k.ipv4);
714 NAT44_COMMON_STATS.active_translations++;
719 static inline void pptp_clear_all_channels(
720 cnat_main_db_entry_t *db)
722 u32 db_index, current_db_index;
723 cnat_main_db_entry_t *temp_db;
725 /* clear all channels */
727 db_index = db->proto_data.pptp_list.next;
728 current_db_index = db - cnat_main_db;
730 while( db_index != EMPTY) {
731 temp_db = cnat_main_db + db_index;
732 db_index = temp_db->proto_data.pptp_list.next;
733 temp_db->entry_expires = 0;
734 if(PREDICT_FALSE(temp_db->proto_data.pptp_list.prev
735 == current_db_index)) { // Decouple child GREs from parent
736 temp_db->proto_data.pptp_list.prev = EMPTY;
740 db->proto_data.pptp_list.next = EMPTY;
743 void pptp_remove_channel_from_tunnel(cnat_main_db_entry_t *db) {
745 cnat_main_db_entry_t *prev_db, *next_db;
747 prev_db = cnat_main_db + db->proto_data.pptp_list.prev;
748 next_db = cnat_main_db + db->proto_data.pptp_list.next;
750 /* remove entry from the tunnel list */
751 if(PREDICT_TRUE(db->proto_data.pptp_list.prev != EMPTY)) {
752 prev_db->proto_data.pptp_list.next =
753 db->proto_data.pptp_list.next ;
756 if(db->proto_data.pptp_list.next != EMPTY) {
757 next_db->proto_data.pptp_list.prev
758 = db->proto_data.pptp_list.prev;
763 void cnat_delete_main_db_entry_v2 (cnat_main_db_entry_t *ep)
766 u32 vrfmap_len, udb_len;
767 cnat_user_db_entry_t *up =0;
768 cnat_portmap_v2_t *pm =0;
769 cnat_portmap_v2_t *my_pm =0;
770 cnat_vrfmap_t *my_vrfmap =0;
771 u16 static_port_range;
772 #ifndef NO_BULK_LOGGING
773 bulk_alloc_size_t bulk_size;
774 int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
776 pool_header_t *h = pool_header(cnat_user_db);
781 if (PREDICT_FALSE(ep->flags & CNAT_DB_NAT64_FLAG) != 0) {
782 /* Preventive check - Not a NAT44 entry */
786 pthread_spin_lock(cnat_db_v2_main.main_db_lockp);
787 if(PREDICT_FALSE(ep->flags &
788 CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE)) {
789 pptp_clear_all_channels(ep);
790 PPTP_DECR(active_tunnels);
793 if(PREDICT_FALSE(ep->flags &
794 CNAT_DB_FLAG_PPTP_GRE_ENTRY)) {
795 pptp_remove_channel_from_tunnel(ep);
796 PPTP_DECR(active_channels);
799 /* This function gets called from various locations..
800 * many times from config handler.. so we
801 * to ensure that multiple sessions if any are
805 if(PREDICT_FALSE(ep->nsessions > 1)) {
806 cnat_session_entry_t *sdb;
807 while(ep->nsessions > 1 &&
808 ep->session_head_index != EMPTY) {
809 sdb = cnat_session_db + ep->session_head_index;
810 cnat_delete_session_db_entry(sdb, TRUE);
814 /* Find the set of portmaps for the outside vrf */
815 vrfmap_len = vec_len(cnat_map_by_vrf);
816 udb_len = vec_len(cnat_user_db);
818 /* In case of invalid user just return, deleting only main db
819 * is not a good idea, since some valid user db entry might be pointing
820 * to that main db and hence leave the dbs in a inconsistent state
822 if (PREDICT_FALSE((ep->user_index >= udb_len) ||
823 (clib_bitmap_get(h->free_bitmap, ep->user_index)))) {
824 #ifdef DEBUG_PRINTF_ENABLED
825 printf("invalid/unused user index in db %d\n", ep->user_index);
827 spp_printf(CNAT_INV_UNUSED_USR_INDEX, 1, (u32 *) &(ep->user_index));
828 cnat_main_db_entry_dump(ep);
832 up = cnat_user_db + ep->user_index;
834 /* Point to the right portmap list */
835 if (PREDICT_FALSE(ep->flags & CNAT_DB_DSLITE_FLAG)) {
836 instance = ep->dslite_nat44_inst_id;
837 pm = dslite_table_db_ptr[instance].portmap_list;
838 if(PREDICT_FALSE((pm == NULL))) {
839 DSLITE_PRINTF(3, "NULL portmap list for dslite_id %u, state %u\n",
840 instance, dslite_table_db_ptr[instance].state);
841 cnat_main_db_entry_dump(ep);
845 STAT_PORT_RANGE_FROM_INST_PTR(&(dslite_table_db_ptr[instance]));
847 * Netflow logging API for delete event
850 BULKSIZE_FROM_VRFMAP(&(dslite_table_db_ptr[instance]));
852 if (PREDICT_FALSE(ep->vrfmap_index >= vrfmap_len)) {
853 #ifdef DEBUG_PRINTF_ENABLED
854 printf("invalid vrfmap index in db\n");
856 spp_printf(CNAT_INVALID_VRFMAP_INDEX, 0, NULL);
857 cnat_main_db_entry_dump(ep);
860 instance = NAT44_RESERVED_INST_ID;
861 my_vrfmap = cnat_map_by_vrf + ep->vrfmap_index;
862 pm = my_vrfmap->portmap_list;
863 static_port_range = cnat_static_port_range;
864 bulk_size = BULKSIZE_FROM_VRFMAP(my_vrfmap);
867 if (PREDICT_FALSE(ep->flags & CNAT_DB_FLAG_PORT_PAIR)) {
868 /* Give back the port(s) */
869 cnat_port_free_v2_bulk(pm, up->portmap_index,
870 PORT_PAIR, ep->out2in_key.k.port, up, static_port_range
871 #ifndef NO_BULK_LOGGING
872 , bulk_size, &nfv9_log_req
876 /* Give back the port(s) */
877 cnat_port_free_v2_bulk (pm, up->portmap_index,
878 PORT_SINGLE, ep->out2in_key.k.port, up, static_port_range
879 #ifndef NO_BULK_LOGGING
880 , bulk_size, &nfv9_log_req
885 if (PREDICT_TRUE(!(ep->flags & CNAT_DB_DSLITE_FLAG))) {
886 if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
887 if(PREDICT_FALSE(my_vrfmap->nf_logging_policy == SESSION_LOG_ENABLE)) {
888 if(ep->nsessions != 0) {
889 cnat_nfv9_nat44_log_session_delete(ep, NULL, my_vrfmap);
892 cnat_nfv9_log_mapping_delete(ep, my_vrfmap
893 #ifndef NO_BULK_LOGGING
898 if(PREDICT_TRUE((my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE) ||
899 (ep->nsessions != 0))) {
900 cnat_syslog_nat44_mapping_delete(ep, my_vrfmap, NULL
901 #ifndef NO_BULK_LOGGING
908 if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
909 if(PREDICT_FALSE( dslite_table_db_ptr[instance].nf_logging_policy ==
910 SESSION_LOG_ENABLE)) {
911 cnat_nfv9_ds_lite_log_session_delete(ep,
912 (dslite_table_db_ptr + instance),NULL);
914 cnat_nfv9_ds_lite_mapping_delete(ep,
915 (dslite_table_db_ptr + instance)
916 #ifndef NO_BULK_LOGGING
922 cnat_syslog_ds_lite_mapping_delete(ep,
923 (dslite_table_db_ptr + instance), NULL
924 #ifndef NO_BULK_LOGGING
928 #endif /* TOBE_PORTED */
934 main_db_index = ep - cnat_main_db;
936 pthread_spin_lock(cnat_db_v2_main.user_db_lockp);
938 pthread_spin_unlock(cnat_db_v2_main.user_db_lockp);
941 * when user reaches max allowed port limit
942 * we generate icmp msg and inc the counter
943 * when counter reach the icmp msg rate limit
944 * we stop icmp msg gen
945 * when a user port is freed
946 * that means we need to clear the msg gen counter
948 * reach max port limit, we can generate new icmp msg again
950 up->icmp_msg_count = 0;
952 up->translation_list_head_index = index_dlist_remelem (
953 up->translation_list_head_index, (u8 *)cnat_main_db,
954 sizeof (cnat_main_db[0]),
955 STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports),
958 cnat_db_in2out_hash_delete(ep, up);
960 if (PREDICT_FALSE(up->ntranslations == 0)) {
961 ASSERT(up->translation_list_head_index == EMPTY);
962 nat44_dslite_common_stats[instance].num_subscribers--;
963 my_index = up->portmap_index;
964 my_pm = pm + my_index;
965 if(PREDICT_TRUE(my_pm->private_ip_users_count)) {
966 my_pm->private_ip_users_count--;
967 #ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED
968 PLATFORM_DEBUG_PRINT("\n cnat_delete_main_db_entry_v2 "
969 "private_ip_users_count = %d",
970 my_pm->private_ip_users_count);
974 cnat_user_db_delete(up);
978 /* Remove from main DB hashes */
979 //cnat_db_in2out_hash_delete(ep);
980 cnat_db_out2in_hash_delete(ep);
982 pool_put(cnat_main_db, ep);
984 if(PREDICT_FALSE(ep->flags & CNAT_DB_FLAG_STATIC_PORT)) {
985 nat44_dslite_common_stats[instance].num_static_translations--;
987 nat44_dslite_common_stats[instance].num_dynamic_translations--;
989 nat44_dslite_common_stats[instance].active_translations--;
990 nat44_dslite_global_stats[!!(instance - 1)].translation_delete_count ++;
992 pthread_spin_unlock(cnat_db_v2_main.main_db_lockp);
995 cnat_main_db_entry_t*
996 cnat_main_db_lookup_entry_out2in (cnat_db_key_bucket_t *ko)
1000 cnat_main_db_entry_t *db;
1002 CNAT_V4_GET_HASH(ko->k.key64,
1004 CNAT_MAIN_HASH_MASK);
1006 index = cnat_out2in_hash[ko->bucket].next;
1007 if (PREDICT_TRUE(index == EMPTY)) {
1012 db = cnat_main_db + index;
1013 if (PREDICT_TRUE(db->out2in_key.key64 == ko->k.key64)) {
1016 index = db->out2in_hash.next;
1017 } while (index != EMPTY);
1022 /* Creates 2 sessions.
1023 * Moves the default dest info from mdb to first session
1024 * Fills the dest_info details in to second session and
1025 * returns the pointer to second session
1027 cnat_session_entry_t *cnat_handle_1to2_session(
1028 cnat_main_db_entry_t *mdb,
1029 cnat_key_t *dest_info)
1031 cnat_key_t old_dest_info;
1033 u32 free_session = 0;
1035 cnat_session_entry_t *session_db1 = NULL, *session_db2 = NULL;
1037 h = pool_header(cnat_session_db);
1038 free_session = vec_len(h->free_indices) - 1;
1040 if (PREDICT_FALSE(free_session < 2)) {
1041 if (mdb->flags & CNAT_DB_DSLITE_FLAG) {
1042 instance = mdb->dslite_nat44_inst_id;
1044 instance = NAT44_RESERVED_INST_ID;
1047 /* we need 2 sessions here, return NULL */
1048 nat44_dslite_common_stats[instance].drops_sessiondb_limit_exceeded++;
1052 old_dest_info.k.ipv4 = mdb->dst_ipv4;
1053 old_dest_info.k.port = mdb->dst_port;
1054 old_dest_info.k.vrf = mdb->in2out_key.k.vrf;
1056 /* create 2 new sessions */
1057 session_db1 = cnat_create_session_db_entry(&old_dest_info,
1060 if(PREDICT_FALSE(session_db1 == NULL)) {
1064 /* update pkt info to session 2 */
1065 session_db2 = cnat_create_session_db_entry(dest_info,
1068 if(PREDICT_FALSE(session_db2 == NULL)) {
1069 cnat_delete_session_db_entry(session_db1, FALSE);
1072 /* update main db info to session 1 */
1073 cnat_dest_update_main2session(mdb, session_db1);
1078 /* The below function shold be called only
1079 * when a NAT44 STATIC entry received traffic
1080 * for the first time. This is to ensure
1081 * the destination is noted and logged
1083 void cnat_add_dest_n_log(
1084 cnat_main_db_entry_t *mdb,
1085 cnat_key_t *dest_info)
1088 if(PREDICT_FALSE(mdb->nsessions != 0)) {
1089 return; /* Should not have been called */
1092 mdb->dst_ipv4 = dest_info->k.ipv4;
1093 mdb->dst_port = dest_info->k.port;
1095 mdb->entry_expires = cnat_current_time;
1098 if (mdb->flags & CNAT_DB_DSLITE_FLAG) {
1099 instance = mdb->dslite_nat44_inst_id;
1100 cnat_session_log_ds_lite_mapping_create(mdb,
1101 (dslite_table_db_ptr + instance),NULL);
1103 instance = NAT44_RESERVED_INST_ID;
1104 cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + mdb->vrfmap_index;
1105 cnat_session_log_nat44_mapping_create(mdb, 0, my_vrfmap);
1110 * this function is called by exception node
1111 * when lookup is fialed in i2o node
1113 * if reash per user port limit,
1114 * set user_db_entry pointer, and error == CNAT_OUT_LIMIT
1116 static cnat_main_db_entry_t*
1117 _cnat_get_main_db_entry_v2(cnat_db_key_bucket_t *ki,
1118 port_pair_t port_pair_type,
1119 port_type_t port_type,
1120 cnat_gen_icmp_info *info,
1121 cnat_key_t *dest_info)
1125 cnat_db_key_bucket_t u_ki, ko;
1126 u32 my_index, free_main, free_user;
1127 u32 current_timestamp;
1128 u16 my_vrfmap_index;
1129 u16 my_vrfmap_entry_found = 0;
1130 cnat_vrfmap_t *my_vrfmap =0;
1131 cnat_portmap_v2_t *pm =0;
1132 cnat_user_db_entry_t *udb = 0;
1133 cnat_main_db_entry_t *db = 0;
1136 cnat_portmap_v2_t *my_pm = 0;
1138 #ifndef NO_BULK_LOGGING
1139 int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
1144 * need to try lookup again because
1145 * second pkt may come here before the entry is created
1146 * by receiving first pkt due to high line rate.
1148 info->gen_icmp_msg = CNAT_NO_ICMP_MSG;
1149 info->error = CNAT_SUCCESS;
1150 db = cnat_main_db_lookup_entry(ki);
1151 if (PREDICT_TRUE(db)) {
1152 /* what if the source is talking to a
1153 * new dest now? We will have to handle this case and
1154 * take care of - creating session db and logging
1156 if(PREDICT_FALSE((!dest_info->k.ipv4) && (!dest_info->k.port))) {
1157 return db; /* if dest_info is null don't create session */
1159 if(PREDICT_TRUE((db->dst_ipv4 == dest_info->k.ipv4) &&
1160 (db->dst_port == dest_info->k.port))) {
1163 dest_info->k.vrf = db->in2out_key.k.vrf;
1164 /* Src is indeed talking to a different dest */
1165 cnat_session_entry_t *session_db2 = NULL;
1166 if(PREDICT_TRUE(db->nsessions == 1)) {
1167 session_db2 = cnat_handle_1to2_session(db, dest_info);
1168 if(PREDICT_TRUE(session_db2 != NULL)) {
1169 CNAT_DB_TIMEOUT_RST(session_db2);
1172 info->error = CNAT_ERR_NO_SESSION_DB;
1175 } else if(PREDICT_FALSE(db->nsessions == 0)) {
1176 /* Should be static entry.. should never happen
1178 if(PREDICT_TRUE(dest_info->k.ipv4 != 0)) {
1179 cnat_add_dest_n_log(db, dest_info);
1183 /* The src has already created multiple sessions.. very rare
1185 session_db2 = cnat_create_session_db_entry(dest_info,
1187 if(PREDICT_TRUE(session_db2 != NULL)) {
1188 CNAT_DB_TIMEOUT_RST(session_db2);
1191 info->error = CNAT_ERR_NO_SESSION_DB;
1199 * step 1. check if outside vrf is configured or not
1200 * and Find the set of portmaps for the outside vrf
1201 * insider vrf is one to one mappted to outside vrf
1202 * key is vrf and ip only
1203 * ki.k.k.vrf has protocol bits, mask out
1205 protocol = ki->k.k.vrf & CNAT_PRO_MASK;
1206 u_ki.k.k.vrf = ki->k.k.vrf & CNAT_VRF_MASK;
1207 u_ki.k.k.ipv4 = ki->k.k.ipv4;
1210 my_vrfmap_index = vrf_map_array[u_ki.k.k.vrf];
1211 my_vrfmap = cnat_map_by_vrf + my_vrfmap_index;
1213 my_vrfmap_entry_found = ((my_vrfmap_index != VRF_MAP_ENTRY_EMPTY) &&
1214 (my_vrfmap->status == S_RUN) &&
1215 (my_vrfmap->i_vrf == u_ki.k.k.vrf));
1217 if (PREDICT_FALSE(!my_vrfmap_entry_found)) {
1218 u32 arr[] = {ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port};
1219 if ((my_vrfmap_index == VRF_MAP_ENTRY_EMPTY) ||
1220 (my_vrfmap->i_vrf == u_ki.k.k.vrf)) {
1221 info->error = CNAT_NO_CONFIG;
1222 CNAT_DEBUG_INSIDE_ERR(CNAT_NO_CONFIG)
1223 spp_printf(CNAT_NO_CONFIG_ERROR, 3, arr);
1225 info->error = CNAT_NO_VRF_RUN;
1226 CNAT_DEBUG_INSIDE_ERR(CNAT_NO_VRF_RUN)
1227 spp_printf(CNAT_NO_VRF_RUN_ERROR, 3, arr);
1233 pm = my_vrfmap->portmap_list;
1235 port_limit = my_vrfmap->port_limit;
1236 if(PREDICT_FALSE(!port_limit)) {
1237 port_limit = cnat_main_db_max_ports_per_user;
1240 * set o2i key with protocl bits
1242 ko.k.k.vrf = my_vrfmap->o_vrf | protocol;
1245 * step 2. check if src vrf, src ip addr is alreay
1247 * if yes, use PORT_ALLOC_DIRECTED
1248 * if no, use PORT_ALLOC_ANY since it is first time
1250 udb = cnat_user_db_lookup_entry(&u_ki);
1251 if (PREDICT_TRUE(udb)) {
1253 * not first time allocate port for this user
1256 if (PREDICT_FALSE(udb->ntranslations >=
1258 /* Check for the port type here. If we are getting
1259 * a STATIC PORT, allow the config.
1261 if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) {
1262 info->error = CNAT_OUT_LIMIT;
1263 CNAT_SET_ICMP_MSG_INFO
1264 CNAT_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT)
1265 port_exceeded_msg_log(u_ki.k.k.ipv4, u_ki.k.k.vrf);
1266 in2out_drops_port_limit_exceeded ++;
1267 u_ki.k.k.port = ki->k.k.port;
1268 u_ki.k.k.vrf = ki->k.k.vrf;
1269 handle_cnat_port_exceeded_logging(udb, &u_ki.k, my_vrfmap);
1273 CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb,
1277 * check if main db has space to accomodate new entry
1279 h = pool_header(cnat_main_db);
1281 free_main = vec_len(h->free_indices) - 1;
1282 if (PREDICT_FALSE(!free_main)) {
1283 info->error = CNAT_MAIN_DB_LIMIT;
1284 CNAT_SET_ICMP_MSG_INFO
1285 in2out_drops_system_limit_reached ++;
1286 CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
1288 current_timestamp = spp_trace_log_get_unix_time_in_seconds();
1289 if (PREDICT_FALSE((current_timestamp - last_log_timestamp) >
1291 spp_printf(CNAT_SESSION_THRESH_EXCEEDED, 0, NULL);
1292 last_log_timestamp = current_timestamp;
1296 printf("Limit reached : OLD USER");
1302 * allocate port, from existing mapping
1304 my_index = udb->portmap_index;
1306 if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
1307 rv = cnat_static_port_alloc_v2_bulk(pm,
1308 PORT_ALLOC_DIRECTED,
1315 cnat_static_port_range
1316 #ifndef NO_BULK_LOGGING
1318 udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1321 , my_vrfmap->ip_n_to_1
1324 } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP) ) {
1326 rv = cnat_dynamic_port_alloc_v2_bulk(pm,
1327 PORT_ALLOC_DIRECTED,
1332 cnat_static_port_range
1333 #ifndef NO_BULK_LOGGING
1335 udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1338 , my_vrfmap->ip_n_to_1,
1339 &(my_vrfmap->rseed_ip)
1344 * For RTSP, two translation entries are created,
1345 * check if main db has space to accomodate two new entry
1347 free_main = free_main - 1;
1348 if (PREDICT_FALSE(!free_main)) {
1349 info->error = CNAT_MAIN_DB_LIMIT;
1350 CNAT_SET_ICMP_MSG_INFO
1351 in2out_drops_system_limit_reached ++;
1352 CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
1356 rv = cnat_dynamic_port_alloc_rtsp_bulk(pm,
1357 PORT_ALLOC_DIRECTED,
1363 cnat_static_port_range
1364 #ifndef NO_BULK_LOGGING
1366 udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1369 , &(my_vrfmap->rseed_ip)
1375 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1377 CNAT_SET_ICMP_MSG_INFO
1378 CNAT_DEBUG_INSIDE_ERR(rv)
1379 in2out_drops_resource_depletion++;
1380 log_port_alloc_error(rv, &(ki->k));
1384 * increment port in use for this user
1386 pthread_spin_lock(cnat_db_v2_main.user_db_lockp);
1387 udb->ntranslations += 1;
1388 pthread_spin_unlock(cnat_db_v2_main.user_db_lockp);
1392 * first time allocate port for this user
1396 * Do not create entry if port limit is invalid
1399 if (PREDICT_FALSE(!port_limit)) {
1400 if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) {
1401 info->error = CNAT_OUT_LIMIT;
1402 in2out_drops_port_limit_exceeded ++;
1403 port_exceeded_msg_log(u_ki.k.k.ipv4, u_ki.k.k.vrf);
1404 CNAT_SET_ICMP_MSG_INFO
1405 CNAT_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT)
1411 * Check if main db has space for new entry
1412 * Allowing a user db entry to be created if main db is not free
1413 * will cause a port to be allocated to that user, which results in
1414 * wastage of that port, hence the check is done here.
1416 h = pool_header(cnat_main_db);
1417 free_main = vec_len(h->free_indices) - 1;
1418 h = pool_header(cnat_user_db);
1419 free_user = vec_len(h->free_indices) - 1;
1422 * If either main_db or user_db does not have entries
1423 * bail out, with appropriate error
1425 if (PREDICT_FALSE(!(free_main && free_user))) {
1428 info->error = CNAT_USER_DB_LIMIT;
1429 log_error = CNAT_USER_DB_LIMIT_ERROR;
1431 info->error = CNAT_MAIN_DB_LIMIT;
1432 log_error = CNAT_MAIN_DB_LIMIT_ERROR;
1434 in2out_drops_system_limit_reached ++;
1435 CNAT_SET_ICMP_MSG_INFO
1436 CNAT_DEBUG_INSIDE_ERR(info->error)
1437 spp_printf(log_error, 0, 0);
1441 if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
1442 rv = cnat_static_port_alloc_v2_bulk(pm,
1450 cnat_static_port_range
1451 #ifndef NO_BULK_LOGGING
1453 udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1456 , my_vrfmap->ip_n_to_1
1459 } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP)) {
1460 rv = cnat_dynamic_port_alloc_v2_bulk(pm,
1466 cnat_static_port_range
1467 #ifndef NO_BULK_LOGGING
1468 , NULL, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1471 , my_vrfmap->ip_n_to_1,
1472 &(my_vrfmap->rseed_ip)
1476 * For RTSP, two translation entries are created,
1477 * check if main db has space to accomodate two new entry
1479 free_main = free_main - 1;
1480 if (PREDICT_FALSE(!free_main)) {
1481 info->error = CNAT_MAIN_DB_LIMIT;
1482 CNAT_SET_ICMP_MSG_INFO
1483 in2out_drops_system_limit_reached ++;
1484 CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
1489 rv = cnat_dynamic_port_alloc_rtsp_bulk(pm,
1496 cnat_static_port_range
1497 #ifndef NO_BULK_LOGGING
1498 , NULL, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1501 , &(my_vrfmap->rseed_ip)
1503 /* TODO: Add the port pair flag here */
1509 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1511 in2out_drops_resource_depletion ++;
1512 CNAT_SET_ICMP_MSG_INFO
1513 CNAT_DEBUG_INSIDE_ERR(rv)
1514 log_port_alloc_error(rv, &(ki->k));
1518 * create entry in user db
1520 udb = cnat_user_db_create_entry(&u_ki, my_index);
1521 NAT44_COMMON_STATS.num_subscribers++;
1522 my_pm = pm + my_index;
1523 if(PREDICT_TRUE(my_pm->private_ip_users_count < PORTS_PER_ADDR)) {
1524 my_pm->private_ip_users_count++;
1525 #ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED
1526 PLATFORM_DEBUG_PRINT("\n cnat_get_main_db_entry_v2 "
1527 "dynamic alloc private_ip_users_count = %d",
1528 my_pm->private_ip_users_count);
1531 PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has "
1532 "reached MAX PORTS_PER_ADDR");
1534 #ifndef NO_BULK_LOGGING
1535 if(PREDICT_TRUE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) {
1536 cnat_update_bulk_range_cache(udb, ko.k.k.port,
1537 BULKSIZE_FROM_VRFMAP(my_vrfmap));
1539 #endif /* #ifndef NO_BULK_LOGGING */
1545 * outside port is allocated for this src vrf/src ip addr
1546 * 1)create a new entry in main db
1547 * 2)setup cnat_out2in_hash key
1548 * 3)setup cnat_in2out_hash key
1550 db = cnat_create_main_db_entry_and_hash(ki, &ko, udb);
1552 translation_create_count ++;
1554 db->dslite_nat44_inst_id = NAT44_RESERVED_INST_ID;
1556 db->vrfmap_index = my_vrfmap - cnat_map_by_vrf;
1559 * don't forget logging
1560 * logging API is unconditional,
1561 * logging configuration check is done inside the inline function
1564 db->dst_ipv4 = dest_info->k.ipv4;
1565 db->dst_port = dest_info->k.port;
1566 if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) {
1570 if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
1571 if(PREDICT_FALSE(my_vrfmap->nf_logging_policy == SESSION_LOG_ENABLE)) {
1572 /* do not log for static entries.. we will log when traffic flows */
1573 if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) {
1574 cnat_nfv9_nat44_log_session_create(db, 0, my_vrfmap);
1577 cnat_nfv9_log_mapping_create(db, my_vrfmap
1578 #ifndef NO_BULK_LOGGING
1583 if(PREDICT_TRUE((my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE) ||
1584 (db->dst_ipv4 || db->dst_port))) {
1585 cnat_syslog_nat44_mapping_create(db, my_vrfmap, 0
1586 #ifndef NO_BULK_LOGGING
1592 if (PREDICT_FALSE(port_pair_type == PORT_PAIR)) {
1593 cnat_main_db_entry_t *db2 = 0;
1594 cnat_db_key_bucket_t new_ki = *ki;
1597 new_ki.k.k.port += 1;
1600 CNAT_V4_GET_HASH(new_ki.k.key64, new_ki.bucket,
1601 CNAT_MAIN_HASH_MASK);
1603 db2 = cnat_create_main_db_entry_and_hash(&new_ki, &ko, udb);
1605 translation_create_count ++;
1607 db2->dslite_nat44_inst_id = NAT44_RESERVED_INST_ID;
1609 db2->vrfmap_index = my_vrfmap - cnat_map_by_vrf;
1610 db2->entry_expires = cnat_current_time;
1611 db2->flags |= CNAT_DB_FLAG_ALG_ENTRY;
1612 pthread_spin_lock(cnat_db_v2_main.user_db_lockp);
1613 udb->ntranslations += 1;
1614 pthread_spin_unlock(cnat_db_v2_main.user_db_lockp);
1615 db2->dst_ipv4 = dest_info->k.ipv4;
1616 db2->dst_port = dest_info->k.port;
1617 db2->nsessions = 0; /* For ALG db, set sessions to 0 - CSCuf78420 */
1619 if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
1620 if(PREDICT_FALSE(my_vrfmap->nf_logging_policy == SESSION_LOG_ENABLE)) {
1621 /* do not log for static entries.. we will log when traffic flows */
1622 if(PREDICT_TRUE(db2->dst_ipv4 || db2->dst_port)) {
1623 cnat_nfv9_nat44_log_session_create(db2, 0, my_vrfmap);
1626 cnat_nfv9_log_mapping_create(db2, my_vrfmap
1627 #ifndef NO_BULK_LOGGING
1632 if(PREDICT_TRUE((my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE) ||
1633 (db2->dst_ipv4 || db2->dst_port))) {
1634 cnat_syslog_nat44_mapping_create(db2, my_vrfmap, 0
1635 #ifndef NO_BULK_LOGGING
1646 cnat_main_db_entry_t*
1647 cnat_get_main_db_entry_v2(cnat_db_key_bucket_t *ki,
1648 port_pair_t port_pair_type,
1649 port_type_t port_type,
1650 cnat_gen_icmp_info *info,
1651 cnat_key_t *dest_info)
1654 cnat_main_db_entry_t *db;
1655 pthread_spin_lock(cnat_db_v2_main.main_db_lockp);
1656 db = _cnat_get_main_db_entry_v2(ki, port_pair_type,
1657 port_type, info, dest_info);
1658 pthread_spin_unlock(cnat_db_v2_main.main_db_lockp);
1663 * this function is called from config handler only
1664 * to allocate a static port based db entry
1666 * the actual mapped address and port are already specified
1668 cnat_main_db_entry_t*
1669 cnat_create_static_main_db_entry_v2 (cnat_db_key_bucket_t *ki,
1670 cnat_db_key_bucket_t *ko,
1671 cnat_vrfmap_t *my_vrfmap,
1672 cnat_gen_icmp_info *info)
1677 cnat_db_key_bucket_t u_ki;
1678 u32 my_index, free_main, free_user;
1679 cnat_portmap_v2_t *pm =0;
1680 cnat_portmap_v2_t *my_pm =0;
1681 cnat_user_db_entry_t *udb = 0;
1682 cnat_main_db_entry_t *db = 0;
1684 #ifndef NO_BULK_LOGGING
1685 int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
1688 /* UNUSED. Therefore not ported to be multi-thread friendly */
1692 * need to try lookup again because
1693 * second pkt may come here before the entry is created
1694 * by receiving first pkt due to high line rate.
1696 info->gen_icmp_msg = CNAT_NO_ICMP_MSG;
1697 info->error = CNAT_SUCCESS;
1698 db = cnat_main_db_lookup_entry(ki);
1701 * If we already have an entry with this inside address, port
1702 * check delete the entry and proceed further. This should
1703 * If yes, something is terribly wrong. Bail out
1705 if (PREDICT_FALSE(db)) {
1707 if (db->flags & CNAT_DB_FLAG_STATIC_PORT) {
1709 if ((db->out2in_key.k.ipv4 == ko->k.k.ipv4) &&
1710 (db->out2in_key.k.port == ko->k.k.port) &&
1711 (db->out2in_key.k.vrf == ko->k.k.vrf)) {
1713 #ifdef DEBUG_PRINTF_ENABLED
1714 printf("Same Static Port Exists ki 0x%16llx ko 0x%16llx",
1718 * We have already programmed this, return
1724 * We already have a static port with different mapping
1725 * Return an error for this case.
1727 info->error = CNAT_ERR_PARSER;
1729 #ifdef DEBUG_PRINTF_ENABLED
1730 printf("Static Port Existing and Diff ki 0x%16llx ko 0x%16llx",
1731 ki, db->out2in_key);
1734 u32 arr[] = {STAT_PORT_CONFIG_IN_USE, (ki->k.k.vrf & CNAT_VRF_MASK),
1735 ki->k.k.ipv4, ki->k.k.port, (ki->k.k.vrf & CNAT_PRO_MASK) };
1736 spp_printf(CNAT_CONFIG_ERROR, 5, arr);
1741 #ifdef DEBUG_PRINTF_ENABLED
1742 printf("Deleting Dynamic entry ki 0x%16llx ko 0x%16llx",
1743 ki, db->out2in_key);
1747 * If for some reason we have dynamic entries, just delete them
1750 cnat_delete_main_db_entry_v2(db);
1755 protocol = ki->k.k.vrf & CNAT_PRO_MASK;
1756 u_ki.k.k.vrf = ki->k.k.vrf & CNAT_VRF_MASK;
1757 u_ki.k.k.ipv4 = ki->k.k.ipv4;
1760 pm = my_vrfmap->portmap_list;
1763 * check if src vrf, src ip addr is already
1765 * if yes, use PORT_ALLOC_DIRECTED
1766 * if no, use PORT_ALLOC_ANY since it is first time
1768 udb = cnat_user_db_lookup_entry(&u_ki);
1769 if (PREDICT_TRUE(udb)) {
1771 * check if main db has space to accomodate new entry
1773 h = pool_header(cnat_main_db);
1775 free_main = vec_len(h->free_indices) - 1;
1776 if (PREDICT_FALSE(!free_main)) {
1777 info->error = CNAT_MAIN_DB_LIMIT;
1778 CNAT_SET_ICMP_MSG_INFO
1779 in2out_drops_system_limit_reached ++;
1780 CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
1782 printf("Limit reached : OLD USER");
1784 spp_printf(CNAT_MAIN_DB_LIMIT_ERROR, 0, 0);
1789 * allocate port, from existing mapping
1791 my_index = udb->portmap_index;
1792 my_pm = pm + my_index;
1793 /* It is quite possible that we hit the scenario of CSCtj17774.
1794 * Delete all the main db entries and add the ipv4 address sent by
1795 * CGN-MA as Static port alloc any
1798 if (PREDICT_FALSE(my_pm->ipv4_address != ko->k.k.ipv4)) {
1799 if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) {
1800 printf("Delete Main db entry and check for"
1801 " ipv4 address sanity pm add = 0x%x ip add = 0x%x\n",
1802 my_pm->ipv4_address, ko->k.k.ipv4);
1805 /* udb is not NULL when we begin with for sure */
1806 head = udb->translation_list_head_index;
1807 db = cnat_main_db + head;
1808 cnat_delete_main_db_entry_v2(db);
1809 } while (!pool_is_free(cnat_user_db, udb));
1811 rv = cnat_mapped_static_port_alloc_v2_bulk (pm,
1812 PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port,
1813 udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), &nfv9_log_req,
1814 my_vrfmap->ip_n_to_1);
1816 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1818 in2out_drops_resource_depletion ++;
1819 CNAT_SET_ICMP_MSG_INFO
1820 CNAT_DEBUG_INSIDE_ERR(rv)
1824 * create entry in user db
1826 udb = cnat_user_db_create_entry(&u_ki, my_index);
1827 my_pm = pm + my_index;
1828 if(PREDICT_TRUE(my_pm->private_ip_users_count < PORTS_PER_ADDR)) {
1829 my_pm->private_ip_users_count++;
1830 #ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED
1831 PLATFORM_DEBUG_PRINT("\n cnat_create_static_main_db_entry_v2 "
1832 "static del n alloc private_ip_users_count = "
1833 "%d",my_pm->private_ip_users_count);
1836 PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has "
1837 "reached MAX PORTS_PER_ADDR");
1839 NAT44_COMMON_STATS.num_subscribers++;
1840 #ifndef NO_BULK_LOGGING
1841 cnat_update_bulk_range_cache(udb, ko->k.k.port,
1842 BULKSIZE_FROM_VRFMAP(my_vrfmap));
1843 #endif /* #ifndef NO_BULK_LOGGING */
1846 rv = cnat_mapped_static_port_alloc_v2_bulk (pm,
1847 PORT_ALLOC_DIRECTED, &my_index, ko->k.k.ipv4, ko->k.k.port,
1848 udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), &nfv9_log_req,
1849 my_vrfmap->ip_n_to_1);
1851 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1853 CNAT_SET_ICMP_MSG_INFO
1854 CNAT_DEBUG_INSIDE_ERR(rv)
1855 log_port_alloc_error(rv, &(ki->k));
1860 * increment port in use for this user
1862 udb->ntranslations += 1;
1865 if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) {
1866 printf ("Static port alloc any\n");
1869 * first time allocate port for this user
1873 * Check if main db has space for new entry
1874 * Allowing a user db entry to be created if main db is not free
1875 * will cause a port to be allocated to that user, which results in
1876 * wastage of that port, hence the check is done here.
1878 h = pool_header(cnat_main_db);
1879 free_main = vec_len(h->free_indices) - 1;
1880 h = pool_header(cnat_user_db);
1881 free_user = vec_len(h->free_indices) - 1;
1884 * If either main_db or user_db does not have entries
1885 * bail out, with appropriate error
1887 if (PREDICT_FALSE(!(free_main && free_user))) {
1890 info->error = CNAT_USER_DB_LIMIT;
1891 log_error = CNAT_USER_DB_LIMIT_ERROR;
1893 info->error = CNAT_MAIN_DB_LIMIT;
1894 log_error = CNAT_MAIN_DB_LIMIT_ERROR;
1896 in2out_drops_system_limit_reached ++;
1897 CNAT_SET_ICMP_MSG_INFO
1898 CNAT_DEBUG_INSIDE_ERR(info->error)
1899 spp_printf(log_error, 0, 0);
1903 rv = cnat_mapped_static_port_alloc_v2_bulk (pm,
1904 PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port,
1905 udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), &nfv9_log_req,
1906 my_vrfmap->ip_n_to_1);
1908 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1910 in2out_drops_resource_depletion ++;
1911 CNAT_SET_ICMP_MSG_INFO
1912 CNAT_DEBUG_INSIDE_ERR(rv)
1913 log_port_alloc_error(rv, &(ki->k));
1917 * create entry in user db
1919 udb = cnat_user_db_create_entry(&u_ki, my_index);
1920 my_pm = pm + my_index;
1921 if(PREDICT_TRUE(my_pm->private_ip_users_count < PORTS_PER_ADDR)) {
1922 my_pm->private_ip_users_count++;
1923 #ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED
1924 PLATFORM_DEBUG_PRINT("\n cnat_create_static_main_db_entry_v2 "
1925 "static alloc private_ip_users_count = %d",
1926 my_pm->private_ip_users_count);
1929 PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has "
1930 "reached MAX PORTS_PER_ADDR");
1932 NAT44_COMMON_STATS.num_subscribers++;
1933 #ifndef NO_BULK_LOGGING
1934 cnat_update_bulk_range_cache(udb, ko->k.k.port,
1935 BULKSIZE_FROM_VRFMAP(my_vrfmap));
1936 #endif /* #ifndef NO_BULK_LOGGING */
1941 * outside port is allocated for this src vrf/src ip addr
1942 * 1)create a new entry in main db
1943 * 2)setup cnat_out2in_hash key
1944 * 3)setup cnat_in2out_hash key
1946 db = cnat_create_main_db_entry_and_hash(ki, ko, udb);
1948 translation_create_count ++;
1949 db->vrfmap_index = my_vrfmap - cnat_map_by_vrf;
1952 * don't forget logging
1953 * logging API is unconditional,
1954 * logging configuration check is done inside the inline function
1957 if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
1958 /* if session logging is enabled .. do not log as there is no
1961 if(PREDICT_FALSE(my_vrfmap->nf_logging_policy != SESSION_LOG_ENABLE)) {
1962 cnat_nfv9_log_mapping_create(db, my_vrfmap
1963 #ifndef NO_BULK_LOGGING
1968 if(PREDICT_FALSE(my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE)) {
1969 cnat_syslog_nat44_mapping_create(db, my_vrfmap, 0
1970 #ifndef NO_BULK_LOGGING
1981 cnat_main_db_entry_t*
1982 dslite_main_db_lookup_entry(dslite_db_key_bucket_t *ki);
1984 cnat_user_db_entry_t*
1985 dslite_user_db_lookup_entry(dslite_db_key_bucket_t *uki);
1987 cnat_user_db_entry_t*
1988 dslite_user_db_create_entry(dslite_db_key_bucket_t *uki, u32 portmap_index);
1990 cnat_main_db_entry_t*
1991 dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki,
1992 cnat_db_key_bucket_t *ko,
1993 cnat_user_db_entry_t *udb);
1997 * this function is called from config handler only
1998 * to allocate a static port based db entry
2000 * the actual mapped address and port are already specified
2002 cnat_main_db_entry_t*
2003 dslite_create_static_main_db_entry_v2 (dslite_db_key_bucket_t *ki,
2004 cnat_db_key_bucket_t *ko,
2005 dslite_table_entry_t *dslite_entry_ptr,
2006 cnat_gen_icmp_info *info)
2011 dslite_db_key_bucket_t u_ki;
2012 u32 my_index, free_main, free_user;
2013 cnat_portmap_v2_t *pm =0;
2014 cnat_portmap_v2_t *my_pm =0;
2015 cnat_user_db_entry_t *udb = 0;
2016 cnat_main_db_entry_t *db = 0;
2018 u16 dslite_id = dslite_entry_ptr->dslite_id;
2019 #ifndef NO_BULK_LOGGING
2020 int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
2022 cnat_vrfmap_t *my_vrfmap =0;
2023 u16 my_vrfmap_index;
2025 /* UNUSED. Therefore not ported to be multi-thread friendly */
2028 * need to try lookup again because
2029 * second pkt may come here before the entry is created
2030 * by receiving first pkt due to high line rate.
2032 info->gen_icmp_msg = CNAT_NO_ICMP_MSG;
2033 info->error = CNAT_SUCCESS;
2034 db = dslite_main_db_lookup_entry(ki);
2037 * If we already have an entry with this inside address, port
2038 * check delete the entry and proceed further. This should
2039 * If yes, something is terribly wrong. Bail out
2041 if (PREDICT_FALSE(db)) {
2043 if (db->flags & CNAT_DB_FLAG_STATIC_PORT) {
2045 if ((db->out2in_key.k.ipv4 == ko->k.k.ipv4) &&
2046 (db->out2in_key.k.port == ko->k.k.port) &&
2047 (db->out2in_key.k.vrf == ko->k.k.vrf)) {
2049 #ifdef DEBUG_PRINTF_ENABLED
2050 printf("Same Static Port Exists ki 0x%16llx ko 0x%16llx",
2054 * We have already programmed this, return
2060 * We already have a static port with different mapping
2061 * Return an error for this case.
2063 info->error = CNAT_ERR_PARSER;
2065 #ifdef DEBUG_PRINTF_ENABLED
2066 printf("Static Port Existing and Diff ki 0x%16llx ko 0x%16llx",
2067 ki, db->out2in_key);
2070 u32 arr[] = {STAT_PORT_CONFIG_IN_USE, (ki->dk.ipv4_key.k.vrf & CNAT_VRF_MASK),
2071 ki->dk.ipv4_key.k.ipv4, ki->dk.ipv4_key.k.port, (ki->dk.ipv4_key.k.vrf & CNAT_PRO_MASK) };
2072 spp_printf(CNAT_CONFIG_ERROR, 5, arr);
2077 #ifdef DEBUG_PRINTF_ENABLED
2078 printf("Deleting Dynamic entry ki 0x%16llx ko 0x%16llx",
2079 ki, db->out2in_key);
2083 * If for some reason we have dynamic entries, just delete them
2086 cnat_delete_main_db_entry_v2(db);
2092 protocol = ki->dk.ipv4_key.k.vrf & CNAT_PRO_MASK;
2093 u_ki.dk.ipv4_key.k.vrf = ki->dk.ipv4_key.k.vrf & CNAT_VRF_MASK;
2094 u_ki.dk.ipv4_key.k.ipv4 = ki->dk.ipv4_key.k.ipv4;
2095 u_ki.dk.ipv4_key.k.port = 0;
2096 u_ki.dk.ipv6[0] = ki->dk.ipv6[0];
2097 u_ki.dk.ipv6[1] = ki->dk.ipv6[1];
2098 u_ki.dk.ipv6[2] = ki->dk.ipv6[2];
2099 u_ki.dk.ipv6[3] = ki->dk.ipv6[3];
2101 my_vrfmap_index = vrf_map_array[u_ki.dk.ipv4_key.k.vrf];
2102 my_vrfmap = cnat_map_by_vrf + my_vrfmap_index;
2104 pm = dslite_entry_ptr->portmap_list;
2107 * check if src vrf, src ip addr is already
2109 * if yes, use PORT_ALLOC_DIRECTED
2110 * if no, use PORT_ALLOC_ANY since it is first time
2112 udb = dslite_user_db_lookup_entry(&u_ki);
2113 if (PREDICT_TRUE(udb)) {
2115 * check if main db has space to accomodate new entry
2117 h = pool_header(cnat_main_db);
2119 free_main = vec_len(h->free_indices) - 1;
2120 if (PREDICT_FALSE(!free_main)) {
2121 info->error = CNAT_MAIN_DB_LIMIT;
2122 nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
2123 DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
2125 printf("Limit reached : OLD USER");
2127 spp_printf(CNAT_MAIN_DB_LIMIT_ERROR, 0, 0);
2132 * allocate port, from existing mapping
2134 my_index = udb->portmap_index;
2135 my_pm = pm + my_index;
2136 /* It is quite possible that we hit the scenario of CSCtj17774.
2137 * Delete all the main db entries and add the ipv4 address sent by
2138 * CGN-MA as Static port alloc any
2141 if (PREDICT_FALSE(my_pm->ipv4_address != ko->k.k.ipv4)) {
2142 if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) {
2143 printf("Delete Main db entry and check for"
2144 " ipv4 address sanity pm add = 0x%x ip add = 0x%x\n",
2145 my_pm->ipv4_address, ko->k.k.ipv4);
2148 /* udb is not NULL when we begin with for sure */
2149 head = udb->translation_list_head_index;
2150 db = cnat_main_db + head;
2151 cnat_delete_main_db_entry_v2(db);
2152 } while (!pool_is_free(cnat_user_db, udb));
2154 rv = cnat_mapped_static_port_alloc_v2_bulk (pm,
2155 PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port,
2156 udb, BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), &nfv9_log_req,
2157 my_vrfmap->ip_n_to_1);
2159 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
2161 nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
2162 DSLITE_DEBUG_INSIDE_ERR(rv)
2166 * create entry in user db
2168 udb = dslite_user_db_create_entry(&u_ki, my_index);
2169 nat44_dslite_common_stats[dslite_id].num_subscribers++;
2170 #ifndef NO_BULK_LOGGING
2171 if(PREDICT_FALSE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) {
2172 cnat_update_bulk_range_cache(udb, ko->k.k.port,
2173 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr));
2175 #endif /* #ifndef NO_BULK_LOGGING */
2178 rv = cnat_mapped_static_port_alloc_v2_bulk (pm,
2179 PORT_ALLOC_DIRECTED, &my_index, ko->k.k.ipv4, ko->k.k.port,
2180 udb, BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), &nfv9_log_req,
2181 my_vrfmap->ip_n_to_1);
2183 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
2185 DSLITE_DEBUG_INSIDE_ERR(rv)
2186 log_port_alloc_error(rv, &(ki->dk.ipv4_key));
2191 * increment port in use for this user
2193 udb->ntranslations += 1;
2196 if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) {
2197 printf ("Static port alloc any\n");
2200 * first time allocate port for this user
2204 * Check if main db has space for new entry
2205 * Allowing a user db entry to be created if main db is not free
2206 * will cause a port to be allocated to that user, which results in
2207 * wastage of that port, hence the check is done here.
2209 h = pool_header(cnat_main_db);
2210 free_main = vec_len(h->free_indices) - 1;
2211 h = pool_header(cnat_user_db);
2212 free_user = vec_len(h->free_indices) - 1;
2215 * If either main_db or user_db does not have entries
2216 * bail out, with appropriate error
2218 if (PREDICT_FALSE(!(free_main && free_user))) {
2221 info->error = CNAT_USER_DB_LIMIT;
2222 log_error = CNAT_USER_DB_LIMIT_ERROR;
2224 info->error = CNAT_MAIN_DB_LIMIT;
2225 log_error = CNAT_MAIN_DB_LIMIT_ERROR;
2227 nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
2228 DSLITE_DEBUG_INSIDE_ERR(info->error)
2229 spp_printf(log_error, 0, 0);
2233 rv = cnat_mapped_static_port_alloc_v2_bulk (pm,
2234 PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port,
2235 udb, BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), &nfv9_log_req,
2236 my_vrfmap->ip_n_to_1);
2238 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
2240 nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
2241 DSLITE_DEBUG_INSIDE_ERR(rv)
2242 log_port_alloc_error(rv, &(ki->dk.ipv4_key));
2246 * create entry in user db
2248 udb = dslite_user_db_create_entry(&u_ki, my_index);
2249 nat44_dslite_common_stats[dslite_id].num_subscribers++;
2250 #ifndef NO_BULK_LOGGING
2251 if(PREDICT_FALSE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) {
2252 cnat_update_bulk_range_cache(udb, ko->k.k.port,
2253 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr));
2255 #endif /* #ifndef NO_BULK_LOGGING */
2260 * outside port is allocated for this src vrf/src ip addr
2261 * 1)create a new entry in main db
2262 * 2)setup cnat_out2in_hash key
2263 * 3)setup cnat_in2out_hash key
2265 db = dslite_create_main_db_entry_and_hash(ki, ko, udb);
2266 db->dslite_nat44_inst_id = dslite_id;
2267 nat44_dslite_common_stats[dslite_id].active_translations++;
2268 dslite_translation_create_count++;
2271 * don't forget logging
2272 * logging API is unconditional,
2273 * logging configuration check is done inside the inline function
2275 #if 0 /* TBD - NEED TO DECIDE ON LOGGING */
2276 if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
2277 /* if session logging is enabled .. do not log as there is no
2280 #endif /* #if 0 - this has to be removed later */
2284 #endif /* TOBE_PORTED */
2287 /* Per port/ip timeout related routines */
2289 u32 cnat_timeout_db_hash_lookup (cnat_key_t t_key)
2294 cnat_timeout_db_entry_t *db;
2296 key.k.ipv4 = t_key.k.ipv4;
2297 key.k.port = t_key.k.port;
2298 key.k.vrf = t_key.k.vrf;
2300 CNAT_V4_GET_HASH(key.key64,
2301 index, CNAT_TIMEOUT_HASH_MASK)
2304 index = cnat_timeout_hash[index].next;
2306 if (PREDICT_FALSE(index == EMPTY))
2310 db = cnat_timeout_db + index;
2311 if (PREDICT_TRUE((db->t_key.timeout_key.key64 & CNAT_TIMEOUT_FULL_MASK)
2312 == (key.key64 & CNAT_TIMEOUT_FULL_MASK)))
2314 index = db->t_hash.next;
2315 } while (index != EMPTY);
2320 /* Pass db_type as MAIN_DB_TYPE if you are passing
2321 * cnat_main_db_entry_t * casted as void * for db
2322 * else pass db_type as SESSION_DB_TYPE
2325 query_and_update_db_timeout(void *db, u8 db_type)
2327 cnat_key_t t_search_key;
2329 cnat_timeout_db_entry_t *timeout_db_entry;
2333 cnat_main_db_entry_t *mdb = NULL;
2334 cnat_session_entry_t *sdb = NULL;
2336 if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) {
2337 mdb = (cnat_main_db_entry_t *)db;
2338 } else if(db_type == SESSION_DB_TYPE) {
2339 sdb = (cnat_session_entry_t *)db;
2344 h = pool_header(cnat_timeout_db);
2345 free = vec_len(h->free_indices) - 1;
2347 if(free == CNAT_TIMEOUT_HASH_SIZE) {
2348 /* No timeout db configured */
2352 /* First search for ip/port pair */
2353 if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) {
2354 t_search_key.k.ipv4 = mdb->dst_ipv4;
2355 t_search_key.k.port = mdb->dst_port;
2356 t_search_key.k.vrf = mdb->in2out_key.k.vrf;
2358 t_search_key.k.ipv4 = sdb->v4_dest_key.k.ipv4;
2359 t_search_key.k.port = sdb->v4_dest_key.k.port;
2360 t_search_key.k.vrf = sdb->v4_dest_key.k.vrf;
2363 index = cnat_timeout_db_hash_lookup(t_search_key);
2365 if(index == EMPTY) {
2366 /* Search for port map */
2367 t_search_key.k.ipv4 = 0;
2369 index = cnat_timeout_db_hash_lookup(t_search_key);
2371 if(index == EMPTY) {
2372 /* Search for ip only map */
2373 if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) {
2374 t_search_key.k.ipv4 = mdb->dst_ipv4;
2376 t_search_key.k.ipv4 = sdb->v4_dest_key.k.ipv4;
2378 t_search_key.k.port = 0;
2380 index = cnat_timeout_db_hash_lookup(t_search_key);
2381 if(index != EMPTY) {
2382 #ifdef DEBUG_PRINTF_ENABLED
2383 printf("%s: ip only map sucess\n","query_and_update_db_timeout");
2387 #ifdef DEBUG_PRINTF_ENABLED
2388 printf("%s: port only map sucess\n", "query_and_update_db_timeout");
2393 #ifdef DEBUG_PRINTF_ENABLED
2394 printf("%s: ip port map sucess\n","query_and_update_db_timeout");
2399 if(index == EMPTY) {
2400 /* No match found, clear timeout */
2401 if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) {
2406 #ifdef DEBUG_PRINTF_ENABLED
2407 printf("%s: No match\n","query_and_update_db_timeout");
2410 /* Match found, update timeout */
2411 timeout_db_entry = cnat_timeout_db + index;
2412 if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) {
2413 mdb->timeout = timeout_db_entry->t_key.timeout_value;
2415 sdb->timeout = timeout_db_entry->t_key.timeout_value;
2417 return timeout_db_entry->t_key.timeout_value;
2425 void cnat_timeout_db_hash_add (cnat_timeout_db_entry_t *t_entry)
2430 cnat_key_t t_key = t_entry->t_key.timeout_key;
2432 key.k.ipv4 = t_key.k.ipv4;
2433 key.k.port = t_key.k.port;
2434 key.k.vrf = t_key.k.vrf;
2436 CNAT_V4_GET_HASH(key.key64,
2437 bucket, CNAT_TIMEOUT_HASH_MASK)
2440 index = cnat_timeout_hash[bucket].next;
2442 /* Add this db entry to the head of the bucket chain */
2443 t_entry->t_hash.next = index;
2444 cnat_timeout_hash[bucket].next = t_entry - cnat_timeout_db;
2450 cnat_timeout_db_create (cnat_timeout_t t_entry)
2452 cnat_timeout_db_entry_t *db;
2453 cnat_key_t t_key = t_entry.timeout_key;
2459 /* UNUSED. Therefore not ported to be multi-thread friendly */
2462 db_index = cnat_timeout_db_hash_lookup(t_key);
2464 if(db_index != EMPTY) {
2465 /* Entry already exists. Check if it is replay or update */
2466 db = cnat_timeout_db + db_index;
2467 db->t_key.timeout_value = t_entry.timeout_value;
2468 return CNAT_SUCCESS;
2471 h = pool_header(cnat_timeout_db);
2472 free = vec_len(h->free_indices) - 1;
2475 return CNAT_OUT_LIMIT;
2479 pool_get(cnat_timeout_db, db);
2482 memset(db, 0, sizeof(*db));
2484 db_index = db - cnat_timeout_db;
2486 db->t_key.timeout_key.k.ipv4 = t_key.k.ipv4;
2487 db->t_key.timeout_key.k.port = t_key.k.port;
2488 db->t_key.timeout_key.k.vrf = t_key.k.vrf;
2489 db->t_key.timeout_value = t_entry.timeout_value;
2492 cnat_timeout_db_hash_add(db);
2493 return CNAT_SUCCESS;
2496 void cnat_timeout_db_delete(cnat_key_t t_key)
2501 cnat_timeout_db_entry_t *this, *prev;
2503 /* UNUSED. Therefore not ported to be multi-thread friendly */
2506 key.k.ipv4 = t_key.k.ipv4;
2507 key.k.port = t_key.k.port;
2508 key.k.vrf = t_key.k.vrf;
2511 CNAT_V4_GET_HASH(key.key64,
2512 bucket, CNAT_TIMEOUT_HASH_MASK)
2515 index = cnat_timeout_hash[bucket].next;
2517 if(index == EMPTY) return;
2521 this = cnat_timeout_db + index;
2523 (this->t_key.timeout_key.key64 & CNAT_TIMEOUT_FULL_MASK) ==
2524 (key.key64 & CNAT_TIMEOUT_FULL_MASK))) {
2526 cnat_timeout_hash[bucket].next = this->t_hash.next;
2529 prev->t_hash.next = this->t_hash.next;
2535 index = this->t_hash.next;
2536 } while (index != EMPTY);
2538 if(index == EMPTY) return;
2541 pool_put(cnat_timeout_db, this);
2545 void cnat_session_db_hash_delete (cnat_session_entry_t *ep)
2549 cnat_session_entry_t *this, *prev;
2551 CNAT_V4_GET_SESSION_HASH(ep->main_db_index, ep->v4_dest_key.k.ipv4,
2552 ep->v4_dest_key.k.port, ep->v4_dest_key.k.vrf, bucket,
2553 CNAT_SESSION_HASH_MASK)
2556 index = cnat_session_hash[bucket].next;
2558 ASSERT(index != EMPTY);
2562 this = cnat_session_db + index;
2563 if (PREDICT_TRUE(this == ep)) {
2565 cnat_session_hash[bucket].next =
2566 ep->cnat_session_hash.next;
2569 prev->cnat_session_hash.next =
2570 ep->cnat_session_hash.next;
2575 index = this->cnat_session_hash.next;
2576 } while (index != EMPTY);
2582 cnat_session_entry_t *
2583 cnat_session_db_edm_lookup_entry(cnat_key_t *ko,u32 session_head_index,
2587 cnat_session_entry_t *db;
2590 index = session_head_index;
2591 if (PREDICT_TRUE(index == EMPTY)) {
2596 db = cnat_session_db + index;
2597 if(PREDICT_TRUE((db->main_db_index == main_db_index) &&
2598 (db->v4_dest_key.k.vrf == ko->k.vrf) &&
2599 (db->v4_dest_key.k.ipv4 == ko->k.ipv4))) {
2603 index = db->cnat_session_hash.next;
2604 } while (index != EMPTY);
2611 cnat_session_entry_t *
2612 cnat_session_db_lookup_entry(cnat_key_t *ko,u32 main_db_index)
2616 cnat_session_entry_t *db;
2618 CNAT_V4_GET_SESSION_HASH(main_db_index, ko->k.ipv4, ko->k.port,
2619 ko->k.vrf, bucket, CNAT_SESSION_HASH_MASK)
2622 index = cnat_session_hash[bucket].next;
2623 if (PREDICT_TRUE(index == EMPTY)) {
2628 db = cnat_session_db + index;
2629 if(PREDICT_TRUE((db->main_db_index == main_db_index) &&
2630 (db->v4_dest_key.k.vrf == ko->k.vrf) &&
2631 (db->v4_dest_key.k.port == ko->k.port) &&
2632 (db->v4_dest_key.k.ipv4 == ko->k.ipv4))) {
2636 index = db->cnat_session_hash.next;
2637 } while (index != EMPTY);
2642 cnat_session_entry_t *
2643 cnat_create_session_db_entry(cnat_key_t *ko,
2644 cnat_main_db_entry_t *bdb, u8 log)
2647 u32 db_index, bucket_out;
2648 cnat_session_entry_t *db = NULL;
2653 db = cnat_session_db_lookup_entry(ko, bdb - cnat_main_db);
2654 if (PREDICT_FALSE(db != NULL)) {
2655 /*printf("Create Session - Entry already Exists\n");*/
2659 h = pool_header(cnat_session_db);
2660 free_session = vec_len(h->free_indices) - 1;
2662 if (bdb->flags & CNAT_DB_DSLITE_FLAG) {
2663 instance = bdb->dslite_nat44_inst_id;
2665 instance = NAT44_RESERVED_INST_ID;
2668 if (PREDICT_FALSE(!free_session)) {
2669 nat44_dslite_common_stats[instance].drops_sessiondb_limit_exceeded++;
2673 if( PREDICT_FALSE(bdb->nsessions == CNAT_MAX_SESSIONS_PER_BIB)) {
2674 /* printf("Create Session - Max sessions per BIB reached\n"); */
2678 pthread_spin_lock(cnat_db_v2_main.session_db_lockp);
2679 pool_get(cnat_session_db, db);
2680 memset(db, 0, sizeof(*db));
2682 db_index = db - cnat_session_db;
2683 db->v4_dest_key.k.port = ko->k.port;
2684 db->v4_dest_key.k.ipv4 = ko->k.ipv4;
2685 db->v4_dest_key.k.vrf = ko->k.vrf;
2687 db->main_list.next = db_index;
2688 db->main_list.prev = db_index;
2689 db->main_db_index = bdb - cnat_main_db;
2691 db->tcp_seq_num = 0;
2695 if(PREDICT_FALSE(log)) {
2697 query_and_update_db_timeout(db, SESSION_DB_TYPE);
2700 if (PREDICT_FALSE(bdb->nsessions == 1)) {
2702 * first port for this src vrf/src ip addr
2704 bdb->session_head_index = db_index;
2706 index_dlist_addtail(bdb->session_head_index,
2707 (u8 *)cnat_session_db, sizeof(cnat_session_db[0]),
2708 STRUCT_OFFSET_OF(cnat_session_entry_t, main_list),
2713 * setup o2i hash key
2715 CNAT_V4_GET_SESSION_HASH(db->main_db_index, ko->k.ipv4, ko->k.port,
2716 ko->k.vrf, bucket_out, CNAT_SESSION_HASH_MASK)
2719 db->cnat_session_hash.next =
2720 cnat_session_hash[bucket_out].next;
2721 cnat_session_hash[bucket_out].next = db_index;
2724 if(PREDICT_FALSE(log)) {
2725 if (bdb->flags & CNAT_DB_DSLITE_FLAG) {
2726 cnat_session_log_ds_lite_mapping_create(bdb,
2727 (dslite_table_db_ptr + instance),db);
2729 cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + bdb->vrfmap_index;
2730 cnat_session_log_nat44_mapping_create(bdb, db, my_vrfmap);
2734 /* Need to set entry_expires here, as we need to override 0 check for
2735 newly established sessions */
2736 db->entry_expires = cnat_current_time;
2737 nat44_dslite_common_stats[instance].sessions++;
2738 pthread_spin_unlock(cnat_db_v2_main.session_db_lockp);
2743 cnat_dest_update_main2session(cnat_main_db_entry_t *mdb,
2744 cnat_session_entry_t *sdb)
2747 sdb->flags = mdb->flags;
2748 sdb->timeout = mdb->timeout;
2749 sdb->entry_expires = mdb->entry_expires;
2750 sdb->alg.delta = mdb->alg.delta;
2751 sdb->tcp_seq_num = mdb->proto_data.seq_pcp.tcp_seq_num;
2753 /* Reset Main db values to 0 */
2754 /* Reset only session specific flags */
2755 mdb->flags &= ~(CNAT_DB_FLAG_TCP_ACTIVE | CNAT_DB_FLAG_UDP_ACTIVE
2756 | CNAT_DB_FLAG_ALG_ENTRY | CNAT_DB_FLAG_ALG_CTRL_FLOW);
2758 mdb->entry_expires = 0;
2760 if(PREDICT_FALSE(!((mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE) ||
2761 (mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_INIT)))) {
2762 mdb->proto_data.seq_pcp.tcp_seq_num = 0;
2771 cnat_dest_update_session2main(cnat_main_db_entry_t *mdb,
2772 cnat_session_entry_t *sdb)
2775 u16 flags = sdb->flags & (CNAT_DB_FLAG_TCP_ACTIVE |
2776 CNAT_DB_FLAG_UDP_ACTIVE | CNAT_DB_FLAG_ALG_ENTRY |
2777 CNAT_DB_FLAG_ALG_CTRL_FLOW);
2778 mdb->flags |= flags;
2779 mdb->timeout = sdb->timeout;
2780 mdb->entry_expires = sdb->entry_expires;
2781 mdb->alg.delta = sdb->alg.delta;
2782 if(PREDICT_FALSE(!((mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE) ||
2783 (mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_INIT)))) {
2784 mdb->proto_data.seq_pcp.tcp_seq_num = sdb->tcp_seq_num;
2786 mdb->dst_ipv4 = sdb->v4_dest_key.k.ipv4;
2787 mdb->dst_port = sdb->v4_dest_key.k.port;
2791 _cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log)
2793 u32 session_db_index;
2795 cnat_main_db_entry_t *be =0;
2796 cnat_session_entry_t *sdb_last = NULL;
2799 if (PREDICT_FALSE(ep->flags & CNAT_DB_NAT64_FLAG) != 0) {
2800 /* Preventive check - Not a NAT44 entry */
2804 pool_header_t *h = pool_header(cnat_main_db);
2806 /* Validate .. just in case we are trying to delete a non existing one */
2807 bdb_len = vec_len(cnat_main_db);
2809 /* In case of invalid user just return, deleting only main db
2810 * is not a good idea, since some valid user db entry might be pointing
2811 * to that main db and hence leave the dbs in a inconsistent state
2813 if (PREDICT_FALSE((ep->main_db_index >= bdb_len) ||
2814 (clib_bitmap_get(h->free_bitmap, ep->main_db_index)))) {
2815 #ifdef DEBUG_PRINTF_ENABLED
2816 printf("invalid/unused user index in db %d\n", ep->main_db_index);
2818 spp_printf(CNAT_INV_UNUSED_USR_INDEX, 1, (u32 *) &(ep->main_db_index));
2822 be = cnat_main_db + ep->main_db_index;
2824 session_db_index = ep - cnat_session_db;
2826 be->session_head_index = index_dlist_remelem (
2827 be->session_head_index, (u8 *)cnat_session_db,
2828 sizeof (cnat_session_db[0]),
2829 STRUCT_OFFSET_OF(cnat_session_entry_t, main_list),
2832 if (be->flags & CNAT_DB_DSLITE_FLAG) {
2833 instance = be->dslite_nat44_inst_id;
2835 instance = NAT44_RESERVED_INST_ID;
2838 if(PREDICT_TRUE(log)) {
2839 if (be->flags & CNAT_DB_DSLITE_FLAG) {
2840 cnat_session_log_ds_lite_mapping_delete(be,
2841 (dslite_table_db_ptr + instance),ep);
2843 cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + be->vrfmap_index;
2844 cnat_session_log_nat44_mapping_delete(be, ep, my_vrfmap);
2849 if (PREDICT_FALSE(be->nsessions == 1 && log)) {
2850 /* There is only 1 session left
2851 * Copy the info back to main db and release the last
2855 sdb_last = cnat_session_db + be->session_head_index;
2856 ASSERT(sdb_last != NULL);
2858 cnat_dest_update_session2main(be, sdb_last);
2859 _cnat_delete_session_db_entry(sdb_last, FALSE);
2862 /* Remove from session DB hashes */
2863 cnat_session_db_hash_delete(ep);
2864 nat44_dslite_common_stats[instance].sessions--;
2866 pool_put(cnat_session_db, ep);
2869 void cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log)
2871 pthread_spin_lock(cnat_db_v2_main.session_db_lockp);
2872 _cnat_delete_session_db_entry (ep, log);
2873 pthread_spin_unlock(cnat_db_v2_main.session_db_lockp);
2876 cnat_main_db_entry_t*
2877 dslite_main_db_lookup_entry(dslite_db_key_bucket_t *ki)
2881 cnat_main_db_entry_t *db;
2882 cnat_user_db_entry_t *userdb;
2884 DSLITE_V6_GET_HASH((&(ki->dk)),
2886 CNAT_MAIN_HASH_MASK);
2888 DSLITE_PRINTF(1,"MDBLU hash..%u\n", ki->bucket);
2890 index = cnat_in2out_hash[ki->bucket].next;
2891 if (PREDICT_TRUE(index == EMPTY)) {
2892 DSLITE_PRINTF(1,"MDBLU index MT..\n");
2897 /* We can add a flag here to indicate if the db entry is for nat44 or
2898 * dslite. If the db entry is for nat44 then we can simply move to the
2901 db = cnat_main_db + index;
2902 userdb = cnat_user_db + db->user_index;
2903 if (PREDICT_TRUE(db->in2out_key.key64 == ki->dk.ipv4_key.key64)
2904 && userdb->ipv6[0] == ki->dk.ipv6[0]
2905 && userdb->ipv6[1] == ki->dk.ipv6[1]
2906 && userdb->ipv6[2] == ki->dk.ipv6[2]
2907 && userdb->ipv6[3] == ki->dk.ipv6[3]) {
2908 DSLITE_PRINTF(1,"MDBLU success..%u\n", index);
2911 index = db->in2out_hash.next;
2912 } while (index != EMPTY);
2914 DSLITE_PRINTF(1,"MDBLU Entry does not exist..\n");
2918 cnat_user_db_entry_t*
2919 dslite_user_db_lookup_entry(dslite_db_key_bucket_t *uki)
2923 cnat_user_db_entry_t *udb=NULL;
2925 DSLITE_V6_GET_HASH((&(uki->dk)),
2927 CNAT_USER_HASH_MASK)
2929 DSLITE_PRINTF(1,"UDBLU hash..%u\n", uki->bucket);
2931 /* now: index in user vector */
2932 index = cnat_user_hash[uki->bucket].next;
2933 if (PREDICT_TRUE(index != EMPTY)) {
2934 DSLITE_PRINTF(1,"UDBLU hash table entry not MT..\n");
2936 udb = cnat_user_db + index;
2937 if (PREDICT_FALSE(udb->key.key64 == uki->dk.ipv4_key.key64)
2938 && udb->ipv6[0] == uki->dk.ipv6[0]
2939 && udb->ipv6[1] == uki->dk.ipv6[1]
2940 && udb->ipv6[2] == uki->dk.ipv6[2]
2941 && udb->ipv6[3] == uki->dk.ipv6[3]) {
2942 DSLITE_PRINTF(1,"UDBLU success..%u\n", index);
2945 index = udb->user_hash.next;
2946 } while (index != EMPTY);
2948 DSLITE_PRINTF(1,"UDBLU Entry doesnt exist..\n");
2952 cnat_user_db_entry_t*
2953 dslite_user_db_create_entry(dslite_db_key_bucket_t *uki,
2956 cnat_user_db_entry_t *udb = NULL;
2958 /* UNUSED. Therefore not ported to be multi-thread friendly */
2961 pool_get(cnat_user_db, udb);
2962 memset(udb, 0, sizeof(*udb));
2964 udb->ntranslations = 1;
2965 udb->portmap_index = portmap_index;
2966 // udb->key.key64 = uki->k.key64;
2968 udb->key.key64 = uki->dk.ipv4_key.key64;
2969 udb->ipv6[0] = uki->dk.ipv6[0];
2970 udb->ipv6[1] = uki->dk.ipv6[1];
2971 udb->ipv6[2] = uki->dk.ipv6[2];
2972 udb->ipv6[3] = uki->dk.ipv6[3];
2974 udb->flags |= CNAT_USER_DB_DSLITE_FLAG;
2975 /* Add this user to the head of the bucket chain */
2976 udb->user_hash.next =
2977 cnat_user_hash[uki->bucket].next;
2978 cnat_user_hash[uki->bucket].next = udb - cnat_user_db;
2980 #ifndef NO_BULK_LOGGING
2981 INIT_BULK_CACHE(udb)
2982 #endif /* NO_BULK_LOGGING */
2988 cnat_main_db_entry_t*
2989 dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki,
2990 cnat_db_key_bucket_t *ko,
2991 cnat_user_db_entry_t *udb)
2996 cnat_main_db_entry_t*
2997 dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki,
2998 cnat_db_key_bucket_t *ko,
2999 cnat_user_db_entry_t *udb)
3003 cnat_main_db_entry_t *db = NULL;
3005 /* UNUSED. Therefore not ported to be multi-thread friendly */
3008 pool_get(cnat_main_db, db);
3009 memset(db, 0, sizeof(*db));
3011 db_index = db - cnat_main_db;
3012 db->in2out_key.k.ipv4 = ki->dk.ipv4_key.k.ipv4;
3013 db->in2out_key.k.port = ki->dk.ipv4_key.k.port;
3014 db->in2out_key.k.vrf = ki->dk.ipv4_key.k.vrf;
3015 db->out2in_key.k.ipv4 = ko->k.k.ipv4;
3016 db->out2in_key.k.port = ko->k.k.port;
3017 db->out2in_key.k.vrf = ko->k.k.vrf;
3019 db->user_ports.next = db_index;
3020 db->user_ports.prev = db_index;
3021 db->user_index = udb - cnat_user_db;
3022 //db->portmap_index = udb->portmap_index;
3023 db->flags |= CNAT_DB_DSLITE_FLAG;
3025 if (PREDICT_FALSE(udb->ntranslations == 1)) {
3027 * first port for this src vrf/src ip addr
3029 udb->translation_list_head_index = db_index;
3030 DSLITE_PRINTF(1,"First translation of this user..\n");
3032 index_dlist_addtail(udb->translation_list_head_index,
3033 (u8 *)cnat_main_db, sizeof(cnat_main_db[0]),
3034 STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports),
3039 * setup o2i hash key
3041 CNAT_V4_GET_HASH(ko->k.key64,
3043 CNAT_MAIN_HASH_MASK)
3044 db->out2in_hash.next = cnat_out2in_hash[ko->bucket].next;
3045 cnat_out2in_hash[ko->bucket].next = db_index;
3047 * setup i2o hash key, bucket is already calculate
3049 db->in2out_hash.next = cnat_in2out_hash[ki->bucket].next;
3050 cnat_in2out_hash[ki->bucket].next = db_index;
3052 DSLITE_PRINTF(1,"Create main db and hash..%u %u %u %u %x\n",
3053 ki->bucket, ko->bucket,
3054 db_index, db->user_index, ko->k.key64);
3057 printf("\nMy_Instance_Number %d: Bucket %d, Db_Index %d",
3058 my_instance_number, ki->bucket, db_index);
3059 printf("\nInside (VRF 0x%x, IP 0x%x, PORT 0x%x)",
3060 db->in2out_key.k.vrf, db->in2out_key.k.ipv4, db->in2out_key.k.port);
3061 printf("\nOutside (VRF 0x%x, IP 0x%x, PORT 0x%x)",
3062 db->out2in_key.k.vrf, db->out2in_key.k.ipv4, db->out2in_key.k.port);
3063 printf("\nUser Index %d, IP 0x%x",
3064 db->user_index, udb->key.k.ipv4);
3067 //nat44_dslite_common_stats[DSLITE_COMMON_STATS].active_translations++;
3072 static inline void handle_dslite_port_exceeded_logging(
3073 cnat_user_db_entry_t *udb,
3075 dslite_table_entry_t *dslite_entry_ptr)
3078 if(PREDICT_TRUE(udb->flags & CNAT_USER_DB_PORT_LIMIT_EXCEEDED)) {
3079 /* Already logged ..*/
3083 /* else, set the flag and call the log API */
3084 udb->flags = udb->flags | CNAT_USER_DB_PORT_LIMIT_EXCEEDED;
3085 cnat_log_ds_lite_port_limit_exceeded(key, dslite_entry_ptr);
3090 void handle_cnat_port_exceeded_logging(
3091 cnat_user_db_entry_t *udb,
3093 cnat_vrfmap_t *vrfmap)
3096 if(PREDICT_TRUE(udb->flags & CNAT_USER_DB_PORT_LIMIT_EXCEEDED)) {
3097 /* Already logged ..*/
3101 /* else, set the flag and call the log API */
3102 udb->flags = udb->flags | CNAT_USER_DB_PORT_LIMIT_EXCEEDED;
3103 cnat_log_nat44_port_limit_exceeded(key,vrfmap);
3108 cnat_main_db_entry_t*
3109 dslite_get_main_db_entry_v2(dslite_db_key_bucket_t *ki,
3110 port_pair_t port_pair_type,
3111 port_type_t port_type,
3112 cnat_gen_icmp_info *info,
3113 dslite_table_entry_t *dslite_entry_ptr,
3114 cnat_key_t *dest_info)
3120 * this function is called by exception node
3121 * when lookup is fialed in i2o node
3123 * if reash per user port limit,
3124 * set user_db_entry pointer, and error == CNAT_OUT_LIMIT
3126 cnat_main_db_entry_t*
3127 dslite_get_main_db_entry_v2(dslite_db_key_bucket_t *ki,
3128 port_pair_t port_pair_type,
3129 port_type_t port_type,
3130 cnat_gen_icmp_info *info,
3131 dslite_table_entry_t *dslite_entry_ptr,
3132 cnat_key_t *dest_info)
3136 dslite_db_key_bucket_t u_ki;
3137 cnat_db_key_bucket_t ko;
3138 u32 my_index, free_main, free_user;
3139 u32 current_timestamp;
3140 cnat_vrfmap_t *my_vrfmap =0;
3141 u16 my_vrfmap_index;
3142 cnat_portmap_v2_t *pm =0;
3143 cnat_user_db_entry_t *udb = 0;
3144 cnat_main_db_entry_t *db = 0;
3146 u16 dslite_id = dslite_entry_ptr->dslite_id;
3148 #ifndef NO_BULK_LOGGING
3149 int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
3152 /* UNUSED. Therefore not ported to be multi-thread friendly */
3156 * need to try lookup again because
3157 * second pkt may come here before the entry is created
3158 * by receiving first pkt due to high line rate.
3160 info->gen_icmp_msg = CNAT_NO_ICMP_MSG;
3161 info->error = CNAT_SUCCESS;
3162 db = dslite_main_db_lookup_entry(ki);
3163 if (PREDICT_TRUE(db)) {
3164 /* what if the source is talking to a
3165 * new dest now? We will have to handle this case and
3166 * take care of - creating session db and logging
3168 if(PREDICT_FALSE((!dest_info->k.ipv4) && (!dest_info->k.port))) {
3169 return db; /* if dest_info is null don't create session */
3172 if(PREDICT_TRUE((db->dst_ipv4 == dest_info->k.ipv4) &&
3173 (db->dst_port == dest_info->k.port))) {
3176 dest_info->k.vrf = db->in2out_key.k.vrf;
3177 /* Src is indeed talking to a different dest */
3178 cnat_session_entry_t *session_db2 = NULL;
3179 if(PREDICT_TRUE(db->nsessions == 1)) {
3180 session_db2 = cnat_handle_1to2_session(db, dest_info);
3181 if(PREDICT_TRUE(session_db2 != NULL)) {
3182 CNAT_DB_TIMEOUT_RST(session_db2);
3185 info->error = CNAT_ERR_NO_SESSION_DB;
3188 } else if(PREDICT_FALSE(db->nsessions == 0)) {
3189 /* Should be static entry.. should never happen
3191 if(PREDICT_TRUE(dest_info->k.ipv4 != 0)) {
3192 cnat_add_dest_n_log(db, dest_info);
3196 /* The src has already created multiple sessions.. very rare
3198 session_db2 = cnat_create_session_db_entry(dest_info,
3200 if(PREDICT_TRUE(session_db2 != NULL)) {
3201 CNAT_DB_TIMEOUT_RST(session_db2);
3204 info->error = CNAT_ERR_NO_SESSION_DB;
3212 * step 1. check if outside vrf is configured or not
3213 * and Find the set of portmaps for the outside vrf
3214 * insider vrf is one to one mappted to outside vrf
3215 * key is vrf and ip only
3216 * ki.k.k.vrf has protocol bits, mask out
3218 protocol = ki->dk.ipv4_key.k.vrf & CNAT_PRO_MASK;
3219 u_ki.dk.ipv4_key.k.vrf = ki->dk.ipv4_key.k.vrf & CNAT_VRF_MASK;
3220 #ifdef DSLITE_USER_IPV4
3221 u_ki.dk.ipv4_key.k.ipv4 = ki->dk.ipv4_key.k.ipv4;
3224 * Inside ipv4 address should be masked, if port limit
3225 * need to be done at B4 element level.
3227 u_ki.dk.ipv4_key.k.ipv4 = 0;
3229 u_ki.dk.ipv4_key.k.port = 0;
3231 u_ki.dk.ipv6[0] = ki->dk.ipv6[0];
3232 u_ki.dk.ipv6[1] = ki->dk.ipv6[1];
3233 u_ki.dk.ipv6[2] = ki->dk.ipv6[2];
3234 u_ki.dk.ipv6[3] = ki->dk.ipv6[3];
3236 my_vrfmap_index = vrf_map_array[u_ki.dk.ipv4_key.k.vrf];
3237 my_vrfmap = cnat_map_by_vrf + my_vrfmap_index;
3238 /* Checking if the inst entry is active or not is done much earlier
3241 my_vrfmap_index = vrf_map_array[u_ki.k.k.vrf];
3242 my_vrfmap = cnat_map_by_vrf + my_vrfmap_index;
3243 my_vrfmap_entry_found = ((my_vrfmap_index != VRF_MAP_ENTRY_EMPTY) &&
3244 (my_vrfmap->status == S_RUN) &&
3245 (my_vrfmap->i_vrf == u_ki.k.k.vrf));
3247 if (PREDICT_FALSE(!my_vrfmap_entry_found)) {
3248 u32 arr[] = {ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port};
3249 if ((my_vrfmap_index == VRF_MAP_ENTRY_EMPTY) ||
3250 (my_vrfmap->i_vrf == u_ki.k.k.vrf)) {
3251 info->error = CNAT_NO_CONFIG;
3252 CNAT_DEBUG_INSIDE_ERR(CNAT_NO_CONFIG)
3253 spp_printf(CNAT_NO_CONFIG_ERROR, 3, arr);
3255 info->error = CNAT_NO_VRF_RUN;
3256 CNAT_DEBUG_INSIDE_ERR(CNAT_NO_VRF_RUN)
3257 spp_printf(CNAT_NO_VRF_RUN_ERROR, 3, arr);
3264 dslite_inst_ptr = dslite_nat44_config_table[dslite_inst_id];
3266 pm = dslite_entry_ptr->portmap_list;
3267 //pm = my_vrfmap->portmap_list;
3270 * set o2i key with protocl bits
3272 ko.k.k.vrf = dslite_entry_ptr->o_vrf | protocol;
3273 //ko.k.k.vrf = my_vrfmap->o_vrf | protocol;
3276 * step 2. check if src vrf, src ip addr is alreay
3278 * if yes, use PORT_ALLOC_DIRECTED
3279 * if no, use PORT_ALLOC_ANY since it is first time
3281 udb = dslite_user_db_lookup_entry(&u_ki);
3282 if (PREDICT_TRUE(udb)) {
3284 * not first time allocate port for this user
3287 if (PREDICT_FALSE(udb->ntranslations >=
3288 dslite_entry_ptr->cnat_main_db_max_ports_per_user)) {
3289 //cnat_main_db_max_ports_per_user))
3291 /* Check for the port type here. If we are getting
3292 * a STATIC PORT, allow the config.
3294 if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) {
3295 info->error = CNAT_OUT_LIMIT;
3296 DSLITE_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT)
3297 port_exceeded_msg_log(u_ki.dk.ipv4_key.k.ipv4, u_ki.dk.ipv4_key.k.vrf);
3298 nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
3299 u_ki.dk.ipv4_key.k.vrf = ki->dk.ipv4_key.k.vrf;
3300 u_ki.dk.ipv4_key.k.port = ki->dk.ipv4_key.k.port;
3301 handle_dslite_port_exceeded_logging(udb, &u_ki.dk, dslite_entry_ptr);
3306 CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb,
3307 dslite_entry_ptr->cnat_main_db_max_ports_per_user)
3310 * check if main db has space to accomodate new entry
3312 h = pool_header(cnat_main_db);
3314 free_main = vec_len(h->free_indices) - 1;
3315 if (PREDICT_FALSE(!free_main)) {
3316 info->error = CNAT_MAIN_DB_LIMIT;
3317 nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++;
3318 DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
3320 current_timestamp = spp_trace_log_get_unix_time_in_seconds();
3321 if (PREDICT_FALSE((current_timestamp - last_log_timestamp) >
3323 spp_printf(CNAT_SESSION_THRESH_EXCEEDED, 0, NULL);
3324 last_log_timestamp = current_timestamp;
3328 printf("Limit reached : OLD USER");
3334 * allocate port, from existing mapping
3336 my_index = udb->portmap_index;
3338 if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
3339 rv = cnat_static_port_alloc_v2_bulk(pm,
3340 PORT_ALLOC_DIRECTED,
3342 ki->dk.ipv4_key.k.ipv4,
3343 ki->dk.ipv4_key.k.port,
3347 STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3348 #ifndef NO_BULK_LOGGING
3350 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3353 , my_vrfmap->ip_n_to_1
3355 } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP) ) {
3357 rv = cnat_dynamic_port_alloc_v2_bulk(pm,
3358 PORT_ALLOC_DIRECTED,
3363 STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3364 #ifndef NO_BULK_LOGGING
3366 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3370 &(dslite_entry_ptr->rseed_ip)
3372 DSLITE_PRINTF(1,"D_PORT_ALLOC %x %u\n", ko.k.k.ipv4, ko.k.k.port);
3375 * For RTSP, two translation entries are created,
3376 * check if main db has space to accomodate two new entry
3378 free_main = free_main - 1;
3380 if (PREDICT_FALSE(!free_main)) {
3381 info->error = CNAT_MAIN_DB_LIMIT;
3382 nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++;
3383 DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
3388 rv = cnat_dynamic_port_alloc_rtsp_bulk(pm,
3389 PORT_ALLOC_DIRECTED,
3391 ki->dk.ipv4_key.k.port,
3395 STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3396 #ifndef NO_BULK_LOGGING
3398 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3401 , &(dslite_entry_ptr->rseed_ip)
3406 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
3407 DSLITE_PRINTF(1,"D_PORT_ALLOC port alloc error\n");
3409 DSLITE_DEBUG_INSIDE_ERR(rv)
3410 nat44_dslite_common_stats[dslite_id].in2out_drops_resource_depletion ++;
3411 log_port_alloc_error(rv, &(ki->dk.ipv4_key));
3415 * increment port in use for this user
3417 udb->ntranslations += 1;
3420 * first time allocate port for this user
3424 * Do not create entry if port limit is invalid
3426 if (PREDICT_FALSE(!(dslite_entry_ptr->cnat_main_db_max_ports_per_user))) {
3427 if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) {
3428 info->error = CNAT_OUT_LIMIT;
3429 nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
3430 port_exceeded_msg_log(u_ki.dk.ipv4_key.k.ipv4, u_ki.dk.ipv4_key.k.vrf);
3431 DSLITE_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT)
3437 * Check if main db has space for new entry
3438 * Allowing a user db entry to be created if main db is not free
3439 * will cause a port to be allocated to that user, which results in
3440 * wastage of that port, hence the check is done here.
3442 h = pool_header(cnat_main_db);
3443 free_main = vec_len(h->free_indices) - 1;
3445 h = pool_header(cnat_user_db);
3446 free_user = vec_len(h->free_indices) - 1;
3449 * If either main_db or user_db does not have entries
3450 * bail out, with appropriate error
3452 if (PREDICT_FALSE(!(free_main && free_user))) {
3455 info->error = CNAT_USER_DB_LIMIT;
3456 log_error = CNAT_USER_DB_LIMIT_ERROR;
3458 info->error = CNAT_MAIN_DB_LIMIT;
3459 log_error = CNAT_MAIN_DB_LIMIT_ERROR;
3461 nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++;
3462 DSLITE_DEBUG_INSIDE_ERR(info->error)
3463 spp_printf(log_error, 0, 0);
3467 if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
3468 rv = cnat_static_port_alloc_v2_bulk(pm,
3471 ki->dk.ipv4_key.k.ipv4,
3472 ki->dk.ipv4_key.k.port,
3476 STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3477 #ifndef NO_BULK_LOGGING
3479 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3482 , my_vrfmap->ip_n_to_1
3485 } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP)) {
3486 rv = cnat_dynamic_port_alloc_v2_bulk(pm,
3492 STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3493 #ifndef NO_BULK_LOGGING
3495 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3499 &(dslite_entry_ptr->rseed_ip)
3501 DSLITE_PRINTF(1,"NU:D PORT ALLOC..%x %u\n", ko.k.k.ipv4,
3506 * For RTSP, two translation entries are created,
3507 * check if main db has space to accomodate two new entry
3509 free_main = free_main - 1;
3511 if (PREDICT_FALSE(!free_main)) {
3512 info->error = CNAT_MAIN_DB_LIMIT;
3513 nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++;
3514 DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT)
3519 rv = cnat_dynamic_port_alloc_rtsp_bulk(pm,
3520 PORT_ALLOC_DIRECTED,
3522 ki->dk.ipv4_key.k.port,
3526 STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3527 #ifndef NO_BULK_LOGGING
3529 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3532 , &(dslite_entry_ptr->rseed_ip)
3534 /* TODO: Add the port pair flag here */
3540 if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
3541 DSLITE_PRINTF(1,"NU:D_PORT_ALLOC port alloc error\n");
3543 nat44_dslite_common_stats[dslite_id].in2out_drops_resource_depletion ++;
3544 DSLITE_DEBUG_INSIDE_ERR(rv)
3545 log_port_alloc_error(rv, &(ki->dk.ipv4_key));
3549 * create entry in user db
3551 udb = dslite_user_db_create_entry(&u_ki, my_index);
3552 nat44_dslite_common_stats[dslite_id].num_subscribers++;
3553 DSLITE_PRINTF(1,"UDB crete entry done..\n");
3554 #ifndef NO_BULK_LOGGING
3555 if(PREDICT_TRUE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) {
3556 cnat_update_bulk_range_cache(udb, ko.k.k.port,
3557 BULKSIZE_FROM_VRFMAP(dslite_entry_ptr));
3559 #endif /* #ifndef NO_BULK_LOGGING */
3564 * outside port is allocated for this src vrf/src ip addr
3565 * 1)create a new entry in main db
3566 * 2)setup cnat_out2in_hash key
3567 * 3)setup cnat_in2out_hash key
3569 db = dslite_create_main_db_entry_and_hash(ki, &ko, udb);
3570 DSLITE_PRINTF(1,"dslite_create_main_db_entry_and_hash done..\n");
3571 //db->vrfmap_index = my_vrfmap - cnat_map_by_vrf;
3572 db->dslite_nat44_inst_id = dslite_id;
3573 nat44_dslite_common_stats[dslite_id].active_translations++;
3574 if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
3575 nat44_dslite_common_stats[dslite_id].num_static_translations++;
3577 nat44_dslite_common_stats[dslite_id].num_dynamic_translations++;
3580 dslite_translation_create_count++;
3582 db->dst_ipv4 = dest_info->k.ipv4;
3583 db->dst_port = dest_info->k.port;
3584 if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) {
3585 /* for static fwding, let the nsessions remain zero */
3590 * don't forget logging
3591 * logging API is unconditional,
3592 * logging configuration check is done inside the inline function
3594 if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
3595 if(PREDICT_FALSE( dslite_entry_ptr->nf_logging_policy ==
3596 SESSION_LOG_ENABLE)) {
3597 if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) {
3598 cnat_nfv9_ds_lite_log_session_create(db,
3599 dslite_entry_ptr,NULL);
3602 cnat_nfv9_ds_lite_mapping_create(db,dslite_entry_ptr
3603 #ifndef NO_BULK_LOGGING
3608 if(PREDICT_TRUE((dslite_entry_ptr->syslog_logging_policy != SESSION_LOG_ENABLE) ||
3609 (db->dst_ipv4 || db->dst_port))) {
3610 cnat_syslog_ds_lite_mapping_create(db,dslite_entry_ptr,NULL
3611 #ifndef NO_BULK_LOGGING
3619 if (PREDICT_FALSE(port_pair_type == PORT_PAIR)) {
3620 cnat_main_db_entry_t *db2 = 0;
3621 dslite_db_key_bucket_t new_ki = *ki;
3624 new_ki.k.k.port += 1;
3627 CNAT_V4_GET_HASH(new_ki.k.key64, new_ki.bucket,
3628 CNAT_MAIN_HASH_MASK);
3630 db2 = cnat_create_main_db_entry_and_hash(&new_ki, &ko, udb);
3632 translation_create_count ++;
3633 db2->dslite_nat44_inst_id = dslite_id;
3634 db2->entry_expires = cnat_current_time;
3635 db2->flags |= CNAT_DB_FLAG_ALG_ENTRY;
3636 udb->ntranslations += 1;
3637 #ifndef NO_BULK_LOGGING
3638 if(PREDICT_FALSE(nfv9_log_req == BULK_ALLOC_NOT_ATTEMPTED))
3639 cnat_nfv9_log_mapping_create(db2, my_vrfmap, nfv9_log_req);
3641 cnat_nfv9_log_mapping_create(db2, my_vrfmap);
3647 #endif /* TOBE_PORTED */
3652 cnat_db_v2_node_fn (vlib_main_t * vm,
3653 vlib_node_runtime_t * node,
3654 vlib_frame_t * frame)
3658 VLIB_REGISTER_NODE (cnat_db_v2_node) = {
3659 .function = cnat_db_v2_node_fn,
3660 .name = "vcgn-db-v2",
3661 .vector_size = sizeof (u32),
3662 .type = VLIB_NODE_TYPE_INTERNAL,
3664 .n_errors = ARRAY_LEN(cnat_db_v2_error_strings),
3665 .error_strings = cnat_db_v2_error_strings,
3667 .n_next_nodes = CNAT_DB_V2_DROP,
3669 /* edit / add dispositions here */
3671 [CNAT_DB_V2_DROP] = "error-drop",
3675 void cnat_db_v2_init (void)
3679 cnat_timeout_db_entry_t * tdb __attribute__((unused));
3681 cgse_nat_db_entry_t *comb_db __attribute__((unused));
3682 cgse_nat_user_db_entry_t *comb_user __attribute__((unused));
3683 cgse_nat_session_db_entry_t *comb_session __attribute__((unused));
3685 n = CNAT_DB_SIZE*1.15; /* add 15% LB margin */
3688 * We also make it multiple of NUM_BITS_IN_UWORD for better
3689 * DB scanning algorithm
3691 if (n % NUM_BITS_IN_UWORD)
3692 n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD));
3694 pool_alloc(cgse_nat_db,n);
3695 for(i=0; i< n; i++) {
3696 pool_get(cgse_nat_db, comb_db);
3699 for(i=0; i< n; i++) {
3700 pool_put(cgse_nat_db, cgse_nat_db + i);
3703 cnat_main_db = &cgse_nat_db->nat44_main_db;
3706 if(PLATFORM_DBL_SUPPORT) {
3707 /* create session table for NAT44 and NAT64 itself */
3708 printf("DBL Support exist %d\n", PLATFORM_DBL_SUPPORT);
3709 n = CNAT_SESSION_DB_SIZE * 1.15; /* add 15% LB margin */
3711 /* Create session table for NAT64 only */
3712 printf("DBL Support Not exist\n");
3713 n = NAT64_MAIN_DB_SIZE * 1.15; /* add 15% LB margin */
3717 * We also make it multiple of NUM_BITS_IN_UWORD for better
3718 * DB scanning algorithm
3720 if (n % NUM_BITS_IN_UWORD)
3721 n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD));
3723 pool_alloc(cgse_session_db,n);
3724 for(i=0; i< n; i++) {
3725 pool_get(cgse_session_db, comb_session);
3728 for(i=0; i< n; i++) {
3729 pool_put(cgse_session_db, cgse_session_db + i);
3732 cnat_session_db = &cgse_session_db->nat44_session_db;
3734 vec_validate(cnat_out2in_hash, CNAT_MAIN_HASH_MASK);
3735 memset(cnat_out2in_hash, 0xff, CNAT_MAIN_HASH_SIZE*sizeof(index_slist_t));
3737 vec_validate(cnat_in2out_hash, CNAT_MAIN_HASH_MASK);
3738 memset(cnat_in2out_hash, 0xff, CNAT_MAIN_HASH_SIZE*sizeof(index_slist_t));
3740 vec_validate(cnat_session_hash, CNAT_SESSION_HASH_MASK);
3741 memset(cnat_session_hash, 0xff, CNAT_SESSION_HASH_SIZE*sizeof(index_slist_t));
3743 n = CNAT_USER_DB_SIZE * 1.15; /* use hash size as db size for LB margin */
3744 if (n % NUM_BITS_IN_UWORD)
3745 n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD));
3747 pool_alloc(cgse_user_db,n);
3748 for(i=0; i< n; i++) {
3749 pool_get(cgse_user_db, comb_user);
3752 for(i=0; i< n; i++) {
3753 pool_put(cgse_user_db, cgse_user_db + i);
3756 cnat_user_db = &cgse_user_db->nat44_user_db;
3758 vec_validate(cnat_user_hash, CNAT_USER_HASH_MASK);
3759 memset(cnat_user_hash, 0xff, CNAT_USER_HASH_SIZE*sizeof(index_slist_t));
3761 n = CNAT_TIMEOUT_HASH_SIZE; /* use hash size as db size for LB margin */
3762 for(i=0; i< n; i++) {
3763 pool_get(cnat_timeout_db, tdb);
3766 for(i=0; i< n; i++) {
3767 pool_put(cnat_timeout_db, cnat_timeout_db + i);
3770 vec_validate(cnat_timeout_hash, CNAT_TIMEOUT_HASH_MASK);
3771 memset(cnat_timeout_hash, 0xff, CNAT_TIMEOUT_HASH_SIZE*sizeof(index_slist_t));
3774 for (i=0;i<CNAT_MAX_VRFMAP_ENTRIES; i++) {
3775 svi_params_array[i].svi_type = CGSE_SVI_TYPE_INFRA;
3779 cnat_db_v2_main.main_db_lockp =
3780 clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
3781 CLIB_CACHE_LINE_BYTES);
3783 cnat_db_v2_main.user_db_lockp =
3784 clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
3785 CLIB_CACHE_LINE_BYTES);
3787 cnat_db_v2_main.session_db_lockp =
3788 clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
3789 CLIB_CACHE_LINE_BYTES);
3791 ASSERT (pthread_spin_init(cnat_db_v2_main.main_db_lockp,
3792 PTHREAD_PROCESS_PRIVATE) == 0);
3793 ASSERT (pthread_spin_init(cnat_db_v2_main.user_db_lockp,
3794 PTHREAD_PROCESS_PRIVATE) == 0);
3795 ASSERT (pthread_spin_init(cnat_db_v2_main.session_db_lockp,
3796 PTHREAD_PROCESS_PRIVATE) == 0);
3798 cnat_db_init_done = 1;
3799 printf("CNAT DB init is successful\n");