delete loopback interface cli
[vpp.git] / vpp-api / java / japi / vppjni_bridge_domain.h
1 /*---------------------------------------------------------------------------
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
29 typedef 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  */
42 typedef 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
52 typedef struct {
53   u32 bd_id;
54   u8 * bd_name;
55 } bd_local_cfg_t;
56
57 typedef struct {
58   u32 bd_id;
59   u32 sw_if_index;
60   u32 shg;
61 } bd_sw_if_oper_t;
62
63 typedef 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
82 typedef 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
96 extern vjbd_main_t vjbd_main;
97
98 always_inline
99 u64 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
118 static_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
126 static_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
131 static_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
140 static_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
146 static_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
169 static_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
186 static_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
199 static_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
206 static_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
215 static_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
222 static_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
253 static_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
269 static_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
289 static_always_inline u32 
290 vjbd_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
307 static_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
325 static_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
338 static_always_inline void 
339 vjbd_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
352 static_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
363 static_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
406 static_always_inline void 
407 vjbd_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
436 static_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
448 static_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
478 static_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__ */