vpp/plugins/vcgn-plugin/vcgn/cnat_va_db.c
Ole Troan ea3e1fc875 Plugins: Clean up the plugin directory so that each plugin has its own
directory and GNU autotools setup.

Change-Id: I6c59d1297389c9413db0c0b9bdf3b759080bf1b8
Signed-off-by: Ole Troan <ot@cisco.com>
2016-06-27 15:04:00 +00:00

287 lines
7.7 KiB
C

/*
*------------------------------------------------------------------
* cnat_va_db.c - virtual assembly database
*
* Copyright (c) 2009, 2013 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cnat_va_db.h>
#include <format.h>
#include <spp_node.h>
#include <spp_alloc.h>
#include <spp_byteorder.h>
#include <spp_main.h>
#include <spp_cache.h>
#include <spp_interface.h>
#include <spp_api.h>
#include <spp_client_api.h>
#include <spp_timers.h>
#include <cnat_db.h>
#include <spp_plugin.h>
#include <cnat_v4_functions.h>
va_bucket_t va_bucket[VA_BUCKETS];
void va_bucket_init () {
u32 i;
/*
* set the pointer in each bucket
* points to nowhere
*/
for (i=0; i<VA_BUCKETS; i++) {
va_bucket[i].next_available_entry = ~0;
}
}
inline void va_db_add_new_entry (u32 bucket_index,
va_lookup_key * key )
{
va_entry_t * entry_p;
u32 head, next;
entry_p = va_db_lookup(bucket_index, key);
if (PREDICT_FALSE(entry_p)) {
FRAG_DEBUG_PRINTF6(
"\nVA_ADD_NEW: Bucket %d fnd Existng entry [%d, %d] -> [%d, %d]\n",
bucket_index, entry_p->src_port,
entry_p->dst_port, key->e.src_port, key->e.dst_port)
/* found match entry, update it */
entry_p->src_port = key->e.src_port;
entry_p->dst_port = key->e.dst_port;
FRAG_DEBUG_PRINTF3("VA_ADD_NEW: Existing bucket %d, counter %d\n",
bucket_index,
va_bucket[bucket_index].new_entry_counter)
} else {
/* no match, add a new one */
head = va_bucket[bucket_index].head_entry;
next = va_bucket[bucket_index].next_available_entry;
FRAG_DEBUG_PRINTF5(
"\nVA_ADD_NEW: Filling bucket %d, index %d with key 0x%llx %x\n",
bucket_index, next, key->k.key64, key->k.key32)
va_bucket[bucket_index].va_entry[next] = key->e;
/* increase next pointer */
va_bucket[bucket_index].next_available_entry = (next+1) & VA_BUCKET_MASK;
if (PREDICT_FALSE(head == va_bucket[bucket_index].next_available_entry)) {
/* adjust head circular pointer */
va_bucket[bucket_index].head_entry = (head+1) & VA_BUCKET_MASK;
}
va_bucket[bucket_index].new_entry_counter++;
FRAG_DEBUG_PRINTF4(
"VA_ADD_NEW: NEW bucket %d, entry %d counter %d\n",
bucket_index, next, va_bucket[bucket_index].new_entry_counter)
}
}
/*
* use the key,
* return pointer to the entry if found,
* NULL if not
*/
inline
va_entry_t * va_db_lookup (u32 bucket_index, va_lookup_key * key)
{
u32 index, next;
va_entry_t * entry_p;
va_bucket_t * bucket;
bucket = &va_bucket[bucket_index];
index = bucket->head_entry;
next = bucket->next_available_entry;
entry_p = NULL;
FRAG_DEBUG_PRINTF4(
"\nVA_DB_LOOKUP: bucket index %d head %d next %d\n",
bucket_index, index, next)
/* loop through the entries in the bucket */
while( index != next) {
if(PREDICT_TRUE(memcmp(&bucket->va_entry[index], key, VA_KEY_SIZE)==0)) {
entry_p = &bucket->va_entry[index];
/*In add frag entry function we are again assigning key's src
port to entry_p's src port. So when a main DB entry is deleted/
timed out, and again another entry is created for the same
src ip and src port pair, the frag's entry_p will have the
previous port info stored and not updated. Hence the below
line is not required*/
/* *(u32*)&key->e.src_port = *(u32*)&entry_p->src_port; */
/* do two ports as u32 :) */
break;
}
index = (index +1) & VA_BUCKET_MASK;
}
#ifdef FRAG_DEBUG
if (PREDICT_TRUE(entry_p)) {
FRAG_DEBUG_PRINTF3("VA_DB_LOOKUP: bucket index %d entry index %d\n",
bucket_index, index)
FRAG_DEBUG_PRINTF5("VA_DB_LOOKUP: SRC-->DST [0x%x, %d] [0x%x, %d]\n",
entry_p->src_ip, entry_p->src_port,
entry_p->dst_ip, entry_p->dst_port)
FRAG_DEBUG_PRINTF3("[vrf 0x%x, id 0x%x]\n",
entry_p->vrf, entry_p->ip_id)
} else {
FRAG_DEBUG_PRINTF1("\nNULL ENTRY\n")
}
#endif
return entry_p;
}
inline
int va_db_delete_entry (u32 bucket_index, va_lookup_key * key)
{
u32 index, next;
int entry_found = 0;
va_bucket_t * bucket;
bucket = &va_bucket[bucket_index];
index = bucket->head_entry;
next = bucket->next_available_entry;
FRAG_DEBUG_PRINTF4(
"\nVA_DB_DELETE_ENTRY: bucket index %d head %d next %d\n",
bucket_index, index, next);
/* loop through the entries in the bucket */
while( index != next) {
if(PREDICT_TRUE(memcmp(&bucket->va_entry[index], key,
VA_KEY_SIZE)==0)) {
/* Clear the entry */
FRAG_DEBUG_PRINTF1("Entry found in delete API");
memset(&bucket->va_entry[index], 0, sizeof(va_entry_t));
entry_found = 1;
break;
}
index = (index +1) & VA_BUCKET_MASK;
}
return entry_found;
}
void cnat_va_bucket_used (int argc, unsigned long * argv)
{
u32 i, sum = 0;;
for(i=0;i<VA_BUCKETS;i++) {
if(PREDICT_TRUE(va_bucket[i].new_entry_counter)) sum++;
}
if (PREDICT_FALSE(!sum)) {
printf("no bucket in use\n");
return;
}
printf("index head next counter (%d bucket in use)\n", sum);
for(i=0;i<VA_BUCKETS;i++) {
if (PREDICT_FALSE(!va_bucket[i].new_entry_counter)) continue;
printf(" %04d %04d %04d %d\n", i,
va_bucket[i].head_entry,
va_bucket[i].next_available_entry,
va_bucket[i].new_entry_counter);
}
}
void cnat_va_dump (int argc, unsigned long * argv)
{
u32 i, sum, index ;
PLATFORM_DEBUG_PRINT("====== SUMMARY ======\n");
PLATFORM_DEBUG_PRINT("Total buckets: %d\n", VA_BUCKETS);
PLATFORM_DEBUG_PRINT("Entries per bucket: %d\n", VA_ENTRY_PER_BUCKET);
sum = 0;
for(i=0; i<VA_BUCKETS; i++) {
if (PREDICT_TRUE(va_bucket[i].new_entry_counter > 0)) sum ++;
}
PLATFORM_DEBUG_PRINT("buckets in use: %d\n", sum);
sum = 0;
for(i=0; i<VA_BUCKETS; i++) {
if ( PREDICT_FALSE(((va_bucket[i].next_available_entry+1) & VA_BUCKET_MASK)
== va_bucket[i].head_entry)) {
sum ++;
}
}
PLATFORM_DEBUG_PRINT("bucket full: %d\n", sum);
/* dump per bucket info */
if (argc == 0 ) return;
index = (u32) argv[0];
if (PREDICT_FALSE(index >= VA_BUCKETS)) {
PLATFORM_DEBUG_PRINT("invalid bucket index %d\n", index);
return;
}
PLATFORM_DEBUG_PRINT("\n====== Bucket %d ======\n", index);
PLATFORM_DEBUG_PRINT("bucket head index %d\n", va_bucket[index].head_entry);
PLATFORM_DEBUG_PRINT("bucket next index %d\n", va_bucket[index].next_available_entry);
PLATFORM_DEBUG_PRINT(" source IP dest IP VRF ip-id srcP dstP\n");
for(i=0;i<VA_ENTRY_PER_BUCKET;i++) {
hex_dump((u8*)&va_bucket[index].va_entry[i], sizeof(va_entry_t));
}
}