blob: b614a5becb5eef1874d6c7e8c8add26d4c1267b2 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*---------------------------------------------------------------------------
2 * Copyright (c) 2009-2014 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
17#ifndef __included_vppjni_bridge_domain_h__
18#define __included_vppjni_bridge_domain_h__
19
20#include <vlib/vlib.h>
21#include <vppinfra/clib.h>
22#include <vppinfra/mhash.h>
23
24/*
25 * The L2fib key is the mac address and bridge domain ID
26 */
27#define MAC_ADDRESS_SIZE 6
28
29typedef struct {
30 union {
31 struct {
32 u16 unused1;
33 u8 mac[MAC_ADDRESS_SIZE];
34 } fields;
35 u64 raw;
36 };
37} l2fib_u64_mac_t;
38
39/*
40 * The l2fib entry results
41 */
42typedef struct {
43 u32 bd_id;
44 l2fib_u64_mac_t mac_addr;
45 u32 sw_if_index;
46 u8 learned:1;
47 u8 bvi:1;
48 u8 filter:1; // drop packets to/from this mac
49 u8 unused1:5;
50} bd_l2fib_oper_t;
51
52typedef struct {
53 u32 bd_id;
54 u8 * bd_name;
55} bd_local_cfg_t;
56
57typedef struct {
58 u32 bd_id;
59 u32 sw_if_index;
60 u32 shg;
61} bd_sw_if_oper_t;
62
63typedef struct {
64 u32 bd_id;
65 u8 flood:1;
66 u8 forward:1;
67 u8 learn:1;
68 u8 uu_flood:1;
69 u8 arp_term:1;
70 u8 unused1:3;
71 u32 bvi_sw_if_index;
72 u32 n_sw_ifs;
73 bd_sw_if_oper_t * bd_sw_if_oper;
74 f64 last_sync_time;
75 mhash_t l2fib_index_by_mac;
76 bd_l2fib_oper_t * l2fib_oper; // vector indexed by l2fib_index
77} vjbd_oper_t;
78
79#define BD_OPER_REFRESH_INTERVAL 2.0
80#define BD_OPER_L2FIB_REFRESH_INTERVAL 5.0
81
82typedef struct {
83 u32 next_bd_id;
84 uword * bd_index_bitmap;
85 uword * bd_index_by_id;
86 mhash_t bd_id_by_name;
87 bd_local_cfg_t * local_cfg; // vector indexed by bd_index
88 vjbd_oper_t * bd_oper; // vector indexed by oper_bd_index
89 f64 bd_oper_last_sync_all_time;
90 bd_sw_if_oper_t * sw_if_oper; // vector indexed by sw_if_index
91 f64 l2fib_oper_last_sync_time;
92 uword * bd_id_by_sw_if_index;
93 uword * oper_bd_index_by_bd_id;
94} vjbd_main_t;
95
96extern vjbd_main_t vjbd_main;
97
98always_inline
99u64 l2fib_mac_to_u64 (u8 * mac_address) {
100 u64 temp;
101
102 // The mac address in memory is A:B:C:D:E:F
103 // The bd id in register is H:L
104#if CLIB_ARCH_IS_LITTLE_ENDIAN
105 // Create the in-register key as F:E:D:C:B:A:H:L
106 // In memory the key is L:H:A:B:C:D:E:F
107 temp = *((u64 *)(mac_address - 2));
108 temp = (temp & ~0xffff);
109#else
110 // Create the in-register key as H:L:A:B:C:D:E:F
111 // In memory the key is H:L:A:B:C:D:E:F
112 temp = *((u64 *)(mac_address)) >> 16;
113#endif
114
115 return temp;
116}
117
118static_always_inline void vjbd_main_init (vjbd_main_t *bdm)
119{
120 bdm->bd_index_by_id = hash_create (0, sizeof(uword));
121 mhash_init_vec_string (&bdm->bd_id_by_name, sizeof (u32));
122 bdm->bd_id_by_sw_if_index = hash_create (0, sizeof (u32));
123 bdm->oper_bd_index_by_bd_id = hash_create (0, sizeof (u32));
124}
125
126static_always_inline u32 vjbd_id_is_valid (vjbd_main_t * bdm, u32 bd_id)
127{
128 return ((bd_id != 0) && (bd_id != ~0) && (bd_id <= bdm->next_bd_id));
129}
130
131static_always_inline u32 vjbd_index_is_free (vjbd_main_t * bdm, u16 bd_index)
132{
133 u32 bd_id = vec_elt_at_index(bdm->local_cfg, bd_index)->bd_id;
134
135 return (!clib_bitmap_get (bdm->bd_index_bitmap, (bd_index)) &&
136 (bd_index < vec_len (bdm->local_cfg)) &&
137 ((bd_id == 0) || (bd_id == ~0)));
138}
139
140static_always_inline u32 vjbd_index_is_valid (vjbd_main_t * bdm, u16 bd_index)
141{
142 return (clib_bitmap_get (bdm->bd_index_bitmap, bd_index) &&
143 (bd_index < vec_len (bdm->local_cfg)));
144}
145
146static_always_inline u32 vjbd_id_from_name (vjbd_main_t * bdm,
147 const u8 * bd_name)
148{
149 u32 bd_id;
150 uword * p;
151
152 ASSERT (vec_c_string_is_terminated (bd_name));
153
154 if (bdm->next_bd_id == 0)
155 return ~0;
156
157 p = mhash_get (&bdm->bd_id_by_name, (void *)bd_name);
158 if (p)
159 {
160 bd_id = p[0];
161 ASSERT (vjbd_id_is_valid (bdm, bd_id));
162 }
163 else
164 bd_id = ~0;
165
166 return bd_id;
167}
168
169static_always_inline u32 vjbd_index_from_id (vjbd_main_t * bdm, u32 bd_id)
170{
171 uword * p;
172 u16 bd_index;
173
174 ASSERT (vjbd_id_is_valid (bdm, bd_id));
175
176 p = hash_get (bdm->bd_index_by_id, bd_id);
177
178 ASSERT (p); // there is always an index associated with a valid bd_id
179 bd_index = p[0];
180
181 ASSERT (vjbd_index_is_valid (bdm, bd_index));
182
183 return bd_index;
184}
185
186static_always_inline u32 vjbd_id_from_index (vjbd_main_t * bdm, u16 bd_index)
187{
188 u32 bd_id;
189
190 ASSERT (vjbd_index_is_valid (bdm, bd_index));
191
192 bd_id = vec_elt_at_index(bdm->local_cfg, bd_index)->bd_id;
193
194 ASSERT (vjbd_id_is_valid (bdm, bd_id));
195
196 return bd_id;
197}
198
199static_always_inline u8 * vjbd_name_from_id (vjbd_main_t * bdm, u32 bd_id)
200{
201 u16 bd_index = vjbd_index_from_id (bdm, bd_id);
202
203 return vec_elt_at_index(bdm->local_cfg, bd_index)->bd_name;
204}
205
206static_always_inline u8 * vjbd_oper_name_from_id (vjbd_main_t * bdm, u32 bd_id)
207{
208 if (vjbd_id_is_valid (bdm, bd_id)) {
209 return format(0, "%s", vjbd_name_from_id(bdm, bd_id));
210 } else {
211 return format(0, "BridgeDomainOper%d", bd_id);
212 }
213}
214
215static_always_inline vjbd_oper_t * vjbd_oper_from_id (vjbd_main_t * bdm,
216 u32 bd_id)
217{
218 u16 bd_index = vjbd_index_from_id (bdm, bd_id);
219 return vec_elt_at_index (bdm->bd_oper, bd_index);
220}
221
222static_always_inline void vjbd_oper_maybe_sync_from_vpp (vjbd_main_t * bdm,
223 u32 bd_id)
224{
225#ifdef VPPJNI_OPER
226 vppjni_vpe_api_msg_main_t *ovam = ovam_get_main ();
227
228 if (bd_id == ~0)
229 {
230 if ((ovam_time_now (ovam) - bdm->bd_oper_last_sync_all_time) >
231 BD_OPER_REFRESH_INTERVAL)
232 {
233 ovam_bridge_domain_dump (bd_id);
234 bdm->bd_oper_last_sync_all_time = ovam_time_now (ovam);
235 }
236 }
237
238 else
239 {
240 vjbd_oper_t * bd_oper = vjbd_oper_from_id (bdm, bd_id);
241
242 if ((ovam_time_now (ovam) - bd_oper->last_sync_time) >
243 BD_OPER_REFRESH_INTERVAL)
244 {
245 ovam_bridge_domain_dump (bd_id);
246
247 bd_oper->last_sync_time = ovam_time_now (ovam);
248 }
249 }
250#endif
251}
252
253static_always_inline u32 vjbd_id_from_sw_if_index (vjbd_main_t * bdm,
254 u32 sw_if_index)
255{
256 bd_sw_if_oper_t * bd_sw_if_oper;
257 u32 bd_id = ~0;
258
259 vjbd_oper_maybe_sync_from_vpp (bdm, ~0);
260 if (sw_if_index < vec_len (bdm->sw_if_oper))
261 {
262 bd_sw_if_oper = vec_elt_at_index (bdm->sw_if_oper, sw_if_index);
263 bd_id = bd_sw_if_oper->bd_id;
264 }
265
266 return bd_id;
267}
268
269static_always_inline u8 * vjbd_name_from_sw_if_index (vjbd_main_t * bdm,
270 u32 sw_if_index)
271{
272 u32 bd_id, bd_index;
273 u8 * bd_name = 0;
274
275 /* DAW-FIXME:
276 ASSERT (ovam_sw_if_index_valid (ovam_get_main(), sw_if_index));
277 */
278 vjbd_oper_maybe_sync_from_vpp (bdm, ~0);
279 bd_id = vjbd_id_from_sw_if_index (bdm, sw_if_index);
280 if (vjbd_id_is_valid (bdm, bd_id))
281 {
282 bd_index = vjbd_index_from_id (bdm, bd_id);
283 bd_name = vec_elt_at_index (bdm->local_cfg, bd_index)->bd_name;
284 }
285
286 return bd_name;
287}
288
289static_always_inline u32
290vjbd_oper_l2fib_index_from_mac (vjbd_oper_t * bd_oper, u8 * mac)
291{
292 u32 l2fib_index;
293 uword * p;
294
295 p = mhash_get (&bd_oper->l2fib_index_by_mac, mac);
296 if (p)
297 {
298 l2fib_index = p[0];
299 ASSERT (l2fib_index < vec_len (bd_oper->l2fib_oper));
300 }
301 else
302 l2fib_index = ~0;
303
304 return l2fib_index;
305}
306
307static_always_inline u32 vjbd_local_cfg_next_id (vjbd_main_t * bdm,
308 u32 bd_id)
309{
310 u32 i, end = vec_len (bdm->local_cfg);
311 u32 next_bd_id = 0;
312
313 if ((bd_id == 0) || vjbd_id_is_valid (bdm, bd_id))
314 for (i = 0; i < end; i++)
315 {
316 u32 curr_bd_id = bdm->local_cfg[i].bd_id;
317 if ((curr_bd_id != ~0) && (curr_bd_id > bd_id) &&
318 ((next_bd_id == 0) || (curr_bd_id < next_bd_id)))
319 next_bd_id = curr_bd_id;
320 }
321
322 return next_bd_id;
323}
324
325static_always_inline u32 vjbd_sw_if_oper_next_index (vjbd_main_t * bdm,
326 u32 start, u32 bd_id)
327{
328 u32 i, end = vec_len (bdm->sw_if_oper);
329
330 if (vjbd_id_is_valid (bdm, bd_id))
331 for (i = start; i < end; i++)
332 if (bdm->sw_if_oper[i].bd_id == bd_id)
333 return i;
334
335 return ~0;
336}
337
338static_always_inline void
339vjbd_oper_l2fib_maybe_sync_from_vpp (vjbd_main_t * bdm)
340{
341#ifdef VPPJNI_OPER
342 vppjni_vpe_api_msg_main_t *ovam = ovam_get_main ();
343 if ((ovam_time_now (ovam) - bdm->l2fib_oper_last_sync_time) >
344 BD_OPER_L2FIB_REFRESH_INTERVAL)
345 {
346 ovam_l2fib_table_dump ();
347 bdm->l2fib_oper_last_sync_time = ovam_time_now (ovam);
348 }
349#endif
350}
351
352static_always_inline void vjbd_l2fib_oper_reset (vjbd_main_t * bdm)
353{
354 vjbd_oper_t * bd_oper;
355
356 vec_foreach (bd_oper, bdm->bd_oper)
357 {
358 mhash_init (&bd_oper->l2fib_index_by_mac, sizeof (u32), MAC_ADDRESS_SIZE);
359 vec_reset_length (bd_oper->l2fib_oper);
360 }
361}
362
363static_always_inline void vjbd_oper_reset (vjbd_main_t * bdm, u32 bd_id)
364{
365 u16 bd_index;
366 u32 si, len;
367 vjbd_oper_t * bd_oper;
368 u32 end;
369
370 if (!bdm->bd_oper)
371 {
372 ASSERT (vec_len (bdm->sw_if_oper) == 0);
373 return;
374 }
375
376 if (bd_id == ~0)
377 {
378 bdm->bd_oper_last_sync_all_time = 0.0;
379 bd_index = 0;
380 end = vec_len (bdm->bd_oper);
381 }
382 else
383 {
384 bd_index = vjbd_index_from_id (bdm, bd_id);
385 end = bd_index + 1;
386 }
387
388 for (; bd_index < end; bd_index++)
389 {
390 bd_oper = vec_elt_at_index (bdm->bd_oper, bd_index);
391 bd_oper->last_sync_time = 0.0;
392
393 len = vec_len (bdm->sw_if_oper);
394 for (si = vjbd_sw_if_oper_next_index (bdm, 0, bd_id);
395 (si != ~0) && (si < len);
396 si = vjbd_sw_if_oper_next_index (bdm, si + 1, bd_id))
397 {
398 bd_sw_if_oper_t * bd_sw_if_oper;
399
400 bd_sw_if_oper = vec_elt_at_index (bdm->sw_if_oper, si);
401 bd_sw_if_oper->bd_id = ~0;
402 }
403 }
404}
405
406static_always_inline void
407vjbd_sw_if_add_del (u32 sw_if_index ,u32 bd_id, u8 bvi, u8 shg, u8 is_add)
408{
409 vjbd_main_t * bdm = &vjbd_main;
410 u16 bd_index = vjbd_index_from_id (bdm, bd_id);
411 vjbd_oper_t * bd_oper = vec_elt_at_index (bdm->bd_oper, bd_index);
412 bd_sw_if_oper_t * bd_sw_if_oper;
413
414 ASSERT (vjbd_id_is_valid (bdm, bd_id));
415 /* DAW-FIXME
416 ASSERT (ovam_sw_if_index_valid (ovam_get_main (), sw_if_index));
417 */
418
419 vec_validate (bdm->sw_if_oper, sw_if_index);
420 bd_sw_if_oper = vec_elt_at_index (bdm->sw_if_oper, sw_if_index);
421 if (is_add)
422 {
423 bd_sw_if_oper->bd_id = bd_id;
424 bd_sw_if_oper->shg = shg;
425 bd_oper->bvi_sw_if_index = bvi ? sw_if_index : ~0;
426 }
427 else
428 {
429 bd_sw_if_oper->bd_id = 0;
430 bd_sw_if_oper->shg = 0;
431 if (bd_oper->bvi_sw_if_index == sw_if_index)
432 bd_oper->bvi_sw_if_index = ~0;
433 }
434}
435
436static_always_inline u32 vjbd_id_sw_if_count (vjbd_main_t * bdm, u32 bd_id)
437{
438 u32 count = 0, i, end = vec_len (bdm->sw_if_oper);
439
440 if (vjbd_id_is_valid (bdm, bd_id))
441 for (count = i = 0; i < end; i++)
442 if (bdm->sw_if_oper[i].bd_id == bd_id)
443 count++;
444
445 return count;
446}
447
448static_always_inline u32 vjbd_find_or_add_bd (vjbd_main_t * bdm, u8 * bd_name)
449{
450 u16 bd_index;
451 u32 bd_id;
452 bd_local_cfg_t * bd_local_cfg;
453 uword mhash_val_bd_id;
454
455 bd_id = vjbd_id_from_name (bdm, bd_name);
456 if (bd_id != ~0)
457 return bd_id;
458
459 mhash_val_bd_id = bd_id = ++bdm->next_bd_id;
460 mhash_set_mem (&bdm->bd_id_by_name, (void *)bd_name, &mhash_val_bd_id, 0);
461
462 bd_index = clib_bitmap_first_clear (bdm->bd_index_bitmap);
463 vec_validate (bdm->local_cfg, bd_index);
464 vec_validate (bdm->bd_oper, bd_index);
465
466 ASSERT (vjbd_index_is_free (bdm, bd_index));
467
468 bd_local_cfg = vec_elt_at_index (bdm->local_cfg, bd_index);
469 bd_local_cfg->bd_id = bd_id;
470 vec_validate_init_c_string (bd_local_cfg->bd_name, bd_name,
471 vec_len (bd_name) - 1);
472 hash_set (bdm->bd_index_by_id, bd_id, bd_index);
473 bdm->bd_index_bitmap = clib_bitmap_set (bdm->bd_index_bitmap,
474 bd_index, 1);
475 return bd_id;
476}
477
478static_always_inline void vjbd_delete_bd (vjbd_main_t * bdm, u32 bd_id)
479{
480 u16 bd_index;
481 bd_local_cfg_t * bd_local_cfg;
482
483 ASSERT (vjbd_id_is_valid (bdm, bd_id));
484
485 // bd must not have any members before deleting
486 ASSERT (!vjbd_id_sw_if_count (bdm, bd_id));
487
488 bd_index = vjbd_index_from_id (bdm, bd_id);
489 bd_local_cfg = vec_elt_at_index (bdm->local_cfg, bd_index);
490 vjbd_oper_reset (bdm, bd_id);
491
492 mhash_unset (&bdm->bd_id_by_name, vjbd_name_from_id (bdm, bd_id), 0);
493 bdm->bd_index_bitmap = clib_bitmap_set (bdm->bd_index_bitmap,
494 bd_index, 0);
495 hash_unset (bdm->bd_index_by_id, bd_id);
496 bd_local_cfg->bd_id = ~0;
497 vec_validate_init_c_string (bd_local_cfg->bd_name, "", 0);
498
499 if (clib_bitmap_is_zero (bdm->bd_index_bitmap))
500 {
501 vec_reset_length (bdm->local_cfg);
502 vec_reset_length (bdm->bd_oper);
503 }
504
505 /* Force a resync of all bd_oper data. */
506 bdm->bd_oper_last_sync_all_time = 0.0;
507 vjbd_oper_maybe_sync_from_vpp (bdm, ~0);
508}
509
510#endif /* __included_vppjni_vpp_bridge_domain_h__ */