aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/vcgn-plugin/vcgn/cnat_ports.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/vcgn-plugin/vcgn/cnat_ports.c')
-rw-r--r--plugins/vcgn-plugin/vcgn/cnat_ports.c1113
1 files changed, 0 insertions, 1113 deletions
diff --git a/plugins/vcgn-plugin/vcgn/cnat_ports.c b/plugins/vcgn-plugin/vcgn/cnat_ports.c
deleted file mode 100644
index 943fb3ed..00000000
--- a/plugins/vcgn-plugin/vcgn/cnat_ports.c
+++ /dev/null
@@ -1,1113 +0,0 @@
-/*
- *------------------------------------------------------------------
- * cnat_ports.c - port allocator
- *
- * Copyright (c) 2008-2014 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *------------------------------------------------------------------
- */
-#include <vlib/vlib.h>
-#include <vnet/vnet.h>
-#include <vppinfra/vec.h>
-#include <vppinfra/hash.h>
-#include <vppinfra/pool.h>
-#include <vppinfra/clib.h>
-#include <vppinfra/bitmap.h>
-
-#include "cnat_db.h"
-#include "cnat_config.h"
-#include "cnat_global.h"
-#include "cnat_logging.h"
-#include "spp_timers.h"
-#include "platform_common.h"
-#include "cgn_bitmap.h"
-#include "spp_platform_trace_log.h"
-#include "cnat_ports.h"
-
-#if 1 /* TOBE_PORTED */
-/* Following is defined elsewhere. */
-#define msg_spp_err(s) \
-do { \
- fprintf(stderr,(i8 *)s); \
- fputs("\n", stderr); \
-} while(0);
-#endif
-
-
-#define PM_90_PERCENT_USE 58980
-/*
- * instance number provisioned from HW
- */
-u8 my_instance_number = 0;
-
-typedef struct {
- u32 cached_next_index;
- /* $$$$ add data here */
-
- /* convenience variables */
- vlib_main_t * vlib_main;
- vnet_main_t * vnet_main;
-} cnat_ports_main_t;
-
-cnat_ports_main_t cnat_ports_main;
-
-static u32 rseed_port; /* random number generator seed */
-
-void
-cnat_db_dump_portmap_for_vrf (u32 vrfmap_index)
-{
- u32 i, pm_len;
- cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + vrfmap_index;
- cnat_portmap_v2_t *pm, *my_pm __attribute__((unused));
-
- pm = my_vrfmap->portmap_list;
- pm_len = vec_len(pm);
-
- for (i = 0; i < pm_len; i++) {
- my_pm = pm + i;
-
- PLATFORM_DEBUG_PRINT("pm %d: IPv4 Addr 0x%x - in use %d private_ip_users_count %d\n",
- i, my_pm->ipv4_address, my_pm->inuse,
- my_pm->private_ip_users_count);
-
- PLATFORM_DEBUG_PRINT("pm %d: IPv4 Addr 0x%x - in use %d "
- "private_ip_users_count %d\n",
- i, my_pm->ipv4_address, my_pm->inuse,
- my_pm->private_ip_users_count);
- }
-}
-
-void
-cnat_db_dump_portmaps ()
-{
- u32 i, vrfmap_index;
-
- for (i = 0; i < CNAT_MAX_VRFMAP_ENTRIES; i++) {
- vrfmap_index = vrf_map_array[i];
-
- if (vrfmap_index == VRF_MAP_ENTRY_EMPTY) {
- continue;
- }
-
- PLATFORM_DEBUG_PRINT("\n\nDumping the port map for uidb_index %d\n", i);
- cnat_db_dump_portmap_for_vrf(vrfmap_index);
- }
-}
-
-#ifndef NO_BULK_LOGGING
-static int check_if_stat_alloc_ok_for_bulk(cnat_portmap_v2_t *pm,
- u16 i_port, bulk_alloc_size_t bulk_size,
- u16 static_port_range)
-{
- uword bit_test_result;
- if(BULK_ALLOC_SIZE_NONE == bulk_size) return 1; /* No issues */
-
- if(i_port < static_port_range) return 1; /* we don't want bulk */
-
- i_port = (i_port/bulk_size) * bulk_size;
- bit_test_result = cgn_clib_bitmap_check_if_all(pm->bm, i_port, bulk_size);
- return(bit_test_result);
-}
-#else /* dummy */
-inline static int check_if_stat_alloc_ok_for_bulk(cnat_portmap_v2_t *pm,
- u16 i_port, bulk_alloc_size_t bulk_size,
- u16 static_port_range)
-{
- return 1;
-}
-#endif /* NO_BULK_LOGGING */
-/*
- * cnat_port_alloc_static_v2
- * public ipv4 address/port allocator for Static Port commands
- * tries to allocate same outside port as inside port
- */
-cnat_errno_t
-cnat_static_port_alloc_v2 (
- 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
-#ifndef NO_BULK_LOGGING
- , bulk_alloc_size_t bulk_size,
- int *nfv9_log_req
-#endif
- , u16 ip_n_to_1
- )
-{
- u32 i, hash_value, my_index, found, max_attempts;
- u16 start_bit, new_port;
- cnat_portmap_v2_t *my_pm = 0;
- u32 pm_len = vec_len(pm);
- uword bit_test_result;
-
-#ifndef NO_BULK_LOGGING
- *nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
-#endif
-
- if (PREDICT_FALSE(pm_len == 0)) {
- return (CNAT_NO_POOL_ANY);
- }
-
- switch (atype) {
-
- case PORT_ALLOC_ANY:
-
- found = 0;
-
- /*
- * Try to hash the IPv4 address to get an index value to select the pm
- */
- hash_value = (i_ipv4_address & 0xffff) ^
- ((i_ipv4_address > 16) & 0xffff);
-
- /*
- * If pm_len <= 256, compact the hash to 8 bits
- */
- if (PREDICT_TRUE(pm_len <= 256)) {
- hash_value = (hash_value & 0xff) ^ ((hash_value > 8) & 0xff);
- }
-
- /*
- * Ensure that the hash value is in the range 0 .. (pm_len-1)
- */
- my_index = hash_value % pm_len;
-
- for (i = 0; i < PORT_PROBE_LIMIT; i++) {
- my_pm = pm + my_index;
- if(PREDICT_TRUE(ip_n_to_1)) {
- if(PREDICT_TRUE(my_pm->private_ip_users_count < ip_n_to_1)) {
- /*
- * Try to find a PM with atlest 33% free and my_port free
- */
- if (PREDICT_TRUE((my_pm->inuse < ((BITS_PER_INST*2)/3)) &&
- clib_bitmap_get_no_check(my_pm->bm,
- i_port) == 1)
-#ifndef NO_BULK_LOGGING
- && check_if_stat_alloc_ok_for_bulk(my_pm, i_port,
- bulk_size,
- static_port_range)
-#endif
- ) {
- found = 1;
- break;
- }
- }
-
- } else {
- /*
- * Try to find a PM with atlest 33% free and my_port free
- */
- if (PREDICT_TRUE((my_pm->inuse < ((BITS_PER_INST*2)/3)) &&
- clib_bitmap_get_no_check(my_pm->bm,
- i_port) == 1)
-#ifndef NO_BULK_LOGGING
- && check_if_stat_alloc_ok_for_bulk(my_pm, i_port,
- bulk_size,
- static_port_range)
-#endif
- ) {
- found = 1;
- break;
- }
- }
- my_index = (my_index + 1) % pm_len;
- }
-
- /*
- * If not found do it the hard way .
- * "hard" way, best-fit.
- */
- if (!found) {
- u32 min_inuse_any, min_inuse_myport;
- u32 min_index_any, min_index_myport;
-
- min_inuse_any = min_inuse_myport = PORTS_PER_ADDR + 1;
- min_index_any = min_index_myport = ~0;
- for (i = 0; i < pm_len; i++) {
- my_pm = pm + i;
- if(PREDICT_TRUE(ip_n_to_1)) {
- if(PREDICT_TRUE(my_pm->private_ip_users_count < ip_n_to_1)) {
- if (PREDICT_FALSE(my_pm->inuse < min_inuse_any)) {
- min_inuse_any = my_pm->inuse;
- min_index_any = my_pm - pm;
- }
- if (PREDICT_FALSE(my_pm->inuse < min_inuse_myport)) {
- if (PREDICT_TRUE(clib_bitmap_get_no_check(
- my_pm->bm,i_port) == 1)
-#ifndef NO_BULK_LOGGING
- && check_if_stat_alloc_ok_for_bulk(my_pm,
- i_port,bulk_size,static_port_range)
-#endif
- ) {
- min_inuse_myport = my_pm->inuse;
- min_index_myport = my_pm - pm;
- }
- }
-
- }
-
- } else {
- if (PREDICT_FALSE(my_pm->inuse < min_inuse_any)) {
- min_inuse_any = my_pm->inuse;
- min_index_any = my_pm - pm;
- }
- if (PREDICT_FALSE(my_pm->inuse < min_inuse_myport)) {
- if (PREDICT_TRUE(clib_bitmap_get_no_check(
- my_pm->bm, i_port) == 1)
-#ifndef NO_BULK_LOGGING
- && check_if_stat_alloc_ok_for_bulk(my_pm, i_port,
- bulk_size, static_port_range)
-#endif
- ) {
- min_inuse_myport = my_pm->inuse;
- min_index_myport = my_pm - pm;
- }
- }
- }
- }
-
- /*
- * Check if we have an exactly matching PM that has
- * myport free. If so use it. If no such PM is
- * available, use any PM
- */
- if (PREDICT_TRUE(min_inuse_myport < PORTS_PER_ADDR)) {
- my_pm = pm + min_index_myport;
- my_index = min_index_myport;
- found = 1;
- } else if (PREDICT_TRUE(min_inuse_any < PORTS_PER_ADDR)) {
- my_pm = pm + min_index_any;
- my_index = min_index_any;
- found = 1;
- }
- }
-
- if (!found) {
- return (CNAT_NO_PORT_ANY);
- }
- break;
-
- case PORT_ALLOC_DIRECTED:
- my_index = *index;
- if (PREDICT_FALSE(my_index > pm_len)) {
- return (CNAT_INV_PORT_DIRECT);
- }
- my_pm = pm + my_index;
- break;
-
- default:
- return (CNAT_ERR_PARSER);
- }
-
- /* Allocate a matching port if possible */
- start_bit = i_port;
- found = 0;
- max_attempts = BITS_PER_INST;
-#ifndef NO_BULK_LOGGING
- if((BULK_ALLOC_SIZE_NONE != bulk_size) &&
- (i_port >= static_port_range)) {
- start_bit = (start_bit/bulk_size) * bulk_size;
- max_attempts = BITS_PER_INST/bulk_size;
- }
-#endif /* NO_BULK_LOGGING */
-
- for (i = 0; i < max_attempts; i++) {
-#ifndef NO_BULK_LOGGING
- if((BULK_ALLOC_SIZE_NONE != bulk_size) &&
- (i_port >= static_port_range)) {
- bit_test_result = cgn_clib_bitmap_check_if_all(my_pm->bm,
- start_bit, bulk_size);
- }
- else
-#endif /* #ifndef NO_BULK_LOGGING */
- bit_test_result = clib_bitmap_get_no_check(my_pm->bm, start_bit);
-
- if (PREDICT_TRUE(bit_test_result)) {
-#ifndef NO_BULK_LOGGING
- if((BULK_ALLOC_SIZE_NONE != bulk_size) &&
- (i_port >= static_port_range)) {
- *nfv9_log_req = start_bit;
- if(i==0) new_port = i_port; /* First go */
- else {
- new_port = bit2port(start_bit);
- if (pair_type == PORT_S_ODD && (new_port & 0x1) == 0)
- new_port++;
- }
- found = 1;
- break;
- }
- else {
-#endif /* NO_BULK_LOGGING */
- new_port = bit2port(start_bit);
- if (pair_type == PORT_S_ODD) {
- if ((new_port & 0x1) == 1) {
- found = 1;
- break;
- }
- } else if (pair_type == PORT_S_EVEN) {
- if ((new_port & 0x1) == 0) {
- found = 1;
- break;
- }
- } else {
- found = 1;
- break;
- }
-#ifndef NO_BULK_LOGGING
- }
-#endif
- }
-#ifndef NO_BULK_LOGGING
- if((BULK_ALLOC_SIZE_NONE != bulk_size) &&
- (i_port >= static_port_range))
- start_bit = (start_bit + bulk_size) % BITS_PER_INST;
- else {
-#endif /* NO_BULK_LOGGING */
- start_bit = (start_bit + 1) % BITS_PER_INST;
- if(PREDICT_FALSE(start_bit == 0)) {
- start_bit = 1; /* Port 0 is invalid, so start from 1 */
- }
-#ifndef NO_BULK_LOGGING
- }
-#endif
- } /* End of for loop */
-
- if (!found) {
- /* Port allocation failure */
- if (atype == PORT_ALLOC_DIRECTED) {
- return (CNAT_NOT_FOUND_DIRECT);
- } else {
- return (CNAT_NOT_FOUND_ANY);
- }
- }
-
- /* Accounting */
- cgn_clib_bitmap_clear_no_check(my_pm->bm, new_port);
- (my_pm->inuse)++;
-
- *index = my_pm - pm;
- *o_ipv4_address = my_pm->ipv4_address;
-
- *o_port = new_port;
-
- return (CNAT_SUCCESS);
-}
-
-/*
- * Try to allocate a portmap structure based on atype field
- */
-cnat_portmap_v2_t *
-cnat_dynamic_addr_alloc_from_pm (
- cnat_portmap_v2_t *pm,
- port_alloc_t atype,
- u32 *index,
- cnat_errno_t *err,
- u16 ip_n_to_1,
- u32 *rseed_ip)
-{
- u32 i, pm_len;
- int my_index;
- int min_inuse, min_index;
-
- cnat_portmap_v2_t *my_pm = 0;
- *err = CNAT_NO_POOL_ANY;
-
- pm_len = vec_len(pm);
-
- switch(atype) {
- case PORT_ALLOC_ANY:
- if (PREDICT_FALSE(pm_len == 0)) {
- my_pm = 0;
- *err = CNAT_NO_POOL_ANY;
- goto done;
- }
-
- /* "Easy" way, first address with at least 200 free ports */
- for (i = 0; i < PORT_PROBE_LIMIT; i++) {
- *rseed_ip = randq1(*rseed_ip);
- my_index = (*rseed_ip) % pm_len;
- my_pm = pm + my_index;
- if (PREDICT_FALSE(ip_n_to_1)) {
- if(PREDICT_TRUE(ip_n_to_1 == 1)) {
- if (PREDICT_FALSE(0 == my_pm->inuse)) {
- goto done;
- }
- } else {
- if(PREDICT_TRUE(my_pm->private_ip_users_count < ip_n_to_1)) {
- if (PREDICT_FALSE(my_pm->inuse < ((BITS_PER_INST*2)/3))) {
- goto done;
- }
- }
- }
- } else {
- if (PREDICT_FALSE(my_pm->inuse < ((BITS_PER_INST*2)/3))) {
- goto done;
- }
- }
- }
-
- /* "hard" way, best-fit. $$$$ Throttle complaint */
- min_inuse = PORTS_PER_ADDR + 1;
- min_index = ~0;
- for (i = 0; i < pm_len; i++) {
- my_pm = pm + i;
- if (PREDICT_FALSE(ip_n_to_1)) {
- if(PREDICT_TRUE(ip_n_to_1 == 1)) {
- if (PREDICT_FALSE(!my_pm->inuse)) {
- min_inuse = my_pm->inuse;
- min_index = my_pm - pm;
- }
- } else {
- if(PREDICT_TRUE(my_pm->private_ip_users_count < ip_n_to_1)) {
- if (PREDICT_TRUE(my_pm->inuse < min_inuse)) {
- min_inuse = my_pm->inuse;
- min_index = my_pm - pm;
- }
-
- }
- }
-
- } else {
- if (PREDICT_TRUE(my_pm->inuse < min_inuse)) {
- min_inuse = my_pm->inuse;
- min_index = my_pm - pm;
- }
- }
- }
-
- if (PREDICT_TRUE(min_inuse < PORTS_PER_ADDR)) {
- my_pm = pm + min_index;
- my_index = min_index;
- goto done;
- }
-
- /* Completely out of ports */
-#ifdef DEBUG_PRINTF_ENABLED
- PLATFORM_DEBUG_PRINT("%s out of ports\n", __FUNCTION__);
-#endif
-
- my_pm = 0;
- *err = CNAT_NO_PORT_ANY;
- break;
-
-
- case PORT_ALLOC_DIRECTED:
- //ASSERT(*index < pm_len);
- if (PREDICT_FALSE(*index > pm_len)) {
- my_pm = 0;
- *err = CNAT_INV_PORT_DIRECT;
- goto done;
- }
- my_pm = pm + *index;
- my_index = *index;
- break;
-
- default:
- msg_spp_err("bad allocation type in cnat_port_alloc");
- my_pm = 0;
- *err = CNAT_ERR_PARSER;
- break;
- }
-
- done:
- if (PREDICT_FALSE(my_pm == NULL)) {
- return (my_pm);
- }
-
- if (PREDICT_FALSE(my_pm->inuse >= BITS_PER_INST)) {
- my_pm = 0;
- if (atype == PORT_ALLOC_DIRECTED) {
- *err = CNAT_BAD_INUSE_DIRECT;
- } else {
- *err = CNAT_BAD_INUSE_ANY;
- }
- }
-
- return (my_pm);
-}
-
-
-/*
- * cnat_port_alloc_v2
- * public ipv4 address/port allocator for dynamic ports
- *
- * 200K users / 20M translations means vec_len(cnat_portmap) will be
- * around 300.
- *
- */
-cnat_errno_t
-cnat_dynamic_port_alloc_v2 (
- 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
-#ifndef NO_BULK_LOGGING
- , bulk_alloc_size_t bulk_size,
- int *nfv9_log_req
-#endif
- , u16 ip_n_to_1,
- u32 *rseed_ip
- )
-{
- int i;
- cnat_errno_t my_err = CNAT_NO_POOL_ANY;
- cnat_portmap_v2_t *my_pm = 0;
- u16 start_bit;
- u16 new_port;
- uword bit_test_result;
- uword max_trys_to_find_port;
-
- ASSERT(index);
- ASSERT(o_ipv4_address);
- ASSERT(o_port);
-
- my_pm = cnat_dynamic_addr_alloc_from_pm(pm, atype, index, &my_err, ip_n_to_1,
- rseed_ip);
-
- if (PREDICT_FALSE(my_pm == NULL)) {
- return (my_err);
- }
- if(PREDICT_FALSE(my_pm->dyn_full == 1)) {
- if (atype == PORT_ALLOC_DIRECTED) {
- return (CNAT_NOT_FOUND_DIRECT);
- } else {
- return (CNAT_NOT_FOUND_ANY);
- }
- }
-
-#if DEBUG > 1
- PLATFORM_DEBUG_PRINT("ALLOC_PORT_V2: My_Instance_Number %d: IP addr 0x%x, Inuse %d\n",
- my_instance_number, my_pm->ipv4_address, my_pm->inuse);
-#endif
-
- rseed_port = randq1(rseed_port);
-
- /*
- * Exclude the static port range for allocating dynamic ports
- */
- start_bit = (rseed_port) % (BITS_PER_INST - static_port_range);
- start_bit = start_bit + static_port_range;
-
-#ifndef NO_BULK_LOGGING
- *nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
- if(BULK_ALLOC_SIZE_NONE != bulk_size)
- {
- /* We need the start port of the range to be alined on integer multiple
- * of bulk_size */
- max_trys_to_find_port = BITS_PER_INST/bulk_size;
- start_bit= ((start_bit + bulk_size -1)/bulk_size) * bulk_size;
- }
- else
-#endif /* #ifndef NO_BULK_LOGGING */
- max_trys_to_find_port = BITS_PER_INST;
-
- /* Allocate a random port / port-pair */
- for (i = 0; i < max_trys_to_find_port; i++) {
-
- /* start_bit is only a u16.. so it can rollover and become zero */
- if (PREDICT_FALSE( /* (start_bit >= BITS_PER_INST) || FIXME u16 cannot be >= 65536 */
- (start_bit < static_port_range))) {
- start_bit = static_port_range;
-#ifndef NO_BULK_LOGGING
- if(BULK_ALLOC_SIZE_NONE != bulk_size) {
- start_bit= ((start_bit + bulk_size -1)/bulk_size) * bulk_size;
- }
-#endif /* #ifndef NO_BULK_LOGGING */
- }
- /* Scan forward from random position */
-#ifndef NO_BULK_LOGGING
- if(BULK_ALLOC_SIZE_NONE != bulk_size) {
- bit_test_result = cgn_clib_bitmap_check_if_all(my_pm->bm,
- start_bit, bulk_size);
- }
- else
-#endif /* #ifndef NO_BULK_LOGGING */
- bit_test_result = clib_bitmap_get_no_check(my_pm->bm, start_bit);
-
- if (PREDICT_TRUE(bit_test_result)) {
- new_port = bit2port(start_bit);
-#ifndef NO_BULK_LOGGING
- if(BULK_ALLOC_SIZE_NONE != bulk_size)
- *nfv9_log_req = new_port;
-#endif
- if ((pair_type == PORT_S_ODD) &&
- (!(new_port & 0x1))) {
-#ifndef NO_BULK_LOGGING
- if(BULK_ALLOC_SIZE_NONE != bulk_size) {
- start_bit++; /* Just use the next one in the bulk range */
- new_port++;
- goto found2;
- }
-#endif /* #ifndef NO_BULK_LOGGING */
- goto notfound;
- } else if ((pair_type == PORT_S_EVEN) &&
- (new_port & 0x1)) {
- goto notfound;
- }
-
- /* OK we got one or two suitable ports */
- goto found2;
- }
-
- notfound:
-#ifndef NO_BULK_LOGGING
- if(BULK_ALLOC_SIZE_NONE != bulk_size)
- start_bit += bulk_size;
- else
-#endif /* #ifndef NO_BULK_LOGGING */
- start_bit++;
-
- } /* end of for loop */
-
- /* Completely out of ports */
-
- /* Port allocation failure */
- /* set dyn_full flag. This would be used to verify
- * for further dyn session before searching for port
- */
- if (atype == PORT_ALLOC_DIRECTED) {
- my_pm->dyn_full = 1;
- return (CNAT_NOT_FOUND_DIRECT);
- } else {
- my_pm->dyn_full = 1;
- return (CNAT_NOT_FOUND_ANY);
- }
-
-
- found2:
-
- /* Accounting */
- cgn_clib_bitmap_clear_no_check (my_pm->bm, start_bit);
- (my_pm->inuse)++;
-
- *index = my_pm - pm;
- *o_ipv4_address = my_pm->ipv4_address;
-
- *o_port = new_port;
- return (CNAT_SUCCESS);
-}
-
-#ifdef TOBE_PORTED
-/*
- * cnat_alloc_port_from_pm
- * Given a portmap structure find port/port_pair that are free
- *
- * The assumption in this function is that bit in bm corresponds
- * to a port number. This is TRUE and hence there is no call
- * to the function bit2port here, though it is done in other
- * places in this file.
- *
- */
-static u32
-cnat_alloc_port_from_pm (
- u32 start_port,
- u32 end_port,
- cnat_portmap_v2_t *my_pm,
- port_pair_t pair_type
-#ifndef NO_BULK_LOGGING
- , bulk_alloc_size_t bulk_size,
- int *nfv9_log_req
-#endif /* #ifnded NO_BULK_ALLOCATION */
- )
-{
- u32 i;
- u32 start_bit;
- u32 total_ports = end_port - start_port + 1;
- uword bit_test_result;
- uword max_trys_to_find_port;
-
- rseed_port = randq1(rseed_port);
-
- start_bit = rseed_port % total_ports;
- start_bit = start_bit + start_port;
-#ifndef NO_BULK_LOGGING
- *nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED;
- if(BULK_ALLOC_SIZE_NONE != bulk_size)
- {
- /* We need the start port of the range to be alined on integer multiple
- * of bulk_size */
- max_trys_to_find_port = total_ports/bulk_size;
- start_bit= ((start_bit + bulk_size -1)/bulk_size) * bulk_size;
- }
- else
-#endif /* #ifndef NO_BULK_LOGGING */
- max_trys_to_find_port = total_ports;
-
- /* Allocate a random port / port-pair */
- for (i = 0; i < max_trys_to_find_port; i++) {
- /* start_bit is only a u16.. so it can rollover and become zero */
- if (PREDICT_FALSE((start_bit >= end_port) ||
- (start_bit < start_port))) {
- start_bit = start_port;
-#ifndef NO_BULK_LOGGING
- if(BULK_ALLOC_SIZE_NONE != bulk_size) {
- start_bit= ((start_bit + bulk_size -1)/bulk_size) * bulk_size;
- }
-#endif /* #ifndef NO_BULK_LOGGING */
- }
-
- /* Scan forward from random position */
-#ifndef NO_BULK_LOGGING
- if(BULK_ALLOC_SIZE_NONE != bulk_size) {
- bit_test_result = cgn_clib_bitmap_check_if_all(my_pm->bm,
- start_bit, bulk_size);
- }
- else
-#endif /* #ifndef NO_BULK_LOGGING */
- bit_test_result = clib_bitmap_get_no_check(my_pm->bm, start_bit);
-
- if (PREDICT_TRUE(bit_test_result)) {
-#ifndef NO_BULK_LOGGING
- if(BULK_ALLOC_SIZE_NONE != bulk_size) {
- /* Got the entire bulk range */
- *nfv9_log_req = bit2port(start_bit);
- return start_bit;
- } else {
-#endif /* #ifndef NO_BULK_LOGGING */
- /*
- * For PORT_PAIR, first port has to be Even
- * subsequent port <= end_port
- * subsequent port should be unallocated
- */
- if ((start_bit & 0x1) ||
- ((start_bit + 1) > end_port) ||
- (clib_bitmap_get_no_check(my_pm->bm,
- (start_bit + 1)) == 0)) {
- goto notfound;
- }
- return (start_bit);
-#ifndef NO_BULK_LOGGING
- }
-#endif /* #ifndef NO_BULK_LOGGING */
- } /* if( free port found ) */
-
-notfound:
-#ifndef NO_BULK_LOGGING
- if(BULK_ALLOC_SIZE_NONE != bulk_size) {
- start_bit += bulk_size;
- } else
-#endif /* #ifndef NO_BULK_LOGGING */
- start_bit++;
-
- }
- return (BITS_PER_INST);
-}
-
-/*
- * cnat_dynamic_port_alloc_rtsp
- * public ipv4 address/port allocator for dynamic ports
- *
- * 200K users / 20M translations means vec_len(cnat_portmap) will be
- * around 300.
- *
- */
-
-cnat_errno_t
-cnat_dynamic_port_alloc_rtsp (
- cnat_portmap_v2_t *pm,
- port_alloc_t atype,
- port_pair_t pair_type,
- u16 start_range,
- u16 end_range,
- u32 *index,
- u32 *o_ipv4_address,
- u16 *o_port
-#ifndef NO_BULK_LOGGING
- , bulk_alloc_size_t bulk_size,
- int *nfv9_log_req
-#endif
- , u32 *rseed_ip
- )
-{
-
- u32 current_timestamp;
- cnat_errno_t my_err = CNAT_NO_POOL_ANY;
- cnat_portmap_v2_t *my_pm = 0;
- u32 alloc_bit;
-
- ASSERT(index);
- ASSERT(o_ipv4_address);
- ASSERT(o_port);
-
- my_pm = cnat_dynamic_addr_alloc_from_pm(pm, atype, index, &my_err, 0,rseed_ip);
-
- if (PREDICT_FALSE(my_pm == NULL)) {
- return (my_err);
- }
-
-#if DEBUG > 1
- PLATFORM_DEBUG_PRINT("ALLOC_PORT_V2: My_Instance_Number %d: IP addr 0x%x, Inuse %d\n",
- my_instance_number, my_pm->ipv4_address, my_pm->inuse);
-#endif
-
- alloc_bit =
- cnat_alloc_port_from_pm(start_range, end_range, my_pm, pair_type
-#ifndef NO_BULK_LOGGING
- , bulk_size, nfv9_log_req
-#endif /* #ifndef NO_BULK_LOGGING */
- );
-
- if (alloc_bit < BITS_PER_INST) {
- if (pair_type == PORT_PAIR) {
- /* Accounting */
- cgn_clib_bitmap_clear_no_check (my_pm->bm, alloc_bit);
- cgn_clib_bitmap_clear_no_check (my_pm->bm, alloc_bit+1);
- (my_pm->inuse) += 2;
- } else {
- /* Accounting */
- cgn_clib_bitmap_clear_no_check (my_pm->bm, alloc_bit);
- (my_pm->inuse)++;
- }
-
- *index = my_pm - pm;
- *o_ipv4_address = my_pm->ipv4_address;
-
- *o_port = bit2port(alloc_bit);;
-
- return (CNAT_SUCCESS);
- }
-
- /* Completely out of ports */
- current_timestamp = spp_trace_log_get_unix_time_in_seconds();
- if (PREDICT_FALSE((current_timestamp - my_pm->last_sent_timestamp) >
- 1000)) {
- spp_printf(CNAT_NO_EXT_PORT_AVAILABLE, 0, NULL);
- my_pm->last_sent_timestamp = current_timestamp;
- }
-
-
- /* Port allocation failure */
- if (atype == PORT_ALLOC_DIRECTED) {
- return (CNAT_NOT_FOUND_DIRECT);
- } else {
- return (CNAT_NOT_FOUND_ANY);
- }
-}
-#else
-cnat_errno_t
-cnat_dynamic_port_alloc_rtsp (
- cnat_portmap_v2_t *pm,
- port_alloc_t atype,
- port_pair_t pair_type,
- u16 start_range,
- u16 end_range,
- u32 *index,
- u32 *o_ipv4_address,
- u16 *o_port
-#ifndef NO_BULK_LOGGING
- , bulk_alloc_size_t bulk_size,
- int *nfv9_log_req
-#endif
- , u32 *rseed_ip
- )
-{
- return (CNAT_NOT_FOUND_ANY);
-}
-#endif
-
-
-/*
- * cnat_mapped_static_port_alloc_v2
- * /
- */
-cnat_errno_t
-cnat_mapped_static_port_alloc_v2 (
- cnat_portmap_v2_t *pm,
- port_alloc_t atype,
- u32 *index,
- u32 ipv4_address,
- u16 port
-#ifndef NO_BULK_LOGGING
- , int *nfv9_log_req,
- bulk_alloc_size_t bulk_size
-#endif
- , u16 ip_n_to_1
- )
-{
- int i;
- u32 pm_len;
- u16 bm_bit;
- cnat_portmap_v2_t *my_pm = 0;
- u32 my_index;
-
- ASSERT(index);
-
- /*
- * Map the port to the bit in the pm bitmap structure.
- * Note that we use ports from 1024..65535, so
- * port number x corresponds to (x-1024) position in bitmap
- */
- bm_bit = port2bit(port);
-
- pm_len = vec_len(pm);
-
- switch(atype) {
- case PORT_ALLOC_ANY:
- if (PREDICT_FALSE(pm_len == 0)) {
- return (CNAT_NO_POOL_ANY);
- }
-
- /*
- * Find the pm that is allocated for this translated IP address
- */
- my_index = pm_len;
-
- for (i = 0; i < pm_len; i++) {
- my_pm = pm + i;
- if (PREDICT_FALSE(my_pm->ipv4_address == ipv4_address)) {
- my_index = i;
- break;
- }
- }
-
- if ((PREDICT_FALSE(my_index >= pm_len)) ||
- ((PREDICT_FALSE(ip_n_to_1)) && (PREDICT_TRUE(my_pm->private_ip_users_count >= ip_n_to_1)))) {
- return (CNAT_NO_POOL_ANY);
- }
-
- break;
-
- case PORT_ALLOC_DIRECTED:
- if (PREDICT_FALSE(*index > pm_len)) {
- return (CNAT_INV_PORT_DIRECT);
- }
-
- my_index = *index;
- my_pm = pm + my_index;
- if (PREDICT_FALSE(my_pm->ipv4_address != ipv4_address)) {
- if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) {
- PLATFORM_DEBUG_PRINT("Delete all main db entry for that particular in ipv4 address\n");
- }
- return (CNAT_INV_PORT_DIRECT);
- }
-
- break;
-
- default:
- msg_spp_err("bad allocation type in cnat_port_alloc");
- return (CNAT_ERR_PARSER);
- }
-
-
- if (PREDICT_FALSE(my_pm == NULL)) {
- return (CNAT_NO_POOL_ANY);
- }
-
- /*
- * Check if the port is already allocated to some other mapping
- */
- if (PREDICT_FALSE(clib_bitmap_get_no_check (my_pm->bm, bm_bit) == 0)) {
- return (CNAT_NO_POOL_ANY);
- }
-
-#if DEBUG > 1
- PLATFORM_DEBUG_PRINT("ALLOC_PORT_V2: My_Instance_Number %d: IP addr 0x%x, Inuse %d\n",
- my_instance_number, my_pm->ipv4_address, my_pm->inuse);
-#endif
-
- /*
- * Indicate that the port is already allocated
- */
- cgn_clib_bitmap_clear_no_check (my_pm->bm, bm_bit);
- (my_pm->inuse)++;
-
- *index = my_index;
-
- return (CNAT_SUCCESS);
-}
-
-void cnat_port_free_v2 (
- cnat_portmap_v2_t *pm,
- int index,
- port_pair_t pair_type,
- u16 base_port,
- u16 static_port_range)
-{
- cnat_portmap_v2_t *my_pm;
- uword bit;
-
- /* check for valid portmap */
- if (PREDICT_FALSE(index > vec_len(pm))) {
- spp_printf(CNAT_INVALID_INDEX_TO_FREE_PORT, 0, 0);
- return;
- }
-
- my_pm = pm + index;
- bit = port2bit(base_port);
-
-#if DEBUG > 0
- if(clib_bitmap_get_no_check(my_pm->bm, bit))
- ASSERT(clib_bitmap_get_no_check(my_pm->bm, bit) == 0);
-#endif
-
- cgn_clib_bitmap_set_no_check(my_pm->bm, bit);
-
- my_pm->inuse -= 1;
- if(base_port >= static_port_range) {
- /* Clear the full flag. we can have a new dynamic session now */
- my_pm->dyn_full = 0;
- }
-
- return;
-}
-
-void cnat_portmap_dump_v2 (cnat_portmap_v2_t *pm, u16 print_limit)
-{
- int i;
- u32 inuse =0;
-
- ASSERT(pm);
-
- for (i = 0; i < BITS_PER_INST; i++) {
- if (PREDICT_FALSE(clib_bitmap_get_no_check (pm->bm, i) == 0)) {
- if (PREDICT_TRUE(inuse++ < print_limit))
- PLATFORM_DEBUG_PRINT(" %d", bit2port(i));
- }
- }
- if (PREDICT_FALSE(inuse >= print_limit)) {
- PLATFORM_DEBUG_PRINT("%d printed, print limit is %d\n",
- inuse, print_limit);
- }
- PLATFORM_DEBUG_PRINT("\n");
-}
-
-
-/*
- * cnat_ports_init
- */
-clib_error_t *cnat_ports_init(vlib_main_t *vm)
-{
- cnat_ports_main_t *mp = &cnat_ports_main;
-
- mp->vlib_main = vm;
- mp->vnet_main = vnet_get_main();
-
- /* suppress crypto-random port numbering */
-#ifdef SOON
- if (spp_get_int_prop("no_crypto_random_ports") == 0)
- crypto_random32(&seed);
-#endif
-
- return 0;
-}
-
-VLIB_INIT_FUNCTION(cnat_ports_init);
-