FD.io VPP  v16.06
Vector Packet Processing
cnat_va_db.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * cnat_va_db.c - virtual assembly database
4  *
5  * Copyright (c) 2009, 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 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <cnat_va_db.h>
24 #include <format.h>
25 #include <spp_node.h>
26 #include <spp_alloc.h>
27 #include <spp_byteorder.h>
28 #include <spp_main.h>
29 #include <spp_cache.h>
30 #include <spp_interface.h>
31 #include <spp_api.h>
32 #include <spp_client_api.h>
33 #include <spp_timers.h>
34 #include <cnat_db.h>
35 #include <spp_plugin.h>
36 #include <cnat_v4_functions.h>
37 
38 
40 
41 void va_bucket_init () {
42 
43  u32 i;
44 
45  /*
46  * set the pointer in each bucket
47  * points to nowhere
48  */
49  for (i=0; i<VA_BUCKETS; i++) {
50  va_bucket[i].next_available_entry = ~0;
51  }
52 
53 }
54 
55 inline void va_db_add_new_entry (u32 bucket_index,
56  va_lookup_key * key )
57 {
58 
59  va_entry_t * entry_p;
60  u32 head, next;
61 
62  entry_p = va_db_lookup(bucket_index, key);
63 
64  if (PREDICT_FALSE(entry_p)) {
66  "\nVA_ADD_NEW: Bucket %d fnd Existng entry [%d, %d] -> [%d, %d]\n",
67  bucket_index, entry_p->src_port,
68  entry_p->dst_port, key->e.src_port, key->e.dst_port)
69 
70  /* found match entry, update it */
71  entry_p->src_port = key->e.src_port;
72  entry_p->dst_port = key->e.dst_port;
73 
74  FRAG_DEBUG_PRINTF3("VA_ADD_NEW: Existing bucket %d, counter %d\n",
75  bucket_index,
76  va_bucket[bucket_index].new_entry_counter)
77 
78  } else {
79 
80  /* no match, add a new one */
81  head = va_bucket[bucket_index].head_entry;
82  next = va_bucket[bucket_index].next_available_entry;
83 
85  "\nVA_ADD_NEW: Filling bucket %d, index %d with key 0x%llx %x\n",
86  bucket_index, next, key->k.key64, key->k.key32)
87 
88  va_bucket[bucket_index].va_entry[next] = key->e;
89 
90  /* increase next pointer */
91  va_bucket[bucket_index].next_available_entry = (next+1) & VA_BUCKET_MASK;
92 
93  if (PREDICT_FALSE(head == va_bucket[bucket_index].next_available_entry)) {
94  /* adjust head circular pointer */
95  va_bucket[bucket_index].head_entry = (head+1) & VA_BUCKET_MASK;
96  }
97 
98  va_bucket[bucket_index].new_entry_counter++;
99 
101  "VA_ADD_NEW: NEW bucket %d, entry %d counter %d\n",
102  bucket_index, next, va_bucket[bucket_index].new_entry_counter)
103  }
104 }
105 
106 
107 /*
108  * use the key,
109  * return pointer to the entry if found,
110  * NULL if not
111  */
112 
113 inline
114 va_entry_t * va_db_lookup (u32 bucket_index, va_lookup_key * key)
115 {
116 
117  u32 index, next;
118  va_entry_t * entry_p;
119  va_bucket_t * bucket;
120 
121  bucket = &va_bucket[bucket_index];
122  index = bucket->head_entry;
123  next = bucket->next_available_entry;
124  entry_p = NULL;
125 
127  "\nVA_DB_LOOKUP: bucket index %d head %d next %d\n",
128  bucket_index, index, next)
129 
130  /* loop through the entries in the bucket */
131  while( index != next) {
132 
133  if(PREDICT_TRUE(memcmp(&bucket->va_entry[index], key, VA_KEY_SIZE)==0)) {
134 
135  entry_p = &bucket->va_entry[index];
136  /*In add frag entry function we are again assigning key's src
137  port to entry_p's src port. So when a main DB entry is deleted/
138  timed out, and again another entry is created for the same
139  src ip and src port pair, the frag's entry_p will have the
140  previous port info stored and not updated. Hence the below
141  line is not required*/
142 
143  /* *(u32*)&key->e.src_port = *(u32*)&entry_p->src_port; */
144  /* do two ports as u32 :) */
145 
146  break;
147  }
148 
149  index = (index +1) & VA_BUCKET_MASK;
150 
151  }
152 
153 #ifdef FRAG_DEBUG
154  if (PREDICT_TRUE(entry_p)) {
155  FRAG_DEBUG_PRINTF3("VA_DB_LOOKUP: bucket index %d entry index %d\n",
156  bucket_index, index)
157  FRAG_DEBUG_PRINTF5("VA_DB_LOOKUP: SRC-->DST [0x%x, %d] [0x%x, %d]\n",
158  entry_p->src_ip, entry_p->src_port,
159  entry_p->dst_ip, entry_p->dst_port)
160  FRAG_DEBUG_PRINTF3("[vrf 0x%x, id 0x%x]\n",
161  entry_p->vrf, entry_p->ip_id)
162  } else {
163  FRAG_DEBUG_PRINTF1("\nNULL ENTRY\n")
164  }
165 #endif
166 
167  return entry_p;
168 
169 }
170 
171 inline
172 int va_db_delete_entry (u32 bucket_index, va_lookup_key * key)
173 {
174 
175  u32 index, next;
176  int entry_found = 0;
177  va_bucket_t * bucket;
178 
179  bucket = &va_bucket[bucket_index];
180  index = bucket->head_entry;
181  next = bucket->next_available_entry;
182 
184  "\nVA_DB_DELETE_ENTRY: bucket index %d head %d next %d\n",
185  bucket_index, index, next);
186 
187  /* loop through the entries in the bucket */
188  while( index != next) {
189  if(PREDICT_TRUE(memcmp(&bucket->va_entry[index], key,
190  VA_KEY_SIZE)==0)) {
191  /* Clear the entry */
192  FRAG_DEBUG_PRINTF1("Entry found in delete API");
193  memset(&bucket->va_entry[index], 0, sizeof(va_entry_t));
194  entry_found = 1;
195  break;
196  }
197  index = (index +1) & VA_BUCKET_MASK;
198  }
199  return entry_found;
200 }
201 
202 
203 
204 void cnat_va_bucket_used (int argc, unsigned long * argv)
205 {
206 
207  u32 i, sum = 0;;
208 
209  for(i=0;i<VA_BUCKETS;i++) {
210 
211  if(PREDICT_TRUE(va_bucket[i].new_entry_counter)) sum++;
212 
213  }
214 
215  if (PREDICT_FALSE(!sum)) {
216  printf("no bucket in use\n");
217  return;
218  }
219 
220  printf("index head next counter (%d bucket in use)\n", sum);
221 
222  for(i=0;i<VA_BUCKETS;i++) {
223 
224  if (PREDICT_FALSE(!va_bucket[i].new_entry_counter)) continue;
225 
226  printf(" %04d %04d %04d %d\n", i,
227  va_bucket[i].head_entry,
228  va_bucket[i].next_available_entry,
229  va_bucket[i].new_entry_counter);
230 
231  }
232 }
233 
234 void cnat_va_dump (int argc, unsigned long * argv)
235 {
236 
237  u32 i, sum, index ;
238 
239  PLATFORM_DEBUG_PRINT("====== SUMMARY ======\n");
240  PLATFORM_DEBUG_PRINT("Total buckets: %d\n", VA_BUCKETS);
241  PLATFORM_DEBUG_PRINT("Entries per bucket: %d\n", VA_ENTRY_PER_BUCKET);
242 
243  sum = 0;
244 
245  for(i=0; i<VA_BUCKETS; i++) {
246  if (PREDICT_TRUE(va_bucket[i].new_entry_counter > 0)) sum ++;
247  }
248 
249  PLATFORM_DEBUG_PRINT("buckets in use: %d\n", sum);
250 
251  sum = 0;
252  for(i=0; i<VA_BUCKETS; i++) {
253 
254  if ( PREDICT_FALSE(((va_bucket[i].next_available_entry+1) & VA_BUCKET_MASK)
255  == va_bucket[i].head_entry)) {
256 
257  sum ++;
258  }
259  }
260 
261  PLATFORM_DEBUG_PRINT("bucket full: %d\n", sum);
262 
263  /* dump per bucket info */
264 
265  if (argc == 0 ) return;
266 
267  index = (u32) argv[0];
268 
269  if (PREDICT_FALSE(index >= VA_BUCKETS)) {
270  PLATFORM_DEBUG_PRINT("invalid bucket index %d\n", index);
271  return;
272  }
273 
274  PLATFORM_DEBUG_PRINT("\n====== Bucket %d ======\n", index);
275 
276  PLATFORM_DEBUG_PRINT("bucket head index %d\n", va_bucket[index].head_entry);
277 
278  PLATFORM_DEBUG_PRINT("bucket next index %d\n", va_bucket[index].next_available_entry);
279 
280  PLATFORM_DEBUG_PRINT(" source IP dest IP VRF ip-id srcP dstP\n");
281 
282  for(i=0;i<VA_ENTRY_PER_BUCKET;i++) {
283  hex_dump((u8*)&va_bucket[index].va_entry[i], sizeof(va_entry_t));
284  }
285 
286 }
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
va_entry_t * va_db_lookup(u32 bucket_index, va_lookup_key *key)
Definition: cnat_va_db.c:114
#define VA_BUCKET_MASK
Definition: cnat_va_db.h:31
#define PREDICT_TRUE(x)
Definition: clib.h:98
#define FRAG_DEBUG_PRINTF3(a, b, c)
Definition: cnat_va_db.h:84
#define FRAG_DEBUG_PRINTF1(a)
Definition: cnat_va_db.h:74
#define NULL
Definition: clib.h:55
#define VA_KEY_SIZE
Definition: cnat_va_db.h:33
void va_bucket_init()
Definition: cnat_va_db.c:41
#define FRAG_DEBUG_PRINTF5(a, b, c, d, e)
Definition: cnat_va_db.h:94
int va_db_delete_entry(u32 bucket_index, va_lookup_key *key)
Definition: cnat_va_db.c:172
void va_db_add_new_entry(u32 bucket_index, va_lookup_key *key)
Definition: cnat_va_db.c:55
va_keys k
Definition: cnat_va_db.h:54
#define PLATFORM_DEBUG_PRINT(...)
void hex_dump(u8 *p, int len)
#define VA_ENTRY_PER_BUCKET
Definition: cnat_va_db.h:30
struct _va_entry va_entry_t
#define FRAG_DEBUG_PRINTF6(a, b, c, d, e, f)
Definition: cnat_va_db.h:99
#define PREDICT_FALSE(x)
Definition: clib.h:97
#define VA_BUCKETS
Definition: cnat_va_db.h:32
struct _va_bucket_t va_bucket_t
void cnat_va_bucket_used(int argc, unsigned long *argv)
Definition: cnat_va_db.c:204
void cnat_va_dump(int argc, unsigned long *argv)
Definition: cnat_va_db.c:234
unsigned int u32
Definition: types.h:88
unsigned char u8
Definition: types.h:56
va_entry_t e
Definition: cnat_va_db.h:53
#define FRAG_DEBUG_PRINTF4(a, b, c, d)
Definition: cnat_va_db.h:89
va_bucket_t va_bucket[VA_BUCKETS]
Definition: cnat_va_db.c:39