FD.io VPP  v16.09
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 mac_lookup (gid_dictionary_t * db, u32 vni, u8 * key)
20 {
21  int rv;
22  BVT (clib_bihash_kv) kv, value;
23 
24  kv.key[0] = mac_to_u64 (key);
25  kv.key[1] = (u64) vni;
26  kv.key[2] = 0;
27 
28  rv = BV (clib_bihash_search_inline_2) (&db->mac_lookup_table, &kv, &value);
29  if (rv == 0)
30  return value.value;
31 
32  return GID_LOOKUP_MISS;
33 }
34 
35 static u32
36 ip4_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t * key)
37 {
38  int i, len;
39  int rv;
40  BVT (clib_bihash_kv) kv, value;
41 
43 
44  for (i = 0; i < len; i++)
45  {
46  int dst_address_length = db->ip4_prefix_lengths_in_search_order[i];
47  ip4_address_t *mask;
48 
49  ASSERT (dst_address_length >= 0 && dst_address_length <= 32);
50 
51  mask = &db->ip4_fib_masks[dst_address_length];
52 
53  kv.key[0] =
54  ((u64) vni << 32) | (ip_prefix_v4 (key).as_u32 & mask->as_u32);
55  kv.key[1] = 0;
56  kv.key[2] = 0;
57 
58  rv =
59  BV (clib_bihash_search_inline_2) (&db->ip4_lookup_table, &kv, &value);
60  if (rv == 0)
61  return value.value;
62  }
63 
64  return GID_LOOKUP_MISS;
65 }
66 
67 static u32
68 ip6_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t * key)
69 {
70  int i, len;
71  int rv;
72  BVT (clib_bihash_kv) kv, value;
73 
75 
76  for (i = 0; i < len; i++)
77  {
78  int dst_address_length = db->ip6_prefix_lengths_in_search_order[i];
79  ip6_address_t *mask;
80 
81  ASSERT (dst_address_length >= 0 && dst_address_length <= 128);
82 
83  mask = &db->ip6_fib_masks[dst_address_length];
84 
85  kv.key[0] = ip_prefix_v6 (key).as_u64[0] & mask->as_u64[0];
86  kv.key[1] = ip_prefix_v6 (key).as_u64[1] & mask->as_u64[1];
87  kv.key[2] = (u64) vni;
88 
89  rv =
90  BV (clib_bihash_search_inline_2) (&db->ip6_lookup_table, &kv, &value);
91  if (rv == 0)
92  return value.value;
93  }
94 
95  return GID_LOOKUP_MISS;
96 }
97 
98 static u32
99 ip_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t * key)
100 {
101  /* XXX for now this only works with ip-prefixes, no lcafs */
102  switch (ip_prefix_version (key))
103  {
104  case IP4:
105  return ip4_lookup (db, vni, key);
106  break;
107  case IP6:
108  return ip6_lookup (db, vni, key);
109  break;
110  default:
111  clib_warning ("address type %d not supported!",
112  ip_prefix_version (key));
113  break;
114  }
115  return ~0;
116 }
117 
118 u32
120 {
121  /* XXX for now this only works with ip-prefixes, no lcafs */
122  switch (gid_address_type (key))
123  {
124  case GID_ADDR_IP_PREFIX:
125  return ip_lookup (db, gid_address_vni (key), &gid_address_ippref (key));
126  case GID_ADDR_MAC:
127  return mac_lookup (db, gid_address_vni (key), gid_address_mac (key));
128  default:
129  clib_warning ("address type %d not supported!", gid_address_type (key));
130  break;
131  }
132  return GID_LOOKUP_MISS;
133 }
134 
135 static void
137 {
138  int i;
140  /* Note: bitmap reversed so this is in fact a longest prefix match */
141 
142  /* *INDENT-OFF* */
144  ({
145  int dst_address_length = 32 - i;
146  vec_add1 (db->ip4_prefix_lengths_in_search_order, dst_address_length);
147  }));
148  /* *INDENT-ON* */
149 
150 }
151 
152 static u32
153 add_del_ip4_key (gid_dictionary_t * db, u32 vni, ip_prefix_t * pref, u32 val,
154  u8 is_add)
155 {
156  BVT (clib_bihash_kv) kv, value;
157  u32 old_val = ~0;
158  ip4_address_t key;
159  u8 plen = ip_prefix_len (pref);
160 
161  clib_memcpy (&key, &ip_prefix_v4 (pref), sizeof (key));
162  key.as_u32 &= db->ip4_fib_masks[plen].as_u32;
163  if (is_add)
164  {
167  32 - plen, 1);
169 
170  db->ip4_prefix_len_refcount[plen]++;
171  }
172  else
173  {
174  ASSERT (db->ip4_prefix_len_refcount[plen] != 0);
175 
176  db->ip4_prefix_len_refcount[plen]--;
177 
178  if (db->ip4_prefix_len_refcount[plen] == 0)
179  {
182  32 - plen, 0);
184  }
185  }
186 
187  kv.key[0] = ((u64) vni << 32) | key.as_u32;
188  kv.key[1] = 0;
189  kv.key[2] = 0;
190 
191  if (BV (clib_bihash_search) (&db->ip4_lookup_table, &kv, &value) == 0)
192  old_val = value.value;
193 
194  if (!is_add)
195  BV (clib_bihash_add_del) (&db->ip4_lookup_table, &kv, 0 /* is_add */ );
196  else
197  {
198  kv.value = val;
199  BV (clib_bihash_add_del) (&db->ip4_lookup_table, &kv, 1 /* is_add */ );
200  }
201  return old_val;
202 }
203 
204 static void
206 {
207  int i;
209  /* Note: bitmap reversed so this is in fact a longest prefix match */
210 
211  /* *INDENT-OFF* */
213  ({
214  int dst_address_length = 128 - i;
215  vec_add1 (db->ip6_prefix_lengths_in_search_order, dst_address_length);
216  }));
217  /* *INDENT-ON* */
218 }
219 
220 static u32
221 add_del_ip6_key (gid_dictionary_t * db, u32 vni, ip_prefix_t * pref, u32 val,
222  u8 is_add)
223 {
224  BVT (clib_bihash_kv) kv, value;
225  u32 old_val = ~0;
226  ip6_address_t key;
227  u8 plen = ip_prefix_len (pref);
228 
229  clib_memcpy (&key, &ip_prefix_v6 (pref), sizeof (key));
230  ip6_address_mask (&key, &db->ip6_fib_masks[plen]);
231  if (is_add)
232  {
235  128 - plen, 1);
237  db->ip6_prefix_len_refcount[plen]++;
238  }
239  else
240  {
241  ASSERT (db->ip6_prefix_len_refcount[plen] != 0);
242 
243  db->ip6_prefix_len_refcount[plen]--;
244 
245  if (db->ip6_prefix_len_refcount[plen] == 0)
246  {
249  128 - plen, 0);
251  }
252  }
253 
254  kv.key[0] = key.as_u64[0];
255  kv.key[1] = key.as_u64[1];
256  kv.key[2] = (u64) vni;
257 // kv.key[2] = ((u64)((fib - im->fibs))<<32) | ip_prefix_len(key);
258 
259  if (BV (clib_bihash_search) (&db->ip6_lookup_table, &kv, &value) == 0)
260  old_val = value.value;
261 
262  if (!is_add)
263  BV (clib_bihash_add_del) (&db->ip6_lookup_table, &kv, 0 /* is_add */ );
264  else
265  {
266  kv.value = val;
267  BV (clib_bihash_add_del) (&db->ip6_lookup_table, &kv, 1 /* is_add */ );
268  }
269  return old_val;
270 }
271 
272 static u32
273 add_del_mac (gid_dictionary_t * db, u32 vni, u8 * mac, u32 val, u8 is_add)
274 {
275  BVT (clib_bihash_kv) kv, value;
276  u32 old_val = ~0;
277 
278  kv.key[0] = ((u64 *) mac)[0];
279  kv.key[1] = (u64) vni;
280  kv.key[2] = 0;
281 
282  if (BV (clib_bihash_search) (&db->mac_lookup_table, &kv, &value) == 0)
283  old_val = value.value;
284 
285  if (!is_add)
286  BV (clib_bihash_add_del) (&db->mac_lookup_table, &kv, 0 /* is_add */ );
287  else
288  {
289  kv.value = val;
290  BV (clib_bihash_add_del) (&db->mac_lookup_table, &kv, 1 /* is_add */ );
291  }
292  return old_val;
293 }
294 
295 static u32
296 add_del_ip (gid_dictionary_t * db, u32 vni, ip_prefix_t * key, u32 value,
297  u8 is_add)
298 {
299  switch (ip_prefix_version (key))
300  {
301  case IP4:
302  return add_del_ip4_key (db, vni, key, value, is_add);
303  break;
304  case IP6:
305  return add_del_ip6_key (db, vni, key, value, is_add);
306  break;
307  default:
308  clib_warning ("address type %d not supported!",
309  ip_prefix_version (key));
310  break;
311  }
312  return ~0;
313 }
314 
315 u32
317  u8 is_add)
318 {
319  /* XXX for now this only works with ip-prefixes, no lcafs */
320  switch (gid_address_type (key))
321  {
322  case GID_ADDR_IP_PREFIX:
323  return add_del_ip (db, gid_address_vni (key), &gid_address_ippref (key),
324  value, is_add);
325  case GID_ADDR_MAC:
326  return add_del_mac (db, gid_address_vni (key), gid_address_mac (key),
327  value, is_add);
328  default:
329  clib_warning ("address type %d not supported!", gid_address_type (key));
330  break;
331  }
332  return ~0;
333 }
334 
335 static void
337 {
338  uword i;
339 
340  memset (db->ip4_prefix_len_refcount, 0,
341  sizeof (db->ip4_prefix_len_refcount));
342 
343  for (i = 0; i < ARRAY_LEN (db->ip4_fib_masks); i++)
344  {
345  u32 m;
346 
347  if (i < 32)
348  m = pow2_mask (i) << (32 - i);
349  else
350  m = ~0;
351  db->ip4_fib_masks[i].as_u32 = clib_host_to_net_u32 (m);
352  }
353  if (db->ip4_lookup_table_nbuckets == 0)
355 
358 
359  if (db->ip4_lookup_table_size == 0)
361 
362  BV (clib_bihash_init) (&db->ip4_lookup_table, "ip4 lookup table",
365 }
366 
367 static void
369 {
370  uword i;
371 
372  memset (db->ip6_prefix_len_refcount, 0,
373  sizeof (db->ip6_prefix_len_refcount));
374 
375  for (i = 0; i < ARRAY_LEN (db->ip6_fib_masks); i++)
376  {
377  u32 j, i0, i1;
378 
379  i0 = i / 32;
380  i1 = i % 32;
381 
382  for (j = 0; j < i0; j++)
383  db->ip6_fib_masks[i].as_u32[j] = ~0;
384 
385  if (i1)
386  db->ip6_fib_masks[i].as_u32[i0] =
387  clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
388  }
389 
390  if (db->ip6_lookup_table_nbuckets == 0)
392 
395 
396  if (db->ip6_lookup_table_size == 0)
398 
399  BV (clib_bihash_init) (&db->ip6_lookup_table, "ip6 lookup table",
402 }
403 
404 static void
406 {
407  if (db->mac_lookup_table_nbuckets == 0)
409 
412 
413  if (db->mac_lookup_table_size == 0)
415 
416  BV (clib_bihash_init) (&db->mac_lookup_table, "mac lookup table",
419 }
420 
421 void
423 {
424  ip4_lookup_init (db);
425  ip6_lookup_init (db);
426  mac_lookup_init (db);
427 }
428 
429 /*
430  * fd.io coding-style-patch-verification: ON
431  *
432  * Local Variables:
433  * eval: (c-set-style "gnu")
434  * End:
435  */
#define ip_prefix_v4(_a)
Definition: lisp_types.h:61
static void ip6_address_mask(ip6_address_t *a, ip6_address_t *mask)
Definition: ip6_packet.h:201
#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:343
#define gid_address_type(_a)
Definition: lisp_types.h:205
uword * ip6_non_empty_dst_address_length_bitmap
uword ip4_lookup_table_size
u64 as_u64[2]
Definition: ip6_packet.h:50
uword mac_lookup_table_size
#define MAC_LOOKUP_DEFAULT_HASH_NUM_BUCKETS
static void ip4_lookup_init(gid_dictionary_t *db)
static u32 add_del_mac(gid_dictionary_t *db, u32 vni, u8 *mac, u32 val, u8 is_add)
#define ip_prefix_len(_a)
Definition: lisp_types.h:60
u32 ip4_prefix_len_refcount[33]
#define IP4_LOOKUP_DEFAULT_HASH_NUM_BUCKETS
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
static void ip4_compute_prefix_lengths_in_search_order(gid_dictionary_t *db)
#define IP4_LOOKUP_DEFAULT_HASH_MEMORY_SIZE
#define ip_prefix_version(_a)
Definition: lisp_types.h:59
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 mac_lookup(gid_dictionary_t *db, u32 vni, u8 *key)
int clib_bihash_add_del(clib_bihash *h, clib_bihash_kv *add_v, int is_add)
Add or delete a (key,value) pair from a bi-hash table.
static uword pow2_mask(uword x)
Definition: clib.h:251
static u32 ip_lookup(gid_dictionary_t *db, u32 vni, ip_prefix_t *key)
static foreach_gid_address_type_fcns u64 mac_to_u64(u8 *m)
Definition: lisp_types.h:242
#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)
u32 gid_dictionary_lookup(gid_dictionary_t *db, gid_address_t *key)
#define clib_bitmap_foreach(i, ai, body)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
u32 gid_dictionary_add_del(gid_dictionary_t *db, gid_address_t *key, u32 value, u8 is_add)
#define gid_address_mac(_a)
Definition: lisp_types.h:211
u64 ip6_prefix_len_refcount[129]
#define ip_prefix_v6(_a)
Definition: lisp_types.h:62
void clib_bihash_init(clib_bihash *h, char *name, u32 nbuckets, uword memory_size)
initialize a bounded index extensible hash table
#define gid_address_ippref(_a)
Definition: lisp_types.h:206
u8 * ip4_prefix_lengths_in_search_order
BVT(clib_bihash)
Definition: l2_fib.c:577
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]
int clib_bihash_search(clib_bihash *h, clib_bihash_kv *search_v, clib_bihash_kv *return_v)
Search a bi-hash table.
u8 * ip6_prefix_lengths_in_search_order
ip6_address_t ip6_fib_masks[129]
u64 uword
Definition: types.h:112
#define gid_address_vni(_a)
Definition: lisp_types.h:212
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
static void mac_lookup_init(gid_dictionary_t *db)
static uword max_log2(uword x)
Definition: clib.h:222
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)
Definition: lisp_types.h:25
#define MAC_LOOKUP_DEFAULT_HASH_MEMORY_SIZE