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