FD.io VPP  v17.01-9-ge7dcee4
Vector Packet Processing
cnat_db_v2.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * cnat_db_v2.c - translation database definitions
4  *
5  * Copyright (c) 2007-2013 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19 #include <vlib/vlib.h>
20 #include <vnet/vnet.h>
21 #include <vppinfra/vec.h>
22 #include <vppinfra/bitmap.h>
23 #include <vppinfra/hash.h>
24 #include <vppinfra/pool.h>
25 #include <vppinfra/clib.h>
26 #include <vppinfra/error.h>
27 
28 #include "cnat_db.h"
29 #include "cnat_config.h"
30 #include "cnat_global.h"
31 #include "cnat_v4_functions.h"
32 #include "cnat_log_api.h"
33 #include "cnat_cli.h"
34 #include "spp_platform_trace_log.h"
35 #include "cnat_bulk_port.h"
36 #include "nat64_db.h"
37 #include "dslite_db.h"
38 #include "cnat_config_api.h"
39 
40 #define HASH_TABLE_SIZE 8192 // hash table size
41 #define THROTTLE_TIME 180 // throttle time value for out of port msg/user
42 
44 
45 typedef struct {
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;
51 
53  /* $$$$ add data here */
54 
55  /* convenience variables */
59 
61 
62 #if 1
63 /* TOBE_PORTED : Remove the following once fixed */
64 #undef PREDICT_TRUE
65 #undef PREDICT_FALSE
66 #define PREDICT_TRUE(x) (x)
67 #define PREDICT_FALSE(x) (x)
68 #endif
69 
70 #define foreach_cnat_db_v2_error \
71 _(DROP, "error-drop packets")
72 
73 typedef enum {
74 #define _(sym,str) CNAT_DB_V2_##sym,
76 #undef _
79 
80 static char * cnat_db_v2_error_strings[] __attribute__((unused)) = {
81 #define _(sym,string) string,
83 #undef _
84 };
85 
86 
87 void cnat_table_entry_fill_map(u32 start_addr, u32 end_addr,
88  cnat_portmap_v2_t **port_map_holder)
89 {
90  u32 this_start_addr, this_end_addr, this_addr, new;
91  u32 loop_count;
92  u32 pm_len, i;
93  cnat_portmap_v2_t *my_pm =0;
94  cnat_portmap_v2_t *pm = 0;
95 
96  my_instance_number = 0;
97 
98  this_start_addr = start_addr;
99  this_end_addr = end_addr;
100 
101  /*
102  * How many new addresses are getting added ??
103  */
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;
107 
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);
114 #endif
115  /* Check whether the address pool add requested already exists */
116  my_pm = pm;
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);
120  return;
121  }
122  my_pm++;
123  }
124 
125  /*
126  * For now give a warning message only....
127  */
128 #if 0
129  if ((total_address_pool_allocated + new) >
131  printf("address pool size (%d) would cross permissible limit (%u) \n",
134  }
135 #endif
136 
138  vec_add2(pm, my_pm, new);
139 
140 #if DEBUG_NOT_COMMENTED
141  printf("total_address_pool_allocated changed from %d to %d (added %d)",
144  printf("vec add is ok\n");
145 #endif
146 
147  memset(my_pm, 0, new*sizeof(*my_pm));
148  this_addr = this_start_addr;
149  loop_count = 0; /* Sanity counter */
150 
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);
154 #endif
155  my_pm->ipv4_address = this_addr;
156  /*
157  * Set all bits to "1" indicating all ports are free
158  */
159  memset(my_pm->bm, 0xff,
160  (((BITS_PER_INST + BITS(uword)-1)/BITS(uword))*(sizeof(uword))));
161  //this_addr += MAX_CORES_PER_PARTITION;
162  this_addr += 1;
163  my_pm++;
164  loop_count++;
165  }
166  /*
167  * We should have loop_count same as the new value
168  */
169  if (loop_count != new) {
170  printf("Mismatch in loop_count (%d) != new (%d)\n",
171  loop_count, new);
172  }
173 
174  *port_map_holder = pm;
175 
176 #if DEBUG_NOT_COMMENTED
177  printf("revised pm len %d\n", vec_len(*port_map_holder));
178 #endif
179 
180  return;
181 }
182 
183 
187  cnat_key_t * key,
188  cnat_vrfmap_t *vrfmap);
189 
191 u32 last_log_timestamp = 0;
192 u32 last_user_dyn_port_exc_timestamp = 0;
193 u32 last_user_stat_port_exc_timestamp = 0;
194 
200 
205 
209 
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 */
213 /*For displaying show cgn <cgn-name> inside-vrf <vrf-name> counters */
214 
215 /*
216  * This is the pool of vrf map structures used by latest main-db functions
217  */
219 
220 /*
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
224  */
227 cnat_ingress_vrfid_name_entry vrfid_name_map[MAX_VRFID] = {{0}};
233 
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; \
239 }
240 
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); \
249 }
250 
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); \
259 }
260 
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
265  */
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) && \
270  max_limit >= 10) { \
271  udb->flags = udb->flags & (~CNAT_USER_DB_PORT_LIMIT_EXCEEDED); \
272  } \
273  }
274 
275 #ifdef TOBE_PORTED
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*/
315 };
316 #endif
317 
318 f64 port_log_timestamps[HASH_TABLE_SIZE]; /* 32 KB array per core */
319 
320 void port_exceeded_msg_log (u32 src_addr, u16 i_vrf)
321 {
322  u32 hash_value;
323  f64 current_timestamp;
325 
326  vlib_main = vlib_get_main();
327  current_timestamp = vlib_time_now((vlib_main_t *) vlib_main);
328 
329  hash_value = ((src_addr >> 16) ^ ((src_addr & 0xffff) ^ i_vrf)) % (1024*8);
330 
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;
336  }
337 
338  return ;
339 }
340 
342 {
343  u32 error_code;
344  u32 arr[] = {k->k.vrf, k->k.ipv4, k->k.port};
345  switch (error)
346  {
347  case CNAT_NO_POOL_ANY:
348  error_code = CNAT_NO_POOL_FOR_ANY_ERROR;
349  break;
350  case CNAT_NO_PORT_ANY:
351  error_code = CNAT_NO_PORT_FOR_ANY_ERROR;
352  break;
353  case CNAT_ERR_PARSER:
354  error_code = CNAT_WRONG_PORT_ALLOC_TYPE;
355  break;
356  case CNAT_BAD_INUSE_ANY:
357  error_code = CNAT_BAD_INUSE_ANY_ERROR;
358  break;
360  error_code = CNAT_BAD_INUSE_DIRECT_ERROR;
361  break;
362  case CNAT_NOT_FOUND_ANY:
363  error_code = CNAT_NOT_FOUND_ANY_ERROR;
364  break;
366  error_code = CNAT_NOT_FOUND_DIRECT_ERROR;
367  break;
369  error_code = CNAT_INV_PORT_FOR_DIRECT_ERROR;
370  break;
371  default:
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 */
374  break;
375  }
376  spp_printf(error_code, 3, arr);
377 }
378 
380  cnat_errno_t error)
381 {
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);
390 #endif
391  {
392  u32 arg[] = {u_ki->k.k.vrf, u_ki->k.k.ipv4, u_ki->k.k.port};
393  spp_printf(error, 3, arg);
394  }
395  }
396 }
397 
399  cnat_errno_t error)
400 {
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);
409 #endif
410  {
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);
413  }
414  }
415 }
416 
418 {
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);
425 #endif
426  {
427  u32 arg[] = {ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port};
429  }
430  }
431 }
432 
434 {
435  u64 a, b, c;
436  u32 index, bucket;
437  cnat_main_db_entry_t *this, *prev;
438 
439 #ifdef DSLITE_DEF
441  dslite_key_t dk = {
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}
444  };
445  DSLITE_V6_GET_HASH((&dk),
446  bucket,
448  DSLITE_PRINTF(1, "Delete1 DSL main hash bucket ..%u\n", bucket);
449  } else {
451  bucket, CNAT_MAIN_HASH_MASK)
452  DSLITE_PRINTF(1, "Delete1 NAT44 main hash bucket ..%u\n", bucket);
453  }
454 #else
456  bucket, CNAT_MAIN_HASH_MASK)
457 #endif
458 
459  index = cnat_in2out_hash[bucket].next;
460 
461  ASSERT(index != EMPTY);
462 
463  prev = 0;
464  do {
465  this = cnat_main_db + index;
466  if (PREDICT_TRUE(this == ep)) {
467  if (prev == 0) {
468  cnat_in2out_hash[bucket].next = ep->in2out_hash.next;
469  return;
470  } else {
471  prev->in2out_hash.next = ep->in2out_hash.next;
472  return;
473  }
474  }
475  prev = this;
476  index = this->in2out_hash.next;
477  } while (index != EMPTY);
478 
479  ASSERT(0);
480 }
481 
483 {
484  u64 a, b, c;
485  u32 index, bucket;
486  cnat_main_db_entry_t *this, *prev;
487 
489  bucket, CNAT_MAIN_HASH_MASK)
490 
491  index = cnat_out2in_hash[bucket].next;
492 
493  ASSERT(index != EMPTY);
494 
495  prev = 0;
496  do {
497  this = cnat_main_db + index;
498  if (PREDICT_TRUE(this == ep)) {
499  if (prev == 0) {
500  cnat_out2in_hash[bucket].next = ep->out2in_hash.next;
501  return;
502  } else {
503  prev->out2in_hash.next = ep->out2in_hash.next;
504  return;
505  }
506  }
507  prev = this;
508  index = this->out2in_hash.next;
509  } while (index != EMPTY);
510 
511  ASSERT(0);
512 }
513 
516 {
517  u64 a, b, c;
518  u32 index;
520 
521  CNAT_V4_GET_HASH(ki->k.key64,
522  ki->bucket,
524 
525  index = cnat_in2out_hash[ki->bucket].next;
526  if (PREDICT_TRUE(index == EMPTY)) {
527  return (NULL);
528  }
529 
530  do {
531  db = cnat_main_db + index;
532  if (PREDICT_TRUE(db->in2out_key.key64 == ki->k.key64)) {
533  return db;
534  }
535  index = db->in2out_hash.next;
536  } while (index != EMPTY);
537 
538  return (NULL);
539 }
540 
542 {
543  u64 a, b, c;
544  u32 index, bucket;
545  cnat_user_db_entry_t *this, *prev;
546 
547  if (PREDICT_FALSE(up->flags & CNAT_USER_DB_NAT64_FLAG) != 0) {
548  /* Preventive check - Not a NAT44 entry */
549  return;
550  }
551 
552  pthread_spin_lock(cnat_db_v2_main.user_db_lockp);
553 #if 1
555  dslite_key_t dk = {
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}}
558  };
559 
560  DSLITE_V6_GET_HASH((&dk),
561  bucket,
563  DSLITE_PRINTF(1, "Delete1 DSL user hash bucket ..%u\n", bucket);
564  } else {
566  bucket, CNAT_USER_HASH_MASK)
567  DSLITE_PRINTF(1, "Delete1 NAT44 user hash bucket ..%u\n", bucket);
568  }
569 #else
571  bucket, CNAT_USER_HASH_MASK)
572  DSLITE_PRINTF(1, "Delete2 NAT44 user hash bucket ..%u\n", bucket);
573 #endif
574 
575  index = cnat_user_hash[bucket].next;
576 
577  ASSERT(index != EMPTY);
578 
579  prev = 0;
580  do {
581  this = cnat_user_db + index;
582  if (PREDICT_TRUE(this == up)) {
583  if (prev == 0) {
584  cnat_user_hash[bucket].next = up->user_hash.next;
585  goto found;
586  } else {
587  prev->user_hash.next = up->user_hash.next;
588  goto found;
589  }
590  }
591  prev = this;
592  index = this->user_hash.next;
593  } while (index != EMPTY);
594 
595  ASSERT(0);
596 
597  found:
598  pool_put(cnat_user_db, up);
599  pthread_spin_unlock(cnat_db_v2_main.user_db_lockp);
600 }
601 
604 {
605  u64 a, b, c;
606  u32 index;
608 
609  CNAT_V4_GET_HASH(uki->k.key64,
610  uki->bucket,
612 
613  /* now: index in user vector */
614  index = cnat_user_hash[uki->bucket].next;
615  if (PREDICT_TRUE(index != EMPTY)) {
616  do {
617  udb = cnat_user_db + index;
618  if (PREDICT_FALSE(udb->key.key64 == uki->k.key64)) {
619  return udb;
620  }
621  index = udb->user_hash.next;
622  } while (index != EMPTY);
623  }
624  return (NULL);
625 }
626 
629  u32 portmap_index)
630 {
631  cnat_user_db_entry_t *udb = NULL;
632 
633  pthread_spin_lock(cnat_db_v2_main.user_db_lockp);
634  pool_get(cnat_user_db, udb);
635  memset(udb, 0, sizeof(*udb));
636 
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;
644 
645 #ifndef NO_BULK_LOGGING
646  INIT_BULK_CACHE(udb)
647 #endif /* NO_BULK_LOGGING */
648  pthread_spin_unlock(cnat_db_v2_main.user_db_lockp);
649  return udb;
650 }
651 
656 {
657  u64 a, b, c;
658  u32 db_index;
660 
661  pool_get(cnat_main_db, db);
662  memset(db, 0, sizeof(*db));
663 
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;
671 
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)) {
678  /*
679  * first port for this src vrf/src ip addr
680  */
681  udb->translation_list_head_index = db_index;
682  } else {
684  (u8 *)cnat_main_db, sizeof(cnat_main_db[0]),
686  db_index);
687  }
688 
689  /*
690  * setup o2i hash key
691  */
692  CNAT_V4_GET_HASH(ko->k.key64,
693  ko->bucket,
695  db->out2in_hash.next = cnat_out2in_hash[ko->bucket].next;
696  cnat_out2in_hash[ko->bucket].next = db_index;
697  /*
698  * setup i2o hash key, bucket is already calculate
699  */
700  db->in2out_hash.next = cnat_in2out_hash[ki->bucket].next;
701  cnat_in2out_hash[ki->bucket].next = db_index;
702 
703 #if DEBUG > 1
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);
712 #endif
713 
714  NAT44_COMMON_STATS.active_translations++;
715 
716  return db;
717 }
718 
719 static inline void pptp_clear_all_channels(
721 {
722  u32 db_index, current_db_index;
723  cnat_main_db_entry_t *temp_db;
724 
725  /* clear all channels */
726 
727  db_index = db->proto_data.pptp_list.next;
728  current_db_index = db - cnat_main_db;
729 
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;
735  == current_db_index)) { // Decouple child GREs from parent
736  temp_db->proto_data.pptp_list.prev = EMPTY;
737  }
738  }
739 
741 }
742 
744 
745  cnat_main_db_entry_t *prev_db, *next_db;
746 
747  prev_db = cnat_main_db + db->proto_data.pptp_list.prev;
748  next_db = cnat_main_db + db->proto_data.pptp_list.next;
749 
750  /* remove entry from the tunnel list */
752  prev_db->proto_data.pptp_list.next =
753  db->proto_data.pptp_list.next ;
754  }
755 
756  if(db->proto_data.pptp_list.next != EMPTY) {
757  next_db->proto_data.pptp_list.prev
758  = db->proto_data.pptp_list.prev;
759  }
760 
761 }
762 
764 {
765  u32 main_db_index;
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;
775 #endif
776  pool_header_t *h = pool_header(cnat_user_db);
777  u16 instance = 0;
778  u32 my_index;
779 
780 
781  if (PREDICT_FALSE(ep->flags & CNAT_DB_NAT64_FLAG) != 0) {
782  /* Preventive check - Not a NAT44 entry */
783  return;
784  }
785 
786  pthread_spin_lock(cnat_db_v2_main.main_db_lockp);
787  if(PREDICT_FALSE(ep->flags &
790  PPTP_DECR(active_tunnels);
791  }
792 
793  if(PREDICT_FALSE(ep->flags &
796  PPTP_DECR(active_channels);
797  }
798 
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
802  * released
803  */
804 
805  if(PREDICT_FALSE(ep->nsessions > 1)) {
807  while(ep->nsessions > 1 &&
808  ep->session_head_index != EMPTY) {
809  sdb = cnat_session_db + ep->session_head_index;
811  }
812  }
813 
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);
817 
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
821  */
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);
826 #endif
829  goto unlock;
830  }
831 
832  up = cnat_user_db + ep->user_index;
833 
834 /* Point to the right portmap list */
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);
842  goto delete_entry;
843  }
844  static_port_range =
846  /*
847  * Netflow logging API for delete event
848  */
849  bulk_size =
851 } else {
852  if (PREDICT_FALSE(ep->vrfmap_index >= vrfmap_len)) {
853 #ifdef DEBUG_PRINTF_ENABLED
854  printf("invalid vrfmap index in db\n");
855 #endif
858  goto delete_entry;
859  }
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);
865 }
866 
868  /* Give back the port(s) */
870  PORT_PAIR, ep->out2in_key.k.port, up, static_port_range
871 #ifndef NO_BULK_LOGGING
872  , bulk_size, &nfv9_log_req
873 #endif
874  );
875  } else {
876  /* Give back the port(s) */
878  PORT_SINGLE, ep->out2in_key.k.port, up, static_port_range
879 #ifndef NO_BULK_LOGGING
880  , bulk_size, &nfv9_log_req
881 #endif
882  );
883  }
884 
885  if (PREDICT_TRUE(!(ep->flags & CNAT_DB_DSLITE_FLAG))) {
886  if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
888  if(ep->nsessions != 0) {
890  }
891  } else {
892  cnat_nfv9_log_mapping_delete(ep, my_vrfmap
893 #ifndef NO_BULK_LOGGING
894  , nfv9_log_req
895 #endif
896  );
897  }
899  (ep->nsessions != 0))) {
901 #ifndef NO_BULK_LOGGING
902  , nfv9_log_req
903 #endif
904  );
905  }
906  }
907  } else {
908  if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
909  if(PREDICT_FALSE( dslite_table_db_ptr[instance].nf_logging_policy ==
912  (dslite_table_db_ptr + instance),NULL);
913  } else {
915  (dslite_table_db_ptr + instance)
916 #ifndef NO_BULK_LOGGING
917  , nfv9_log_req
918 #endif
919  );
920  }
921 #ifdef TOBE_PORTED
922  cnat_syslog_ds_lite_mapping_delete(ep,
923  (dslite_table_db_ptr + instance), NULL
924 #ifndef NO_BULK_LOGGING
925  , nfv9_log_req
926 #endif
927  );
928 #endif /* TOBE_PORTED */
929  }
930  }
931 
932 delete_entry:
933 
934  main_db_index = ep - cnat_main_db;
935 
936  pthread_spin_lock(cnat_db_v2_main.user_db_lockp);
937  up->ntranslations--;
938  pthread_spin_unlock(cnat_db_v2_main.user_db_lockp);
939 
940  /*
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
947  * so that next time
948  * reach max port limit, we can generate new icmp msg again
949  */
950  up->icmp_msg_count = 0;
951 
953  up->translation_list_head_index, (u8 *)cnat_main_db,
954  sizeof (cnat_main_db[0]),
956  main_db_index);
957 
959 
960  if (PREDICT_FALSE(up->ntranslations == 0)) {
962  nat44_dslite_common_stats[instance].num_subscribers--;
963  my_index = up->portmap_index;
964  my_pm = pm + my_index;
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);
971 #endif
972 
973  }
975 
976  }
977 
978  /* Remove from main DB hashes */
979  //cnat_db_in2out_hash_delete(ep);
981 
982  pool_put(cnat_main_db, ep);
983 
985  nat44_dslite_common_stats[instance].num_static_translations--;
986  } else {
987  nat44_dslite_common_stats[instance].num_dynamic_translations--;
988  }
989  nat44_dslite_common_stats[instance].active_translations--;
990  nat44_dslite_global_stats[!!(instance - 1)].translation_delete_count ++;
991 unlock:
992  pthread_spin_unlock(cnat_db_v2_main.main_db_lockp);
993 }
994 
997 {
998  u64 a, b, c;
999  u32 index;
1001 
1002  CNAT_V4_GET_HASH(ko->k.key64,
1003  ko->bucket,
1005 
1006  index = cnat_out2in_hash[ko->bucket].next;
1007  if (PREDICT_TRUE(index == EMPTY)) {
1008  return (NULL);
1009  }
1010 
1011  do {
1012  db = cnat_main_db + index;
1013  if (PREDICT_TRUE(db->out2in_key.key64 == ko->k.key64)) {
1014  return db;
1015  }
1016  index = db->out2in_hash.next;
1017  } while (index != EMPTY);
1018 
1019  return (NULL);
1020 }
1021 
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
1026  */
1028  cnat_main_db_entry_t *mdb,
1029  cnat_key_t *dest_info)
1030 {
1031  cnat_key_t old_dest_info;
1032  pool_header_t *h;
1033  u32 free_session = 0;
1034  u16 instance;
1035  cnat_session_entry_t *session_db1 = NULL, *session_db2 = NULL;
1036 
1037  h = pool_header(cnat_session_db);
1038  free_session = vec_len(h->free_indices) - 1;
1039 
1040  if (PREDICT_FALSE(free_session < 2)) {
1041  if (mdb->flags & CNAT_DB_DSLITE_FLAG) {
1042  instance = mdb->dslite_nat44_inst_id;
1043  } else {
1044  instance = NAT44_RESERVED_INST_ID;
1045  }
1046 
1047  /* we need 2 sessions here, return NULL */
1048  nat44_dslite_common_stats[instance].drops_sessiondb_limit_exceeded++;
1049  return NULL;
1050  }
1051 
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;
1055 
1056  /* create 2 new sessions */
1057  session_db1 = cnat_create_session_db_entry(&old_dest_info,
1058  mdb, FALSE);
1059 
1060  if(PREDICT_FALSE(session_db1 == NULL)) {
1061  return NULL;
1062  }
1063 
1064  /* update pkt info to session 2 */
1065  session_db2 = cnat_create_session_db_entry(dest_info,
1066  mdb, TRUE);
1067 
1068  if(PREDICT_FALSE(session_db2 == NULL)) {
1069  cnat_delete_session_db_entry(session_db1, FALSE);
1070  return NULL;
1071  }
1072  /* update main db info to session 1 */
1073  cnat_dest_update_main2session(mdb, session_db1);
1074 
1075  return session_db2;
1076 }
1077 
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
1082  */
1084  cnat_main_db_entry_t *mdb,
1085  cnat_key_t *dest_info)
1086 {
1087 
1088  if(PREDICT_FALSE(mdb->nsessions != 0)) {
1089  return; /* Should not have been called */
1090  }
1091 
1092  mdb->dst_ipv4 = dest_info->k.ipv4;
1093  mdb->dst_port = dest_info->k.port;
1094  mdb->nsessions = 1;
1096  u16 instance;
1097 
1098  if (mdb->flags & CNAT_DB_DSLITE_FLAG) {
1099  instance = mdb->dslite_nat44_inst_id;
1101  (dslite_table_db_ptr + instance),NULL);
1102  } else {
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);
1106  }
1107 }
1108 
1109 /*
1110  * this function is called by exception node
1111  * when lookup is fialed in i2o node
1112  *
1113  * if reash per user port limit,
1114  * set user_db_entry pointer, and error == CNAT_OUT_LIMIT
1115  */
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)
1122 {
1123  u16 protocol;
1124  cnat_errno_t rv;
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;
1134  pool_header_t *h;
1135  u16 port_limit;
1136  cnat_portmap_v2_t *my_pm = 0;
1137 
1138 #ifndef NO_BULK_LOGGING
1139  int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
1140 #endif
1141 
1142 
1143  /*
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.
1147  */
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
1155  */
1156  if(PREDICT_FALSE((!dest_info->k.ipv4) && (!dest_info->k.port))) {
1157  return db; /* if dest_info is null don't create session */
1158  }
1159  if(PREDICT_TRUE((db->dst_ipv4 == dest_info->k.ipv4) &&
1160  (db->dst_port == dest_info->k.port))) {
1161  return db;
1162  }
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);
1170  return db;
1171  } else {
1172  info->error = CNAT_ERR_NO_SESSION_DB;
1173  return NULL;
1174  }
1175  } else if(PREDICT_FALSE(db->nsessions == 0)) {
1176  /* Should be static entry.. should never happen
1177  */
1178  if(PREDICT_TRUE(dest_info->k.ipv4 != 0)) {
1179  cnat_add_dest_n_log(db, dest_info);
1180  }
1181  return db;
1182  } else {
1183  /* The src has already created multiple sessions.. very rare
1184  */
1185  session_db2 = cnat_create_session_db_entry(dest_info,
1186  db, TRUE);
1187  if(PREDICT_TRUE(session_db2 != NULL)) {
1188  CNAT_DB_TIMEOUT_RST(session_db2);
1189  return db;
1190  } else {
1191  info->error = CNAT_ERR_NO_SESSION_DB;
1192  return NULL;
1193  }
1194  }
1195 
1196  }
1197 
1198  /*
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
1204  */
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;
1208  u_ki.k.k.port = 0;
1209 
1210  my_vrfmap_index = vrf_map_array[u_ki.k.k.vrf];
1211  my_vrfmap = cnat_map_by_vrf + my_vrfmap_index;
1212 
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));
1216 
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;
1224  } else {
1225  info->error = CNAT_NO_VRF_RUN;
1228  }
1229 
1230  return (NULL);
1231  }
1232 
1233  pm = my_vrfmap->portmap_list;
1234 
1235  port_limit = my_vrfmap->port_limit;
1236  if(PREDICT_FALSE(!port_limit)) {
1237  port_limit = cnat_main_db_max_ports_per_user;
1238  }
1239  /*
1240  * set o2i key with protocl bits
1241  */
1242  ko.k.k.vrf = my_vrfmap->o_vrf | protocol;
1243 
1244  /*
1245  * step 2. check if src vrf, src ip addr is alreay
1246  * in the user db
1247  * if yes, use PORT_ALLOC_DIRECTED
1248  * if no, use PORT_ALLOC_ANY since it is first time
1249  */
1250  udb = cnat_user_db_lookup_entry(&u_ki);
1251  if (PREDICT_TRUE(udb)) {
1252  /*
1253  * not first time allocate port for this user
1254  * check limit
1255  */
1256  if (PREDICT_FALSE(udb->ntranslations >=
1257  port_limit)) {
1258  /* Check for the port type here. If we are getting
1259  * a STATIC PORT, allow the config.
1260  */
1261  if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) {
1262  info->error = 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);
1270  return (NULL);
1271  }
1272  }
1274  port_limit)
1275 
1276  /*
1277  * check if main db has space to accomodate new entry
1278  */
1279  h = pool_header(cnat_main_db);
1280 
1281  free_main = vec_len(h->free_indices) - 1;
1282  if (PREDICT_FALSE(!free_main)) {
1283  info->error = CNAT_MAIN_DB_LIMIT;
1285  in2out_drops_system_limit_reached ++;
1287 
1288  current_timestamp = spp_trace_log_get_unix_time_in_seconds();
1289  if (PREDICT_FALSE((current_timestamp - last_log_timestamp) >
1290  1800)) {
1292  last_log_timestamp = current_timestamp;
1293  }
1294 
1295 #ifdef UT_TEST_CODE
1296  printf("Limit reached : OLD USER");
1297 #endif
1298  return NULL;
1299  }
1300 
1301  /*
1302  * allocate port, from existing mapping
1303  */
1304  my_index = udb->portmap_index;
1305 
1306  if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
1309  port_pair_type,
1310  ki->k.k.ipv4,
1311  ki->k.k.port,
1312  &my_index,
1313  &(ko.k.k.ipv4),
1314  &(ko.k.k.port),
1316 #ifndef NO_BULK_LOGGING
1317  ,
1318  udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1319  &nfv9_log_req
1320 #endif
1321  , my_vrfmap->ip_n_to_1
1322  );
1323 
1324  } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP) ) {
1325 
1328  port_pair_type,
1329  &my_index,
1330  &(ko.k.k.ipv4),
1331  &(ko.k.k.port),
1333 #ifndef NO_BULK_LOGGING
1334  ,
1335  udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1336  &nfv9_log_req
1337 #endif
1338  , my_vrfmap->ip_n_to_1,
1339  &(my_vrfmap->rseed_ip)
1340  );
1341 
1342  } else {
1343  /*
1344  * For RTSP, two translation entries are created,
1345  * check if main db has space to accomodate two new entry
1346  */
1347  free_main = free_main - 1;
1348  if (PREDICT_FALSE(!free_main)) {
1349  info->error = CNAT_MAIN_DB_LIMIT;
1351  in2out_drops_system_limit_reached ++;
1353 
1354  return NULL;
1355  } else {
1358  port_pair_type,
1359  ki->k.k.port,
1360  &my_index,
1361  &(ko.k.k.ipv4),
1362  &(ko.k.k.port),
1364 #ifndef NO_BULK_LOGGING
1365  ,
1366  udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1367  &nfv9_log_req
1368 #endif
1369  , &(my_vrfmap->rseed_ip)
1370  );
1371  }
1372  }
1373 
1374 
1375  if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1376  info->error = rv;
1379  in2out_drops_resource_depletion++;
1380  log_port_alloc_error(rv, &(ki->k));
1381  return (NULL);
1382  }
1383  /*
1384  * increment port in use for this user
1385  */
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);
1389 
1390  } else {
1391  /*
1392  * first time allocate port for this user
1393  */
1394 
1395  /*
1396  * Do not create entry if port limit is invalid
1397  */
1398 
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);
1406  return (NULL);
1407  }
1408  }
1409 
1410  /*
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.
1415  */
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;
1420 
1421  /*
1422  * If either main_db or user_db does not have entries
1423  * bail out, with appropriate error
1424  */
1425  if (PREDICT_FALSE(!(free_main && free_user))) {
1426  u32 log_error;
1427  if(free_main) {
1428  info->error = CNAT_USER_DB_LIMIT;
1429  log_error = CNAT_USER_DB_LIMIT_ERROR;
1430  } else {
1431  info->error = CNAT_MAIN_DB_LIMIT;
1432  log_error = CNAT_MAIN_DB_LIMIT_ERROR;
1433  }
1434  in2out_drops_system_limit_reached ++;
1437  spp_printf(log_error, 0, 0);
1438  return NULL;
1439  }
1440 
1441  if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
1444  port_pair_type,
1445  ki->k.k.ipv4,
1446  ki->k.k.port,
1447  &my_index,
1448  &(ko.k.k.ipv4),
1449  &(ko.k.k.port),
1451 #ifndef NO_BULK_LOGGING
1452  ,
1453  udb, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1454  &nfv9_log_req
1455 #endif
1456  , my_vrfmap->ip_n_to_1
1457  );
1458 
1459  } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP)) {
1462  port_pair_type,
1463  &my_index,
1464  &(ko.k.k.ipv4),
1465  &(ko.k.k.port),
1467 #ifndef NO_BULK_LOGGING
1468  , NULL, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1469  &nfv9_log_req
1470 #endif
1471  , my_vrfmap->ip_n_to_1,
1472  &(my_vrfmap->rseed_ip)
1473  );
1474  } else {
1475  /*
1476  * For RTSP, two translation entries are created,
1477  * check if main db has space to accomodate two new entry
1478  */
1479  free_main = free_main - 1;
1480  if (PREDICT_FALSE(!free_main)) {
1481  info->error = CNAT_MAIN_DB_LIMIT;
1483  in2out_drops_system_limit_reached ++;
1485 
1486  return NULL;
1487  } else {
1488 
1491  port_pair_type,
1492  ki->k.k.port,
1493  &my_index,
1494  &(ko.k.k.ipv4),
1495  &(ko.k.k.port),
1497 #ifndef NO_BULK_LOGGING
1498  , NULL, BULKSIZE_FROM_VRFMAP(my_vrfmap),
1499  &nfv9_log_req
1500 #endif
1501  , &(my_vrfmap->rseed_ip)
1502  );
1503  /* TODO: Add the port pair flag here */
1504  }
1505  }
1506 
1507 
1508 
1509  if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1510  info->error = rv;
1511  in2out_drops_resource_depletion ++;
1514  log_port_alloc_error(rv, &(ki->k));
1515  return (NULL);
1516  }
1517  /*
1518  * create entry in user db
1519  */
1520  udb = cnat_user_db_create_entry(&u_ki, my_index);
1521  NAT44_COMMON_STATS.num_subscribers++;
1522  my_pm = pm + my_index;
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);
1529 #endif
1530  } else {
1531  PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has "
1532  "reached MAX PORTS_PER_ADDR");
1533  }
1534 #ifndef NO_BULK_LOGGING
1535  if(PREDICT_TRUE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) {
1537  BULKSIZE_FROM_VRFMAP(my_vrfmap));
1538  }
1539 #endif /* #ifndef NO_BULK_LOGGING */
1540 
1541  }
1542 
1543  /*
1544  * step 3:
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
1549  */
1550  db = cnat_create_main_db_entry_and_hash(ki, &ko, udb);
1551 
1553 #ifdef DSLITE_DEF
1555 #endif
1556  db->vrfmap_index = my_vrfmap - cnat_map_by_vrf;
1557 
1558  /*
1559  * don't forget logging
1560  * logging API is unconditional,
1561  * logging configuration check is done inside the inline function
1562  */
1563 
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)) {
1567  db->nsessions++;
1568  }
1569 
1570  if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
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);
1575  }
1576  } else {
1577  cnat_nfv9_log_mapping_create(db, my_vrfmap
1578 #ifndef NO_BULK_LOGGING
1579  , nfv9_log_req
1580 #endif
1581  );
1582  }
1584  (db->dst_ipv4 || db->dst_port))) {
1585  cnat_syslog_nat44_mapping_create(db, my_vrfmap, 0
1586 #ifndef NO_BULK_LOGGING
1587  , nfv9_log_req
1588 #endif
1589  );
1590  }
1591  }
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;
1595  u64 a, b, c;
1596 
1597  new_ki.k.k.port += 1;
1598  ko.k.k.port += 1;
1599 
1600  CNAT_V4_GET_HASH(new_ki.k.key64, new_ki.bucket,
1602 
1603  db2 = cnat_create_main_db_entry_and_hash(&new_ki, &ko, udb);
1604 
1606 #ifdef DSLITE_DEF
1608 #endif
1609  db2->vrfmap_index = my_vrfmap - cnat_map_by_vrf;
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 */
1618 
1619  if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) {
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);
1624  }
1625  } else {
1626  cnat_nfv9_log_mapping_create(db2, my_vrfmap
1627 #ifndef NO_BULK_LOGGING
1628  , nfv9_log_req
1629 #endif
1630  );
1631  }
1633  (db2->dst_ipv4 || db2->dst_port))) {
1634  cnat_syslog_nat44_mapping_create(db2, my_vrfmap, 0
1635 #ifndef NO_BULK_LOGGING
1636  , nfv9_log_req
1637 #endif
1638  );
1639  }
1640  }
1641  }
1642 
1643  return db;
1644 }
1645 
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)
1652 {
1653 
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);
1659  return db;
1660 }
1661 
1662 /*
1663  * this function is called from config handler only
1664  * to allocate a static port based db entry
1665  *
1666  * the actual mapped address and port are already specified
1667  */
1671  cnat_vrfmap_t *my_vrfmap,
1672  cnat_gen_icmp_info *info)
1673 {
1674  u16 protocol;
1675  u32 head;
1676  cnat_errno_t rv;
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;
1683  pool_header_t *h;
1684 #ifndef NO_BULK_LOGGING
1685  int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
1686 #endif
1687 
1688  /* UNUSED. Therefore not ported to be multi-thread friendly */
1689  ASSERT(0);
1690 
1691  /*
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.
1695  */
1697  info->error = CNAT_SUCCESS;
1698  db = cnat_main_db_lookup_entry(ki);
1699 
1700  /*
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
1704  */
1705  if (PREDICT_FALSE(db)) {
1706 
1707  if (db->flags & CNAT_DB_FLAG_STATIC_PORT) {
1708 
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)) {
1712 
1713 #ifdef DEBUG_PRINTF_ENABLED
1714  printf("Same Static Port Exists ki 0x%16llx ko 0x%16llx",
1715  ki->k, ko->k);
1716 #endif
1717  /*
1718  * We have already programmed this, return
1719  */
1720  return (db);
1721  }
1722 
1723  /*
1724  * We already have a static port with different mapping
1725  * Return an error for this case.
1726  */
1727  info->error = CNAT_ERR_PARSER;
1728 
1729 #ifdef DEBUG_PRINTF_ENABLED
1730  printf("Static Port Existing and Diff ki 0x%16llx ko 0x%16llx",
1731  ki, db->out2in_key);
1732 #endif
1733  {
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);
1737  }
1738  return (db);
1739  }
1740 
1741 #ifdef DEBUG_PRINTF_ENABLED
1742  printf("Deleting Dynamic entry ki 0x%16llx ko 0x%16llx",
1743  ki, db->out2in_key);
1744 #endif
1745 
1746  /*
1747  * If for some reason we have dynamic entries, just delete them
1748  * and proceed.
1749  */
1751 
1752  db = NULL;
1753  }
1754 
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;
1758  u_ki.k.k.port = 0;
1759 
1760  pm = my_vrfmap->portmap_list;
1761 
1762  /*
1763  * check if src vrf, src ip addr is already
1764  * in the user db
1765  * if yes, use PORT_ALLOC_DIRECTED
1766  * if no, use PORT_ALLOC_ANY since it is first time
1767  */
1768  udb = cnat_user_db_lookup_entry(&u_ki);
1769  if (PREDICT_TRUE(udb)) {
1770  /*
1771  * check if main db has space to accomodate new entry
1772  */
1773  h = pool_header(cnat_main_db);
1774 
1775  free_main = vec_len(h->free_indices) - 1;
1776  if (PREDICT_FALSE(!free_main)) {
1777  info->error = CNAT_MAIN_DB_LIMIT;
1779  in2out_drops_system_limit_reached ++;
1781 #ifdef UT_TEST_CODE
1782  printf("Limit reached : OLD USER");
1783 #endif
1785  return NULL;
1786  }
1787 
1788  /*
1789  * allocate port, from existing mapping
1790  */
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
1796  */
1797 
1798  if (PREDICT_FALSE(my_pm->ipv4_address != ko->k.k.ipv4)) {
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);
1803  }
1804  do {
1805  /* udb is not NULL when we begin with for sure */
1806  head = udb->translation_list_head_index;
1807  db = cnat_main_db + head;
1809  } while (!pool_is_free(cnat_user_db, udb));
1810 
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);
1815 
1816  if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1817  info->error = rv;
1818  in2out_drops_resource_depletion ++;
1821  return (NULL);
1822  }
1823  /*
1824  * create entry in user db
1825  */
1826  udb = cnat_user_db_create_entry(&u_ki, my_index);
1827  my_pm = pm + my_index;
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);
1834 #endif
1835  } else {
1836  PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has "
1837  "reached MAX PORTS_PER_ADDR");
1838  }
1839  NAT44_COMMON_STATS.num_subscribers++;
1840 #ifndef NO_BULK_LOGGING
1842  BULKSIZE_FROM_VRFMAP(my_vrfmap));
1843 #endif /* #ifndef NO_BULK_LOGGING */
1844  } else {
1845 
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);
1850 
1851  if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1852  info->error = rv;
1855  log_port_alloc_error(rv, &(ki->k));
1856  return (NULL);
1857  }
1858 
1859  /*
1860  * increment port in use for this user
1861  */
1862  udb->ntranslations += 1;
1863  }
1864  } else {
1866  printf ("Static port alloc any\n");
1867  }
1868  /*
1869  * first time allocate port for this user
1870  */
1871 
1872  /*
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.
1877  */
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;
1882 
1883  /*
1884  * If either main_db or user_db does not have entries
1885  * bail out, with appropriate error
1886  */
1887  if (PREDICT_FALSE(!(free_main && free_user))) {
1888  u32 log_error;
1889  if(free_main) {
1890  info->error = CNAT_USER_DB_LIMIT;
1891  log_error = CNAT_USER_DB_LIMIT_ERROR;
1892  } else {
1893  info->error = CNAT_MAIN_DB_LIMIT;
1894  log_error = CNAT_MAIN_DB_LIMIT_ERROR;
1895  }
1896  in2out_drops_system_limit_reached ++;
1899  spp_printf(log_error, 0, 0);
1900  return NULL;
1901  }
1902 
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);
1907 
1908  if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
1909  info->error = rv;
1910  in2out_drops_resource_depletion ++;
1913  log_port_alloc_error(rv, &(ki->k));
1914  return (NULL);
1915  }
1916  /*
1917  * create entry in user db
1918  */
1919  udb = cnat_user_db_create_entry(&u_ki, my_index);
1920  my_pm = pm + my_index;
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);
1927 #endif
1928  } else {
1929  PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has "
1930  "reached MAX PORTS_PER_ADDR");
1931  }
1932  NAT44_COMMON_STATS.num_subscribers++;
1933 #ifndef NO_BULK_LOGGING
1935  BULKSIZE_FROM_VRFMAP(my_vrfmap));
1936 #endif /* #ifndef NO_BULK_LOGGING */
1937  }
1938 
1939  /*
1940  * step 3:
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
1945  */
1946  db = cnat_create_main_db_entry_and_hash(ki, ko, udb);
1947 
1949  db->vrfmap_index = my_vrfmap - cnat_map_by_vrf;
1950 
1951  /*
1952  * don't forget logging
1953  * logging API is unconditional,
1954  * logging configuration check is done inside the inline function
1955  */
1956 
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
1959  * traffic yet
1960  */
1962  cnat_nfv9_log_mapping_create(db, my_vrfmap
1963 #ifndef NO_BULK_LOGGING
1964  , nfv9_log_req
1965 #endif
1966  );
1967  }
1969  cnat_syslog_nat44_mapping_create(db, my_vrfmap, 0
1970 #ifndef NO_BULK_LOGGING
1971  , nfv9_log_req
1972 #endif
1973  );
1974  }
1975  }
1976 
1977  return db;
1978 }
1979 
1980 
1983 
1986 
1989 
1993  cnat_user_db_entry_t *udb);
1994 
1995 #ifdef TOBE_PORTED
1996 /*
1997  * this function is called from config handler only
1998  * to allocate a static port based db entry
1999  *
2000  * the actual mapped address and port are already specified
2001  */
2003 dslite_create_static_main_db_entry_v2 (dslite_db_key_bucket_t *ki,
2005  dslite_table_entry_t *dslite_entry_ptr,
2006  cnat_gen_icmp_info *info)
2007 {
2008  u16 protocol;
2009  u32 head;
2010  cnat_errno_t rv;
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;
2017  pool_header_t *h;
2018  u16 dslite_id = dslite_entry_ptr->dslite_id;
2019 #ifndef NO_BULK_LOGGING
2020  int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
2021 #endif
2022  cnat_vrfmap_t *my_vrfmap =0;
2023  u16 my_vrfmap_index;
2024 
2025  /* UNUSED. Therefore not ported to be multi-thread friendly */
2026  ASSERT(0);
2027  /*
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.
2031  */
2033  info->error = CNAT_SUCCESS;
2034  db = dslite_main_db_lookup_entry(ki);
2035 
2036  /*
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
2040  */
2041  if (PREDICT_FALSE(db)) {
2042 
2043  if (db->flags & CNAT_DB_FLAG_STATIC_PORT) {
2044 
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)) {
2048 
2049 #ifdef DEBUG_PRINTF_ENABLED
2050  printf("Same Static Port Exists ki 0x%16llx ko 0x%16llx",
2051  ki->k, ko->k);
2052 #endif
2053  /*
2054  * We have already programmed this, return
2055  */
2056  return (db);
2057  }
2058 
2059  /*
2060  * We already have a static port with different mapping
2061  * Return an error for this case.
2062  */
2063  info->error = CNAT_ERR_PARSER;
2064 
2065 #ifdef DEBUG_PRINTF_ENABLED
2066  printf("Static Port Existing and Diff ki 0x%16llx ko 0x%16llx",
2067  ki, db->out2in_key);
2068 #endif
2069  {
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);
2073  }
2074  return (db);
2075  }
2076 
2077 #ifdef DEBUG_PRINTF_ENABLED
2078  printf("Deleting Dynamic entry ki 0x%16llx ko 0x%16llx",
2079  ki, db->out2in_key);
2080 #endif
2081 
2082  /*
2083  * If for some reason we have dynamic entries, just delete them
2084  * and proceed.
2085  */
2087 
2088  db = NULL;
2089  }
2090 
2091 
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];
2100 
2101  my_vrfmap_index = vrf_map_array[u_ki.dk.ipv4_key.k.vrf];
2102  my_vrfmap = cnat_map_by_vrf + my_vrfmap_index;
2103 
2104  pm = dslite_entry_ptr->portmap_list;
2105 
2106  /*
2107  * check if src vrf, src ip addr is already
2108  * in the user db
2109  * if yes, use PORT_ALLOC_DIRECTED
2110  * if no, use PORT_ALLOC_ANY since it is first time
2111  */
2112  udb = dslite_user_db_lookup_entry(&u_ki);
2113  if (PREDICT_TRUE(udb)) {
2114  /*
2115  * check if main db has space to accomodate new entry
2116  */
2117  h = pool_header(cnat_main_db);
2118 
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 ++;
2124 #ifdef UT_TEST_CODE
2125  printf("Limit reached : OLD USER");
2126 #endif
2128  return NULL;
2129  }
2130 
2131  /*
2132  * allocate port, from existing mapping
2133  */
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
2139  */
2140 
2141  if (PREDICT_FALSE(my_pm->ipv4_address != ko->k.k.ipv4)) {
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);
2146  }
2147  do {
2148  /* udb is not NULL when we begin with for sure */
2149  head = udb->translation_list_head_index;
2150  db = cnat_main_db + head;
2152  } while (!pool_is_free(cnat_user_db, udb));
2153 
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);
2158 
2159  if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
2160  info->error = rv;
2161  nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
2163  return (NULL);
2164  }
2165  /*
2166  * create entry in user db
2167  */
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))) {
2173  BULKSIZE_FROM_VRFMAP(dslite_entry_ptr));
2174  }
2175 #endif /* #ifndef NO_BULK_LOGGING */
2176  } else {
2177 
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);
2182 
2183  if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
2184  info->error = rv;
2186  log_port_alloc_error(rv, &(ki->dk.ipv4_key));
2187  return (NULL);
2188  }
2189 
2190  /*
2191  * increment port in use for this user
2192  */
2193  udb->ntranslations += 1;
2194  }
2195  } else {
2197  printf ("Static port alloc any\n");
2198  }
2199  /*
2200  * first time allocate port for this user
2201  */
2202 
2203  /*
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.
2208  */
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;
2213 
2214  /*
2215  * If either main_db or user_db does not have entries
2216  * bail out, with appropriate error
2217  */
2218  if (PREDICT_FALSE(!(free_main && free_user))) {
2219  u32 log_error;
2220  if(free_main) {
2221  info->error = CNAT_USER_DB_LIMIT;
2222  log_error = CNAT_USER_DB_LIMIT_ERROR;
2223  } else {
2224  info->error = CNAT_MAIN_DB_LIMIT;
2225  log_error = CNAT_MAIN_DB_LIMIT_ERROR;
2226  }
2227  nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
2229  spp_printf(log_error, 0, 0);
2230  return NULL;
2231  }
2232 
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);
2237 
2238  if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
2239  info->error = rv;
2240  nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++;
2242  log_port_alloc_error(rv, &(ki->dk.ipv4_key));
2243  return (NULL);
2244  }
2245  /*
2246  * create entry in user db
2247  */
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))) {
2253  BULKSIZE_FROM_VRFMAP(dslite_entry_ptr));
2254  }
2255 #endif /* #ifndef NO_BULK_LOGGING */
2256  }
2257 
2258  /*
2259  * step 3:
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
2264  */
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++;
2269 
2270  /*
2271  * don't forget logging
2272  * logging API is unconditional,
2273  * logging configuration check is done inside the inline function
2274  */
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
2278  * traffic yet
2279  */
2280 #endif /* #if 0 - this has to be removed later */
2281 
2282  return db;
2283 }
2284 #endif /* TOBE_PORTED */
2285 
2286 
2287 /* Per port/ip timeout related routines */
2288 static
2290 {
2291  cnat_key_t key;
2292  u64 a, b, c;
2293  u32 index;
2295 
2296  key.k.ipv4 = t_key.k.ipv4;
2297  key.k.port = t_key.k.port;
2298  key.k.vrf = t_key.k.vrf;
2299 
2300  CNAT_V4_GET_HASH(key.key64,
2301  index, CNAT_TIMEOUT_HASH_MASK)
2302 
2303 
2304  index = cnat_timeout_hash[index].next;
2305 
2306  if (PREDICT_FALSE(index == EMPTY))
2307  return EMPTY;
2308 
2309  do {
2310  db = cnat_timeout_db + index;
2312  == (key.key64 & CNAT_TIMEOUT_FULL_MASK)))
2313  break;
2314  index = db->t_hash.next;
2315  } while (index != EMPTY);
2316 
2317  return index;
2318 }
2319 
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
2323  */
2324 u16
2326 {
2327  cnat_key_t t_search_key;
2328  u32 index;
2329  cnat_timeout_db_entry_t *timeout_db_entry;
2330  pool_header_t *h;
2331  u32 free;
2332 
2333  cnat_main_db_entry_t *mdb = NULL;
2334  cnat_session_entry_t *sdb = NULL;
2335 
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;
2340  } else {
2341  return 0;
2342  }
2343 
2344  h = pool_header(cnat_timeout_db);
2345  free = vec_len(h->free_indices) - 1;
2346 
2347  if(free == CNAT_TIMEOUT_HASH_SIZE) {
2348  /* No timeout db configured */
2349  return 0;
2350  }
2351 
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;
2357  } else {
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;
2361  }
2362 
2363  index = cnat_timeout_db_hash_lookup(t_search_key);
2364 
2365  if(index == EMPTY) {
2366  /* Search for port map */
2367  t_search_key.k.ipv4 = 0;
2368 
2369  index = cnat_timeout_db_hash_lookup(t_search_key);
2370 
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;
2375  } else {
2376  t_search_key.k.ipv4 = sdb->v4_dest_key.k.ipv4;
2377  }
2378  t_search_key.k.port = 0;
2379 
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");
2384 #endif
2385  }
2386  } else {
2387 #ifdef DEBUG_PRINTF_ENABLED
2388  printf("%s: port only map sucess\n", "query_and_update_db_timeout");
2389 #endif
2390  }
2391 
2392  } else {
2393 #ifdef DEBUG_PRINTF_ENABLED
2394  printf("%s: ip port map sucess\n","query_and_update_db_timeout");
2395 #endif
2396 
2397  }
2398 
2399  if(index == EMPTY) {
2400  /* No match found, clear timeout */
2401  if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) {
2402  mdb->timeout = 0;
2403  } else {
2404  sdb->timeout = 0;
2405  }
2406 #ifdef DEBUG_PRINTF_ENABLED
2407  printf("%s: No match\n","query_and_update_db_timeout");
2408 #endif
2409  } else {
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;
2414  } else {
2415  sdb->timeout = timeout_db_entry->t_key.timeout_value;
2416  }
2417  return timeout_db_entry->t_key.timeout_value;
2418  }
2419  return 0;
2420 }
2421 
2422 
2423 
2424 static
2426 {
2427  cnat_key_t key;
2428  u64 a, b, c;
2429  u32 index, bucket;
2430  cnat_key_t t_key = t_entry->t_key.timeout_key;
2431 
2432  key.k.ipv4 = t_key.k.ipv4;
2433  key.k.port = t_key.k.port;
2434  key.k.vrf = t_key.k.vrf;
2435 
2436  CNAT_V4_GET_HASH(key.key64,
2437  bucket, CNAT_TIMEOUT_HASH_MASK)
2438 
2439 
2440  index = cnat_timeout_hash[bucket].next;
2441 
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;
2445 }
2446 
2447 
2448 
2449 u16
2451 {
2453  cnat_key_t t_key = t_entry.timeout_key;
2454  u32 db_index;
2455 
2456  pool_header_t *h;
2457  u32 free;
2458 
2459  /* UNUSED. Therefore not ported to be multi-thread friendly */
2460  ASSERT(0);
2461 
2462  db_index = cnat_timeout_db_hash_lookup(t_key);
2463 
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;
2469  }
2470 
2471  h = pool_header(cnat_timeout_db);
2472  free = vec_len(h->free_indices) - 1;
2473 
2474  if(free == 0) {
2475  return CNAT_OUT_LIMIT;
2476  }
2477 
2478 
2479  pool_get(cnat_timeout_db, db);
2480  ASSERT(db);
2481 
2482  memset(db, 0, sizeof(*db));
2483 
2484  db_index = db - cnat_timeout_db;
2485 
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;
2490 
2491 
2493  return CNAT_SUCCESS;
2494 }
2495 
2497 {
2498  cnat_key_t key;
2499  u64 a, b, c;
2500  u32 index, bucket;
2501  cnat_timeout_db_entry_t *this, *prev;
2502 
2503  /* UNUSED. Therefore not ported to be multi-thread friendly */
2504  ASSERT(0);
2505 
2506  key.k.ipv4 = t_key.k.ipv4;
2507  key.k.port = t_key.k.port;
2508  key.k.vrf = t_key.k.vrf;
2509 
2510 
2511  CNAT_V4_GET_HASH(key.key64,
2512  bucket, CNAT_TIMEOUT_HASH_MASK)
2513 
2514 
2515  index = cnat_timeout_hash[bucket].next;
2516 
2517  if(index == EMPTY) return;
2518 
2519  prev = 0;
2520  do {
2521  this = cnat_timeout_db + index;
2522  if (PREDICT_TRUE(
2523  (this->t_key.timeout_key.key64 & CNAT_TIMEOUT_FULL_MASK) ==
2524  (key.key64 & CNAT_TIMEOUT_FULL_MASK))) {
2525  if (prev == 0) {
2526  cnat_timeout_hash[bucket].next = this->t_hash.next;
2527  goto found;
2528  } else {
2529  prev->t_hash.next = this->t_hash.next;
2530  goto found;
2531  }
2532  }
2533 
2534  prev = this;
2535  index = this->t_hash.next;
2536  } while (index != EMPTY);
2537 
2538  if(index == EMPTY) return;
2539 
2540  found:
2541  pool_put(cnat_timeout_db, this);
2542 
2543 }
2544 
2546 {
2547  u32 a, b, c;
2548  u32 index, bucket;
2549  cnat_session_entry_t *this, *prev;
2550 
2552  ep->v4_dest_key.k.port, ep->v4_dest_key.k.vrf, bucket,
2554 
2555 
2556  index = cnat_session_hash[bucket].next;
2557 
2558  ASSERT(index != EMPTY);
2559 
2560  prev = 0;
2561  do {
2562  this = cnat_session_db + index;
2563  if (PREDICT_TRUE(this == ep)) {
2564  if (prev == 0) {
2565  cnat_session_hash[bucket].next =
2566  ep->cnat_session_hash.next;
2567  return;
2568  } else {
2569  prev->cnat_session_hash.next =
2570  ep->cnat_session_hash.next;
2571  return;
2572  }
2573  }
2574  prev = this;
2575  index = this->cnat_session_hash.next;
2576  } while (index != EMPTY);
2577 
2578  ASSERT(0);
2579 
2580 }
2581 
2584  u32 main_db_index)
2585 {
2586  u32 index;
2588 
2589 
2590  index = session_head_index;
2591  if (PREDICT_TRUE(index == EMPTY)) {
2592  return (NULL);
2593  }
2594 
2595  do {
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))) {
2600 
2601  return db;
2602  }
2603  index = db->cnat_session_hash.next;
2604  } while (index != EMPTY);
2605 
2606  return (NULL);
2607 }
2608 
2609 
2610 
2613 {
2614  u32 a, b, c;
2615  u32 index, bucket;
2617 
2618  CNAT_V4_GET_SESSION_HASH(main_db_index, ko->k.ipv4, ko->k.port,
2619  ko->k.vrf, bucket, CNAT_SESSION_HASH_MASK)
2620 
2621 
2622  index = cnat_session_hash[bucket].next;
2623  if (PREDICT_TRUE(index == EMPTY)) {
2624  return (NULL);
2625  }
2626 
2627  do {
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))) {
2633 
2634  return db;
2635  }
2636  index = db->cnat_session_hash.next;
2637  } while (index != EMPTY);
2638 
2639  return (NULL);
2640 }
2641 
2644  cnat_main_db_entry_t *bdb, u8 log)
2645 {
2646  u32 a, b, c;
2647  u32 db_index, bucket_out;
2648  cnat_session_entry_t *db = NULL;
2649  pool_header_t *h;
2650  u32 free_session;
2651  u16 instance;
2652 
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");*/
2656  return db;
2657  }
2658 
2659  h = pool_header(cnat_session_db);
2660  free_session = vec_len(h->free_indices) - 1;
2661 
2662  if (bdb->flags & CNAT_DB_DSLITE_FLAG) {
2663  instance = bdb->dslite_nat44_inst_id;
2664  } else {
2665  instance = NAT44_RESERVED_INST_ID;
2666  }
2667 
2668  if (PREDICT_FALSE(!free_session)) {
2669  nat44_dslite_common_stats[instance].drops_sessiondb_limit_exceeded++;
2670  return NULL;
2671  }
2672 
2674  /* printf("Create Session - Max sessions per BIB reached\n"); */
2675  return NULL;
2676  }
2677 
2678  pthread_spin_lock(cnat_db_v2_main.session_db_lockp);
2679  pool_get(cnat_session_db, db);
2680  memset(db, 0, sizeof(*db));
2681 
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;
2686 
2687  db->main_list.next = db_index;
2688  db->main_list.prev = db_index;
2689  db->main_db_index = bdb - cnat_main_db;
2690 
2691  db->tcp_seq_num = 0;
2692  db->ack_no = 0;
2693  db->window = 0;
2694 
2695  if(PREDICT_FALSE(log)) {
2696  bdb->nsessions++;
2698  }
2699 
2700  if (PREDICT_FALSE(bdb->nsessions == 1)) {
2701  /*
2702  * first port for this src vrf/src ip addr
2703  */
2704  bdb->session_head_index = db_index;
2705  } else {
2707  (u8 *)cnat_session_db, sizeof(cnat_session_db[0]),
2709  db_index);
2710  }
2711 
2712  /*
2713  * setup o2i hash key
2714  */
2716  ko->k.vrf, bucket_out, CNAT_SESSION_HASH_MASK)
2717 
2718 
2719  db->cnat_session_hash.next =
2720  cnat_session_hash[bucket_out].next;
2721  cnat_session_hash[bucket_out].next = db_index;
2722 
2723 
2724  if(PREDICT_FALSE(log)) {
2725  if (bdb->flags & CNAT_DB_DSLITE_FLAG) {
2727  (dslite_table_db_ptr + instance),db);
2728  } else {
2729  cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + bdb->vrfmap_index;
2730  cnat_session_log_nat44_mapping_create(bdb, db, my_vrfmap);
2731  }
2732  }
2733 
2734  /* Need to set entry_expires here, as we need to override 0 check for
2735  newly established sessions */
2737  nat44_dslite_common_stats[instance].sessions++;
2738  pthread_spin_unlock(cnat_db_v2_main.session_db_lockp);
2739  return db;
2740 }
2741 
2742 void
2744  cnat_session_entry_t *sdb)
2745 {
2746 
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;
2752 
2753  /* Reset Main db values to 0 */
2754  /* Reset only session specific flags */
2757  mdb->timeout = 0;
2758  mdb->entry_expires = 0;
2759  mdb->alg.delta = 0;
2761  (mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_INIT)))) {
2762  mdb->proto_data.seq_pcp.tcp_seq_num = 0;
2763  }
2764 
2765  mdb->dst_ipv4 = 0;
2766  mdb->dst_port = 0;
2767 }
2768 
2769 
2770 void
2772  cnat_session_entry_t *sdb)
2773 {
2774 
2778  mdb->flags |= flags;
2779  mdb->timeout = sdb->timeout;
2780  mdb->entry_expires = sdb->entry_expires;
2781  mdb->alg.delta = sdb->alg.delta;
2783  (mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_INIT)))) {
2784  mdb->proto_data.seq_pcp.tcp_seq_num = sdb->tcp_seq_num;
2785  }
2786  mdb->dst_ipv4 = sdb->v4_dest_key.k.ipv4;
2787  mdb->dst_port = sdb->v4_dest_key.k.port;
2788 }
2789 
2790 static void
2791 _cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log)
2792 {
2793  u32 session_db_index;
2794  u32 bdb_len;
2795  cnat_main_db_entry_t *be =0;
2796  cnat_session_entry_t *sdb_last = NULL;
2797  u16 instance;
2798 
2799  if (PREDICT_FALSE(ep->flags & CNAT_DB_NAT64_FLAG) != 0) {
2800  /* Preventive check - Not a NAT44 entry */
2801  return;
2802  }
2803 
2804  pool_header_t *h = pool_header(cnat_main_db);
2805 
2806  /* Validate .. just in case we are trying to delete a non existing one */
2807  bdb_len = vec_len(cnat_main_db);
2808 
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
2812  */
2813  if (PREDICT_FALSE((ep->main_db_index >= bdb_len) ||
2815 #ifdef DEBUG_PRINTF_ENABLED
2816  printf("invalid/unused user index in db %d\n", ep->main_db_index);
2817 #endif
2819  return;
2820  }
2821 
2822  be = cnat_main_db + ep->main_db_index;
2823 
2824  session_db_index = ep - cnat_session_db;
2825 
2827  be->session_head_index, (u8 *)cnat_session_db,
2828  sizeof (cnat_session_db[0]),
2830  session_db_index);
2831 
2832  if (be->flags & CNAT_DB_DSLITE_FLAG) {
2833  instance = be->dslite_nat44_inst_id;
2834  } else {
2835  instance = NAT44_RESERVED_INST_ID;
2836  }
2837 
2838  if(PREDICT_TRUE(log)) {
2839  if (be->flags & CNAT_DB_DSLITE_FLAG) {
2841  (dslite_table_db_ptr + instance),ep);
2842  } else {
2843  cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + be->vrfmap_index;
2844  cnat_session_log_nat44_mapping_delete(be, ep, my_vrfmap);
2845  }
2846  be->nsessions--;
2847  }
2848 
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
2852  * existing session
2853  */
2854 
2855  sdb_last = cnat_session_db + be->session_head_index;
2856  ASSERT(sdb_last != NULL);
2857 
2858  cnat_dest_update_session2main(be, sdb_last);
2859  _cnat_delete_session_db_entry(sdb_last, FALSE);
2860  }
2861 
2862  /* Remove from session DB hashes */
2864  nat44_dslite_common_stats[instance].sessions--;
2865 
2866  pool_put(cnat_session_db, ep);
2867 }
2868 
2870 {
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);
2874 }
2875 
2878 {
2879  u64 a, b, c;
2880  u32 index;
2882  cnat_user_db_entry_t *userdb;
2883 
2884  DSLITE_V6_GET_HASH((&(ki->dk)),
2885  ki->bucket,
2887 
2888  DSLITE_PRINTF(1,"MDBLU hash..%u\n", ki->bucket);
2889 
2890  index = cnat_in2out_hash[ki->bucket].next;
2891  if (PREDICT_TRUE(index == EMPTY)) {
2892  DSLITE_PRINTF(1,"MDBLU index MT..\n");
2893  return (NULL);
2894  }
2895 
2896  do {
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
2899  * one.
2900  */
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);
2909  return db;
2910  }
2911  index = db->in2out_hash.next;
2912  } while (index != EMPTY);
2913 
2914  DSLITE_PRINTF(1,"MDBLU Entry does not exist..\n");
2915  return (NULL);
2916 }
2917 
2920 {
2921  u64 a, b, c;
2922  u32 index;
2924 
2925  DSLITE_V6_GET_HASH((&(uki->dk)),
2926  uki->bucket,
2928 
2929  DSLITE_PRINTF(1,"UDBLU hash..%u\n", uki->bucket);
2930 
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");
2935  do {
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);
2943  return udb;
2944  }
2945  index = udb->user_hash.next;
2946  } while (index != EMPTY);
2947  }
2948  DSLITE_PRINTF(1,"UDBLU Entry doesnt exist..\n");
2949  return (NULL);
2950 }
2951 
2954  u32 portmap_index)
2955 {
2956  cnat_user_db_entry_t *udb = NULL;
2957 
2958  /* UNUSED. Therefore not ported to be multi-thread friendly */
2959  ASSERT(0);
2960 
2961  pool_get(cnat_user_db, udb);
2962  memset(udb, 0, sizeof(*udb));
2963 
2964  udb->ntranslations = 1;
2965  udb->portmap_index = portmap_index;
2966 // udb->key.key64 = uki->k.key64;
2967 
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];
2973 
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;
2979 
2980 #ifndef NO_BULK_LOGGING
2981  INIT_BULK_CACHE(udb)
2982 #endif /* NO_BULK_LOGGING */
2983 
2984  return udb;
2985 }
2986 
2987 #ifndef TOBE_PORTED
2991  cnat_user_db_entry_t *udb)
2992 {
2993  return 0;
2994 }
2995 #else
2999  cnat_user_db_entry_t *udb)
3000 {
3001  u64 a, b, c;
3002  u32 db_index;
3003  cnat_main_db_entry_t *db = NULL;
3004 
3005  /* UNUSED. Therefore not ported to be multi-thread friendly */
3006  ASSERT(0);
3007 
3008  pool_get(cnat_main_db, db);
3009  memset(db, 0, sizeof(*db));
3010 
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;
3018 
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;
3024 
3025  if (PREDICT_FALSE(udb->ntranslations == 1)) {
3026  /*
3027  * first port for this src vrf/src ip addr
3028  */
3029  udb->translation_list_head_index = db_index;
3030  DSLITE_PRINTF(1,"First translation of this user..\n");
3031  } else {
3033  (u8 *)cnat_main_db, sizeof(cnat_main_db[0]),
3035  db_index);
3036  }
3037 
3038  /*
3039  * setup o2i hash key
3040  */
3041  CNAT_V4_GET_HASH(ko->k.key64,
3042  ko->bucket,
3044  db->out2in_hash.next = cnat_out2in_hash[ko->bucket].next;
3045  cnat_out2in_hash[ko->bucket].next = db_index;
3046  /*
3047  * setup i2o hash key, bucket is already calculate
3048  */
3049  db->in2out_hash.next = cnat_in2out_hash[ki->bucket].next;
3050  cnat_in2out_hash[ki->bucket].next = db_index;
3051 
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);
3055 
3056 #if DEBUG > 1
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);
3065 #endif
3066 
3067  //nat44_dslite_common_stats[DSLITE_COMMON_STATS].active_translations++;
3068 
3069  return db;
3070 }
3071 
3072 static inline void handle_dslite_port_exceeded_logging(
3073  cnat_user_db_entry_t *udb,
3074  dslite_key_t * key,
3075  dslite_table_entry_t *dslite_entry_ptr)
3076 {
3077 
3079  /* Already logged ..*/
3080  return;
3081  }
3082 
3083  /* else, set the flag and call the log API */
3085  cnat_log_ds_lite_port_limit_exceeded(key, dslite_entry_ptr);
3086  return;
3087 }
3088 #endif
3089 
3091  cnat_user_db_entry_t *udb,
3092  cnat_key_t * key,
3093  cnat_vrfmap_t *vrfmap)
3094 {
3095 
3097  /* Already logged ..*/
3098  return;
3099  }
3100 
3101  /* else, set the flag and call the log API */
3104  return;
3105 }
3106 
3107 #ifndef TOBE_PORTED
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)
3115 {
3116  return 0;
3117 }
3118 #else
3119 /*
3120  * this function is called by exception node
3121  * when lookup is fialed in i2o node
3122  *
3123  * if reash per user port limit,
3124  * set user_db_entry pointer, and error == CNAT_OUT_LIMIT
3125  */
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)
3133 {
3134  u16 protocol;
3135  cnat_errno_t rv;
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;
3145  pool_header_t *h;
3146  u16 dslite_id = dslite_entry_ptr->dslite_id;
3147 
3148 #ifndef NO_BULK_LOGGING
3149  int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
3150 #endif
3151 
3152  /* UNUSED. Therefore not ported to be multi-thread friendly */
3153  ASSERT(0);
3154 
3155  /*
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.
3159  */
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
3167  */
3168  if(PREDICT_FALSE((!dest_info->k.ipv4) && (!dest_info->k.port))) {
3169  return db; /* if dest_info is null don't create session */
3170  }
3171 
3172  if(PREDICT_TRUE((db->dst_ipv4 == dest_info->k.ipv4) &&
3173  (db->dst_port == dest_info->k.port))) {
3174  return db;
3175  }
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);
3183  return db;
3184  } else {
3185  info->error = CNAT_ERR_NO_SESSION_DB;
3186  return NULL;
3187  }
3188  } else if(PREDICT_FALSE(db->nsessions == 0)) {
3189  /* Should be static entry.. should never happen
3190  */
3191  if(PREDICT_TRUE(dest_info->k.ipv4 != 0)) {
3192  cnat_add_dest_n_log(db, dest_info);
3193  }
3194  return db;
3195  } else {
3196  /* The src has already created multiple sessions.. very rare
3197  */
3198  session_db2 = cnat_create_session_db_entry(dest_info,
3199  db, TRUE);
3200  if(PREDICT_TRUE(session_db2 != NULL)) {
3201  CNAT_DB_TIMEOUT_RST(session_db2);
3202  return db;
3203  } else {
3204  info->error = CNAT_ERR_NO_SESSION_DB;
3205  return NULL;
3206  }
3207  }
3208 
3209  }
3210 
3211  /*
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
3217  */
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;
3222 #else
3223  /*
3224  * Inside ipv4 address should be masked, if port limit
3225  * need to be done at B4 element level.
3226  */
3227  u_ki.dk.ipv4_key.k.ipv4 = 0;
3228 #endif
3229  u_ki.dk.ipv4_key.k.port = 0;
3230 
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];
3235 
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
3239  */
3240 #if 0
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));
3246 
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;
3254  } else {
3255  info->error = CNAT_NO_VRF_RUN;
3258  }
3259 
3260  return (NULL);
3261  }
3262 #endif
3263 /*
3264  dslite_inst_ptr = dslite_nat44_config_table[dslite_inst_id];
3265 */
3266  pm = dslite_entry_ptr->portmap_list;
3267  //pm = my_vrfmap->portmap_list;
3268 
3269  /*
3270  * set o2i key with protocl bits
3271  */
3272  ko.k.k.vrf = dslite_entry_ptr->o_vrf | protocol;
3273  //ko.k.k.vrf = my_vrfmap->o_vrf | protocol;
3274 
3275  /*
3276  * step 2. check if src vrf, src ip addr is alreay
3277  * in the user db
3278  * if yes, use PORT_ALLOC_DIRECTED
3279  * if no, use PORT_ALLOC_ANY since it is first time
3280  */
3281  udb = dslite_user_db_lookup_entry(&u_ki);
3282  if (PREDICT_TRUE(udb)) {
3283  /*
3284  * not first time allocate port for this user
3285  * check limit
3286  */
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))
3290 
3291  /* Check for the port type here. If we are getting
3292  * a STATIC PORT, allow the config.
3293  */
3294  if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) {
3295  info->error = CNAT_OUT_LIMIT;
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);
3302  return (NULL);
3303  }
3304  }
3305 
3307  dslite_entry_ptr->cnat_main_db_max_ports_per_user)
3308 
3309  /*
3310  * check if main db has space to accomodate new entry
3311  */
3312  h = pool_header(cnat_main_db);
3313 
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 ++;
3319 
3320  current_timestamp = spp_trace_log_get_unix_time_in_seconds();
3321  if (PREDICT_FALSE((current_timestamp - last_log_timestamp) >
3322  1800)) {
3324  last_log_timestamp = current_timestamp;
3325  }
3326 
3327 #ifdef UT_TEST_CODE
3328  printf("Limit reached : OLD USER");
3329 #endif
3330  return NULL;
3331  }
3332 
3333  /*
3334  * allocate port, from existing mapping
3335  */
3336  my_index = udb->portmap_index;
3337 
3338  if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
3341  port_pair_type,
3342  ki->dk.ipv4_key.k.ipv4,
3343  ki->dk.ipv4_key.k.port,
3344  &my_index,
3345  &(ko.k.k.ipv4),
3346  &(ko.k.k.port),
3347  STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3348 #ifndef NO_BULK_LOGGING
3349  , udb,
3350  BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3351  &nfv9_log_req
3352 #endif
3353  , my_vrfmap->ip_n_to_1
3354  );
3355  } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP) ) {
3356 
3359  port_pair_type,
3360  &my_index,
3361  &(ko.k.k.ipv4),
3362  &(ko.k.k.port),
3363  STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3364 #ifndef NO_BULK_LOGGING
3365  , udb,
3366  BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3367  &nfv9_log_req
3368 #endif
3369  , 0,
3370  &(dslite_entry_ptr->rseed_ip)
3371  );
3372  DSLITE_PRINTF(1,"D_PORT_ALLOC %x %u\n", ko.k.k.ipv4, ko.k.k.port);
3373  } else {
3374  /*
3375  * For RTSP, two translation entries are created,
3376  * check if main db has space to accomodate two new entry
3377  */
3378  free_main = free_main - 1;
3379 
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 ++;
3384 
3385  return NULL;
3386  } else {
3387 
3390  port_pair_type,
3391  ki->dk.ipv4_key.k.port,
3392  &my_index,
3393  &(ko.k.k.ipv4),
3394  &(ko.k.k.port),
3395  STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3396 #ifndef NO_BULK_LOGGING
3397  , udb,
3398  BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3399  &nfv9_log_req
3400 #endif
3401  , &(dslite_entry_ptr->rseed_ip)
3402  );
3403  }
3404  }
3405 
3406  if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
3407  DSLITE_PRINTF(1,"D_PORT_ALLOC port alloc error\n");
3408  info->error = rv;
3410  nat44_dslite_common_stats[dslite_id].in2out_drops_resource_depletion ++;
3411  log_port_alloc_error(rv, &(ki->dk.ipv4_key));
3412  return (NULL);
3413  }
3414  /*
3415  * increment port in use for this user
3416  */
3417  udb->ntranslations += 1;
3418  } else {
3419  /*
3420  * first time allocate port for this user
3421  */
3422 
3423  /*
3424  * Do not create entry if port limit is invalid
3425  */
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 ++;
3432  return (NULL);
3433  }
3434  }
3435 
3436  /*
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.
3441  */
3442  h = pool_header(cnat_main_db);
3443  free_main = vec_len(h->free_indices) - 1;
3444 
3445  h = pool_header(cnat_user_db);
3446  free_user = vec_len(h->free_indices) - 1;
3447 
3448  /*
3449  * If either main_db or user_db does not have entries
3450  * bail out, with appropriate error
3451  */
3452  if (PREDICT_FALSE(!(free_main && free_user))) {
3453  u32 log_error;
3454  if(free_main) {
3455  info->error = CNAT_USER_DB_LIMIT;
3456  log_error = CNAT_USER_DB_LIMIT_ERROR;
3457  } else {
3458  info->error = CNAT_MAIN_DB_LIMIT;
3459  log_error = CNAT_MAIN_DB_LIMIT_ERROR;
3460  }
3461  nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++;
3463  spp_printf(log_error, 0, 0);
3464  return NULL;
3465  }
3466 
3467  if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) {
3470  port_pair_type,
3471  ki->dk.ipv4_key.k.ipv4,
3472  ki->dk.ipv4_key.k.port,
3473  &my_index,
3474  &(ko.k.k.ipv4),
3475  &(ko.k.k.port),
3476  STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3477 #ifndef NO_BULK_LOGGING
3478  , NULL,
3479  BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3480  &nfv9_log_req
3481 #endif
3482  , my_vrfmap->ip_n_to_1
3483 
3484  );
3485  } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP)) {
3488  port_pair_type,
3489  &my_index,
3490  &(ko.k.k.ipv4),
3491  &(ko.k.k.port),
3492  STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3493 #ifndef NO_BULK_LOGGING
3494  , NULL,
3495  BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3496  &nfv9_log_req
3497 #endif
3498  , 0,
3499  &(dslite_entry_ptr->rseed_ip)
3500  );
3501  DSLITE_PRINTF(1,"NU:D PORT ALLOC..%x %u\n", ko.k.k.ipv4,
3502  ko.k.k.port);
3503 
3504  } else {
3505  /*
3506  * For RTSP, two translation entries are created,
3507  * check if main db has space to accomodate two new entry
3508  */
3509  free_main = free_main - 1;
3510 
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 ++;
3515 
3516  return NULL;
3517  } else {
3518 
3521  port_pair_type,
3522  ki->dk.ipv4_key.k.port,
3523  &my_index,
3524  &(ko.k.k.ipv4),
3525  &(ko.k.k.port),
3526  STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr)
3527 #ifndef NO_BULK_LOGGING
3528  , NULL,
3529  BULKSIZE_FROM_VRFMAP(dslite_entry_ptr),
3530  &nfv9_log_req
3531 #endif
3532  , &(dslite_entry_ptr->rseed_ip)
3533  );
3534  /* TODO: Add the port pair flag here */
3535  }
3536  }
3537 
3538 
3539 
3540  if (PREDICT_FALSE(rv != CNAT_SUCCESS)) {
3541  DSLITE_PRINTF(1,"NU:D_PORT_ALLOC port alloc error\n");
3542  info->error = rv;
3543  nat44_dslite_common_stats[dslite_id].in2out_drops_resource_depletion ++;
3545  log_port_alloc_error(rv, &(ki->dk.ipv4_key));
3546  return (NULL);
3547  }
3548  /*
3549  * create entry in user db
3550  */
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))) {
3557  BULKSIZE_FROM_VRFMAP(dslite_entry_ptr));
3558  }
3559 #endif /* #ifndef NO_BULK_LOGGING */
3560  }
3561 
3562  /*
3563  * step 3:
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
3568  */
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++;
3576  } else {
3577  nat44_dslite_common_stats[dslite_id].num_dynamic_translations++;
3578  }
3579 
3581 
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 */
3586  db->nsessions++;
3587  }
3588 
3589  /*
3590  * don't forget logging
3591  * logging API is unconditional,
3592  * logging configuration check is done inside the inline function
3593  */
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)) {
3599  dslite_entry_ptr,NULL);
3600  }
3601  } else {
3602  cnat_nfv9_ds_lite_mapping_create(db,dslite_entry_ptr
3603 #ifndef NO_BULK_LOGGING
3604  ,nfv9_log_req
3605 #endif
3606  );
3607  }
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
3612  ,nfv9_log_req
3613 #endif
3614  );
3615  }
3616  }
3617 
3618 #if 0
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;
3622  u64 a, b, c;
3623 
3624  new_ki.k.k.port += 1;
3625  ko.k.k.port += 1;
3626 
3627  CNAT_V4_GET_HASH(new_ki.k.key64, new_ki.bucket,
3629 
3630  db2 = cnat_create_main_db_entry_and_hash(&new_ki, &ko, udb);
3631 
3633  db2->dslite_nat44_inst_id = dslite_id;
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);
3640 #else
3641  cnat_nfv9_log_mapping_create(db2, my_vrfmap);
3642 #endif
3643  }
3644 #endif
3645  return db;
3646 }
3647 #endif /* TOBE_PORTED */
3648 
3649 #if 0
3650 /* TOBE_PORTED */
3651 uword
3652 cnat_db_v2_node_fn (vlib_main_t * vm,
3653  vlib_node_runtime_t * node,
3654  vlib_frame_t * frame)
3655 {
3656  return 0;
3657 }
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),
3663 
3664  .n_errors = ARRAY_LEN(cnat_db_v2_error_strings),
3665  .error_strings = cnat_db_v2_error_strings,
3666 
3667  .n_next_nodes = CNAT_DB_V2_DROP,
3668 
3669  /* edit / add dispositions here */
3670  .next_nodes = {
3671  [CNAT_DB_V2_DROP] = "error-drop",
3672  },
3673 };
3674 #endif
3675 void cnat_db_v2_init (void)
3676 {
3677 
3678  u32 i, n, lockinit;
3679  cnat_timeout_db_entry_t * tdb __attribute__((unused));
3680 
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));
3684 
3685  n = CNAT_DB_SIZE*1.15; /* add 15% LB margin */
3686 
3687  /*
3688  * We also make it multiple of NUM_BITS_IN_UWORD for better
3689  * DB scanning algorithm
3690  */
3691  if (n % NUM_BITS_IN_UWORD)
3692  n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD));
3693 
3694  pool_alloc(cgse_nat_db,n);
3695  for(i=0; i< n; i++) {
3696  pool_get(cgse_nat_db, comb_db);
3697  }
3698 
3699  for(i=0; i< n; i++) {
3700  pool_put(cgse_nat_db, cgse_nat_db + i);
3701  }
3702 
3703  cnat_main_db = &cgse_nat_db->nat44_main_db;
3704 
3705  /* For Sessions */
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 */
3710  } else {
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 */
3714  }
3715 
3716  /*
3717  * We also make it multiple of NUM_BITS_IN_UWORD for better
3718  * DB scanning algorithm
3719  */
3720  if (n % NUM_BITS_IN_UWORD)
3721  n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD));
3722 
3723  pool_alloc(cgse_session_db,n);
3724  for(i=0; i< n; i++) {
3725  pool_get(cgse_session_db, comb_session);
3726  }
3727 
3728  for(i=0; i< n; i++) {
3729  pool_put(cgse_session_db, cgse_session_db + i);
3730  }
3731 
3732  cnat_session_db = &cgse_session_db->nat44_session_db;
3733 
3734  vec_validate(cnat_out2in_hash, CNAT_MAIN_HASH_MASK);
3735  memset(cnat_out2in_hash, 0xff, CNAT_MAIN_HASH_SIZE*sizeof(index_slist_t));
3736 
3737  vec_validate(cnat_in2out_hash, CNAT_MAIN_HASH_MASK);
3738  memset(cnat_in2out_hash, 0xff, CNAT_MAIN_HASH_SIZE*sizeof(index_slist_t));
3739 
3740  vec_validate(cnat_session_hash, CNAT_SESSION_HASH_MASK);
3741  memset(cnat_session_hash, 0xff, CNAT_SESSION_HASH_SIZE*sizeof(index_slist_t));
3742 
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));
3746 
3747  pool_alloc(cgse_user_db,n);
3748  for(i=0; i< n; i++) {
3749  pool_get(cgse_user_db, comb_user);
3750  }
3751 
3752  for(i=0; i< n; i++) {
3753  pool_put(cgse_user_db, cgse_user_db + i);
3754  }
3755 
3756  cnat_user_db = &cgse_user_db->nat44_user_db;
3757 
3758  vec_validate(cnat_user_hash, CNAT_USER_HASH_MASK);
3759  memset(cnat_user_hash, 0xff, CNAT_USER_HASH_SIZE*sizeof(index_slist_t));
3760 
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);
3764  }
3765 
3766  for(i=0; i< n; i++) {
3767  pool_put(cnat_timeout_db, cnat_timeout_db + i);
3768  }
3769 
3770  vec_validate(cnat_timeout_hash, CNAT_TIMEOUT_HASH_MASK);
3771  memset(cnat_timeout_hash, 0xff, CNAT_TIMEOUT_HASH_SIZE*sizeof(index_slist_t));
3772 
3773 #ifdef TOBE_PORTED
3774  for (i=0;i<CNAT_MAX_VRFMAP_ENTRIES; i++) {
3775  svi_params_array[i].svi_type = CGSE_SVI_TYPE_INFRA;
3776  }
3777 #endif
3778 
3779  cnat_db_v2_main.main_db_lockp =
3782 
3783  cnat_db_v2_main.user_db_lockp =
3786 
3787  cnat_db_v2_main.session_db_lockp =
3790 
3791  lockinit = pthread_spin_init(cnat_db_v2_main.main_db_lockp,
3792  PTHREAD_PROCESS_PRIVATE);
3793  ASSERT (lockinit == 0);
3794 
3795  lockinit = pthread_spin_init(cnat_db_v2_main.user_db_lockp,
3796  PTHREAD_PROCESS_PRIVATE);
3797  ASSERT (lockinit == 0);
3798 
3799  lockinit = pthread_spin_init(cnat_db_v2_main.session_db_lockp,
3800  PTHREAD_PROCESS_PRIVATE);
3801  ASSERT (lockinit == 0);
3802 
3803  cnat_db_init_done = 1;
3804  printf("CNAT DB init is successful\n");
3805  return;
3806 }
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
u32 main_db_index
Definition: cnat_db.h:342
void cnat_nfv9_ds_lite_log_session_delete(cnat_main_db_entry_t *db, dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb)
u16 flags
Definition: cnat_db.h:159
#define CLIB_CACHE_LINE_ALIGN_MARK(mark)
Definition: cache.h:68
index_slist_t * cnat_out2in_hash
Definition: cnat_db_v2.c:195
void cnat_add_dest_n_log(cnat_main_db_entry_t *mdb, cnat_key_t *dest_info)
Definition: cnat_db_v2.c:1083
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
u32 total_address_pool_allocated
Definition: cnat_show.c:43
#define DSLITE_PRINTF(level,...)
Definition: dslite_db.h:28
a
Definition: bitmap.h:516
cnat_main_db_entry_t * cnat_main_db_lookup_entry(cnat_db_key_bucket_t *ki)
Definition: cnat_db_v2.c:515
#define foreach_cnat_db_v2_error
Definition: cnat_db_v2.c:70
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
u32 private_ip_users_count
Definition: cnat_ports.h:77
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
u32 ipv6[4]
Definition: cnat_db.h:118
void dslite_db_debug_error(dslite_db_key_bucket_t *u_ki, cnat_errno_t error)
Definition: cnat_db_v2.c:398
#define CNAT_USER_DB_NAT64_FLAG
Definition: cnat_db.h:298
u32 user_index
Definition: cnat_db.h:195
#define CNAT_USER_DB_PORT_LIMIT_EXCEEDED
Definition: cnat_db.h:300
#define pool_alloc(P, N)
Allocate N more free elements to pool (unspecified alignment).
Definition: pool.h:247
u16 delta
Definition: cnat_db.h:360
#define NAT44_RESERVED_INST_ID
Definition: cnat_config.h:40
cnat_user_db_entry_t * cnat_user_db
Definition: cnat_db_v2.c:202
Fixed length block allocator.
cnat_main_db_entry_t * dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki, cnat_db_key_bucket_t *ko, cnat_user_db_entry_t *udb)
Definition: cnat_db_v2.c:2989
#define NULL
Definition: clib.h:55
u32 debug_i_addr_start
cnat_timeout_db_entry_t * cnat_timeout_db
Definition: cnat_db_v2.c:204
u32 * free_indices
Vector of free indices.
Definition: pool.h:58
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
u32 cnat_current_time
Definition: cnat_global.c:29
u32 tcp_seq_num
Definition: cnat_db.h:369
u32 session_head_index
Definition: cnat_db.h:263
#define CNAT_DB_FLAG_PPTP_TUNNEL_INIT
Definition: cnat_db.h:170
void cnat_nfv9_ds_lite_mapping_delete(cnat_main_db_entry_t *db, dslite_table_entry_t *dslite_entry, int bulk_alloc)
u64 key64
Definition: cnat_db.h:109
cnat_main_db_entry_t * dslite_get_main_db_entry_v2(dslite_db_key_bucket_t *ki, port_pair_t port_pair_type, port_type_t port_type, cnat_gen_icmp_info *info, dslite_table_entry_t *dslite_entry_ptr, cnat_key_t *dest_info)
Definition: cnat_db_v2.c:3109
void cnat_user_db_delete(cnat_user_db_entry_t *up)
Definition: cnat_db_v2.c:541
u16 cnat_static_port_range
Definition: cnat_config.c:53
u32 ack_no
Definition: cnat_db.h:372
#define NAT64_MAIN_DB_SIZE
Definition: nat64_db.h:36
Definition: cnat_db.h:153
#define CNAT_DB_FLAG_ALG_CTRL_FLOW
Definition: cnat_db.h:183
static void cnat_log_ds_lite_port_limit_exceeded(dslite_key_t *key, dslite_table_entry_t *dslite_entry_ptr)
Definition: cnat_log_api.h:45
#define PREDICT_TRUE(x)
Definition: cnat_db_v2.c:66
cnat_session_entry_t * cnat_session_db
Definition: cnat_db_v2.c:203
#define CNAT_TIMEOUT_HASH_SIZE
Definition: cnat_db.h:72
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:521
cnat_errno_t cnat_dynamic_port_alloc_rtsp_bulk(cnat_portmap_v2_t *pm, port_alloc_t atype, port_pair_t pair_type, u16 i_port, u32 *index, u32 *o_ipv4_address, u16 *o_port, u16 static_port_range, cnat_user_db_entry_t *udb, bulk_alloc_size_t bulk_size, int *nfv9_log_req, u32 *rseed_ip)
u16 cnat_main_db_max_ports_per_user
Definition: dslite_defs.h:114
pthread_spinlock_t * main_db_lockp
Definition: cnat_db_v2.c:48
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:62
cnat_main_db_entry_t * cnat_get_main_db_entry_v2(cnat_db_key_bucket_t *ki, port_pair_t port_pair_type, port_type_t port_type, cnat_gen_icmp_info *info, cnat_key_t *dest_info)
Definition: cnat_db_v2.c:1647
#define CNAT_MAIN_HASH_SIZE
Definition: cnat_db.h:55
index_slist_t in2out_hash
Definition: cnat_db.h:156
static void cnat_timeout_db_hash_add(cnat_timeout_db_entry_t *t_entry)
Definition: cnat_db_v2.c:2425
#define CNAT_DB_FLAG_STATIC_PORT
Definition: cnat_db.h:164
cnat_errno_t
Definition: cnat_cli.h:26
#define pool_is_free(P, E)
Use free bitmap to query whether given element is free.
Definition: pool.h:203
#define MAIN_DB_TYPE
Definition: cnat_db.h:626
static void cnat_log_nat44_port_limit_exceeded(cnat_key_t *key, cnat_vrfmap_t *vrfmap)
Definition: cnat_log_api.h:53
u8 flags
Definition: cnat_db.h:296
void cnat_syslog_ds_lite_mapping_create(cnat_main_db_entry_t *db, dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb, int bulk_alloc)
void cnat_nfv9_nat44_log_session_create(cnat_main_db_entry_t *db, cnat_session_entry_t *sdb, cnat_vrfmap_t *vrfmap)
pthread_spinlock_t * user_db_lockp
Definition: cnat_db_v2.c:49
cnat_errno_t error
Definition: cnat_db.h:528
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
#define CNAT_DB_FLAG_PORT_PAIR
Definition: cnat_db.h:160
port_type_t
Definition: cnat_ports.h:89
u8 nf_logging_policy
Definition: dslite_defs.h:162
#define CNAT_VRF_MASK
Definition: cnat_db.h:96
void cnat_timeout_db_delete(cnat_key_t t_key)
Definition: cnat_db_v2.c:2496
cnat_key_t v4_dest_key
Definition: cnat_db.h:345
cnat_errno_t cnat_static_port_alloc_v2_bulk(cnat_portmap_v2_t *pm, port_alloc_t atype, port_pair_t pair_type, u32 i_ipv4_address, u16 i_port, u32 *index, u32 *o_ipv4_address, u16 *o_port, u16 static_port_range, cnat_user_db_entry_t *udb, bulk_alloc_size_t bulk_size, int *nfv9_log_req, u16 ip_n_to_1)
#define CNAT_MAX_SESSIONS_PER_BIB
Definition: cnat_db.h:67
u8 cnat_db_init_done
Definition: cnat_db_v2.c:43
cnat_portmap_v2_t * portmap_list
Definition: cnat_db.h:430
cnat_key_t timeout_key
Definition: cnat_db.h:136
u32 no_sessions
Definition: cnat_db_v2.c:232
vnet_main_t * vnet_main
Definition: cnat_db_v2.c:57
void cnat_delete_session_db_entry(cnat_session_entry_t *ep, u8 log)
Definition: cnat_db_v2.c:2869
cnat_session_entry_t * cnat_session_db_lookup_entry(cnat_key_t *ko, u32 main_db_index)
Definition: cnat_db_v2.c:2612
u16 cnat_main_db_max_ports_per_user
Definition: cnat_config.c:48
static void cnat_session_log_ds_lite_mapping_delete(cnat_main_db_entry_t *db, dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb)
Definition: cnat_log_api.h:105
index_slist_t out2in_hash
Definition: cnat_db.h:155
#define PPTP_DECR(ctr)
Definition: cnat_config.h:240
#define CGSE_SVI_TYPE_INFRA
Definition: cgse_defs.h:31
u16 query_and_update_db_timeout(void *db, u8 db_type)
Definition: cnat_db_v2.c:2325
#define CNAT_DB_FLAG_PPTP_GRE_ENTRY
Definition: cnat_db.h:174
#define MAX_VRFID
Definition: cnat_db.h:28
void cnat_session_db_hash_delete(cnat_session_entry_t *ep)
Definition: cnat_db_v2.c:2545
#define CNAT_DB_TIMEOUT_RST(db)
Definition: cnat_db.h:561
#define PLATFORM_DEBUG_PRINT(...)
void cnat_syslog_nat44_mapping_delete(cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb, int bulk_alloc)
Definition: cnat_syslog.c:453
Definition: dslite_defs.h:106
#define HASH_TABLE_SIZE
Definition: cnat_db_v2.c:40
void spp_printf(u16 error_code, u16 num_args, u32 *arg)
u16 cnat_timeout_db_create(cnat_timeout_t t_entry)
Definition: cnat_db_v2.c:2450
index_dlist_t main_list
Definition: cnat_db.h:356
cnat_main_db_entry_t * dslite_main_db_lookup_entry(dslite_db_key_bucket_t *ki)
Definition: cnat_db_v2.c:2877
u64 in2out_drops_system_limit_reached
Definition: cnat_db_v2.c:229
void cnat_dest_update_session2main(cnat_main_db_entry_t *mdb, cnat_session_entry_t *sdb)
Definition: cnat_db_v2.c:2771
static void cnat_session_log_ds_lite_mapping_create(cnat_main_db_entry_t *db, dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb)
Definition: cnat_log_api.h:97
union cnat_main_db_entry_t::@266 proto_data
cnat_key_t k
Definition: cnat_db.h:113
unsigned long u64
Definition: types.h:89
static void log_port_alloc_error(cnat_errno_t error, cnat_key_t *k)
Definition: cnat_db_v2.c:341
#define CNAT_PRO_MASK
Definition: cnat_db.h:97
#define CNAT_DB_NAT64_FLAG
Definition: cnat_db.h:189
#define CNAT_DEBUG_INSIDE_ERR(err)
Definition: cnat_db_v2.c:241
u32 dslite_translation_create_count
int vlib_main(vlib_main_t *volatile vm, unformat_input_t *input)
Definition: main.c:1599
static u32 cnat_timeout_db_hash_lookup(cnat_key_t t_key)
Definition: cnat_db_v2.c:2289
static char * cnat_db_v2_error_strings[]
Definition: cnat_db_v2.c:80
u64 in2out_drops_port_limit_exceeded
Definition: cnat_db_v2.c:228
cgse_nat_user_db_entry_t * cgse_user_db
Definition: cnat_db_v2.c:207
u16 port_limit
Definition: cnat_db.h:444
#define PORTS_PER_ADDR
Definition: cnat_ports.h:26
u16 dst_port
Definition: cnat_db.h:257
#define CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb, max_limit)
Definition: cnat_db_v2.c:266
void cnat_dest_update_main2session(cnat_main_db_entry_t *mdb, cnat_session_entry_t *sdb)
Definition: cnat_db_v2.c:2743
cnat_errno_t cnat_mapped_static_port_alloc_v2_bulk(cnat_portmap_v2_t *pm, port_alloc_t atype, u32 *index, u32 ipv4_address, u16 port, cnat_user_db_entry_t *udb, bulk_alloc_size_t bulk_size, int *nfv9_log_req, u16 ip_n_to_1)
u16 timeout
Definition: cnat_db.h:224
#define CNAT_DB_FLAG_ALG_ENTRY
Definition: cnat_db.h:166
u16 ntranslations
Definition: cnat_db.h:290
#define CNAT_MAX_VRFMAP_ENTRIES
Definition: cnat_db.h:103
cnat_main_db_entry_t nat44_main_db
Definition: nat64_db.h:338
#define CNAT_SESSION_DB_SIZE
Definition: cnat_db.h:62
u16 o_vrf
Definition: dslite_defs.h:112
static pool_header_t * pool_header(void *v)
Get pool header from user pool pointer.
Definition: pool.h:67
void cnat_db_in2out_hash_delete(cnat_main_db_entry_t *ep, cnat_user_db_entry_t *up)
Definition: cnat_db_v2.c:433
dslite_table_entry_t * dslite_table_db_ptr
Definition: cnat_global.c:52
#define CNAT_TIMEOUT_HASH_MASK
Definition: cnat_db.h:73
index_slist_t user_hash
Definition: cnat_db.h:287
cnat_key_t key
Definition: cnat_db.h:309
cnat_user_db_entry_t nat44_user_db
Definition: nat64_db.h:348
u16 debug_i_vrf
void cnat_port_free_v2_bulk(cnat_portmap_v2_t *pm, int index, port_pair_t ptype, u16 base_port, cnat_user_db_entry_t *udb, u16 static_port_range, bulk_alloc_size_t bulk_size, int *nfv9_log_req)
u8 nf_logging_policy
Definition: cnat_db.h:440
cnat_main_db_entry_t * cnat_create_static_main_db_entry_v2(cnat_db_key_bucket_t *ki, cnat_db_key_bucket_t *ko, cnat_vrfmap_t *my_vrfmap, cnat_gen_icmp_info *info)
Definition: cnat_db_v2.c:1669
u32 debug_i_addr_end
index_slist_t t_hash
Definition: cnat_db.h:142
void cnat_nfv9_ds_lite_log_session_create(cnat_main_db_entry_t *db, dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb)
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
void cnat_update_bulk_range_cache(cnat_user_db_entry_t *udb, u16 o_port, bulk_alloc_size_t bulk_size)
#define S_RUN
Definition: cnat_db.h:416
void handle_cnat_port_exceeded_logging(cnat_user_db_entry_t *udb, cnat_key_t *key, cnat_vrfmap_t *vrfmap)
Definition: cnat_db_v2.c:3090
cnat_db_v2_main_t cnat_db_v2_main
Definition: cnat_db_v2.c:60
#define CACHE_ALLOC_NO_LOG_REQUIRED
cnat_user_db_entry_t * dslite_user_db_lookup_entry(dslite_db_key_bucket_t *uki)
Definition: cnat_db_v2.c:2919
void cnat_db_debug_i2o_drop(cnat_db_key_bucket_t *ki)
Definition: cnat_db_v2.c:417
index_slist_t cnat_session_hash
Definition: cnat_db.h:339
index_slist_t * cnat_session_hash
Definition: cnat_db_v2.c:199
void cnat_nfv9_log_mapping_delete(cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap, int bulk_alloc)
cnat_errno_t cnat_dynamic_port_alloc_v2_bulk(cnat_portmap_v2_t *pm, port_alloc_t atype, port_pair_t pair_type, u32 *index, u32 *o_ipv4_address, u16 *o_port, u16 static_port_range, cnat_user_db_entry_t *udb, bulk_alloc_size_t bulk_size, int *nfv9_log_req, u16 ip_n_to_1, u32 *rseed_ip)
pthread_spinlock_t * session_db_lockp
Definition: cnat_db_v2.c:50
u16 timeout
Definition: cnat_db.h:351
u32 entry_expires
Definition: cnat_db.h:354
index_dlist_t pptp_list
Definition: cnat_db.h:249
u16 flags
Definition: cnat_db.h:348
#define CNAT_SESSION_HASH_MASK
Definition: cnat_db.h:64
cgse_nat_session_db_entry_t * cgse_session_db
Definition: cnat_db_v2.c:208
u32 portmap_index
Definition: cnat_db.h:306
u32 translation_list_head_index
Definition: cnat_db.h:303
void cnat_nfv9_nat44_log_session_delete(cnat_main_db_entry_t *db, cnat_session_entry_t *sdb, cnat_vrfmap_t *vrfmap)
cnat_global_counters_t cnat_global_counters
Definition: cnat_db_v2.c:190
cnat_portmap_v2_t * portmap_list
Definition: dslite_defs.h:119
#define CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE
Definition: cnat_db.h:171
svmdb_client_t * c
u8 icmp_msg_count
Definition: cnat_db.h:293
void cnat_main_db_entry_dump(cnat_main_db_entry_t *db)
Definition: cnat_show.c:108
void port_exceeded_msg_log(u32 src_addr, u16 i_vrf)
Definition: cnat_db_v2.c:320
#define SESSION_LOG_ENABLE
Definition: cnat_db.h:693
cnat_main_db_entry_t * cnat_main_db
Definition: cnat_db_v2.c:201
void cnat_db_v2_init(void)
Definition: cnat_db_v2.c:3675
void cnat_delete_main_db_entry_v2(cnat_main_db_entry_t *ep)
Definition: cnat_db_v2.c:763
#define BITS_PER_INST
Definition: cnat_ports.h:30
#define CNAT_DB_DSLITE_FLAG
Definition: cnat_db.h:188
#define ARRAY_LEN(x)
Definition: clib.h:59
cnat_main_db_entry_t * cnat_main_db_lookup_entry_out2in(cnat_db_key_bucket_t *ko)
Definition: cnat_db_v2.c:996
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
u8 my_instance_number
Definition: cnat_ports.c:51
cnat_db_key_t k
Definition: cnat_db.h:108
u8 syslog_logging_policy
Definition: dslite_defs.h:161
#define BULKSIZE_FROM_VRFMAP(vrfmap)
#define STAT_PORT_RANGE_FROM_INST_PTR(inst)
Definition: dslite_defs.h:333
u16 timeout_value
Definition: cnat_db.h:137
#define CNAT_DB_FLAG_TCP_ACTIVE
Definition: cnat_db.h:161
#define BULK_ALLOC_NOT_ATTEMPTED
cnat_key_t ipv4_key
Definition: cnat_db.h:119
#define CNAT_DEBUG_GLOBAL_ALL
Definition: cnat_cli.h:94
u32 ipv6[4]
Definition: cnat_db.h:310
struct cnat_main_db_entry_t::@266::seq_pcp_t seq_pcp
Definition: cnat_db.h:285
u32 spp_trace_log_get_unix_time_in_seconds(void)
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u32 entry_expires
Definition: cnat_db.h:213
Definition: cnat_db.h:140
static void pptp_clear_all_channels(cnat_main_db_entry_t *db)
Definition: cnat_db_v2.c:719
index_dlist_t user_ports
Definition: cnat_db.h:204
#define TRUE
Definition: cnat_db.h:78
#define PLATFORM_DBL_SUPPORT
#define CNAT_SET_ICMP_MSG_INFO
Definition: cnat_db_v2.c:234
index_slist_t * cnat_in2out_hash
Definition: cnat_db_v2.c:196
cnat_session_entry_t * cnat_create_session_db_entry(cnat_key_t *ko, cnat_main_db_entry_t *bdb, u8 log)
Definition: cnat_db_v2.c:2643
vhost_vring_state_t state
Definition: vhost-user.h:80
cnat_session_entry_t * cnat_session_db_edm_lookup_entry(cnat_key_t *ko, u32 session_head_index, u32 main_db_index)
Definition: cnat_db_v2.c:2583
cnat_key_t out2in_key
Definition: cnat_db.h:198
Bitmaps built as vectors of machine words.
u32 global_debug_flag
u32 rseed_ip
Definition: cnat_db.h:443
port_pair_t
Definition: cnat_ports.h:82
void cnat_nfv9_log_mapping_create(cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap, int bulk_alloc)
#define CNAT_USER_DB_DSLITE_FLAG
Definition: cnat_db.h:299
index_slist_t * cnat_user_hash
Definition: cnat_db_v2.c:197
#define VRF_MAP_ENTRY_EMPTY
Definition: cnat_db.h:506
#define CNAT_USER_DB_SIZE
Definition: cnat_db.h:58
cgse_nat_db_entry_t * cgse_nat_db
Definition: cnat_db_v2.c:206
void index_dlist_addtail(u32 head_index, u8 *vector, u32 elsize, u32 offset, u32 index_to_add)
Definition: index_list.c:83
u64 uword
Definition: types.h:112
u16 nsessions
Definition: cnat_db.h:266
u32 window
Definition: cnat_db.h:375
#define NAT44_COMMON_STATS
Definition: cnat_db.h:690
#define DSLITE_DEBUG_INSIDE_ERR(err)
Definition: cnat_db_v2.c:251
uword * free_bitmap
Bitmap of indices of free objects.
Definition: pool.h:55
#define CNAT_V4_GET_SESSION_HASH(main_index, in_addr, port, vrf, hash, mask)
Definition: cnat_db.h:543
Definition: cnat_db.h:336
u16 ip_n_to_1
Definition: cnat_db.h:433
unsigned short u16
Definition: types.h:57
u8 syslog_logging_policy
Definition: cnat_db.h:441
cnat_user_db_entry_t * cnat_user_db_lookup_entry(cnat_db_key_bucket_t *uki)
Definition: cnat_db_v2.c:603
struct _cnat_svi_params_entry cnat_svi_params_entry
u16 dslite_nat44_inst_id
Definition: cnat_db.h:260
uword bm[(BITS_PER_INST+BITS(uword)-1)/BITS(uword)]
Definition: cnat_ports.h:75
#define CNAT_MAIN_HASH_MASK
Definition: cnat_db.h:56
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define CNAT_TIMEOUT_FULL_MASK
Definition: cnat_db.h:74
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
#define CNAT_USER_HASH_SIZE
Definition: cnat_db.h:59
u16 delta
Definition: cnat_db.h:217
void cnat_table_entry_fill_map(u32 start_addr, u32 end_addr, cnat_portmap_v2_t **port_map_holder)
Definition: cnat_db_v2.c:87
#define CNAT_USER_HASH_MASK
Definition: cnat_db.h:60
#define NUM_BITS_IN_UWORD
Definition: cnat_db.h:69
#define PREDICT_FALSE(x)
Definition: cnat_db_v2.c:67
u32 dst_ipv4
Definition: cnat_db.h:254
cnat_session_entry_t * cnat_handle_1to2_session(cnat_main_db_entry_t *mdb, cnat_key_t *dest_info)
Definition: cnat_db_v2.c:1027
u16 vrfmap_index
Definition: cnat_db.h:192
vlib_main_t * vlib_main
Definition: cnat_db_v2.c:56
#define DSLITE_V6_GET_HASH(in_key, hash, mask)
Definition: dslite_db.h:77
bulk_alloc_size_t
#define THROTTLE_TIME
Definition: cnat_db_v2.c:41
#define CNAT_DB_SIZE
Definition: cnat_db.h:54
static void cnat_session_log_nat44_mapping_create(cnat_main_db_entry_t *db, cnat_session_entry_t *sdb, cnat_vrfmap_t *vrfmap)
Definition: cnat_log_api.h:80
u64 no_translation_entry_drops
Definition: cnat_db_v2.c:231
cnat_user_db_entry_t * cnat_user_db_create_entry(cnat_db_key_bucket_t *uki, u32 portmap_index)
Definition: cnat_db_v2.c:628
#define SESSION_DB_TYPE
Definition: cnat_db.h:627
#define FALSE
Definition: cnat_db.h:79
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:117
u64 in2out_drops_resource_depletion
Definition: cnat_db_v2.c:230
u32 rseed_ip
Definition: dslite_defs.h:167
cnat_user_db_entry_t * dslite_user_db_create_entry(dslite_db_key_bucket_t *uki, u32 portmap_index)
Definition: cnat_db_v2.c:2953
u32 translation_create_count
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u32 translation_delete_count
void cnat_nfv9_ds_lite_mapping_create(cnat_main_db_entry_t *db, dslite_table_entry_t *dslite_entry, int bulk_alloc)
#define EMPTY
Definition: index_list.h:24
struct _cnat_ingress_vrfid_name_entry cnat_ingress_vrfid_name_entry
cnat_main_db_entry_t * cnat_create_main_db_entry_and_hash(cnat_db_key_bucket_t *ki, cnat_db_key_bucket_t *ko, cnat_user_db_entry_t *udb)
Definition: cnat_db_v2.c:653
#define CNAT_SESSION_HASH_SIZE
Definition: cnat_db.h:63
#define CNAT_DB_FLAG_UDP_ACTIVE
Definition: cnat_db.h:163
Definition: nat64_db.h:337
dslite_key_t dk
Definition: cnat_db.h:127
#define CNAT_V4_GET_HASH(key64, hash, mask)
Definition: cnat_db.h:536
void cnat_db_debug_error(cnat_db_key_bucket_t *u_ki, cnat_errno_t error)
Definition: cnat_db_v2.c:379
u16 dslite_id
Definition: dslite_defs.h:109
u32 flags
Definition: vhost-user.h:75
cnat_timeout_t t_key
Definition: cnat_db.h:141
cnat_db_v2_error_t
Definition: cnat_db_v2.c:73
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
static void cnat_session_log_nat44_mapping_delete(cnat_main_db_entry_t *db, cnat_session_entry_t *sdb, cnat_vrfmap_t *vrfmap)
Definition: cnat_log_api.h:88
void cnat_db_out2in_hash_delete(cnat_main_db_entry_t *ep)
Definition: cnat_db_v2.c:482
union cnat_main_db_entry_t::@265 alg
#define BITS(x)
Definition: clib.h:58
void pptp_remove_channel_from_tunnel(cnat_main_db_entry_t *db)
Definition: cnat_db_v2.c:743
Definition: nat64_db.h:342
void cnat_syslog_nat44_mapping_create(cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb, int bulk_alloc)
Definition: cnat_syslog.c:436
#define CNAT_MAX_ADDR_POOL_SIZE_PER_CORE
Definition: cnat_cli.h:123
union cnat_session_entry_t::@267 alg
cnat_vrfmap_t * cnat_map_by_vrf
Definition: cnat_db_v2.c:218
Definition: nat64_db.h:347
cnat_key_t in2out_key
Definition: cnat_db.h:201
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".
index_slist_t * cnat_timeout_hash
Definition: cnat_db_v2.c:198
cnat_icmp_msg_t gen_icmp_msg
Definition: cnat_db.h:529
#define INIT_BULK_CACHE(udb)
cnat_session_entry_t nat44_session_db
Definition: nat64_db.h:343
u32 index_dlist_remelem(u32 head_index, u8 *vector, u32 elsize, u32 offset, u32 index_to_delete)
Definition: index_list.c:103