FD.io VPP  v16.06
Vector Packet Processing
vppjni_bridge_domain.h
Go to the documentation of this file.
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 {
34  } fields;
36  };
38 
39 /*
40  * The l2fib entry results
41  */
42 typedef struct {
46  u8 learned:1;
47  u8 bvi:1;
48  u8 filter:1; // drop packets to/from this mac
49  u8 unused1:5;
51 
52 typedef struct {
56 
57 typedef struct {
62 
63 typedef struct {
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;
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 {
87  bd_local_cfg_t * local_cfg; // vector indexed by bd_index
88  vjbd_oper_t * bd_oper; // vector indexed by oper_bd_index
90  bd_sw_if_oper_t * sw_if_oper; // vector indexed by sw_if_index
94 } vjbd_main_t;
95 
96 extern vjbd_main_t vjbd_main;
97 
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 
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 
127 {
128  return ((bd_id != 0) && (bd_id != ~0) && (bd_id <= bdm->next_bd_id));
129 }
130 
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 
141 {
142  return (clib_bitmap_get (bdm->bd_index_bitmap, bd_index) &&
143  (bd_index < vec_len (bdm->local_cfg)));
144 }
145 
147  const u8 * bd_name)
148 {
149  u32 bd_id;
150  uword * p;
151 
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 
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 
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 
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 
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 
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 
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) >
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) >
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 
254  u32 sw_if_index)
255 {
256  bd_sw_if_oper_t * bd_sw_if_oper;
257  u32 bd_id = ~0;
258 
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 
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  */
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 
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 
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 
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 
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) >
345  {
346  ovam_l2fib_table_dump ();
347  bdm->l2fib_oper_last_sync_time = ovam_time_now (ovam);
348  }
349 #endif
350 }
351 
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 
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 
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 
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 
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);
474  bd_index, 1);
475  return bd_id;
476 }
477 
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);
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 
500  {
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;
508 }
509 
510 #endif /* __included_vppjni_vpp_bridge_domain_h__ */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:394
Definition: mhash.h:46
#define hash_set(h, key, value)
Definition: hash.h:237
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
#define vec_c_string_is_terminated(V)
Test whether a vector is a NULL terminated c-string.
Definition: vec.h:924
#define hash_unset(h, key)
Definition: hash.h:243
always_inline void mhash_init_vec_string(mhash_t *h, uword n_value_bytes)
Definition: mhash.h:81
static_always_inline u32 vjbd_oper_l2fib_index_from_mac(vjbd_oper_t *bd_oper, u8 *mac)
uword * bd_id_by_sw_if_index
uword mhash_unset(mhash_t *h, void *key, uword *old_value)
Definition: mhash.c:350
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static_always_inline u32 vjbd_local_cfg_next_id(vjbd_main_t *bdm, u32 bd_id)
static_always_inline void vjbd_delete_bd(vjbd_main_t *bdm, u32 bd_id)
static_always_inline void vjbd_l2fib_oper_reset(vjbd_main_t *bdm)
#define static_always_inline
Definition: clib.h:85
static_always_inline u32 vjbd_id_sw_if_count(vjbd_main_t *bdm, u32 bd_id)
static_always_inline u32 vjbd_index_from_id(vjbd_main_t *bdm, u32 bd_id)
#define always_inline
Definition: clib.h:84
bd_sw_if_oper_t * sw_if_oper
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static_always_inline u32 vjbd_index_is_free(vjbd_main_t *bdm, u16 bd_index)
unsigned long u64
Definition: types.h:89
static_always_inline u32 vjbd_id_from_index(vjbd_main_t *bdm, u16 bd_index)
static_always_inline u8 * vjbd_name_from_id(vjbd_main_t *bdm, u32 bd_id)
l2fib_u64_mac_t mac_addr
static_always_inline void vjbd_main_init(vjbd_main_t *bdm)
#define BD_OPER_L2FIB_REFRESH_INTERVAL
static_always_inline void vjbd_oper_maybe_sync_from_vpp(vjbd_main_t *bdm, u32 bd_id)
#define hash_get(h, key)
Definition: hash.h:231
always_inline uword clib_bitmap_first_clear(uword *ai)
Definition: bitmap.h:343
uword mhash_set_mem(mhash_t *h, void *key, uword *new_value, uword *old_value)
Definition: mhash.c:272
vjbd_main_t vjbd_main
always_inline uword * clib_bitmap_set(uword *ai, uword i, uword value)
Definition: bitmap.h:132
static_always_inline u32 vjbd_id_from_name(vjbd_main_t *bdm, const u8 *bd_name)
always_inline uword clib_bitmap_get(uword *ai, uword i)
Definition: bitmap.h:158
static_always_inline u8 * vjbd_name_from_sw_if_index(vjbd_main_t *bdm, u32 sw_if_index)
vjbd_oper_t * bd_oper
bd_sw_if_oper_t * bd_sw_if_oper
void mhash_init(mhash_t *h, uword n_value_bytes, uword n_key_bytes)
Definition: mhash.c:169
static_always_inline void vjbd_oper_l2fib_maybe_sync_from_vpp(vjbd_main_t *bdm)
static_always_inline void vjbd_oper_reset(vjbd_main_t *bdm, u32 bd_id)
static_always_inline u32 vjbd_id_is_valid(vjbd_main_t *bdm, u32 bd_id)
static_always_inline u32 vjbd_find_or_add_bd(vjbd_main_t *bdm, u8 *bd_name)
static_always_inline u8 * vjbd_oper_name_from_id(vjbd_main_t *bdm, u32 bd_id)
static_always_inline u32 vjbd_id_from_sw_if_index(vjbd_main_t *bdm, u32 sw_if_index)
#define vec_validate_init_c_string(V, S, L)
Make a vector containing a NULL terminated c-string.
Definition: vec.h:909
#define hash_create(elts, value_bytes)
Definition: hash.h:615
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
uword * oper_bd_index_by_bd_id
static_always_inline u32 vjbd_sw_if_oper_next_index(vjbd_main_t *bdm, u32 start, u32 bd_id)
#define MAC_ADDRESS_SIZE
u64 uword
Definition: types.h:112
always_inline uword clib_bitmap_is_zero(uword *ai)
Definition: bitmap.h:50
mhash_t l2fib_index_by_mac
unsigned short u16
Definition: types.h:57
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:140
unsigned char u8
Definition: types.h:56
always_inline u64 l2fib_mac_to_u64(u8 *mac_address)
static_always_inline void vjbd_sw_if_add_del(u32 sw_if_index, u32 bd_id, u8 bvi, u8 shg, u8 is_add)
static_always_inline u32 vjbd_index_is_valid(vjbd_main_t *bdm, u16 bd_index)
#define vec_foreach(var, vec)
Vector iterator.
bd_local_cfg_t * local_cfg
bd_l2fib_oper_t * l2fib_oper
static_always_inline vjbd_oper_t * vjbd_oper_from_id(vjbd_main_t *bdm, u32 bd_id)
#define BD_OPER_REFRESH_INTERVAL
always_inline uword * mhash_get(mhash_t *h, void *key)
Definition: mhash.h:104