FD.io VPP  v17.10-9-gd594711
Vector Packet Processing
l2_fib.c
Go to the documentation of this file.
1 /*
2  * l2_fib.c : layer 2 forwarding table (aka mac table)
3  *
4  * Copyright (c) 2013 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 
19 #include <vlib/vlib.h>
20 #include <vnet/vnet.h>
21 #include <vnet/pg/pg.h>
22 #include <vnet/ethernet/ethernet.h>
23 #include <vlib/cli.h>
24 
25 #include <vppinfra/error.h>
26 #include <vppinfra/hash.h>
27 #include <vnet/l2/l2_input.h>
28 #include <vnet/l2/l2_fib.h>
29 #include <vnet/l2/l2_learn.h>
30 #include <vnet/l2/l2_bd.h>
31 
33 
34 #include <vlibmemory/api.h>
35 #include <vnet/vnet_msg_enum.h>
36 
37 #define vl_typedefs /* define message structures */
38 #include <vnet/vnet_all_api_h.h>
39 #undef vl_typedefs
40 
41 #define vl_endianfun /* define message structures */
42 #include <vnet/vnet_all_api_h.h>
43 #undef vl_endianfun
44 
45 /**
46  * @file
47  * @brief Ethernet MAC Address FIB Table Management.
48  *
49  * The MAC Address forwarding table for bridge-domains is called the l2fib.
50  * Entries are added automatically as part of mac learning, but MAC Addresses
51  * entries can also be added manually.
52  *
53  */
54 
56 
57 /** Format sw_if_index. If the value is ~0, use the text "N/A" */
58 u8 *
60 {
61  vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
62  u32 sw_if_index = va_arg (*args, u32);
63  if (sw_if_index == ~0)
64  return format (s, "N/A");
65 
66  vnet_sw_interface_t *swif = vnet_get_sw_interface_safe (vnm, sw_if_index);
67  if (!swif)
68  return format (s, "Stale");
69 
70  return format (s, "%U", format_vnet_sw_interface_name, vnm,
71  vnet_get_sw_interface_safe (vnm, sw_if_index));
72 }
73 
74 void
75 l2fib_table_dump (u32 bd_index, l2fib_entry_key_t ** l2fe_key,
76  l2fib_entry_result_t ** l2fe_res)
77 {
78  l2fib_main_t *msm = &l2fib_main;
79  BVT (clib_bihash) * h = &msm->mac_table;
80  BVT (clib_bihash_bucket) * b;
83  l2fib_entry_result_t result;
84  int i, j, k;
85 
86  for (i = 0; i < h->nbuckets; i++)
87  {
88  b = &h->buckets[i];
89  if (b->offset == 0)
90  continue;
91  v = BV (clib_bihash_get_value) (h, b->offset);
92  for (j = 0; j < (1 << b->log2_pages); j++)
93  {
94  for (k = 0; k < BIHASH_KVP_PER_PAGE; k++)
95  {
96  if (v->kvp[k].key == ~0ULL && v->kvp[k].value == ~0ULL)
97  continue;
98 
99  key.raw = v->kvp[k].key;
100  result.raw = v->kvp[k].value;
101 
102  if ((bd_index == ~0) || (bd_index == key.fields.bd_index))
103  {
104  vec_add1 (*l2fe_key, key);
105  vec_add1 (*l2fe_res, result);
106  }
107  }
108  v++;
109  }
110  }
111 }
112 
113 /** Display the contents of the l2fib. */
114 static clib_error_t *
116  unformat_input_t * input, vlib_cli_command_t * cmd)
117 {
118  bd_main_t *bdm = &bd_main;
119  l2fib_main_t *msm = &l2fib_main;
120  l2_bridge_domain_t *bd_config;
121  BVT (clib_bihash) * h = &msm->mac_table;
122  BVT (clib_bihash_bucket) * b;
123  BVT (clib_bihash_value) * v;
124  l2fib_entry_key_t key;
125  l2fib_entry_result_t result;
126  u32 first_entry = 1;
127  u64 total_entries = 0;
128  int i, j, k;
129  u8 verbose = 0;
130  u8 raw = 0;
131  u8 learn = 0;
132  u32 bd_id, bd_index = ~0;
133  u8 now = (u8) (vlib_time_now (vm) / 60);
134  u8 *s = 0;
135 
136  if (unformat (input, "raw"))
137  raw = 1;
138  else if (unformat (input, "verbose"))
139  verbose = 1;
140  else if (unformat (input, "bd_index %d", &bd_index))
141  verbose = 1;
142  else if (unformat (input, "learn"))
143  {
144  learn = 1;
145  verbose = 0;
146  }
147  else if (unformat (input, "bd_id %d", &bd_id))
148  {
149  uword *p = hash_get (bdm->bd_index_by_bd_id, bd_id);
150  if (p)
151  {
152  if (learn == 0)
153  verbose = 1;
154  bd_index = p[0];
155  }
156  else
157  {
158  vlib_cli_output (vm, "no such bridge domain id");
159  return 0;
160  }
161  }
162 
163  for (i = 0; i < h->nbuckets; i++)
164  {
165  b = &h->buckets[i];
166  if (b->offset == 0)
167  continue;
168  v = BV (clib_bihash_get_value) (h, b->offset);
169  for (j = 0; j < (1 << b->log2_pages); j++)
170  {
171  for (k = 0; k < BIHASH_KVP_PER_PAGE; k++)
172  {
173  if (v->kvp[k].key == ~0ULL && v->kvp[k].value == ~0ULL)
174  continue;
175 
176  if ((verbose || learn) && first_entry)
177  {
178  first_entry = 0;
179  vlib_cli_output (vm,
180  "%=19s%=7s%=7s%=8s%=9s%=7s%=7s%=5s%=30s",
181  "Mac-Address", "BD-Idx", "If-Idx",
182  "BSN-ISN", "Age(min)", "static", "filter",
183  "bvi", "Interface-Name");
184  }
185 
186  key.raw = v->kvp[k].key;
187  result.raw = v->kvp[k].value;
188 
189  if ((verbose || learn)
190  & ((bd_index >> 31) || (bd_index == key.fields.bd_index)))
191  {
192  if (learn && result.fields.age_not)
193  {
194  total_entries++;
195  continue; /* skip provisioned macs */
196  }
197 
199  key.fields.bd_index);
200 
201  if (bd_config->mac_age && !result.fields.age_not)
202  {
203  i16 delta = now - result.fields.timestamp;
204  delta += delta < 0 ? 256 : 0;
205  s = format (s, "%d", delta);
206  }
207  else
208  s = format (s, "-");
209 
210  vlib_cli_output (vm,
211  "%=19U%=7d%=7d %3d/%-3d%=9v%=7s%=7s%=5s%=30U",
213  key.fields.bd_index,
214  result.fields.sw_if_index == ~0
215  ? -1 : result.fields.sw_if_index,
216  result.fields.sn.bd, result.fields.sn.swif,
217  s, result.fields.static_mac ? "*" : "-",
218  result.fields.filter ? "*" : "-",
219  result.fields.bvi ? "*" : "-",
221  msm->vnet_main, result.fields.sw_if_index);
222  vec_reset_length (s);
223  }
224  total_entries++;
225  }
226  v++;
227  }
228  }
229 
230  if (total_entries == 0)
231  vlib_cli_output (vm, "no l2fib entries");
232  else
233  {
235  vlib_cli_output (vm, "L2FIB total/learned entries: %d/%d "
236  "Last scan time: %.4esec Learn limit: %d ",
237  total_entries, lm->global_learn_count,
239  if (lm->client_pid)
240  vlib_cli_output (vm, "L2MAC events client PID: %d "
241  "Last e-scan time: %.4esec Delay: %.2esec "
242  "Max macs in event: %d",
243  lm->client_pid, msm->evt_scan_duration,
245  }
246 
247  if (raw)
248  vlib_cli_output (vm, "Raw Hash Table:\n%U\n",
249  BV (format_bihash), h, 1 /* verbose */ );
250 
251  vec_free (s);
252  return 0;
253 }
254 
255 /*?
256  * This command dispays the MAC Address entries of the L2 FIB table.
257  * Output can be filtered to just get the number of MAC Addresses or display
258  * each MAC Address for all bridge domains or just a single bridge domain.
259  *
260  * @cliexpar
261  * Example of how to display the number of MAC Address entries in the L2
262  * FIB table:
263  * @cliexstart{show l2fib}
264  * 3 l2fib entries
265  * @cliexend
266  * Example of how to display all the MAC Address entries in the L2
267  * FIB table:
268  * @cliexstart{show l2fib verbose}
269  * Mac Address BD Idx Interface Index static filter bvi refresh timestamp
270  * 52:54:00:53:18:33 1 GigabitEthernet0/8/0.200 3 0 0 0 0 0
271  * 52:54:00:53:18:55 1 GigabitEthernet0/8/0.200 3 1 0 0 0 0
272  * 52:54:00:53:18:77 1 N/A -1 1 1 0 0 0
273  * 3 l2fib entries
274  * @cliexend
275 ?*/
276 /* *INDENT-OFF* */
277 VLIB_CLI_COMMAND (show_l2fib_cli, static) = {
278  .path = "show l2fib",
279  .short_help = "show l2fib [verbose | learn | bd_id <nn> | bd_index <nn> | raw",
280  .function = show_l2fib,
281 };
282 /* *INDENT-ON* */
283 
284 
285 /* Remove all entries from the l2fib */
286 void
288 {
289  l2fib_main_t *mp = &l2fib_main;
290 
291  /* Remove all entries */
292  BV (clib_bihash_free) (&mp->mac_table);
293  BV (clib_bihash_init) (&mp->mac_table, "l2fib mac table",
296 }
297 
298 /** Clear all entries in L2FIB.
299  * @TODO: Later we may want a way to remove only the non-static entries
300  */
301 static clib_error_t *
303  unformat_input_t * input, vlib_cli_command_t * cmd)
304 {
306  return 0;
307 }
308 
309 /*?
310  * This command clears all the MAC Address entries from the L2 FIB table.
311  *
312  * @cliexpar
313  * Example of how to clear the L2 FIB Table:
314  * @cliexcmd{clear l2fib}
315  * Example to show the L2 FIB Table has been cleared:
316  * @cliexstart{show l2fib verbose}
317  * no l2fib entries
318  * @cliexend
319 ?*/
320 /* *INDENT-OFF* */
321 VLIB_CLI_COMMAND (clear_l2fib_cli, static) = {
322  .path = "clear l2fib",
323  .short_help = "clear l2fib",
324  .function = clear_l2fib,
325 };
326 /* *INDENT-ON* */
327 
328 static inline l2fib_seq_num_t
329 l2fib_cur_seq_num (u32 bd_index, u32 sw_if_index)
330 {
331  l2_bridge_domain_t *bd_config = l2input_bd_config (bd_index);
332  /* *INDENT-OFF* */
333  return (l2fib_seq_num_t) {
334  .swif = *l2fib_swif_seq_num (sw_if_index),
335  .bd = bd_config->seq_num,
336  };
337  /* *INDENT-ON* */
338 }
339 
340 /**
341  * Add an entry to the l2fib.
342  * If the entry already exists then overwrite it
343  */
344 void
345 l2fib_add_entry (u64 mac, u32 bd_index,
346  u32 sw_if_index, u8 static_mac, u8 filter_mac, u8 bvi_mac)
347 {
348  l2fib_entry_key_t key;
349  l2fib_entry_result_t result;
350  __attribute__ ((unused)) u32 bucket_contents;
351  l2fib_main_t *fm = &l2fib_main;
353  BVT (clib_bihash_kv) kv;
354 
355  /* set up key */
356  key.raw = l2fib_make_key ((u8 *) & mac, bd_index);
357 
358  /* check if entry alread exist */
359  if (BV (clib_bihash_search) (&fm->mac_table, &kv, &kv))
360  {
361  /* decrement counter if overwriting a learned mac */
362  result.raw = kv.value;
363  if ((result.fields.age_not == 0) && (lm->global_learn_count))
364  lm->global_learn_count--;
365  }
366 
367  /* set up result */
368  result.raw = 0; /* clear all fields */
369  result.fields.sw_if_index = sw_if_index;
370  result.fields.static_mac = static_mac;
371  result.fields.filter = filter_mac;
372  result.fields.bvi = bvi_mac;
373  result.fields.age_not = 1; /* no aging for provisioned entry */
374 
375  kv.key = key.raw;
376  kv.value = result.raw;
377 
378  BV (clib_bihash_add_del) (&fm->mac_table, &kv, 1 /* is_add */ );
379 }
380 
381 /**
382  * Add an entry to the L2FIB.
383  * The CLI format is:
384  * l2fib add <mac> <bd> <intf> [static] [bvi]
385  * l2fib add <mac> <bd> filter
386  * Note that filter and bvi entries are always static
387  */
388 static clib_error_t *
390  unformat_input_t * input, vlib_cli_command_t * cmd)
391 {
392  bd_main_t *bdm = &bd_main;
393  vnet_main_t *vnm = vnet_get_main ();
394  clib_error_t *error = 0;
395  u64 mac;
396  u32 bd_id;
397  u32 bd_index;
398  u32 sw_if_index = ~0;
399  u32 filter_mac = 0;
400  u32 static_mac = 0;
401  u32 bvi_mac = 0;
402  uword *p;
403 
404  if (!unformat_user (input, unformat_ethernet_address, &mac))
405  {
406  error = clib_error_return (0, "expected mac address `%U'",
407  format_unformat_error, input);
408  goto done;
409  }
410 
411  if (!unformat (input, "%d", &bd_id))
412  {
413  error = clib_error_return (0, "expected bridge domain ID `%U'",
414  format_unformat_error, input);
415  goto done;
416  }
417 
418  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
419  if (!p)
420  {
421  error = clib_error_return (0, "bridge domain ID %d invalid", bd_id);
422  goto done;
423  }
424  bd_index = p[0];
425 
426  if (unformat (input, "filter"))
427  {
428  filter_mac = 1;
429  static_mac = 1;
430 
431  }
432  else
433  {
434 
435  if (!unformat_user
436  (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
437  {
438  error = clib_error_return (0, "unknown interface `%U'",
439  format_unformat_error, input);
440  goto done;
441  }
442  if (unformat (input, "static"))
443  {
444  static_mac = 1;
445  }
446  else if (unformat (input, "bvi"))
447  {
448  bvi_mac = 1;
449  static_mac = 1;
450  }
451  }
452 
453  if (vec_len (l2input_main.configs) <= sw_if_index)
454  {
455  error = clib_error_return (0, "Interface sw_if_index %d not in L2 mode",
456  sw_if_index);
457  goto done;
458  }
459 
460  if (filter_mac)
461  l2fib_add_filter_entry (mac, bd_index);
462  else
463  l2fib_add_fwd_entry (mac, bd_index, sw_if_index, static_mac, bvi_mac);
464 
465 done:
466  return error;
467 }
468 
469 /*?
470  * This command adds a MAC Address entry to the L2 FIB table
471  * of an existing bridge-domain. The MAC Address can be static
472  * or dynamic. This command also allows a filter to be added,
473  * such that packets with given MAC Addresses (source mac or
474  * destination mac match) are dropped.
475  *
476  * @cliexpar
477  * Example of how to add a dynamic MAC Address entry to the L2 FIB table
478  * of a bridge-domain (where 200 is the bridge-domain-id):
479  * @cliexcmd{l2fib add 52:54:00:53:18:33 200 GigabitEthernet0/8/0.200}
480  * Example of how to add a static MAC Address entry to the L2 FIB table
481  * of a bridge-domain (where 200 is the bridge-domain-id):
482  * @cliexcmd{l2fib add 52:54:00:53:18:55 200 GigabitEthernet0/8/0.200 static}
483  * Example of how to add a filter such that a packet with the given MAC
484  * Address will be dropped in a given bridge-domain (where 200 is the
485  * bridge-domain-id):
486  * @cliexcmd{l2fib add 52:54:00:53:18:77 200 filter}
487  * Example of show command of the provisioned MAC Addresses and filters:
488  * @cliexstart{show l2fib verbose}
489  * Mac Address BD Idx Interface Index static filter bvi refresh timestamp
490  * 52:54:00:53:18:33 1 GigabitEthernet0/8/0.200 3 0 0 0 0 0
491  * 52:54:00:53:18:55 1 GigabitEthernet0/8/0.200 3 1 0 0 0 0
492  * 52:54:00:53:18:77 1 N/A -1 1 1 0 0 0
493  * 3 l2fib entries
494  * @cliexend
495 ?*/
496 /* *INDENT-OFF* */
497 VLIB_CLI_COMMAND (l2fib_add_cli, static) = {
498  .path = "l2fib add",
499  .short_help = "l2fib add <mac> <bridge-domain-id> filter | <intf> [static | bvi]",
500  .function = l2fib_add,
501 };
502 /* *INDENT-ON* */
503 
504 
505 static clib_error_t *
507  unformat_input_t * input, vlib_cli_command_t * cmd)
508 {
509  clib_error_t *error = 0;
510  u64 mac, save_mac;
511  u32 bd_index = 0;
512  u32 sw_if_index = 8;
513  u32 bvi_mac = 0;
514  u32 is_add = 0;
515  u32 is_del = 0;
516  u32 is_check = 0;
517  u32 count = 1;
518  int mac_set = 0;
519  int i;
520 
522  {
523  if (unformat (input, "mac %U", unformat_ethernet_address, &mac))
524  mac_set = 1;
525  else if (unformat (input, "add"))
526  is_add = 1;
527  else if (unformat (input, "del"))
528  is_del = 1;
529  else if (unformat (input, "check"))
530  is_check = 1;
531  else if (unformat (input, "count %d", &count))
532  ;
533  else
534  break;
535  }
536 
537  if (mac_set == 0)
538  return clib_error_return (0, "mac not set");
539 
540  if (is_add == 0 && is_del == 0 && is_check == 0)
541  return clib_error_return (0,
542  "noop: pick at least one of (add,del,check)");
543 
544  save_mac = mac;
545 
546  if (is_add)
547  {
548  for (i = 0; i < count; i++)
549  {
550  u64 tmp;
551  l2fib_add_fwd_entry (mac, bd_index, sw_if_index, mac, bvi_mac);
552  tmp = clib_net_to_host_u64 (mac);
553  tmp >>= 16;
554  tmp++;
555  tmp <<= 16;
556  mac = clib_host_to_net_u64 (tmp);
557  }
558  }
559 
560  if (is_check)
561  {
562  BVT (clib_bihash_kv) kv;
563  l2fib_main_t *mp = &l2fib_main;
564 
565  mac = save_mac;
566 
567  for (i = 0; i < count; i++)
568  {
569  u64 tmp;
570  kv.key = l2fib_make_key ((u8 *) & mac, bd_index);
571  if (BV (clib_bihash_search) (&mp->mac_table, &kv, &kv))
572  {
573  clib_warning ("key %U AWOL", format_ethernet_address, &mac);
574  break;
575  }
576  tmp = clib_net_to_host_u64 (mac);
577  tmp >>= 16;
578  tmp++;
579  tmp <<= 16;
580  mac = clib_host_to_net_u64 (tmp);
581  }
582  }
583 
584  if (is_del)
585  {
586  for (i = 0; i < count; i++)
587  {
588  u64 tmp;
589 
590  l2fib_del_entry (mac, bd_index);
591 
592  tmp = clib_net_to_host_u64 (mac);
593  tmp >>= 16;
594  tmp++;
595  tmp <<= 16;
596  mac = clib_host_to_net_u64 (tmp);
597  }
598  }
599 
600  return error;
601 }
602 
603 /*?
604  * The set of '<em>test l2fib</em>' commands allow the L2 FIB table of the default
605  * bridge domain (bridge-domain-id of 0) to be modified.
606  *
607  * @cliexpar
608  * @parblock
609  * Example of how to add a set of 4 sequential MAC Address entries to L2
610  * FIB table of the default bridge-domain:
611  * @cliexcmd{test l2fib add mac 52:54:00:53:00:00 count 4}
612  *
613  * Show the set of 4 sequential MAC Address entries that were added:
614  * @cliexstart{show l2fib verbose}
615  * Mac Address BD Idx Interface Index static filter bvi refresh timestamp
616  * 52:54:00:53:00:00 0 GigabitEthernet0/8/0.300 8 0 0 0 0 0
617  * 52:54:00:53:00:01 0 GigabitEthernet0/8/0.300 8 0 0 0 0 0
618  * 52:54:00:53:00:03 0 GigabitEthernet0/8/0.300 8 0 0 0 0 0
619  * 52:54:00:53:00:02 0 GigabitEthernet0/8/0.300 8 0 0 0 0 0
620  * 4 l2fib entries
621  * @cliexend
622  *
623  * Example of how to check that the set of 4 sequential MAC Address
624  * entries were added to L2 FIB table of the default
625  * bridge-domain. Used a count of 5 to produce an error:
626  *
627  * @cliexcmd{test l2fib check mac 52:54:00:53:00:00 count 5}
628  * The output of the check command is in the log files. Log file
629  * location may vary based on your OS and Version:
630  *
631  * <b><em># tail -f /var/log/messages | grep l2fib_test_command_fn</em></b>
632  *
633  * Sep 7 17:15:24 localhost vnet[4952]: l2fib_test_command_fn:446: key 52:54:00:53:00:04 AWOL
634  *
635  * Example of how to delete a set of 4 sequential MAC Address entries
636  * from L2 FIB table of the default bridge-domain:
637  * @cliexcmd{test l2fib del mac 52:54:00:53:00:00 count 4}
638  * @endparblock
639 ?*/
640 /* *INDENT-OFF* */
641 VLIB_CLI_COMMAND (l2fib_test_command, static) = {
642  .path = "test l2fib",
643  .short_help = "test l2fib [add|del|check] mac <base-addr> count <nn>",
644  .function = l2fib_test_command_fn,
645 };
646 /* *INDENT-ON* */
647 
648 
649 /**
650  * Delete an entry from the l2fib.
651  * Return 0 if the entry was deleted, or 1 if it was not found
652  */
653 static u32
655 {
656 
657  l2fib_entry_result_t result;
658  l2fib_main_t *mp = &l2fib_main;
659  BVT (clib_bihash_kv) kv;
660 
661  /* set up key */
662  kv.key = raw_key;
663 
664  if (BV (clib_bihash_search) (&mp->mac_table, &kv, &kv))
665  return 1;
666 
667  result.raw = kv.value;
668 
669  /* decrement counter if dynamically learned mac */
670  if ((result.fields.age_not == 0) && (l2learn_main.global_learn_count))
672 
673  /* Remove entry from hash table */
674  BV (clib_bihash_add_del) (&mp->mac_table, &kv, 0 /* is_add */ );
675  return 0;
676 }
677 
678 /**
679  * Delete an entry from the l2fib.
680  * Return 0 if the entry was deleted, or 1 if it was not found
681  */
682 u32
683 l2fib_del_entry (u64 mac, u32 bd_index)
684 {
685  return l2fib_del_entry_by_key (l2fib_make_key ((u8 *) & mac, bd_index));
686 }
687 
688 /**
689  * Delete an entry from the L2FIB.
690  * The CLI format is:
691  * l2fib del <mac> <bd-id>
692  */
693 static clib_error_t *
695  unformat_input_t * input, vlib_cli_command_t * cmd)
696 {
697  bd_main_t *bdm = &bd_main;
698  clib_error_t *error = 0;
699  u64 mac;
700  u32 bd_id;
701  u32 bd_index;
702  uword *p;
703 
704  if (!unformat_user (input, unformat_ethernet_address, &mac))
705  {
706  error = clib_error_return (0, "expected mac address `%U'",
707  format_unformat_error, input);
708  goto done;
709  }
710 
711  if (!unformat (input, "%d", &bd_id))
712  {
713  error = clib_error_return (0, "expected bridge domain ID `%U'",
714  format_unformat_error, input);
715  goto done;
716  }
717 
718  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
719  if (!p)
720  {
721  error = clib_error_return (0, "bridge domain ID %d invalid", bd_id);
722  goto done;
723  }
724  bd_index = p[0];
725 
726  /* Delete the entry */
727  if (l2fib_del_entry (mac, bd_index))
728  {
729  error = clib_error_return (0, "mac entry not found");
730  goto done;
731  }
732 
733 done:
734  return error;
735 }
736 
737 /*?
738  * This command deletes an existing MAC Address entry from the L2 FIB
739  * table of an existing bridge-domain.
740  *
741  * @cliexpar
742  * Example of how to delete a MAC Address entry from the L2 FIB table of a bridge-domain (where 200 is the bridge-domain-id):
743  * @cliexcmd{l2fib del 52:54:00:53:18:33 200}
744 ?*/
745 /* *INDENT-OFF* */
746 VLIB_CLI_COMMAND (l2fib_del_cli, static) = {
747  .path = "l2fib del",
748  .short_help = "l2fib del <mac> <bridge-domain-id>",
749  .function = l2fib_del,
750 };
751 /* *INDENT-ON* */
752 
753 /**
754  Kick off ager to scan MACs to age/delete MAC entries
755 */
756 void
758 {
760 
761  /* check if there is at least one bd with mac aging enabled */
762  l2_bridge_domain_t *bd_config;
763  vec_foreach (bd_config, l2input_main.bd_configs)
764  {
765  if (bd_config->bd_id != ~0 && bd_config->mac_age != 0)
766  {
768  break;
769  }
770  }
771 
773  evt, 0);
774 }
775 
776 /**
777  Flush all non static MACs from an interface
778 */
779 void
781 {
782  *l2fib_swif_seq_num (sw_if_index) += 1;
784 }
785 
786 /**
787  Flush all non static MACs in a bridge domain
788 */
789 void
791 {
792  l2_bridge_domain_t *bd_config = l2input_bd_config (bd_index);
793  bd_config->seq_num += 1;
795 }
796 
797 /**
798  Flush all non static MACs - flushes all valid BDs
799 */
800 void
802 {
803  l2_bridge_domain_t *bd_config;
804  vec_foreach (bd_config, l2input_main.bd_configs)
805  if (bd_is_valid (bd_config))
806  bd_config->seq_num += 1;
807 
809 }
810 
811 
812 /**
813  Flush MACs, except static ones, associated with an interface
814  The CLI format is:
815  l2fib flush-mac interface <if-name>
816 */
817 static clib_error_t *
819  unformat_input_t * input, vlib_cli_command_t * cmd)
820 {
821  vnet_main_t *vnm = vnet_get_main ();
822  clib_error_t *error = 0;
823  u32 sw_if_index;
824 
825  if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
826  {
827  error = clib_error_return (0, "unknown interface `%U'",
828  format_unformat_error, input);
829  goto done;
830  }
831 
832  l2fib_flush_int_mac (vm, sw_if_index);
833 
834 done:
835  return error;
836 }
837 
838 /**
839  Flush all MACs, except static ones
840  The CLI format is:
841  l2fib flush-mac all
842 */
843 static clib_error_t *
845  unformat_input_t * input, vlib_cli_command_t * cmd)
846 {
847  l2fib_flush_all_mac (vm);
848  return 0;
849 }
850 
851 /*?
852  * This command kick off ager to delete all existing MAC Address entries,
853  * except static ones, associated with an interface from the L2 FIB table.
854  *
855  * @cliexpar
856  * Example of how to flush MAC Address entries learned on an interface from the L2 FIB table:
857  * @cliexcmd{l2fib flush-mac interface GigabitEthernet2/1/0}
858 ?*/
859 /* *INDENT-OFF* */
860 VLIB_CLI_COMMAND (l2fib_flush_mac_all_cli, static) = {
861  .path = "l2fib flush-mac all",
862  .short_help = "l2fib flush-mac all",
863  .function = l2fib_flush_mac_all,
864 };
865 /* *INDENT-ON* */
866 
867 /*?
868  * This command kick off ager to delete all existing MAC Address entries,
869  * except static ones, associated with an interface from the L2 FIB table.
870  *
871  * @cliexpar
872  * Example of how to flush MAC Address entries learned on an interface from the L2 FIB table:
873  * @cliexcmd{l2fib flush-mac interface GigabitEthernet2/1/0}
874 ?*/
875 /* *INDENT-OFF* */
876 VLIB_CLI_COMMAND (l2fib_flush_mac_int_cli, static) = {
877  .path = "l2fib flush-mac interface",
878  .short_help = "l2fib flush-mac interface <if-name>",
879  .function = l2fib_flush_mac_int,
880 };
881 /* *INDENT-ON* */
882 
883 /**
884  Flush bridge-domain MACs except static ones.
885  The CLI format is:
886  l2fib flush-mac bridge-domain <bd-id>
887 */
888 static clib_error_t *
890  unformat_input_t * input, vlib_cli_command_t * cmd)
891 {
892  bd_main_t *bdm = &bd_main;
893  clib_error_t *error = 0;
894  u32 bd_index, bd_id;
895  uword *p;
896 
897  if (!unformat (input, "%d", &bd_id))
898  {
899  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
900  format_unformat_error, input);
901  goto done;
902  }
903 
904  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
905  if (p)
906  bd_index = *p;
907  else
908  return clib_error_return (0, "No such bridge domain %d", bd_id);
909 
910  l2fib_flush_bd_mac (vm, bd_index);
911 
912 done:
913  return error;
914 }
915 
916 /*?
917  * This command kick off ager to delete all existing MAC Address entries,
918  * except static ones, in a bridge domain from the L2 FIB table.
919  *
920  * @cliexpar
921  * Example of how to flush MAC Address entries learned in a bridge domain from the L2 FIB table:
922  * @cliexcmd{l2fib flush-mac bridge-domain 1000}
923 ?*/
924 /* *INDENT-OFF* */
925 VLIB_CLI_COMMAND (l2fib_flush_mac_bd_cli, static) = {
926  .path = "l2fib flush-mac bridge-domain",
927  .short_help = "l2fib flush-mac bridge-domain <bd-id>",
928  .function = l2fib_flush_mac_bd,
929 };
930 /* *INDENT-ON* */
931 
932 clib_error_t *
934 {
935  l2_input_config_t *config = l2input_intf_config (sw_if_index);
936  if ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) == 0 && config->bridge)
937  l2fib_flush_int_mac (vnm->vlib_main, sw_if_index);
938  return 0;
939 }
940 
942 
943 BVT (clib_bihash) * get_mac_table (void)
944 {
945  l2fib_main_t *mp = &l2fib_main;
946  return &mp->mac_table;
947 }
948 
950 allocate_mac_evt_buf (u32 client, u32 client_index)
951 {
952  l2fib_main_t *fm = &l2fib_main;
954  (sizeof (*mp) + (fm->max_macs_in_event * sizeof (vl_api_mac_entry_t)));
955  mp->_vl_msg_id = htons (VL_API_L2_MACS_EVENT);
956  mp->pid = htonl (client);
957  mp->client_index = client_index;
958  return mp;
959 }
960 
962 l2fib_scan (vlib_main_t * vm, f64 start_time, u8 event_only)
963 {
964  l2fib_main_t *fm = &l2fib_main;
966 
967  BVT (clib_bihash) * h = &fm->mac_table;
968  int i, j, k;
969  f64 last_start = start_time;
970  f64 accum_t = 0;
971  f64 delta_t = 0;
972  u32 evt_idx = 0;
973  u32 learn_count = 0;
974  u32 client = lm->client_pid;
975  u32 cl_idx = lm->client_index;
976  vl_api_l2_macs_event_t *mp = 0;
978 
979  if (client)
980  {
981  mp = allocate_mac_evt_buf (client, cl_idx);
983  }
984 
985  for (i = 0; i < h->nbuckets; i++)
986  {
987  /* allow no more than 20us without a pause */
988  delta_t = vlib_time_now (vm) - last_start;
989  if (delta_t > 20e-6)
990  {
991  vlib_process_suspend (vm, 100e-6); /* suspend for 100 us */
992  last_start = vlib_time_now (vm);
993  accum_t += delta_t;
994  }
995 
996  if (i < (h->nbuckets - 3))
997  {
998  BVT (clib_bihash_bucket) * b = &h->buckets[i + 3];
1000  b = &h->buckets[i + 1];
1001  if (b->offset)
1002  {
1003  BVT (clib_bihash_value) * v =
1004  BV (clib_bihash_get_value) (h, b->offset);
1006  }
1007  }
1008 
1009  BVT (clib_bihash_bucket) * b = &h->buckets[i];
1010  if (b->offset == 0)
1011  continue;
1012  BVT (clib_bihash_value) * v = BV (clib_bihash_get_value) (h, b->offset);
1013  for (j = 0; j < (1 << b->log2_pages); j++)
1014  {
1015  for (k = 0; k < BIHASH_KVP_PER_PAGE; k++)
1016  {
1017  if (v->kvp[k].key == ~0ULL && v->kvp[k].value == ~0ULL)
1018  continue;
1019 
1020  l2fib_entry_key_t key = {.raw = v->kvp[k].key };
1021  l2fib_entry_result_t result = {.raw = v->kvp[k].value };
1022 
1023  if (result.fields.age_not == 0)
1024  learn_count++;
1025 
1026  if (client)
1027  {
1028  if (PREDICT_FALSE (evt_idx >= fm->max_macs_in_event))
1029  {
1030  /* event message full, send it and start a new one */
1031  if (q && (q->cursize < q->maxsize))
1032  {
1033  mp->n_macs = htonl (evt_idx);
1034  vl_msg_api_send_shmem (q, (u8 *) & mp);
1035  mp = allocate_mac_evt_buf (client, cl_idx);
1036  }
1037  else
1038  {
1039  clib_warning ("MAC event to pid %d queue stuffed!"
1040  " %d MAC entries lost", client,
1041  evt_idx);
1042  }
1043  evt_idx = 0;
1044  }
1045 
1046  if (result.fields.lrn_evt)
1047  {
1048  /* copy mac entry to event msg */
1049  clib_memcpy (mp->mac[evt_idx].mac_addr, key.fields.mac,
1050  6);
1051  mp->mac[evt_idx].is_del = 0;
1052  mp->mac[evt_idx].sw_if_index =
1053  htonl (result.fields.sw_if_index);
1054  /* clear event bit and update mac entry */
1055  result.fields.lrn_evt = 0;
1056  BVT (clib_bihash_kv) kv;
1057  kv.key = key.raw;
1058  kv.value = result.raw;
1059  BV (clib_bihash_add_del) (&fm->mac_table, &kv, 1);
1060  evt_idx++;
1061  continue; /* skip aging */
1062  }
1063  }
1064 
1065  if (event_only || result.fields.age_not)
1066  continue; /* skip aging - static_mac alsways age_not */
1067 
1068  /* start aging processing */
1069  u32 bd_index = key.fields.bd_index;
1070  u32 sw_if_index = result.fields.sw_if_index;
1071  u16 sn = l2fib_cur_seq_num (bd_index, sw_if_index).as_u16;
1072  if (result.fields.sn.as_u16 != sn)
1073  goto age_out; /* stale mac */
1074 
1075  l2_bridge_domain_t *bd_config =
1077 
1078  if (bd_config->mac_age == 0)
1079  continue; /* skip aging */
1080 
1081  i16 delta = (u8) (start_time / 60) - result.fields.timestamp;
1082  delta += delta < 0 ? 256 : 0;
1083 
1084  if (delta < bd_config->mac_age)
1085  continue; /* still valid */
1086 
1087  age_out:
1088  if (client)
1089  {
1090  /* copy mac entry to event msg */
1091  clib_memcpy (mp->mac[evt_idx].mac_addr, key.fields.mac, 6);
1092  mp->mac[evt_idx].is_del = 1;
1093  mp->mac[evt_idx].sw_if_index =
1094  htonl (result.fields.sw_if_index);
1095  evt_idx++;
1096  }
1097  /* delete mac entry */
1098  BVT (clib_bihash_kv) kv;
1099  kv.key = key.raw;
1100  BV (clib_bihash_add_del) (&fm->mac_table, &kv, 0);
1101  learn_count--;
1102  }
1103  v++;
1104  }
1105  }
1106 
1107  /* keep learn count consistent */
1108  l2learn_main.global_learn_count = learn_count;
1109 
1110  if (mp)
1111  {
1112  /* send any outstanding mac event message else free message buffer */
1113  if (evt_idx)
1114  {
1115  if (q && (q->cursize < q->maxsize))
1116  {
1117  mp->n_macs = htonl (evt_idx);
1118  vl_msg_api_send_shmem (q, (u8 *) & mp);
1119  }
1120  else
1121  {
1122  clib_warning ("MAC event to pid %d queue stuffed!"
1123  " %d MAC entries lost", client, evt_idx);
1124  vl_msg_api_free (mp);
1125  }
1126  }
1127  else
1128  vl_msg_api_free (mp);
1129  }
1130  return delta_t + accum_t;
1131 }
1132 
1133 /* Maximum f64 value */
1134 #define TIME_MAX (1.7976931348623157e+308)
1135 
1136 static uword
1138  vlib_frame_t * f)
1139 {
1140  uword event_type, *event_data = 0;
1141  l2fib_main_t *fm = &l2fib_main;
1143  bool enabled = 0;
1144  f64 start_time, next_age_scan_time = TIME_MAX;
1145 
1146  while (1)
1147  {
1148  if (lm->client_pid)
1150  else if (enabled)
1151  {
1152  f64 t = next_age_scan_time - vlib_time_now (vm);
1154  }
1155  else
1157 
1158  event_type = vlib_process_get_events (vm, &event_data);
1159  vec_reset_length (event_data);
1160 
1161  start_time = vlib_time_now (vm);
1162  enum
1163  { SCAN_MAC_AGE, SCAN_MAC_EVENT, SCAN_DISABLE } scan = SCAN_MAC_AGE;
1164 
1165  switch (event_type)
1166  {
1167  case ~0: /* timer expired */
1168  if (lm->client_pid != 0 && start_time < next_age_scan_time)
1169  scan = SCAN_MAC_EVENT;
1170  break;
1171 
1173  enabled = 1;
1174  break;
1175 
1177  enabled = 0;
1178  scan = SCAN_DISABLE;
1179  break;
1180 
1182  break;
1183 
1184  default:
1185  ASSERT (0);
1186  }
1187 
1188  if (scan == SCAN_MAC_EVENT)
1189  l2fib_main.evt_scan_duration = l2fib_scan (vm, start_time, 1);
1190  else
1191  {
1192  if (scan == SCAN_MAC_AGE)
1193  l2fib_main.age_scan_duration = l2fib_scan (vm, start_time, 0);
1194  if (scan == SCAN_DISABLE)
1195  {
1196  l2fib_main.age_scan_duration = 0;
1197  l2fib_main.evt_scan_duration = 0;
1198  }
1199  /* schedule next scan */
1200  if (enabled)
1201  next_age_scan_time = start_time + L2FIB_AGE_SCAN_INTERVAL;
1202  else
1203  next_age_scan_time = TIME_MAX;
1204  }
1205  }
1206  return 0;
1207 }
1208 
1209 /* *INDENT-OFF* */
1211  .function = l2fib_mac_age_scanner_process,
1212  .type = VLIB_NODE_TYPE_PROCESS,
1213  .name = "l2fib-mac-age-scanner-process",
1214 };
1215 /* *INDENT-ON* */
1216 
1217 clib_error_t *
1219 {
1220  l2fib_main_t *mp = &l2fib_main;
1221  l2fib_entry_key_t test_key;
1222  u8 test_mac[6];
1223 
1224  mp->vlib_main = vm;
1225  mp->vnet_main = vnet_get_main ();
1226 
1227  /* Create the hash table */
1228  BV (clib_bihash_init) (&mp->mac_table, "l2fib mac table",
1230 
1231  /* verify the key constructor is good, since it is endian-sensitive */
1232  memset (test_mac, 0, sizeof (test_mac));
1233  test_mac[0] = 0x11;
1234  test_key.raw = 0;
1235  test_key.raw = l2fib_make_key ((u8 *) & test_mac, 0x1234);
1236  ASSERT (test_key.fields.mac[0] == 0x11);
1237  ASSERT (test_key.fields.bd_index == 0x1234);
1238 
1239  return 0;
1240 }
1241 
1243 
1244 /*
1245  * fd.io coding-style-patch-verification: ON
1246  *
1247  * Local Variables:
1248  * eval: (c-set-style "gnu")
1249  * End:
1250  */
static_always_inline void * allocate_mac_evt_buf(u32 client, u32 client_index)
Definition: l2_fib.c:950
static void l2fib_add_fwd_entry(u64 mac, u32 bd_index, u32 sw_if_index, u8 static_mac, u8 bvi_mac)
Definition: l2_fib.h:379
f64 evt_scan_duration
Definition: l2_fib.h:52
static clib_error_t * l2fib_test_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2_fib.c:506
u32 global_learn_count
Definition: l2_learn.h:32
l2_input_config_t * configs
Definition: l2_input.h:66
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
u8 * format_vnet_sw_if_index_name_with_NA(u8 *s, va_list *args)
Format sw_if_index.
Definition: l2_fib.c:59
vlib_main_t * vlib_main
Definition: l2_fib.h:62
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:699
#define BIHASH_KVP_PER_PAGE
Definition: bihash_16_8.h:20
static uword * vlib_process_wait_for_event(vlib_main_t *vm)
Definition: node_funcs.h:619
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vnet_main_t * vnet_main
Definition: l2_fib.h:63
void clib_bihash_free(clib_bihash *h)
Destroy a bounded index extensible hash table.
l2_input_config_t * l2input_intf_config(u32 sw_if_index)
Get a pointer to the config for the given interface.
Definition: l2_input.c:524
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:221
u32 l2fib_del_entry(u64 mac, u32 bd_index)
Delete an entry from the l2fib.
Definition: l2_fib.c:683
clib_error_t * l2fib_init(vlib_main_t *vm)
Definition: l2_fib.c:1218
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:518
static_always_inline u8 * l2fib_swif_seq_num(u32 sw_if_index)
Definition: l2_fib.h:408
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
#define L2FIB_MEMORY_SIZE
Definition: l2_fib.h:28
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
unformat_function_t unformat_vnet_sw_interface
u32 max_macs_in_event
Definition: l2_fib.h:59
Definition: l2_fib.h:108
static clib_error_t * l2fib_del(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Delete an entry from the L2FIB.
Definition: l2_fib.c:694
u32 client_index
Definition: l2_learn.h:39
Entry for learned or aged MAC in L2 MAC Events.
Definition: l2.api:161
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static uword vlib_process_suspend(vlib_main_t *vm, f64 dt)
Suspend a vlib cooperative multi-tasking thread for a period of time.
Definition: node_funcs.h:448
#define L2FIB_AGE_SCAN_INTERVAL
Definition: l2_fib.h:31
#define static_always_inline
Definition: clib.h:85
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
int clib_bihash_add_del(clib_bihash *h, clib_bihash_kv *add_v, int is_add)
Add or delete a (key,value) pair from a bi-hash table.
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
Definition: node_funcs.h:542
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define clib_error_return(e, args...)
Definition: error.h:99
unsigned long u64
Definition: types.h:89
L2 MAC event for a list of learned or aged MACs.
Definition: l2.api:175
uword * bd_index_by_bd_id
Definition: l2_bd.h:27
void * vl_msg_api_alloc(int nbytes)
u32 sw_if_index
Definition: l2.api:163
void l2fib_start_ager_scan(vlib_main_t *vm)
Kick off ager to scan MACs to age/delete MAC entries.
Definition: l2_fib.c:757
#define hash_get(h, key)
Definition: hash.h:248
f64 event_scan_delay
Definition: l2_fib.h:56
format_function_t format_vnet_sw_interface_name
u8 is_del
Definition: l2.api:165
vlib_main_t * vlib_main
Definition: vnet.h:78
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:950
static void l2fib_add_filter_entry(u64 mac, u32 bd_index)
Definition: l2_fib.h:386
#define v
Definition: acl.c:323
struct _unformat_input_t unformat_input_t
void vl_msg_api_free(void *)
void l2fib_flush_bd_mac(vlib_main_t *vm, u32 bd_index)
Flush all non static MACs in a bridge domain.
Definition: l2_fib.c:790
#define PREDICT_FALSE(x)
Definition: clib.h:97
void l2fib_flush_all_mac(vlib_main_t *vm)
Flush all non static MACs - flushes all valid BDs.
Definition: l2_fib.c:801
#define L2FIB_NUM_BUCKETS
Definition: l2_fib.h:27
static_always_inline f64 l2fib_scan(vlib_main_t *vm, f64 start_time, u8 event_only)
Definition: l2_fib.c:962
void clib_bihash_init(clib_bihash *h, char *name, u32 nbuckets, uword memory_size)
initialize a bounded index extensible hash table
l2fib_main_t l2fib_main
Definition: l2_fib.c:55
u64 raw
Definition: l2_fib.h:126
static u32 bd_is_valid(l2_bridge_domain_t *bd_config)
Definition: l2_bd.h:114
static clib_error_t * clear_l2fib(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Clear all entries in L2FIB.
Definition: l2_fib.c:302
BVT(clib_bihash)
Definition: l2_fib.c:943
clib_error_t * l2fib_sw_interface_up_down(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: l2_fib.c:933
static clib_error_t * show_l2fib(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Display the contents of the l2fib.
Definition: l2_fib.c:115
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
static clib_error_t * l2fib_flush_mac_all(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Flush all MACs, except static ones The CLI format is: l2fib flush-mac all.
Definition: l2_fib.c:844
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
vlib_main_t * vm
Definition: buffer.c:283
vec_header_t h
Definition: buffer.c:282
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
void l2fib_add_entry(u64 mac, u32 bd_index, u32 sw_if_index, u8 static_mac, u8 filter_mac, u8 bvi_mac)
Add an entry to the l2fib.
Definition: l2_fib.c:345
static clib_error_t * l2fib_flush_mac_int(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Flush MACs, except static ones, associated with an interface The CLI format is: l2fib flush-mac inter...
Definition: l2_fib.c:818
#define clib_warning(format, args...)
Definition: error.h:59
f64 age_scan_duration
Definition: l2_fib.h:53
#define clib_memcpy(a, b, c)
Definition: string.h:69
static vnet_sw_interface_t * vnet_get_sw_interface_safe(vnet_main_t *vnm, u32 sw_if_index)
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
void l2fib_clear_table(void)
Definition: l2_fib.c:287
struct l2fib_entry_key_t::@178::@180 fields
static l2fib_seq_num_t l2fib_cur_seq_num(u32 bd_index, u32 sw_if_index)
Definition: l2_fib.c:329
static_always_inline l2_bridge_domain_t * l2input_bd_config(u32 bd_index)
Definition: l2_input.h:90
u8 mac_addr[6]
Definition: l2.api:164
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:572
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
Definition: format.c:227
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
int clib_bihash_search(clib_bihash *h, clib_bihash_kv *search_v, clib_bihash_kv *return_v)
Search a bi-hash table.
Definition: l2_fib.h:71
static uword l2fib_mac_age_scanner_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: l2_fib.c:1137
vl_api_mac_entry_t mac[n_macs]
Definition: l2.api:180
struct l2fib_entry_result_t::@186::@188 fields
size_t count
Definition: vapi.c:40
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(l2fib_sw_interface_up_down)
u32 global_learn_limit
Definition: l2_learn.h:35
#define TIME_MAX
Definition: l2_fib.c:1134
u64 uword
Definition: types.h:112
template key/value backing page structure
Definition: bihash_doc.h:44
static clib_error_t * l2fib_flush_mac_bd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Flush bridge-domain MACs except static ones.
Definition: l2_fib.c:889
unsigned short u16
Definition: types.h:57
l2input_main_t l2input_main
Definition: l2_input.c:113
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
static u64 l2fib_make_key(u8 *mac_address, u16 bd_index)
Definition: l2_fib.h:152
l2_bridge_domain_t * bd_configs
Definition: l2_input.h:69
void l2fib_table_dump(u32 bd_index, l2fib_entry_key_t **l2fe_key, l2fib_entry_result_t **l2fe_res)
Definition: l2_fib.c:75
short i16
Definition: types.h:46
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
l2learn_main_t l2learn_main
Definition: l2_learn.h:51
#define vec_foreach(var, vec)
Vector iterator.
static void * clib_bihash_get_value(clib_bihash *h, uword offset)
Get pointer to value page given its clib mheap offset.
u32 flags
Definition: vhost-user.h:77
bd_main_t bd_main
Definition: l2_bd.c:44
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
static clib_error_t * l2fib_add(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Add an entry to the L2FIB.
Definition: l2_fib.c:389
vlib_node_registration_t l2fib_mac_age_scanner_process_node
(constructor) VLIB_REGISTER_NODE (l2fib_mac_age_scanner_process_node)
Definition: l2_fib.c:1210
u32 client_pid
Definition: l2_learn.h:38
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
static u32 l2fib_del_entry_by_key(u64 raw_key)
Delete an entry from the l2fib.
Definition: l2_fib.c:654
void l2fib_flush_int_mac(vlib_main_t *vm, u32 sw_if_index)
Flush all non static MACs from an interface.
Definition: l2_fib.c:780
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
u64 raw
Definition: l2_fib.h:85
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
struct _unix_shared_memory_queue unix_shared_memory_queue_t