blob: 564ee8ea84d26d3112addcf65e78347ca9777d12 [file] [log] [blame]
Florin Corase127a7e2016-02-18 22:20:01 +01001/*
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
Filip Tehlard5fcc462016-10-17 16:20:18 +020018typedef struct
19{
20 void *arg;
21 ip_prefix_t src;
22 foreach_subprefix_match_cb_t cb;
23 union
24 {
25 gid_ip4_table_t *ip4_table;
26 gid_ip6_table_t *ip6_table;
27 };
28} sfib_entry_arg_t;
29
30static u32 ip4_lookup (gid_ip4_table_t * db, u32 vni, ip_prefix_t * key);
31
32static u32 ip6_lookup (gid_ip6_table_t * db, u32 vni, ip_prefix_t * key);
33
Neale Rannsf50bac12019-12-06 05:53:17 +000034static int
Filip Tehlard5fcc462016-10-17 16:20:18 +020035foreach_sfib4_subprefix (BVT (clib_bihash_kv) * kvp, void *arg)
36{
37 sfib_entry_arg_t *a = arg;
38 u32 ip = (u32) kvp->key[0];
39 ip4_address_t *mask;
40 u8 plen = ip_prefix_len (&a->src);
41
Filip Tehlar218170b2016-10-26 14:58:18 +020042 ASSERT (plen <= 32);
Filip Tehlard5fcc462016-10-17 16:20:18 +020043 mask = &a->ip4_table->ip4_fib_masks[plen];
44
Filip Tehlarfb9931f2016-12-09 13:52:38 +010045 u32 src_ip = ip_prefix_v4 (&a->src).as_u32;
Filip Tehlard5fcc462016-10-17 16:20:18 +020046 src_ip &= mask->as_u32;
Filip Tehlarfb9931f2016-12-09 13:52:38 +010047 ip &= mask->as_u32;
48
Filip Tehlard5fcc462016-10-17 16:20:18 +020049 if (src_ip == ip)
50 {
51 /* found sub-prefix of src prefix */
52 (a->cb) (kvp->value, a->arg);
53 }
Neale Rannsf50bac12019-12-06 05:53:17 +000054 return (BIHASH_WALK_CONTINUE);
Filip Tehlard5fcc462016-10-17 16:20:18 +020055}
56
57static void
58gid_dict_foreach_ip4_subprefix (gid_dictionary_t * db, u32 vni,
59 ip_prefix_t * src, ip_prefix_t * dst,
60 foreach_subprefix_match_cb_t cb, void *arg)
61{
62 u32 sfi;
63 gid_ip4_table_t *sfib4;
64 sfib_entry_arg_t a;
65
66 sfi = ip4_lookup (&db->dst_ip4_table, vni, dst);
67 if (GID_LOOKUP_MISS == sfi)
68 return;
69
70 sfib4 = pool_elt_at_index (db->src_ip4_table_pool, sfi);
71
72 a.arg = arg;
73 a.cb = cb;
74 a.src = src[0];
75 a.ip4_table = sfib4;
76
77 BV (clib_bihash_foreach_key_value_pair) (&sfib4->ip4_lookup_table,
78 foreach_sfib4_subprefix, &a);
79}
80
Neale Rannsf50bac12019-12-06 05:53:17 +000081static int
Filip Tehlard5fcc462016-10-17 16:20:18 +020082foreach_sfib6_subprefix (BVT (clib_bihash_kv) * kvp, void *arg)
83{
84 sfib_entry_arg_t *a = arg;
85 ip6_address_t ip;
86 ip6_address_t *mask;
87 u8 plen = ip_prefix_len (&a->src);
88
89 mask = &a->ip6_table->ip6_fib_masks[plen];
90 ip.as_u64[0] = kvp->key[0];
91 ip.as_u64[1] = kvp->key[1];
92
93 if (ip6_address_is_equal_masked (&ip_prefix_v6 (&a->src), &ip, mask))
94 {
95 /* found sub-prefix of src prefix */
96 (a->cb) (kvp->value, a->arg);
97 }
Neale Rannsf50bac12019-12-06 05:53:17 +000098 return (BIHASH_WALK_CONTINUE);
Filip Tehlard5fcc462016-10-17 16:20:18 +020099}
100
101static void
102gid_dict_foreach_ip6_subprefix (gid_dictionary_t * db, u32 vni,
103 ip_prefix_t * src, ip_prefix_t * dst,
104 foreach_subprefix_match_cb_t cb, void *arg)
105{
106 u32 sfi;
107 gid_ip6_table_t *sfib6;
108 sfib_entry_arg_t a;
109
110 sfi = ip6_lookup (&db->dst_ip6_table, vni, dst);
111 if (GID_LOOKUP_MISS == sfi)
112 return;
113
114 sfib6 = pool_elt_at_index (db->src_ip6_table_pool, sfi);
115
116 a.arg = arg;
117 a.cb = cb;
118 a.src = src[0];
119 a.ip6_table = sfib6;
120
121 BV (clib_bihash_foreach_key_value_pair) (&sfib6->ip6_lookup_table,
122 foreach_sfib6_subprefix, &a);
123}
124
125void
126gid_dict_foreach_subprefix (gid_dictionary_t * db, gid_address_t * eid,
127 foreach_subprefix_match_cb_t cb, void *arg)
128{
129 ip_prefix_t *ippref = &gid_address_sd_dst_ippref (eid);
130
Neale Rannsea93e482019-11-12 17:16:47 +0000131 if (AF_IP4 == ip_prefix_version (ippref))
Filip Tehlard5fcc462016-10-17 16:20:18 +0200132 gid_dict_foreach_ip4_subprefix (db, gid_address_vni (eid),
133 &gid_address_sd_src_ippref (eid),
134 &gid_address_sd_dst_ippref (eid), cb,
135 arg);
136 else
137 gid_dict_foreach_ip6_subprefix (db, gid_address_vni (eid),
138 &gid_address_sd_src_ippref (eid),
139 &gid_address_sd_dst_ippref (eid), cb,
140 arg);
141}
142
Filip Tehlard5a65db2017-05-17 17:21:10 +0200143void
Neale Rannsf50bac12019-12-06 05:53:17 +0000144gid_dict_foreach_l2_arp_ndp_entry (gid_dictionary_t * db,
145 BV (clib_bihash_foreach_key_value_pair_cb)
146 cb, void *ht)
Filip Tehlard5a65db2017-05-17 17:21:10 +0200147{
Filip Tehlar05879992017-09-05 15:46:09 +0200148 gid_l2_arp_ndp_table_t *tab = &db->arp_ndp_table;
149 BV (clib_bihash_foreach_key_value_pair) (&tab->arp_ndp_lookup_table, cb,
150 ht);
Filip Tehlard5a65db2017-05-17 17:21:10 +0200151}
152
Florin Corasdca88042016-09-14 16:01:38 +0200153static void
154make_mac_sd_key (BVT (clib_bihash_kv) * kv, u32 vni, u8 src_mac[6],
155 u8 dst_mac[6])
156{
157 kv->key[0] = (u64) vni;
158 kv->key[1] = mac_to_u64 (dst_mac);
159 kv->key[2] = src_mac ? mac_to_u64 (src_mac) : (u64) 0;
160}
161
Florin Corase127a7e2016-02-18 22:20:01 +0100162static u32
Florin Corasdca88042016-09-14 16:01:38 +0200163mac_sd_lookup (gid_mac_table_t * db, u32 vni, u8 * dst, u8 * src)
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200164{
165 int rv;
Florin Corasa2157cf2016-08-16 21:09:14 +0200166 BVT (clib_bihash_kv) kv, value;
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200167
Florin Corasdca88042016-09-14 16:01:38 +0200168 make_mac_sd_key (&kv, vni, src, dst);
Florin Corasa2157cf2016-08-16 21:09:14 +0200169 rv = BV (clib_bihash_search_inline_2) (&db->mac_lookup_table, &kv, &value);
Florin Corasdca88042016-09-14 16:01:38 +0200170
171 /* no match, try with src 0, catch all for dst */
172 if (rv != 0)
173 {
174 kv.key[2] = 0;
175 rv = BV (clib_bihash_search_inline_2) (&db->mac_lookup_table, &kv,
176 &value);
177 if (rv == 0)
178 return value.value;
179 }
180 else
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200181 return value.value;
182
183 return GID_LOOKUP_MISS;
184}
185
186static u32
Filip Tehlarf3e3fd32016-09-30 12:47:59 +0200187ip4_lookup_exact_match (gid_ip4_table_t * db, u32 vni, ip_prefix_t * key)
188{
189 int rv;
190 BVT (clib_bihash_kv) kv, value;
191
192 ip4_address_t *mask;
193
194 mask = &db->ip4_fib_masks[ip_prefix_len (key)];
195
196 kv.key[0] = ((u64) vni << 32) | (ip_prefix_v4 (key).as_u32 & mask->as_u32);
197 kv.key[1] = 0;
198 kv.key[2] = 0;
199
200 rv = BV (clib_bihash_search_inline_2) (&db->ip4_lookup_table, &kv, &value);
201 if (rv == 0)
202 return value.value;
203
204 return GID_LOOKUP_MISS;
205}
206
207static u32
Florin Corasdca88042016-09-14 16:01:38 +0200208ip4_lookup (gid_ip4_table_t * db, u32 vni, ip_prefix_t * key)
Florin Corase127a7e2016-02-18 22:20:01 +0100209{
210 int i, len;
211 int rv;
Florin Corasa2157cf2016-08-16 21:09:14 +0200212 BVT (clib_bihash_kv) kv, value;
Florin Corase127a7e2016-02-18 22:20:01 +0100213
214 len = vec_len (db->ip4_prefix_lengths_in_search_order);
215
216 for (i = 0; i < len; i++)
217 {
218 int dst_address_length = db->ip4_prefix_lengths_in_search_order[i];
Florin Corasa2157cf2016-08-16 21:09:14 +0200219 ip4_address_t *mask;
Florin Corase127a7e2016-02-18 22:20:01 +0100220
Florin Corasa2157cf2016-08-16 21:09:14 +0200221 ASSERT (dst_address_length >= 0 && dst_address_length <= 32);
Florin Corase127a7e2016-02-18 22:20:01 +0100222
223 mask = &db->ip4_fib_masks[dst_address_length];
224
Florin Corasa2157cf2016-08-16 21:09:14 +0200225 kv.key[0] =
226 ((u64) vni << 32) | (ip_prefix_v4 (key).as_u32 & mask->as_u32);
Florin Corase127a7e2016-02-18 22:20:01 +0100227 kv.key[1] = 0;
228 kv.key[2] = 0;
229
Florin Corasa2157cf2016-08-16 21:09:14 +0200230 rv =
231 BV (clib_bihash_search_inline_2) (&db->ip4_lookup_table, &kv, &value);
Florin Corase127a7e2016-02-18 22:20:01 +0100232 if (rv == 0)
Florin Corasa2157cf2016-08-16 21:09:14 +0200233 return value.value;
Florin Corase127a7e2016-02-18 22:20:01 +0100234 }
235
236 return GID_LOOKUP_MISS;
237}
238
239static u32
Filip Tehlarf3e3fd32016-09-30 12:47:59 +0200240ip6_lookup_exact_match (gid_ip6_table_t * db, u32 vni, ip_prefix_t * key)
241{
242 int rv;
243 BVT (clib_bihash_kv) kv, value;
244
245 ip6_address_t *mask;
246 mask = &db->ip6_fib_masks[ip_prefix_len (key)];
247
248 kv.key[0] = ip_prefix_v6 (key).as_u64[0] & mask->as_u64[0];
249 kv.key[1] = ip_prefix_v6 (key).as_u64[1] & mask->as_u64[1];
250 kv.key[2] = (u64) vni;
251
252 rv = BV (clib_bihash_search_inline_2) (&db->ip6_lookup_table, &kv, &value);
253 if (rv == 0)
254 return value.value;
255
256 return GID_LOOKUP_MISS;
257}
258
259static u32
Florin Corasdca88042016-09-14 16:01:38 +0200260ip6_lookup (gid_ip6_table_t * db, u32 vni, ip_prefix_t * key)
Florin Corase127a7e2016-02-18 22:20:01 +0100261{
262 int i, len;
263 int rv;
Florin Corasa2157cf2016-08-16 21:09:14 +0200264 BVT (clib_bihash_kv) kv, value;
Florin Corase127a7e2016-02-18 22:20:01 +0100265
266 len = vec_len (db->ip6_prefix_lengths_in_search_order);
267
268 for (i = 0; i < len; i++)
269 {
270 int dst_address_length = db->ip6_prefix_lengths_in_search_order[i];
Florin Corasa2157cf2016-08-16 21:09:14 +0200271 ip6_address_t *mask;
Florin Corase127a7e2016-02-18 22:20:01 +0100272
Florin Corasa2157cf2016-08-16 21:09:14 +0200273 ASSERT (dst_address_length >= 0 && dst_address_length <= 128);
Florin Corase127a7e2016-02-18 22:20:01 +0100274
275 mask = &db->ip6_fib_masks[dst_address_length];
276
Florin Corasa2157cf2016-08-16 21:09:14 +0200277 kv.key[0] = ip_prefix_v6 (key).as_u64[0] & mask->as_u64[0];
278 kv.key[1] = ip_prefix_v6 (key).as_u64[1] & mask->as_u64[1];
279 kv.key[2] = (u64) vni;
Florin Corase127a7e2016-02-18 22:20:01 +0100280
Florin Corasa2157cf2016-08-16 21:09:14 +0200281 rv =
282 BV (clib_bihash_search_inline_2) (&db->ip6_lookup_table, &kv, &value);
Florin Corase127a7e2016-02-18 22:20:01 +0100283 if (rv == 0)
Florin Corasa2157cf2016-08-16 21:09:14 +0200284 return value.value;
Florin Corase127a7e2016-02-18 22:20:01 +0100285 }
286
287 return GID_LOOKUP_MISS;
288}
289
290static u32
Florin Corasdca88042016-09-14 16:01:38 +0200291ip_sd_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst,
292 ip_prefix_t * src)
Florin Corase127a7e2016-02-18 22:20:01 +0100293{
Florin Corasdca88042016-09-14 16:01:38 +0200294 u32 sfi;
295 gid_ip4_table_t *sfib4;
296 gid_ip6_table_t *sfib6;
297
298 switch (ip_prefix_version (dst))
Florin Corase127a7e2016-02-18 22:20:01 +0100299 {
Neale Rannsea93e482019-11-12 17:16:47 +0000300 case AF_IP4:
Florin Corasdca88042016-09-14 16:01:38 +0200301 sfi = ip4_lookup (&db->dst_ip4_table, vni, dst);
302 if (GID_LOOKUP_MISS != sfi)
303 sfib4 = pool_elt_at_index (db->src_ip4_table_pool, sfi);
304 else
305 return GID_LOOKUP_MISS;
306
307 if (!src)
308 {
309 ip_prefix_t sp;
Dave Barachb7b92992018-10-17 10:38:51 -0400310 clib_memset (&sp, 0, sizeof (sp));
Filip Tehlarf3e3fd32016-09-30 12:47:59 +0200311 return ip4_lookup_exact_match (sfib4, 0, &sp);
Florin Corasdca88042016-09-14 16:01:38 +0200312 }
313 else
314 return ip4_lookup (sfib4, 0, src);
315
Florin Corase127a7e2016-02-18 22:20:01 +0100316 break;
Neale Rannsea93e482019-11-12 17:16:47 +0000317 case AF_IP6:
Florin Corasdca88042016-09-14 16:01:38 +0200318 sfi = ip6_lookup (&db->dst_ip6_table, vni, dst);
319 if (GID_LOOKUP_MISS != sfi)
320 sfib6 = pool_elt_at_index (db->src_ip6_table_pool, sfi);
321 else
322 return GID_LOOKUP_MISS;
323
324 if (!src)
325 {
326 ip_prefix_t sp;
Dave Barachb7b92992018-10-17 10:38:51 -0400327 clib_memset (&sp, 0, sizeof (sp));
Neale Rannsea93e482019-11-12 17:16:47 +0000328 ip_prefix_version (&sp) = AF_IP6;
Filip Tehlarf3e3fd32016-09-30 12:47:59 +0200329 return ip6_lookup_exact_match (sfib6, 0, &sp);
Florin Corasdca88042016-09-14 16:01:38 +0200330 }
331 else
332 return ip6_lookup (sfib6, 0, src);
333
Florin Corase127a7e2016-02-18 22:20:01 +0100334 break;
335 default:
Florin Corasa2157cf2016-08-16 21:09:14 +0200336 clib_warning ("address type %d not supported!",
Florin Corasdca88042016-09-14 16:01:38 +0200337 ip_prefix_version (dst));
Florin Corase127a7e2016-02-18 22:20:01 +0100338 break;
339 }
Florin Corasdca88042016-09-14 16:01:38 +0200340 return GID_LOOKUP_MISS;
Florin Corase127a7e2016-02-18 22:20:01 +0100341}
342
Filip Tehlard5a65db2017-05-17 17:21:10 +0200343static void
Filip Tehlar05879992017-09-05 15:46:09 +0200344make_arp_ndp_key (BVT (clib_bihash_kv) * kv, u32 bd, ip_address_t * addr)
Filip Tehlard5a65db2017-05-17 17:21:10 +0200345{
Filip Tehlar05879992017-09-05 15:46:09 +0200346 kv->key[0] = ((u64) bd << 32) | (u32) ip_addr_version (addr);
Neale Rannsea93e482019-11-12 17:16:47 +0000347 if (ip_addr_version (addr) == AF_IP4)
Filip Tehlar05879992017-09-05 15:46:09 +0200348 {
Neale Ranns3ec09e92020-02-24 13:32:30 +0000349 kv->key[1] = (u64) ip_addr_v4 (addr).as_u32;
Filip Tehlar05879992017-09-05 15:46:09 +0200350 kv->key[2] = (u64) 0;
351 }
352 else
353 {
Neale Ranns3ec09e92020-02-24 13:32:30 +0000354 kv->key[1] = (u64) ip_addr_v6 (addr).as_u64[0];
355 kv->key[2] = (u64) ip_addr_v6 (addr).as_u64[1];
Filip Tehlar05879992017-09-05 15:46:09 +0200356 }
Filip Tehlard5a65db2017-05-17 17:21:10 +0200357}
358
Filip Tehlaref2a5bf2017-05-30 07:14:46 +0200359static void
360make_nsh_key (BVT (clib_bihash_kv) * kv, u32 vni, u32 spi, u8 si)
361{
362 kv->key[0] = (u64) vni;
363 kv->key[1] = (u64) spi;
364 kv->key[2] = (u64) si;
365}
366
Filip Tehlard5a65db2017-05-17 17:21:10 +0200367static u64
Filip Tehlar05879992017-09-05 15:46:09 +0200368arp_ndp_lookup (gid_l2_arp_ndp_table_t * db, u32 bd, ip_address_t * key)
Filip Tehlard5a65db2017-05-17 17:21:10 +0200369{
370 int rv;
371 BVT (clib_bihash_kv) kv, value;
372
Filip Tehlar05879992017-09-05 15:46:09 +0200373 make_arp_ndp_key (&kv, bd, key);
374 rv = BV (clib_bihash_search_inline_2) (&db->arp_ndp_lookup_table, &kv,
375 &value);
Filip Tehlard5a65db2017-05-17 17:21:10 +0200376
377 if (rv == 0)
378 return value.value;
379
380 return GID_LOOKUP_MISS_L2;
381}
382
Filip Tehlaref2a5bf2017-05-30 07:14:46 +0200383static u32
384nsh_lookup (gid_nsh_table_t * db, u32 vni, u32 spi, u8 si)
385{
386 int rv;
387 BVT (clib_bihash_kv) kv, value;
388
389 make_nsh_key (&kv, vni, spi, si);
390 rv = BV (clib_bihash_search_inline_2) (&db->nsh_lookup_table, &kv, &value);
391
392 if (rv == 0)
393 return value.value;
394
395 return GID_LOOKUP_MISS;
396}
397
Filip Tehlard5a65db2017-05-17 17:21:10 +0200398u64
Florin Corase127a7e2016-02-18 22:20:01 +0100399gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key)
400{
Florin Corase127a7e2016-02-18 22:20:01 +0100401 switch (gid_address_type (key))
402 {
Filip Tehlarbeceab92016-04-20 17:21:55 +0200403 case GID_ADDR_IP_PREFIX:
Florin Corasdca88042016-09-14 16:01:38 +0200404 return ip_sd_lookup (db, gid_address_vni (key),
405 &gid_address_ippref (key), 0);
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200406 case GID_ADDR_MAC:
Florin Corasdca88042016-09-14 16:01:38 +0200407 return mac_sd_lookup (&db->sd_mac_table, gid_address_vni (key),
408 gid_address_mac (key), 0);
409 case GID_ADDR_SRC_DST:
410 switch (gid_address_sd_dst_type (key))
411 {
412 case FID_ADDR_IP_PREF:
413 return ip_sd_lookup (db, gid_address_vni (key),
414 &gid_address_sd_dst_ippref (key),
415 &gid_address_sd_src_ippref (key));
416 break;
417 case FID_ADDR_MAC:
418 return mac_sd_lookup (&db->sd_mac_table, gid_address_vni (key),
419 gid_address_sd_dst_mac (key),
420 gid_address_sd_src_mac (key));
421 break;
422 default:
423 clib_warning ("Source/Dest address type %d not supported!",
424 gid_address_sd_dst_type (key));
425 break;
426 }
427 break;
Filip Tehlard5a65db2017-05-17 17:21:10 +0200428 case GID_ADDR_ARP:
Filip Tehlar05879992017-09-05 15:46:09 +0200429 case GID_ADDR_NDP:
430 return arp_ndp_lookup (&db->arp_ndp_table, gid_address_arp_ndp_bd (key),
431 &gid_address_arp_ndp_ip (key));
Filip Tehlaref2a5bf2017-05-30 07:14:46 +0200432 case GID_ADDR_NSH:
433 return nsh_lookup (&db->nsh_table, gid_address_vni (key),
434 gid_address_nsh_spi (key), gid_address_nsh_si (key));
Florin Corase127a7e2016-02-18 22:20:01 +0100435 default:
Florin Corasa2157cf2016-08-16 21:09:14 +0200436 clib_warning ("address type %d not supported!", gid_address_type (key));
Florin Corase127a7e2016-02-18 22:20:01 +0100437 break;
438 }
Florin Corasf727db92016-06-23 15:01:58 +0200439 return GID_LOOKUP_MISS;
Florin Corase127a7e2016-02-18 22:20:01 +0100440}
441
Florin Corasdca88042016-09-14 16:01:38 +0200442u32
443gid_dictionary_sd_lookup (gid_dictionary_t * db, gid_address_t * dst,
444 gid_address_t * src)
445{
446 switch (gid_address_type (dst))
447 {
448 case GID_ADDR_IP_PREFIX:
449 return ip_sd_lookup (db, gid_address_vni (dst),
450 &gid_address_ippref (dst),
451 &gid_address_ippref (src));
452 case GID_ADDR_MAC:
453 return mac_sd_lookup (&db->sd_mac_table, gid_address_vni (dst),
454 gid_address_mac (dst), gid_address_mac (src));
Filip Tehlard5fcc462016-10-17 16:20:18 +0200455 case GID_ADDR_SRC_DST:
456 switch (gid_address_sd_dst_type (dst))
457 {
458 case FID_ADDR_IP_PREF:
459 return ip_sd_lookup (db, gid_address_vni (dst),
460 &gid_address_sd_dst_ippref (dst),
461 &gid_address_sd_src_ippref (dst));
462 break;
463 case FID_ADDR_MAC:
464 return mac_sd_lookup (&db->sd_mac_table, gid_address_vni (dst),
465 gid_address_sd_dst_mac (dst),
466 gid_address_sd_src_mac (dst));
467 break;
468 default:
469 clib_warning ("Source/Dest address type %d not supported!",
470 gid_address_sd_dst_type (dst));
471 break;
472 }
Filip Tehlar218170b2016-10-26 14:58:18 +0200473 break;
Filip Tehlaref2a5bf2017-05-30 07:14:46 +0200474 case GID_ADDR_NSH:
475 return gid_dictionary_lookup (db, dst);
476 break;
Florin Corasdca88042016-09-14 16:01:38 +0200477 default:
478 clib_warning ("address type %d not supported!", gid_address_type (dst));
479 break;
480 }
481 return GID_LOOKUP_MISS;
482}
483
Florin Corase127a7e2016-02-18 22:20:01 +0100484static void
Florin Corasdca88042016-09-14 16:01:38 +0200485ip4_compute_prefix_lengths_in_search_order (gid_ip4_table_t * db)
Florin Corase127a7e2016-02-18 22:20:01 +0100486{
487 int i;
488 vec_reset_length (db->ip4_prefix_lengths_in_search_order);
489 /* Note: bitmap reversed so this is in fact a longest prefix match */
Florin Corasa2157cf2016-08-16 21:09:14 +0200490
491 /* *INDENT-OFF* */
Florin Corase127a7e2016-02-18 22:20:01 +0100492 clib_bitmap_foreach (i, db->ip4_non_empty_dst_address_length_bitmap,
493 ({
494 int dst_address_length = 32 - i;
495 vec_add1 (db->ip4_prefix_lengths_in_search_order, dst_address_length);
496 }));
Florin Corasa2157cf2016-08-16 21:09:14 +0200497 /* *INDENT-ON* */
498
Florin Corase127a7e2016-02-18 22:20:01 +0100499}
500
501static u32
Florin Corasdca88042016-09-14 16:01:38 +0200502add_del_ip4_key (gid_ip4_table_t * db, u32 vni, ip_prefix_t * pref, u32 val,
Florin Corasa2157cf2016-08-16 21:09:14 +0200503 u8 is_add)
Florin Corase127a7e2016-02-18 22:20:01 +0100504{
Florin Corasa2157cf2016-08-16 21:09:14 +0200505 BVT (clib_bihash_kv) kv, value;
Florin Corase127a7e2016-02-18 22:20:01 +0100506 u32 old_val = ~0;
507 ip4_address_t key;
508 u8 plen = ip_prefix_len (pref);
509
Florin Corasa2157cf2016-08-16 21:09:14 +0200510 clib_memcpy (&key, &ip_prefix_v4 (pref), sizeof (key));
Florin Corase127a7e2016-02-18 22:20:01 +0100511 key.as_u32 &= db->ip4_fib_masks[plen].as_u32;
512 if (is_add)
513 {
Florin Corasa2157cf2016-08-16 21:09:14 +0200514 db->ip4_non_empty_dst_address_length_bitmap =
515 clib_bitmap_set (db->ip4_non_empty_dst_address_length_bitmap,
516 32 - plen, 1);
Florin Corase127a7e2016-02-18 22:20:01 +0100517 ip4_compute_prefix_lengths_in_search_order (db);
518
519 db->ip4_prefix_len_refcount[plen]++;
520 }
521 else
522 {
Florin Corasa2157cf2016-08-16 21:09:14 +0200523 ASSERT (db->ip4_prefix_len_refcount[plen] != 0);
Florin Corase127a7e2016-02-18 22:20:01 +0100524
525 db->ip4_prefix_len_refcount[plen]--;
526
527 if (db->ip4_prefix_len_refcount[plen] == 0)
Florin Corasa2157cf2016-08-16 21:09:14 +0200528 {
529 db->ip4_non_empty_dst_address_length_bitmap =
530 clib_bitmap_set (db->ip4_non_empty_dst_address_length_bitmap,
531 32 - plen, 0);
532 ip4_compute_prefix_lengths_in_search_order (db);
533 }
Florin Corase127a7e2016-02-18 22:20:01 +0100534 }
535
536 kv.key[0] = ((u64) vni << 32) | key.as_u32;
537 kv.key[1] = 0;
538 kv.key[2] = 0;
539
Florin Corasa2157cf2016-08-16 21:09:14 +0200540 if (BV (clib_bihash_search) (&db->ip4_lookup_table, &kv, &value) == 0)
Florin Corase127a7e2016-02-18 22:20:01 +0100541 old_val = value.value;
542
543 if (!is_add)
Filip Tehlarf3fe8202017-02-15 13:27:08 +0100544 {
545 BV (clib_bihash_add_del) (&db->ip4_lookup_table, &kv, 0 /* is_add */ );
546 db->count--;
547 }
Florin Corase127a7e2016-02-18 22:20:01 +0100548 else
549 {
550 kv.value = val;
Florin Corasa2157cf2016-08-16 21:09:14 +0200551 BV (clib_bihash_add_del) (&db->ip4_lookup_table, &kv, 1 /* is_add */ );
Filip Tehlarf3fe8202017-02-15 13:27:08 +0100552 db->count++;
Florin Corase127a7e2016-02-18 22:20:01 +0100553 }
554 return old_val;
555}
556
557static void
Florin Corasdca88042016-09-14 16:01:38 +0200558ip4_lookup_init (gid_ip4_table_t * db)
559{
Dave Barach11b40e72019-10-11 11:31:43 -0400560 BVT (clib_bihash_init2_args) _a, *a = &_a;
Florin Corasdca88042016-09-14 16:01:38 +0200561 uword i;
562
Dave Barachb7b92992018-10-17 10:38:51 -0400563 clib_memset (db->ip4_prefix_len_refcount, 0,
564 sizeof (db->ip4_prefix_len_refcount));
Florin Corasdca88042016-09-14 16:01:38 +0200565
566 for (i = 0; i < ARRAY_LEN (db->ip4_fib_masks); i++)
567 {
568 u32 m;
569
570 if (i < 32)
571 m = pow2_mask (i) << (32 - i);
572 else
573 m = ~0;
574 db->ip4_fib_masks[i].as_u32 = clib_host_to_net_u32 (m);
575 }
576 if (db->ip4_lookup_table_nbuckets == 0)
577 db->ip4_lookup_table_nbuckets = IP4_LOOKUP_DEFAULT_HASH_NUM_BUCKETS;
578
579 db->ip4_lookup_table_nbuckets =
580 1 << max_log2 (db->ip4_lookup_table_nbuckets);
581
582 if (db->ip4_lookup_table_size == 0)
583 db->ip4_lookup_table_size = IP4_LOOKUP_DEFAULT_HASH_MEMORY_SIZE;
584
Dave Barach11b40e72019-10-11 11:31:43 -0400585 /*
586 * Danger Will Robinson, Danger! gid_ip4_table_t's are allocated from
587 * a pool. They MUST NOT be listed on the clib_all_bihashes list...
588 */
589 memset (a, 0, sizeof (*a));
590 a->h = &db->ip4_lookup_table;
591 a->name = "LISP ip4 lookup table";
592 a->nbuckets = db->ip4_lookup_table_nbuckets;
593 a->memory_size = db->ip4_lookup_table_size;
594 a->dont_add_to_all_bihash_list = 1; /* See comment above */
595
596 BV (clib_bihash_init2) (a);
Florin Corasdca88042016-09-14 16:01:38 +0200597}
598
599static u32
600add_del_sd_ip4_key (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst_pref,
601 ip_prefix_t * src_pref, u32 val, u8 is_add)
602{
603 u32 sfi, old_val = ~0;
604 gid_ip4_table_t *sfib;
605
Filip Tehlarf3e3fd32016-09-30 12:47:59 +0200606 sfi = ip4_lookup_exact_match (&db->dst_ip4_table, vni, dst_pref);
Florin Corasdca88042016-09-14 16:01:38 +0200607
608 if (is_add)
609 {
610 if (GID_LOOKUP_MISS == sfi)
611 {
612 pool_get (db->src_ip4_table_pool, sfib);
613 ip4_lookup_init (sfib);
614 add_del_ip4_key (&db->dst_ip4_table, vni, dst_pref,
615 sfib - db->src_ip4_table_pool, is_add);
616 if (src_pref)
617 add_del_ip4_key (sfib, 0 /* vni */ , src_pref, val, is_add);
618 else
619 {
620 ip_prefix_t sp;
Dave Barachb7b92992018-10-17 10:38:51 -0400621 clib_memset (&sp, 0, sizeof (sp));
Florin Corasdca88042016-09-14 16:01:38 +0200622 add_del_ip4_key (sfib, 0 /* vni */ , &sp, val, is_add);
623 }
624 }
625 else
626 {
627 ASSERT (!pool_is_free_index (db->src_ip4_table_pool, sfi));
628 sfib = pool_elt_at_index (db->src_ip4_table_pool, sfi);
629 if (src_pref)
630 {
Filip Tehlarf3e3fd32016-09-30 12:47:59 +0200631 old_val = ip4_lookup_exact_match (sfib, 0, src_pref);
Florin Corasdca88042016-09-14 16:01:38 +0200632 add_del_ip4_key (sfib, 0 /* vni */ , src_pref, val, is_add);
633 }
634 else
635 {
636 ip_prefix_t sp;
Dave Barachb7b92992018-10-17 10:38:51 -0400637 clib_memset (&sp, 0, sizeof (sp));
Florin Corasdca88042016-09-14 16:01:38 +0200638 old_val =
639 add_del_ip4_key (sfib, 0 /* vni */ , &sp, val, is_add);
640 }
641 }
642 }
643 else
644 {
645 if (GID_LOOKUP_MISS != sfi)
646 {
Florin Corasdca88042016-09-14 16:01:38 +0200647 sfib = pool_elt_at_index (db->src_ip4_table_pool, sfi);
648 if (src_pref)
649 old_val = add_del_ip4_key (sfib, 0, src_pref, 0, is_add);
650 else
651 {
652 ip_prefix_t sp;
Dave Barachb7b92992018-10-17 10:38:51 -0400653 clib_memset (&sp, 0, sizeof (sp));
Florin Corasdca88042016-09-14 16:01:38 +0200654 old_val = add_del_ip4_key (sfib, 0, &sp, 0, is_add);
655 }
Filip Tehlarf3fe8202017-02-15 13:27:08 +0100656
657 if (sfib->count == 0)
658 add_del_ip4_key (&db->dst_ip4_table, vni, dst_pref, 0, is_add);
Florin Corasdca88042016-09-14 16:01:38 +0200659 }
660 else
661 clib_warning ("cannot delete dst mapping %U!", format_ip_prefix,
662 dst_pref);
663 }
664 return old_val;
665}
666
667static void
668ip6_compute_prefix_lengths_in_search_order (gid_ip6_table_t * db)
Florin Corase127a7e2016-02-18 22:20:01 +0100669{
670 int i;
671 vec_reset_length (db->ip6_prefix_lengths_in_search_order);
672 /* Note: bitmap reversed so this is in fact a longest prefix match */
Florin Corasa2157cf2016-08-16 21:09:14 +0200673
674 /* *INDENT-OFF* */
Florin Corase127a7e2016-02-18 22:20:01 +0100675 clib_bitmap_foreach (i, db->ip6_non_empty_dst_address_length_bitmap,
676 ({
677 int dst_address_length = 128 - i;
678 vec_add1 (db->ip6_prefix_lengths_in_search_order, dst_address_length);
679 }));
Florin Corasa2157cf2016-08-16 21:09:14 +0200680 /* *INDENT-ON* */
Florin Corase127a7e2016-02-18 22:20:01 +0100681}
682
683static u32
Florin Corasdca88042016-09-14 16:01:38 +0200684add_del_ip6_key (gid_ip6_table_t * db, u32 vni, ip_prefix_t * pref, u32 val,
Florin Corasa2157cf2016-08-16 21:09:14 +0200685 u8 is_add)
Florin Corase127a7e2016-02-18 22:20:01 +0100686{
Florin Corasa2157cf2016-08-16 21:09:14 +0200687 BVT (clib_bihash_kv) kv, value;
Florin Corase127a7e2016-02-18 22:20:01 +0100688 u32 old_val = ~0;
689 ip6_address_t key;
690 u8 plen = ip_prefix_len (pref);
691
Florin Corasa2157cf2016-08-16 21:09:14 +0200692 clib_memcpy (&key, &ip_prefix_v6 (pref), sizeof (key));
Florin Corase127a7e2016-02-18 22:20:01 +0100693 ip6_address_mask (&key, &db->ip6_fib_masks[plen]);
694 if (is_add)
695 {
Florin Corasa2157cf2016-08-16 21:09:14 +0200696 db->ip6_non_empty_dst_address_length_bitmap =
697 clib_bitmap_set (db->ip6_non_empty_dst_address_length_bitmap,
698 128 - plen, 1);
Florin Corase127a7e2016-02-18 22:20:01 +0100699 ip6_compute_prefix_lengths_in_search_order (db);
700 db->ip6_prefix_len_refcount[plen]++;
701 }
702 else
703 {
Florin Corasa2157cf2016-08-16 21:09:14 +0200704 ASSERT (db->ip6_prefix_len_refcount[plen] != 0);
Florin Corase127a7e2016-02-18 22:20:01 +0100705
706 db->ip6_prefix_len_refcount[plen]--;
707
708 if (db->ip6_prefix_len_refcount[plen] == 0)
Florin Corasa2157cf2016-08-16 21:09:14 +0200709 {
710 db->ip6_non_empty_dst_address_length_bitmap =
711 clib_bitmap_set (db->ip6_non_empty_dst_address_length_bitmap,
712 128 - plen, 0);
713 ip6_compute_prefix_lengths_in_search_order (db);
714 }
Florin Corase127a7e2016-02-18 22:20:01 +0100715 }
716
717 kv.key[0] = key.as_u64[0];
718 kv.key[1] = key.as_u64[1];
719 kv.key[2] = (u64) vni;
720// kv.key[2] = ((u64)((fib - im->fibs))<<32) | ip_prefix_len(key);
721
Florin Corasa2157cf2016-08-16 21:09:14 +0200722 if (BV (clib_bihash_search) (&db->ip6_lookup_table, &kv, &value) == 0)
Florin Corase127a7e2016-02-18 22:20:01 +0100723 old_val = value.value;
724
725 if (!is_add)
Filip Tehlarf3fe8202017-02-15 13:27:08 +0100726 {
727 BV (clib_bihash_add_del) (&db->ip6_lookup_table, &kv, 0 /* is_add */ );
728 db->count--;
729 }
Florin Corase127a7e2016-02-18 22:20:01 +0100730 else
731 {
732 kv.value = val;
Florin Corasa2157cf2016-08-16 21:09:14 +0200733 BV (clib_bihash_add_del) (&db->ip6_lookup_table, &kv, 1 /* is_add */ );
Filip Tehlarf3fe8202017-02-15 13:27:08 +0100734 db->count++;
Florin Corase127a7e2016-02-18 22:20:01 +0100735 }
736 return old_val;
737}
738
739static u32
Florin Corasdca88042016-09-14 16:01:38 +0200740add_del_mac (gid_mac_table_t * db, u32 vni, u8 * dst_mac, u8 * src_mac,
741 u32 val, u8 is_add)
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200742{
Florin Corasa2157cf2016-08-16 21:09:14 +0200743 BVT (clib_bihash_kv) kv, value;
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200744 u32 old_val = ~0;
745
Florin Corasdca88042016-09-14 16:01:38 +0200746 make_mac_sd_key (&kv, vni, src_mac, dst_mac);
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200747
Florin Corasa2157cf2016-08-16 21:09:14 +0200748 if (BV (clib_bihash_search) (&db->mac_lookup_table, &kv, &value) == 0)
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200749 old_val = value.value;
750
751 if (!is_add)
Filip Tehlarf3fe8202017-02-15 13:27:08 +0100752 {
753 BV (clib_bihash_add_del) (&db->mac_lookup_table, &kv, 0 /* is_add */ );
754 db->count--;
755 }
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200756 else
757 {
758 kv.value = val;
Florin Corasa2157cf2016-08-16 21:09:14 +0200759 BV (clib_bihash_add_del) (&db->mac_lookup_table, &kv, 1 /* is_add */ );
Filip Tehlarf3fe8202017-02-15 13:27:08 +0100760 db->count++;
Filip Tehlar8e39bb42016-06-24 14:16:34 +0200761 }
762 return old_val;
763}
764
Florin Corase127a7e2016-02-18 22:20:01 +0100765static void
Florin Corasdca88042016-09-14 16:01:38 +0200766ip6_lookup_init (gid_ip6_table_t * db)
Florin Corase127a7e2016-02-18 22:20:01 +0100767{
768 uword i;
Dave Barach11b40e72019-10-11 11:31:43 -0400769 BVT (clib_bihash_init2_args) _a, *a = &_a;
Florin Corase127a7e2016-02-18 22:20:01 +0100770
Dave Barachb7b92992018-10-17 10:38:51 -0400771 clib_memset (db->ip6_prefix_len_refcount, 0,
772 sizeof (db->ip6_prefix_len_refcount));
Florin Corase127a7e2016-02-18 22:20:01 +0100773
Florin Corasa2157cf2016-08-16 21:09:14 +0200774 for (i = 0; i < ARRAY_LEN (db->ip6_fib_masks); i++)
Florin Corase127a7e2016-02-18 22:20:01 +0100775 {
776 u32 j, i0, i1;
777
778 i0 = i / 32;
779 i1 = i % 32;
780
781 for (j = 0; j < i0; j++)
Florin Corasa2157cf2016-08-16 21:09:14 +0200782 db->ip6_fib_masks[i].as_u32[j] = ~0;
Florin Corase127a7e2016-02-18 22:20:01 +0100783
784 if (i1)
Florin Corasa2157cf2016-08-16 21:09:14 +0200785 db->ip6_fib_masks[i].as_u32[i0] =
786 clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
Florin Corase127a7e2016-02-18 22:20:01 +0100787 }
788
789 if (db->ip6_lookup_table_nbuckets == 0)
790 db->ip6_lookup_table_nbuckets = IP6_LOOKUP_DEFAULT_HASH_NUM_BUCKETS;
791
Florin Corasa2157cf2016-08-16 21:09:14 +0200792 db->ip6_lookup_table_nbuckets =
793 1 << max_log2 (db->ip6_lookup_table_nbuckets);
Florin Corase127a7e2016-02-18 22:20:01 +0100794
795 if (db->ip6_lookup_table_size == 0)
796 db->ip6_lookup_table_size = IP6_LOOKUP_DEFAULT_HASH_MEMORY_SIZE;
797
Dave Barach11b40e72019-10-11 11:31:43 -0400798 /*
799 * Danger Will Robinson, Danger! gid_ip6_table_t's are allocated from
800 * a pool. They MUST NOT be listed on the clib_all_bihashes list...
801 */
802 memset (a, 0, sizeof (*a));
803 a->h = &db->ip6_lookup_table;
804 a->name = "LISP ip6 lookup table";
805 a->nbuckets = db->ip6_lookup_table_nbuckets;
806 a->memory_size = db->ip6_lookup_table_size;
807 a->dont_add_to_all_bihash_list = 1; /* See comment above */
808
809 BV (clib_bihash_init2) (a);
Florin Corase127a7e2016-02-18 22:20:01 +0100810}
811
Florin Corasdca88042016-09-14 16:01:38 +0200812static u32
813add_del_sd_ip6_key (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst_pref,
814 ip_prefix_t * src_pref, u32 val, u8 is_add)
815{
816 u32 sfi, old_val = ~0;
817 gid_ip6_table_t *sfib;
818
Filip Tehlarf3e3fd32016-09-30 12:47:59 +0200819 sfi = ip6_lookup_exact_match (&db->dst_ip6_table, vni, dst_pref);
Florin Corasdca88042016-09-14 16:01:38 +0200820
821 if (is_add)
822 {
823 if (GID_LOOKUP_MISS == sfi)
824 {
825 pool_get (db->src_ip6_table_pool, sfib);
826 ip6_lookup_init (sfib);
827 add_del_ip6_key (&db->dst_ip6_table, vni, dst_pref,
828 sfib - db->src_ip6_table_pool, is_add);
829 if (src_pref)
830 add_del_ip6_key (sfib, 0 /* vni */ , src_pref, val, is_add);
831 else
832 {
833 ip_prefix_t sp;
Dave Barachb7b92992018-10-17 10:38:51 -0400834 clib_memset (&sp, 0, sizeof (sp));
Neale Rannsea93e482019-11-12 17:16:47 +0000835 ip_prefix_version (&sp) = AF_IP6;
Florin Corasdca88042016-09-14 16:01:38 +0200836 add_del_ip6_key (sfib, 0 /* vni */ , &sp, val, is_add);
837 }
838 }
839 else
840 {
841 ASSERT (!pool_is_free_index (db->src_ip6_table_pool, sfi));
842 sfib = pool_elt_at_index (db->src_ip6_table_pool, sfi);
843 if (src_pref)
844 {
Filip Tehlarf3e3fd32016-09-30 12:47:59 +0200845 old_val = ip6_lookup_exact_match (sfib, 0, src_pref);
Florin Corasdca88042016-09-14 16:01:38 +0200846 add_del_ip6_key (sfib, 0 /* vni */ , src_pref, val, is_add);
847 }
848 else
849 {
850 ip_prefix_t sp;
Dave Barachb7b92992018-10-17 10:38:51 -0400851 clib_memset (&sp, 0, sizeof (sp));
Neale Rannsea93e482019-11-12 17:16:47 +0000852 ip_prefix_version (&sp) = AF_IP6;
Florin Corasdca88042016-09-14 16:01:38 +0200853 old_val =
854 add_del_ip6_key (sfib, 0 /* vni */ , &sp, val, is_add);
855 }
856 }
857 }
858 else
859 {
860 if (GID_LOOKUP_MISS != sfi)
861 {
Florin Corasdca88042016-09-14 16:01:38 +0200862 sfib = pool_elt_at_index (db->src_ip6_table_pool, sfi);
863 if (src_pref)
864 old_val = add_del_ip6_key (sfib, 0, src_pref, 0, is_add);
865 else
866 {
867 ip_prefix_t sp;
Dave Barachb7b92992018-10-17 10:38:51 -0400868 clib_memset (&sp, 0, sizeof (sp));
Neale Rannsea93e482019-11-12 17:16:47 +0000869 ip_prefix_version (&sp) = AF_IP6;
Florin Corasdca88042016-09-14 16:01:38 +0200870 old_val = add_del_ip6_key (sfib, 0, &sp, 0, is_add);
871 }
Filip Tehlarf3fe8202017-02-15 13:27:08 +0100872
873 if (sfib->count == 0)
874 add_del_ip6_key (&db->dst_ip6_table, vni, dst_pref, 0, is_add);
Florin Corasdca88042016-09-14 16:01:38 +0200875 }
876 else
877 clib_warning ("cannot delete dst mapping %U!", format_ip_prefix,
878 dst_pref);
879 }
880 return old_val;
881}
882
883static u32
884add_del_ip (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst_key,
885 ip_prefix_t * src_key, u32 value, u8 is_add)
886{
887 switch (ip_prefix_version (dst_key))
888 {
Neale Rannsea93e482019-11-12 17:16:47 +0000889 case AF_IP4:
Florin Corasdca88042016-09-14 16:01:38 +0200890 return add_del_sd_ip4_key (db, vni, dst_key, src_key, value, is_add);
891 break;
Neale Rannsea93e482019-11-12 17:16:47 +0000892 case AF_IP6:
Florin Corasdca88042016-09-14 16:01:38 +0200893 return add_del_sd_ip6_key (db, vni, dst_key, src_key, value, is_add);
894 break;
895 default:
896 clib_warning ("address type %d not supported!",
897 ip_prefix_version (dst_key));
898 break;
899 }
900 return ~0;
901}
902
903static u32
904add_del_sd (gid_dictionary_t * db, u32 vni, source_dest_t * key, u32 value,
905 u8 is_add)
906{
907 switch (sd_dst_type (key))
908 {
909 case FID_ADDR_IP_PREF:
910 add_del_ip (db, vni, &sd_dst_ippref (key), &sd_src_ippref (key),
911 value, is_add);
912
913 case FID_ADDR_MAC:
914 return add_del_mac (&db->sd_mac_table, vni, sd_dst_mac (key),
915 sd_src_mac (key), value, is_add);
916
917 default:
Paul Vinciguerrabdc0e6b2018-09-22 05:32:50 -0700918 clib_warning ("SD address type %d not supported!", sd_dst_type (key));
Florin Corasdca88042016-09-14 16:01:38 +0200919 break;
920 }
921
922 return ~0;
923}
924
Filip Tehlaref2a5bf2017-05-30 07:14:46 +0200925static u64
Filip Tehlar05879992017-09-05 15:46:09 +0200926add_del_arp_ndp (gid_l2_arp_ndp_table_t * db, u32 bd, ip_address_t * key,
927 u64 value, u8 is_add)
Filip Tehlard5a65db2017-05-17 17:21:10 +0200928{
929 BVT (clib_bihash_kv) kv, result;
930 u32 old_val = ~0;
931
Filip Tehlar05879992017-09-05 15:46:09 +0200932 make_arp_ndp_key (&kv, bd, key);
933 if (BV (clib_bihash_search) (&db->arp_ndp_lookup_table, &kv, &result) == 0)
Filip Tehlard5a65db2017-05-17 17:21:10 +0200934 old_val = result.value;
935
936 if (is_add)
937 {
938 kv.value = value;
Filip Tehlar05879992017-09-05 15:46:09 +0200939 BV (clib_bihash_add_del) (&db->arp_ndp_lookup_table, &kv,
940 1 /* is_add */ );
Filip Tehlard5a65db2017-05-17 17:21:10 +0200941 db->count++;
942 }
943 else
944 {
Filip Tehlar05879992017-09-05 15:46:09 +0200945 BV (clib_bihash_add_del) (&db->arp_ndp_lookup_table, &kv,
946 0 /* is_add */ );
Filip Tehlard5a65db2017-05-17 17:21:10 +0200947 db->count--;
948 }
949 return old_val;
950}
951
Filip Tehlaref2a5bf2017-05-30 07:14:46 +0200952static u32
953add_del_nsh (gid_nsh_table_t * db, u32 vni, u32 spi, u8 si, u32 value,
954 u8 is_add)
955{
956 BVT (clib_bihash_kv) kv, result;
957 u32 old_val = ~0;
958
959 make_nsh_key (&kv, vni, spi, si);
960 if (BV (clib_bihash_search) (&db->nsh_lookup_table, &kv, &result) == 0)
961 old_val = result.value;
962
963 if (is_add)
964 {
965 kv.value = value;
966 BV (clib_bihash_add_del) (&db->nsh_lookup_table, &kv, 1 /* is_add */ );
967 db->count++;
968 }
969 else
970 {
971 BV (clib_bihash_add_del) (&db->nsh_lookup_table, &kv, 0 /* is_add */ );
972 db->count--;
973 }
974 return old_val;
975}
976
Florin Corasdca88042016-09-14 16:01:38 +0200977u32
Filip Tehlard5a65db2017-05-17 17:21:10 +0200978gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u64 value,
Florin Corasdca88042016-09-14 16:01:38 +0200979 u8 is_add)
980{
981 switch (gid_address_type (key))
982 {
983 case GID_ADDR_IP_PREFIX:
984 return add_del_ip (db, gid_address_vni (key), &gid_address_ippref (key),
Filip Tehlard5a65db2017-05-17 17:21:10 +0200985 0, (u32) value, is_add);
Florin Corasdca88042016-09-14 16:01:38 +0200986 case GID_ADDR_MAC:
987 return add_del_mac (&db->sd_mac_table, gid_address_vni (key),
Filip Tehlard5a65db2017-05-17 17:21:10 +0200988 gid_address_mac (key), 0, (u32) value, is_add);
Florin Corasdca88042016-09-14 16:01:38 +0200989 case GID_ADDR_SRC_DST:
990 return add_del_sd (db, gid_address_vni (key), &gid_address_sd (key),
Filip Tehlard5a65db2017-05-17 17:21:10 +0200991 (u32) value, is_add);
992 case GID_ADDR_ARP:
Filip Tehlar05879992017-09-05 15:46:09 +0200993 case GID_ADDR_NDP:
994 return add_del_arp_ndp (&db->arp_ndp_table,
995 gid_address_arp_ndp_bd (key),
996 &gid_address_arp_ndp_ip (key), value, is_add);
Filip Tehlaref2a5bf2017-05-30 07:14:46 +0200997 case GID_ADDR_NSH:
998 return add_del_nsh (&db->nsh_table, gid_address_vni (key),
999 gid_address_nsh_spi (key), gid_address_nsh_si (key),
1000 value, is_add);
1001
Florin Corasdca88042016-09-14 16:01:38 +02001002 default:
1003 clib_warning ("address type %d not supported!", gid_address_type (key));
1004 break;
1005 }
1006 return ~0;
1007}
1008
Filip Tehlar8e39bb42016-06-24 14:16:34 +02001009static void
Florin Corasdca88042016-09-14 16:01:38 +02001010mac_lookup_init (gid_mac_table_t * db)
Filip Tehlar8e39bb42016-06-24 14:16:34 +02001011{
1012 if (db->mac_lookup_table_nbuckets == 0)
1013 db->mac_lookup_table_nbuckets = MAC_LOOKUP_DEFAULT_HASH_NUM_BUCKETS;
1014
Florin Corasa2157cf2016-08-16 21:09:14 +02001015 db->mac_lookup_table_nbuckets =
1016 1 << max_log2 (db->mac_lookup_table_nbuckets);
Filip Tehlar8e39bb42016-06-24 14:16:34 +02001017
1018 if (db->mac_lookup_table_size == 0)
1019 db->mac_lookup_table_size = MAC_LOOKUP_DEFAULT_HASH_MEMORY_SIZE;
1020
Florin Corasa2157cf2016-08-16 21:09:14 +02001021 BV (clib_bihash_init) (&db->mac_lookup_table, "mac lookup table",
1022 db->mac_lookup_table_nbuckets,
1023 db->mac_lookup_table_size);
Filip Tehlar8e39bb42016-06-24 14:16:34 +02001024}
1025
Filip Tehlard5a65db2017-05-17 17:21:10 +02001026static void
Filip Tehlar05879992017-09-05 15:46:09 +02001027arp_ndp_lookup_init (gid_l2_arp_ndp_table_t * db)
Filip Tehlard5a65db2017-05-17 17:21:10 +02001028{
Filip Tehlar05879992017-09-05 15:46:09 +02001029 if (db->arp_ndp_lookup_table_nbuckets == 0)
1030 db->arp_ndp_lookup_table_nbuckets =
1031 ARP_NDP_LOOKUP_DEFAULT_HASH_NUM_BUCKETS;
Filip Tehlard5a65db2017-05-17 17:21:10 +02001032
Filip Tehlar05879992017-09-05 15:46:09 +02001033 db->arp_ndp_lookup_table_nbuckets =
1034 1 << max_log2 (db->arp_ndp_lookup_table_nbuckets);
Filip Tehlard5a65db2017-05-17 17:21:10 +02001035
Filip Tehlar05879992017-09-05 15:46:09 +02001036 if (db->arp_ndp_lookup_table_size == 0)
1037 db->arp_ndp_lookup_table_size = ARP_NDP_LOOKUP_DEFAULT_HASH_MEMORY_SIZE;
Filip Tehlard5a65db2017-05-17 17:21:10 +02001038
Filip Tehlar05879992017-09-05 15:46:09 +02001039 BV (clib_bihash_init) (&db->arp_ndp_lookup_table, "arp ndp lookup table",
1040 db->arp_ndp_lookup_table_nbuckets,
1041 db->arp_ndp_lookup_table_size);
Filip Tehlard5a65db2017-05-17 17:21:10 +02001042}
1043
Filip Tehlaref2a5bf2017-05-30 07:14:46 +02001044static void
1045nsh_lookup_init (gid_nsh_table_t * db)
1046{
1047 if (db->nsh_lookup_table_nbuckets == 0)
1048 db->nsh_lookup_table_nbuckets = MAC_LOOKUP_DEFAULT_HASH_NUM_BUCKETS;
1049
1050 db->nsh_lookup_table_nbuckets =
1051 1 << max_log2 (db->nsh_lookup_table_nbuckets);
1052
1053 if (db->nsh_lookup_table_size == 0)
1054 db->nsh_lookup_table_size = MAC_LOOKUP_DEFAULT_HASH_MEMORY_SIZE;
1055
1056 BV (clib_bihash_init) (&db->nsh_lookup_table, "nsh lookup table",
1057 db->nsh_lookup_table_nbuckets,
1058 db->nsh_lookup_table_size);
1059}
1060
Florin Corase127a7e2016-02-18 22:20:01 +01001061void
1062gid_dictionary_init (gid_dictionary_t * db)
1063{
Florin Corasdca88042016-09-14 16:01:38 +02001064 ip4_lookup_init (&db->dst_ip4_table);
1065 ip6_lookup_init (&db->dst_ip6_table);
1066 mac_lookup_init (&db->sd_mac_table);
Filip Tehlar05879992017-09-05 15:46:09 +02001067 arp_ndp_lookup_init (&db->arp_ndp_table);
Filip Tehlaref2a5bf2017-05-30 07:14:46 +02001068 nsh_lookup_init (&db->nsh_table);
Florin Corase127a7e2016-02-18 22:20:01 +01001069}
1070
Florin Corasa2157cf2016-08-16 21:09:14 +02001071/*
1072 * fd.io coding-style-patch-verification: ON
1073 *
1074 * Local Variables:
1075 * eval: (c-set-style "gnu")
1076 * End:
1077 */