/* *------------------------------------------------------------------ * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 [%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 0)) sum ++; } PLATFORM_DEBUG_PRINT("buckets in use: %d\n", sum); sum = 0; for(i=0; i= 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