2fd909621ae6aa0cc2e2357c948a39fe0b34e1b7
[vpp.git] / vnet / vnet / lisp-cp / gid_dictionary.c
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
16 #include <vnet/lisp-cp/gid_dictionary.h>
17
18 static void
19 make_mac_sd_key (BVT (clib_bihash_kv) * kv, u32 vni, u8 src_mac[6],
20                  u8 dst_mac[6])
21 {
22   kv->key[0] = (u64) vni;
23   kv->key[1] = mac_to_u64 (dst_mac);
24   kv->key[2] = src_mac ? mac_to_u64 (src_mac) : (u64) 0;
25 }
26
27 static u32
28 mac_sd_lookup (gid_mac_table_t * db, u32 vni, u8 * dst, u8 * src)
29 {
30   int rv;
31   BVT (clib_bihash_kv) kv, value;
32
33   make_mac_sd_key (&kv, vni, src, dst);
34   rv = BV (clib_bihash_search_inline_2) (&db->mac_lookup_table, &kv, &value);
35
36   /* no match, try with src 0, catch all for dst */
37   if (rv != 0)
38     {
39       kv.key[2] = 0;
40       rv = BV (clib_bihash_search_inline_2) (&db->mac_lookup_table, &kv,
41                                              &value);
42       if (rv == 0)
43         return value.value;
44     }
45   else
46     return value.value;
47
48   return GID_LOOKUP_MISS;
49 }
50
51 static u32
52 ip4_lookup_exact_match (gid_ip4_table_t * db, u32 vni, ip_prefix_t * key)
53 {
54   int rv;
55   BVT (clib_bihash_kv) kv, value;
56
57   ip4_address_t *mask;
58
59   mask = &db->ip4_fib_masks[ip_prefix_len (key)];
60
61   kv.key[0] = ((u64) vni << 32) | (ip_prefix_v4 (key).as_u32 & mask->as_u32);
62   kv.key[1] = 0;
63   kv.key[2] = 0;
64
65   rv = BV (clib_bihash_search_inline_2) (&db->ip4_lookup_table, &kv, &value);
66   if (rv == 0)
67     return value.value;
68
69   return GID_LOOKUP_MISS;
70 }
71
72 static u32
73 ip4_lookup (gid_ip4_table_t * db, u32 vni, ip_prefix_t * key)
74 {
75   int i, len;
76   int rv;
77   BVT (clib_bihash_kv) kv, value;
78
79   len = vec_len (db->ip4_prefix_lengths_in_search_order);
80
81   for (i = 0; i < len; i++)
82     {
83       int dst_address_length = db->ip4_prefix_lengths_in_search_order[i];
84       ip4_address_t *mask;
85
86       ASSERT (dst_address_length >= 0 && dst_address_length <= 32);
87
88       mask = &db->ip4_fib_masks[dst_address_length];
89
90       kv.key[0] =
91         ((u64) vni << 32) | (ip_prefix_v4 (key).as_u32 & mask->as_u32);
92       kv.key[1] = 0;
93       kv.key[2] = 0;
94
95       rv =
96         BV (clib_bihash_search_inline_2) (&db->ip4_lookup_table, &kv, &value);
97       if (rv == 0)
98         return value.value;
99     }
100
101   return GID_LOOKUP_MISS;
102 }
103
104 static u32
105 ip6_lookup_exact_match (gid_ip6_table_t * db, u32 vni, ip_prefix_t * key)
106 {
107   int rv;
108   BVT (clib_bihash_kv) kv, value;
109
110   ip6_address_t *mask;
111   mask = &db->ip6_fib_masks[ip_prefix_len (key)];
112
113   kv.key[0] = ip_prefix_v6 (key).as_u64[0] & mask->as_u64[0];
114   kv.key[1] = ip_prefix_v6 (key).as_u64[1] & mask->as_u64[1];
115   kv.key[2] = (u64) vni;
116
117   rv = BV (clib_bihash_search_inline_2) (&db->ip6_lookup_table, &kv, &value);
118   if (rv == 0)
119     return value.value;
120
121   return GID_LOOKUP_MISS;
122 }
123
124 static u32
125 ip6_lookup (gid_ip6_table_t * db, u32 vni, ip_prefix_t * key)
126 {
127   int i, len;
128   int rv;
129   BVT (clib_bihash_kv) kv, value;
130
131   len = vec_len (db->ip6_prefix_lengths_in_search_order);
132
133   for (i = 0; i < len; i++)
134     {
135       int dst_address_length = db->ip6_prefix_lengths_in_search_order[i];
136       ip6_address_t *mask;
137
138       ASSERT (dst_address_length >= 0 && dst_address_length <= 128);
139
140       mask = &db->ip6_fib_masks[dst_address_length];
141
142       kv.key[0] = ip_prefix_v6 (key).as_u64[0] & mask->as_u64[0];
143       kv.key[1] = ip_prefix_v6 (key).as_u64[1] & mask->as_u64[1];
144       kv.key[2] = (u64) vni;
145
146       rv =
147         BV (clib_bihash_search_inline_2) (&db->ip6_lookup_table, &kv, &value);
148       if (rv == 0)
149         return value.value;
150     }
151
152   return GID_LOOKUP_MISS;
153 }
154
155 static u32
156 ip_sd_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst,
157               ip_prefix_t * src)
158 {
159   u32 sfi;
160   gid_ip4_table_t *sfib4;
161   gid_ip6_table_t *sfib6;
162
163   switch (ip_prefix_version (dst))
164     {
165     case IP4:
166       sfi = ip4_lookup (&db->dst_ip4_table, vni, dst);
167       if (GID_LOOKUP_MISS != sfi)
168         sfib4 = pool_elt_at_index (db->src_ip4_table_pool, sfi);
169       else
170         return GID_LOOKUP_MISS;
171
172       if (!src)
173         {
174           ip_prefix_t sp;
175           memset (&sp, 0, sizeof (sp));
176           return ip4_lookup_exact_match (sfib4, 0, &sp);
177         }
178       else
179         return ip4_lookup (sfib4, 0, src);
180
181       break;
182     case IP6:
183       sfi = ip6_lookup (&db->dst_ip6_table, vni, dst);
184       if (GID_LOOKUP_MISS != sfi)
185         sfib6 = pool_elt_at_index (db->src_ip6_table_pool, sfi);
186       else
187         return GID_LOOKUP_MISS;
188
189       if (!src)
190         {
191           ip_prefix_t sp;
192           memset (&sp, 0, sizeof (sp));
193           ip_prefix_version (&sp) = IP6;
194           return ip6_lookup_exact_match (sfib6, 0, &sp);
195         }
196       else
197         return ip6_lookup (sfib6, 0, src);
198
199       break;
200     default:
201       clib_warning ("address type %d not supported!",
202                     ip_prefix_version (dst));
203       break;
204     }
205   return GID_LOOKUP_MISS;
206 }
207
208 u32
209 gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key)
210 {
211   switch (gid_address_type (key))
212     {
213     case GID_ADDR_IP_PREFIX:
214       return ip_sd_lookup (db, gid_address_vni (key),
215                            &gid_address_ippref (key), 0);
216     case GID_ADDR_MAC:
217       return mac_sd_lookup (&db->sd_mac_table, gid_address_vni (key),
218                             gid_address_mac (key), 0);
219     case GID_ADDR_SRC_DST:
220       switch (gid_address_sd_dst_type (key))
221         {
222         case FID_ADDR_IP_PREF:
223           return ip_sd_lookup (db, gid_address_vni (key),
224                                &gid_address_sd_dst_ippref (key),
225                                &gid_address_sd_src_ippref (key));
226           break;
227         case FID_ADDR_MAC:
228           return mac_sd_lookup (&db->sd_mac_table, gid_address_vni (key),
229                                 gid_address_sd_dst_mac (key),
230                                 gid_address_sd_src_mac (key));
231           break;
232         default:
233           clib_warning ("Source/Dest address type %d not supported!",
234                         gid_address_sd_dst_type (key));
235           break;
236         }
237       break;
238     default:
239       clib_warning ("address type %d not supported!", gid_address_type (key));
240       break;
241     }
242   return GID_LOOKUP_MISS;
243 }
244
245 u32
246 gid_dictionary_sd_lookup (gid_dictionary_t * db, gid_address_t * dst,
247                           gid_address_t * src)
248 {
249   switch (gid_address_type (dst))
250     {
251     case GID_ADDR_IP_PREFIX:
252       return ip_sd_lookup (db, gid_address_vni (dst),
253                            &gid_address_ippref (dst),
254                            &gid_address_ippref (src));
255     case GID_ADDR_MAC:
256       return mac_sd_lookup (&db->sd_mac_table, gid_address_vni (dst),
257                             gid_address_mac (dst), gid_address_mac (src));
258     default:
259       clib_warning ("address type %d not supported!", gid_address_type (dst));
260       break;
261     }
262   return GID_LOOKUP_MISS;
263 }
264
265 static void
266 ip4_compute_prefix_lengths_in_search_order (gid_ip4_table_t * db)
267 {
268   int i;
269   vec_reset_length (db->ip4_prefix_lengths_in_search_order);
270   /* Note: bitmap reversed so this is in fact a longest prefix match */
271
272   /* *INDENT-OFF* */
273   clib_bitmap_foreach (i, db->ip4_non_empty_dst_address_length_bitmap,
274   ({
275     int dst_address_length = 32 - i;
276     vec_add1 (db->ip4_prefix_lengths_in_search_order, dst_address_length);
277   }));
278   /* *INDENT-ON* */
279
280 }
281
282 static u32
283 add_del_ip4_key (gid_ip4_table_t * db, u32 vni, ip_prefix_t * pref, u32 val,
284                  u8 is_add)
285 {
286   BVT (clib_bihash_kv) kv, value;
287   u32 old_val = ~0;
288   ip4_address_t key;
289   u8 plen = ip_prefix_len (pref);
290
291   clib_memcpy (&key, &ip_prefix_v4 (pref), sizeof (key));
292   key.as_u32 &= db->ip4_fib_masks[plen].as_u32;
293   if (is_add)
294     {
295       db->ip4_non_empty_dst_address_length_bitmap =
296         clib_bitmap_set (db->ip4_non_empty_dst_address_length_bitmap,
297                          32 - plen, 1);
298       ip4_compute_prefix_lengths_in_search_order (db);
299
300       db->ip4_prefix_len_refcount[plen]++;
301     }
302   else
303     {
304       ASSERT (db->ip4_prefix_len_refcount[plen] != 0);
305
306       db->ip4_prefix_len_refcount[plen]--;
307
308       if (db->ip4_prefix_len_refcount[plen] == 0)
309         {
310           db->ip4_non_empty_dst_address_length_bitmap =
311             clib_bitmap_set (db->ip4_non_empty_dst_address_length_bitmap,
312                              32 - plen, 0);
313           ip4_compute_prefix_lengths_in_search_order (db);
314         }
315     }
316
317   kv.key[0] = ((u64) vni << 32) | key.as_u32;
318   kv.key[1] = 0;
319   kv.key[2] = 0;
320
321   if (BV (clib_bihash_search) (&db->ip4_lookup_table, &kv, &value) == 0)
322     old_val = value.value;
323
324   if (!is_add)
325     BV (clib_bihash_add_del) (&db->ip4_lookup_table, &kv, 0 /* is_add */ );
326   else
327     {
328       kv.value = val;
329       BV (clib_bihash_add_del) (&db->ip4_lookup_table, &kv, 1 /* is_add */ );
330     }
331   return old_val;
332 }
333
334 static void
335 ip4_lookup_init (gid_ip4_table_t * db)
336 {
337   uword i;
338
339   memset (db->ip4_prefix_len_refcount, 0,
340           sizeof (db->ip4_prefix_len_refcount));
341
342   for (i = 0; i < ARRAY_LEN (db->ip4_fib_masks); i++)
343     {
344       u32 m;
345
346       if (i < 32)
347         m = pow2_mask (i) << (32 - i);
348       else
349         m = ~0;
350       db->ip4_fib_masks[i].as_u32 = clib_host_to_net_u32 (m);
351     }
352   if (db->ip4_lookup_table_nbuckets == 0)
353     db->ip4_lookup_table_nbuckets = IP4_LOOKUP_DEFAULT_HASH_NUM_BUCKETS;
354
355   db->ip4_lookup_table_nbuckets =
356     1 << max_log2 (db->ip4_lookup_table_nbuckets);
357
358   if (db->ip4_lookup_table_size == 0)
359     db->ip4_lookup_table_size = IP4_LOOKUP_DEFAULT_HASH_MEMORY_SIZE;
360
361   BV (clib_bihash_init) (&db->ip4_lookup_table, "ip4 lookup table",
362                          db->ip4_lookup_table_nbuckets,
363                          db->ip4_lookup_table_size);
364 }
365
366 static u32
367 add_del_sd_ip4_key (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst_pref,
368                     ip_prefix_t * src_pref, u32 val, u8 is_add)
369 {
370   u32 sfi, old_val = ~0;
371   gid_ip4_table_t *sfib;
372
373   sfi = ip4_lookup_exact_match (&db->dst_ip4_table, vni, dst_pref);
374
375   if (is_add)
376     {
377       if (GID_LOOKUP_MISS == sfi)
378         {
379           pool_get (db->src_ip4_table_pool, sfib);
380           ip4_lookup_init (sfib);
381           add_del_ip4_key (&db->dst_ip4_table, vni, dst_pref,
382                            sfib - db->src_ip4_table_pool, is_add);
383           if (src_pref)
384             add_del_ip4_key (sfib, 0 /* vni */ , src_pref, val, is_add);
385           else
386             {
387               ip_prefix_t sp;
388               memset (&sp, 0, sizeof (sp));
389               add_del_ip4_key (sfib, 0 /* vni */ , &sp, val, is_add);
390             }
391         }
392       else
393         {
394           ASSERT (!pool_is_free_index (db->src_ip4_table_pool, sfi));
395           sfib = pool_elt_at_index (db->src_ip4_table_pool, sfi);
396           if (src_pref)
397             {
398               old_val = ip4_lookup_exact_match (sfib, 0, src_pref);
399               add_del_ip4_key (sfib, 0 /* vni */ , src_pref, val, is_add);
400             }
401           else
402             {
403               ip_prefix_t sp;
404               memset (&sp, 0, sizeof (sp));
405               old_val =
406                 add_del_ip4_key (sfib, 0 /* vni */ , &sp, val, is_add);
407             }
408         }
409     }
410   else
411     {
412       if (GID_LOOKUP_MISS != sfi)
413         {
414           add_del_ip4_key (&db->dst_ip4_table, vni, dst_pref, 0, is_add);
415           sfib = pool_elt_at_index (db->src_ip4_table_pool, sfi);
416           if (src_pref)
417             old_val = add_del_ip4_key (sfib, 0, src_pref, 0, is_add);
418           else
419             {
420               ip_prefix_t sp;
421               memset (&sp, 0, sizeof (sp));
422               old_val = add_del_ip4_key (sfib, 0, &sp, 0, is_add);
423             }
424         }
425       else
426         clib_warning ("cannot delete dst mapping %U!", format_ip_prefix,
427                       dst_pref);
428     }
429   return old_val;
430 }
431
432 static void
433 ip6_compute_prefix_lengths_in_search_order (gid_ip6_table_t * db)
434 {
435   int i;
436   vec_reset_length (db->ip6_prefix_lengths_in_search_order);
437   /* Note: bitmap reversed so this is in fact a longest prefix match */
438
439   /* *INDENT-OFF* */
440   clib_bitmap_foreach (i, db->ip6_non_empty_dst_address_length_bitmap,
441   ({
442     int dst_address_length = 128 - i;
443     vec_add1 (db->ip6_prefix_lengths_in_search_order, dst_address_length);
444   }));
445   /* *INDENT-ON* */
446 }
447
448 static u32
449 add_del_ip6_key (gid_ip6_table_t * db, u32 vni, ip_prefix_t * pref, u32 val,
450                  u8 is_add)
451 {
452   BVT (clib_bihash_kv) kv, value;
453   u32 old_val = ~0;
454   ip6_address_t key;
455   u8 plen = ip_prefix_len (pref);
456
457   clib_memcpy (&key, &ip_prefix_v6 (pref), sizeof (key));
458   ip6_address_mask (&key, &db->ip6_fib_masks[plen]);
459   if (is_add)
460     {
461       db->ip6_non_empty_dst_address_length_bitmap =
462         clib_bitmap_set (db->ip6_non_empty_dst_address_length_bitmap,
463                          128 - plen, 1);
464       ip6_compute_prefix_lengths_in_search_order (db);
465       db->ip6_prefix_len_refcount[plen]++;
466     }
467   else
468     {
469       ASSERT (db->ip6_prefix_len_refcount[plen] != 0);
470
471       db->ip6_prefix_len_refcount[plen]--;
472
473       if (db->ip6_prefix_len_refcount[plen] == 0)
474         {
475           db->ip6_non_empty_dst_address_length_bitmap =
476             clib_bitmap_set (db->ip6_non_empty_dst_address_length_bitmap,
477                              128 - plen, 0);
478           ip6_compute_prefix_lengths_in_search_order (db);
479         }
480     }
481
482   kv.key[0] = key.as_u64[0];
483   kv.key[1] = key.as_u64[1];
484   kv.key[2] = (u64) vni;
485 //  kv.key[2] = ((u64)((fib - im->fibs))<<32) | ip_prefix_len(key);
486
487   if (BV (clib_bihash_search) (&db->ip6_lookup_table, &kv, &value) == 0)
488     old_val = value.value;
489
490   if (!is_add)
491     BV (clib_bihash_add_del) (&db->ip6_lookup_table, &kv, 0 /* is_add */ );
492   else
493     {
494       kv.value = val;
495       BV (clib_bihash_add_del) (&db->ip6_lookup_table, &kv, 1 /* is_add */ );
496     }
497   return old_val;
498 }
499
500 static u32
501 add_del_mac (gid_mac_table_t * db, u32 vni, u8 * dst_mac, u8 * src_mac,
502              u32 val, u8 is_add)
503 {
504   BVT (clib_bihash_kv) kv, value;
505   u32 old_val = ~0;
506
507   make_mac_sd_key (&kv, vni, src_mac, dst_mac);
508
509   if (BV (clib_bihash_search) (&db->mac_lookup_table, &kv, &value) == 0)
510     old_val = value.value;
511
512   if (!is_add)
513     BV (clib_bihash_add_del) (&db->mac_lookup_table, &kv, 0 /* is_add */ );
514   else
515     {
516       kv.value = val;
517       BV (clib_bihash_add_del) (&db->mac_lookup_table, &kv, 1 /* is_add */ );
518     }
519   return old_val;
520 }
521
522 static void
523 ip6_lookup_init (gid_ip6_table_t * db)
524 {
525   uword i;
526
527   memset (db->ip6_prefix_len_refcount, 0,
528           sizeof (db->ip6_prefix_len_refcount));
529
530   for (i = 0; i < ARRAY_LEN (db->ip6_fib_masks); i++)
531     {
532       u32 j, i0, i1;
533
534       i0 = i / 32;
535       i1 = i % 32;
536
537       for (j = 0; j < i0; j++)
538         db->ip6_fib_masks[i].as_u32[j] = ~0;
539
540       if (i1)
541         db->ip6_fib_masks[i].as_u32[i0] =
542           clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
543     }
544
545   if (db->ip6_lookup_table_nbuckets == 0)
546     db->ip6_lookup_table_nbuckets = IP6_LOOKUP_DEFAULT_HASH_NUM_BUCKETS;
547
548   db->ip6_lookup_table_nbuckets =
549     1 << max_log2 (db->ip6_lookup_table_nbuckets);
550
551   if (db->ip6_lookup_table_size == 0)
552     db->ip6_lookup_table_size = IP6_LOOKUP_DEFAULT_HASH_MEMORY_SIZE;
553
554   BV (clib_bihash_init) (&db->ip6_lookup_table, "ip6 lookup table",
555                          db->ip6_lookup_table_nbuckets,
556                          db->ip6_lookup_table_size);
557 }
558
559 static u32
560 add_del_sd_ip6_key (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst_pref,
561                     ip_prefix_t * src_pref, u32 val, u8 is_add)
562 {
563   u32 sfi, old_val = ~0;
564   gid_ip6_table_t *sfib;
565
566   sfi = ip6_lookup_exact_match (&db->dst_ip6_table, vni, dst_pref);
567
568   if (is_add)
569     {
570       if (GID_LOOKUP_MISS == sfi)
571         {
572           pool_get (db->src_ip6_table_pool, sfib);
573           ip6_lookup_init (sfib);
574           add_del_ip6_key (&db->dst_ip6_table, vni, dst_pref,
575                            sfib - db->src_ip6_table_pool, is_add);
576           if (src_pref)
577             add_del_ip6_key (sfib, 0 /* vni */ , src_pref, val, is_add);
578           else
579             {
580               ip_prefix_t sp;
581               memset (&sp, 0, sizeof (sp));
582               ip_prefix_version (&sp) = IP6;
583               add_del_ip6_key (sfib, 0 /* vni */ , &sp, val, is_add);
584             }
585         }
586       else
587         {
588           ASSERT (!pool_is_free_index (db->src_ip6_table_pool, sfi));
589           sfib = pool_elt_at_index (db->src_ip6_table_pool, sfi);
590           if (src_pref)
591             {
592               old_val = ip6_lookup_exact_match (sfib, 0, src_pref);
593               add_del_ip6_key (sfib, 0 /* vni */ , src_pref, val, is_add);
594             }
595           else
596             {
597               ip_prefix_t sp;
598               memset (&sp, 0, sizeof (sp));
599               ip_prefix_version (&sp) = IP6;
600               old_val =
601                 add_del_ip6_key (sfib, 0 /* vni */ , &sp, val, is_add);
602             }
603         }
604     }
605   else
606     {
607       if (GID_LOOKUP_MISS != sfi)
608         {
609           add_del_ip6_key (&db->dst_ip6_table, vni, dst_pref, 0, is_add);
610           sfib = pool_elt_at_index (db->src_ip6_table_pool, sfi);
611           if (src_pref)
612             old_val = add_del_ip6_key (sfib, 0, src_pref, 0, is_add);
613           else
614             {
615               ip_prefix_t sp;
616               memset (&sp, 0, sizeof (sp));
617               ip_prefix_version (&sp) = IP6;
618               old_val = add_del_ip6_key (sfib, 0, &sp, 0, is_add);
619             }
620         }
621       else
622         clib_warning ("cannot delete dst mapping %U!", format_ip_prefix,
623                       dst_pref);
624     }
625   return old_val;
626 }
627
628 static u32
629 add_del_ip (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst_key,
630             ip_prefix_t * src_key, u32 value, u8 is_add)
631 {
632   switch (ip_prefix_version (dst_key))
633     {
634     case IP4:
635       return add_del_sd_ip4_key (db, vni, dst_key, src_key, value, is_add);
636       break;
637     case IP6:
638       return add_del_sd_ip6_key (db, vni, dst_key, src_key, value, is_add);
639       break;
640     default:
641       clib_warning ("address type %d not supported!",
642                     ip_prefix_version (dst_key));
643       break;
644     }
645   return ~0;
646 }
647
648 static u32
649 add_del_sd (gid_dictionary_t * db, u32 vni, source_dest_t * key, u32 value,
650             u8 is_add)
651 {
652   switch (sd_dst_type (key))
653     {
654     case FID_ADDR_IP_PREF:
655       add_del_ip (db, vni, &sd_dst_ippref (key), &sd_src_ippref (key),
656                   value, is_add);
657
658     case FID_ADDR_MAC:
659       return add_del_mac (&db->sd_mac_table, vni, sd_dst_mac (key),
660                           sd_src_mac (key), value, is_add);
661
662     default:
663       clib_warning ("SD address type %d not supprted!", sd_dst_type (key));
664       break;
665     }
666
667   return ~0;
668 }
669
670 u32
671 gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u32 value,
672                         u8 is_add)
673 {
674   switch (gid_address_type (key))
675     {
676     case GID_ADDR_IP_PREFIX:
677       return add_del_ip (db, gid_address_vni (key), &gid_address_ippref (key),
678                          0, value, is_add);
679     case GID_ADDR_MAC:
680       return add_del_mac (&db->sd_mac_table, gid_address_vni (key),
681                           gid_address_mac (key), 0, value, is_add);
682     case GID_ADDR_SRC_DST:
683       return add_del_sd (db, gid_address_vni (key), &gid_address_sd (key),
684                          value, is_add);
685     default:
686       clib_warning ("address type %d not supported!", gid_address_type (key));
687       break;
688     }
689   return ~0;
690 }
691
692 static void
693 mac_lookup_init (gid_mac_table_t * db)
694 {
695   if (db->mac_lookup_table_nbuckets == 0)
696     db->mac_lookup_table_nbuckets = MAC_LOOKUP_DEFAULT_HASH_NUM_BUCKETS;
697
698   db->mac_lookup_table_nbuckets =
699     1 << max_log2 (db->mac_lookup_table_nbuckets);
700
701   if (db->mac_lookup_table_size == 0)
702     db->mac_lookup_table_size = MAC_LOOKUP_DEFAULT_HASH_MEMORY_SIZE;
703
704   BV (clib_bihash_init) (&db->mac_lookup_table, "mac lookup table",
705                          db->mac_lookup_table_nbuckets,
706                          db->mac_lookup_table_size);
707 }
708
709 void
710 gid_dictionary_init (gid_dictionary_t * db)
711 {
712   ip4_lookup_init (&db->dst_ip4_table);
713   ip6_lookup_init (&db->dst_ip6_table);
714   mac_lookup_init (&db->sd_mac_table);
715 }
716
717 /*
718  * fd.io coding-style-patch-verification: ON
719  *
720  * Local Variables:
721  * eval: (c-set-style "gnu")
722  * End:
723  */