FD.io VPP  v16.06
Vector Packet Processing
gid_dictionary.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
17 
18 static u32
19 ip4_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t *key)
20 {
21  int i, len;
22  int rv;
23  BVT(clib_bihash_kv) kv, value;
24 
26 
27  for (i = 0; i < len; i++)
28  {
29  int dst_address_length = db->ip4_prefix_lengths_in_search_order[i];
30  ip4_address_t * mask;
31 
32  ASSERT(dst_address_length >= 0 && dst_address_length <= 32);
33 
34  mask = &db->ip4_fib_masks[dst_address_length];
35 
36  kv.key[0] = ((u64) vni << 32) | (ip_prefix_v4(key).as_u32 & mask->as_u32);
37  kv.key[1] = 0;
38  kv.key[2] = 0;
39 
40  rv = BV(clib_bihash_search_inline_2)(&db->ip4_lookup_table, &kv, &value);
41  if (rv == 0)
42  return value.value;
43  }
44 
45  return GID_LOOKUP_MISS;
46 }
47 
48 static u32
49 ip6_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t *key)
50 {
51  int i, len;
52  int rv;
53  BVT(clib_bihash_kv) kv, value;
54 
56 
57  for (i = 0; i < len; i++)
58  {
59  int dst_address_length = db->ip6_prefix_lengths_in_search_order[i];
60  ip6_address_t * mask;
61 
62  ASSERT(dst_address_length >= 0 && dst_address_length <= 128);
63 
64  mask = &db->ip6_fib_masks[dst_address_length];
65 
66  kv.key[0] = ip_prefix_v6(key).as_u64[0] & mask->as_u64[0];
67  kv.key[1] = ip_prefix_v6(key).as_u64[1] & mask->as_u64[1];
68  kv.key[2] = (u64)vni;
69 
70  rv = BV(clib_bihash_search_inline_2)(&db->ip6_lookup_table, &kv, &value);
71  if (rv == 0)
72  return value.value;
73  }
74 
75  return GID_LOOKUP_MISS;
76 }
77 
78 static u32
79 ip_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t *key)
80 {
81  /* XXX for now this only works with ip-prefixes, no lcafs */
82  switch (ip_prefix_version (key))
83  {
84  case IP4:
85  return ip4_lookup (db, vni, key);
86  break;
87  case IP6:
88  return ip6_lookup (db, vni, key);
89  break;
90  default:
91  clib_warning ("address type %d not supported!", ip_prefix_version(key));
92  break;
93  }
94  return ~0;
95 }
96 
97 u32
99 {
100  /* XXX for now this only works with ip-prefixes, no lcafs */
101  switch (gid_address_type (key))
102  {
103  case GID_ADDR_IP_PREFIX:
104  return ip_lookup (db, gid_address_vni(key), &gid_address_ippref(key));
105  break;
106  default:
107  clib_warning ("address type %d not supported!", gid_address_type(key));
108  break;
109  }
110  return ~0;
111 }
112 
113 static void
115 {
116  int i;
118  /* Note: bitmap reversed so this is in fact a longest prefix match */
120  ({
121  int dst_address_length = 32 - i;
122  vec_add1 (db->ip4_prefix_lengths_in_search_order, dst_address_length);
123  }));
124 }
125 
126 static u32
127 add_del_ip4_key (gid_dictionary_t *db, u32 vni, ip_prefix_t * pref, u32 val,
128  u8 is_add)
129 {
130  BVT(clib_bihash_kv) kv, value;
131  u32 old_val = ~0;
132  ip4_address_t key;
133  u8 plen = ip_prefix_len (pref);
134 
135  clib_memcpy (&key, &ip_prefix_v4(pref), sizeof(key));
136  key.as_u32 &= db->ip4_fib_masks[plen].as_u32;
137  if (is_add)
138  {
141  1);
143 
144  db->ip4_prefix_len_refcount[plen]++;
145  }
146  else
147  {
148  ASSERT(db->ip4_prefix_len_refcount[plen] != 0);
149 
150  db->ip4_prefix_len_refcount[plen]--;
151 
152  if (db->ip4_prefix_len_refcount[plen] == 0)
153  {
156  0);
158  }
159  }
160 
161  kv.key[0] = ((u64) vni << 32) | key.as_u32;
162  kv.key[1] = 0;
163  kv.key[2] = 0;
164 
165  if (BV(clib_bihash_search)(&db->ip4_lookup_table, &kv, &value) == 0)
166  old_val = value.value;
167 
168  if (!is_add)
169  BV(clib_bihash_add_del) (&db->ip4_lookup_table, &kv, 0 /* is_add */);
170  else
171  {
172  kv.value = val;
173  BV(clib_bihash_add_del) (&db->ip4_lookup_table, &kv, 1 /* is_add */);
174  }
175  return old_val;
176 }
177 
178 static void
180 {
181  int i;
183  /* Note: bitmap reversed so this is in fact a longest prefix match */
185  ({
186  int dst_address_length = 128 - i;
187  vec_add1 (db->ip6_prefix_lengths_in_search_order, dst_address_length);
188  }));
189 }
190 
191 static u32
192 add_del_ip6_key (gid_dictionary_t *db, u32 vni, ip_prefix_t *pref, u32 val,
193  u8 is_add)
194 {
195  BVT(clib_bihash_kv) kv, value;
196  u32 old_val = ~0;
197  ip6_address_t key;
198  u8 plen = ip_prefix_len (pref);
199 
200  clib_memcpy (&key, &ip_prefix_v6(pref), sizeof(key));
201  ip6_address_mask (&key, &db->ip6_fib_masks[plen]);
202  if (is_add)
203  {
205  db->ip6_non_empty_dst_address_length_bitmap, 128 - plen, 1);
207  db->ip6_prefix_len_refcount[plen]++;
208  }
209  else
210  {
211  ASSERT(db->ip6_prefix_len_refcount[plen] != 0);
212 
213  db->ip6_prefix_len_refcount[plen]--;
214 
215  if (db->ip6_prefix_len_refcount[plen] == 0)
216  {
218  db->ip6_non_empty_dst_address_length_bitmap, 128 - plen, 0);
220  }
221  }
222 
223  kv.key[0] = key.as_u64[0];
224  kv.key[1] = key.as_u64[1];
225  kv.key[2] = (u64) vni;
226 // kv.key[2] = ((u64)((fib - im->fibs))<<32) | ip_prefix_len(key);
227 
228  if (BV(clib_bihash_search)(&db->ip6_lookup_table, &kv, &value) == 0)
229  old_val = value.value;
230 
231  if (!is_add)
232  BV(clib_bihash_add_del) (&db->ip6_lookup_table, &kv, 0 /* is_add */);
233  else
234  {
235  kv.value = val;
236  BV(clib_bihash_add_del) (&db->ip6_lookup_table, &kv, 1 /* is_add */);
237  }
238  return old_val;
239 }
240 
241 static u32
242 add_del_ip (gid_dictionary_t *db, u32 vni, ip_prefix_t *key, u32 value,
243  u8 is_add)
244 {
245  switch (ip_prefix_version(key))
246  {
247  case IP4:
248  return add_del_ip4_key (db, vni, key, value, is_add);
249  break;
250  case IP6:
251  return add_del_ip6_key (db, vni, key, value, is_add);
252  break;
253  default:
254  clib_warning("address type %d not supported!", ip_prefix_version (key));
255  break;
256  }
257  return ~0;
258 }
259 
260 u32
262  u8 is_add)
263 {
264  /* XXX for now this only works with ip-prefixes, no lcafs */
265  switch (gid_address_type (key))
266  {
267  case GID_ADDR_IP_PREFIX:
268  return add_del_ip (db, gid_address_vni(key), &gid_address_ippref(key),
269  value, is_add);
270  break;
271  default:
272  clib_warning ("address type %d not supported!", gid_address_type (key));
273  break;
274  }
275  return ~0;
276 }
277 
278 static void
280 {
281  uword i;
282 
283  memset(db->ip4_prefix_len_refcount, 0, sizeof(db->ip4_prefix_len_refcount));
284 
285  for (i = 0; i < ARRAY_LEN (db->ip4_fib_masks); i++)
286  {
287  u32 m;
288 
289  if (i < 32)
290  m = pow2_mask (i) << (32 - i);
291  else
292  m = ~0;
293  db->ip4_fib_masks[i].as_u32 = clib_host_to_net_u32 (m);
294  }
295  if (db->ip4_lookup_table_nbuckets == 0)
297 
299 
300  if (db->ip4_lookup_table_size == 0)
302 
303  BV(clib_bihash_init) (&db->ip4_lookup_table, "ip4 lookup table",
305 }
306 
307 static void
309 {
310  uword i;
311 
312  memset(db->ip6_prefix_len_refcount, 0, sizeof(db->ip6_prefix_len_refcount));
313 
314  for (i = 0; i < ARRAY_LEN(db->ip6_fib_masks); i++)
315  {
316  u32 j, i0, i1;
317 
318  i0 = i / 32;
319  i1 = i % 32;
320 
321  for (j = 0; j < i0; j++)
322  db->ip6_fib_masks[i].as_u32[j] = ~0;
323 
324  if (i1)
325  db->ip6_fib_masks[i].as_u32[i0] = clib_host_to_net_u32 (
326  pow2_mask (i1) << (32 - i1));
327  }
328 
329  if (db->ip6_lookup_table_nbuckets == 0)
331 
333 
334  if (db->ip6_lookup_table_size == 0)
336 
337  BV(clib_bihash_init) (&db->ip6_lookup_table, "ip6 lookup table",
339 }
340 
341 void
343 {
344  ip4_lookup_init (db);
345  ip6_lookup_init (db);
346 }
347 
#define ip_prefix_v4(_a)
Definition: lisp_types.h:56
#define IP6_LOOKUP_DEFAULT_HASH_NUM_BUCKETS
static void ip6_compute_prefix_lengths_in_search_order(gid_dictionary_t *db)
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
#define gid_address_type(_a)
Definition: lisp_types.h:161
uword * ip6_non_empty_dst_address_length_bitmap
uword ip4_lookup_table_size
u64 as_u64[2]
Definition: ip6_packet.h:50
static void ip4_lookup_init(gid_dictionary_t *db)
#define ip_prefix_len(_a)
Definition: lisp_types.h:55
u32 ip4_prefix_len_refcount[33]
#define IP4_LOOKUP_DEFAULT_HASH_NUM_BUCKETS
always_inline uword max_log2(uword x)
Definition: clib.h:216
static void ip4_compute_prefix_lengths_in_search_order(gid_dictionary_t *db)
#define IP4_LOOKUP_DEFAULT_HASH_MEMORY_SIZE
int BV() clib_bihash_add_del(BVT(clib_bihash)*h, BVT(clib_bihash_kv)*add_v, int is_add)
#define ip_prefix_version(_a)
Definition: lisp_types.h:54
void gid_dictionary_init(gid_dictionary_t *db)
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static u32 add_del_ip4_key(gid_dictionary_t *db, u32 vni, ip_prefix_t *pref, u32 val, u8 is_add)
static void ip6_lookup_init(gid_dictionary_t *db)
static u32 ip_lookup(gid_dictionary_t *db, u32 vni, ip_prefix_t *key)
void BV() clib_bihash_init(BVT(clib_bihash)*h, char *name, u32 nbuckets, uword memory_size)
#define clib_warning(format, args...)
Definition: error.h:59
unsigned long u64
Definition: types.h:89
static u32 add_del_ip6_key(gid_dictionary_t *db, u32 vni, ip_prefix_t *pref, u32 val, u8 is_add)
int BV() clib_bihash_search(BVT(clib_bihash)*h, BVT(clib_bihash_kv)*search_key, BVT(clib_bihash_kv)*valuep)
u32 gid_dictionary_lookup(gid_dictionary_t *db, gid_address_t *key)
#define clib_bitmap_foreach(i, ai, body)
Definition: bitmap.h:308
u32 gid_dictionary_add_del(gid_dictionary_t *db, gid_address_t *key, u32 value, u8 is_add)
u64 ip6_prefix_len_refcount[129]
#define ip_prefix_v6(_a)
Definition: lisp_types.h:57
always_inline uword * clib_bitmap_set(uword *ai, uword i, uword value)
Definition: bitmap.h:132
#define gid_address_ippref(_a)
Definition: lisp_types.h:162
u8 * ip4_prefix_lengths_in_search_order
u32 as_u32[4]
Definition: ip6_packet.h:49
static u32 add_del_ip(gid_dictionary_t *db, u32 vni, ip_prefix_t *key, u32 value, u8 is_add)
#define clib_memcpy(a, b, c)
Definition: string.h:63
#define ARRAY_LEN(x)
Definition: clib.h:59
struct _gid_address_t gid_address_t
#define ASSERT(truth)
#define IP6_LOOKUP_DEFAULT_HASH_MEMORY_SIZE
unsigned int u32
Definition: types.h:88
#define GID_LOOKUP_MISS
static u32 ip6_lookup(gid_dictionary_t *db, u32 vni, ip_prefix_t *key)
ip4_address_t ip4_fib_masks[33]
u8 * ip6_prefix_lengths_in_search_order
#define BV(a)
ip6_address_t ip6_fib_masks[129]
static int BV() clib_bihash_search_inline_2(BVT(clib_bihash)*h, BVT(clib_bihash_kv)*search_key, BVT(clib_bihash_kv)*valuep)
u64 uword
Definition: types.h:112
#define gid_address_vni(_a)
Definition: lisp_types.h:166
#define BVT(a)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
uword ip6_lookup_table_size
Definition: lisp_types.h:24
uword * ip4_non_empty_dst_address_length_bitmap
static u32 ip4_lookup(gid_dictionary_t *db, u32 vni, ip_prefix_t *key)
always_inline void ip6_address_mask(ip6_address_t *a, ip6_address_t *mask)
Definition: ip6_packet.h:201
always_inline uword pow2_mask(uword x)
Definition: clib.h:242
Definition: lisp_types.h:25