FD.io VPP  v16.12-rc0-308-g931be3a
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_fib.h>
28 #include <vnet/l2/l2_learn.h>
29 #include <vnet/l2/l2_bd.h>
30 
32 
33 /**
34  * @file
35  * @brief Ethernet MAC Address FIB Table Management.
36  *
37  * The MAC Address forwarding table for bridge-domains is called the l2fib.
38  * Entries are added automatically as part of mac learning, but MAC Addresses
39  * entries can also be added manually.
40  *
41  */
42 
43 typedef struct
44 {
45 
46  /* hash table */
47  BVT (clib_bihash) mac_table;
48 
49  /* convenience variables */
52 } l2fib_main_t;
53 
55 
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  else
66  return format (s, "%U",
68  vnet_get_sw_interface (vnm, sw_if_index));
69 }
70 
71 void
72 l2fib_table_dump (u32 bd_index, l2fib_entry_key_t ** l2fe_key,
73  l2fib_entry_result_t ** l2fe_res)
74 {
75  l2fib_main_t *msm = &l2fib_main;
76  BVT (clib_bihash) * h = &msm->mac_table;
78  BVT (clib_bihash_value) * v;
80  l2fib_entry_result_t result;
81  int i, j, k;
82 
83  for (i = 0; i < h->nbuckets; i++)
84  {
85  b = &h->buckets[i];
86  if (b->offset == 0)
87  continue;
88  v = BV (clib_bihash_get_value) (h, b->offset);
89  for (j = 0; j < (1 << b->log2_pages); j++)
90  {
91  for (k = 0; k < BIHASH_KVP_PER_PAGE; k++)
92  {
93  if (v->kvp[k].key == ~0ULL && v->kvp[k].value == ~0ULL)
94  continue;
95 
96  key.raw = v->kvp[k].key;
97  result.raw = v->kvp[k].value;
98 
99  if ((bd_index == ~0) || (bd_index == key.fields.bd_index))
100  {
101  vec_add1 (*l2fe_key, key);
102  vec_add1 (*l2fe_res, result);
103  }
104  }
105  v++;
106  }
107  }
108 }
109 
110 /** Display the contents of the l2fib. */
111 static clib_error_t *
113  unformat_input_t * input, vlib_cli_command_t * cmd)
114 {
115  bd_main_t *bdm = &bd_main;
116  l2fib_main_t *msm = &l2fib_main;
117  BVT (clib_bihash) * h = &msm->mac_table;
119  BVT (clib_bihash_value) * v;
120  l2fib_entry_key_t key;
121  l2fib_entry_result_t result;
122  u32 first_entry = 1;
123  u64 total_entries = 0;
124  int i, j, k;
125  u8 verbose = 0;
126  u8 raw = 0;
127  u32 bd_id, bd_index = ~0;
128 
129  if (unformat (input, "raw"))
130  raw = 1;
131  else if (unformat (input, "verbose"))
132  verbose = 1;
133  else if (unformat (input, "bd_index %d", &bd_index))
134  verbose = 1;
135  else if (unformat (input, "bd_id %d", &bd_id))
136  {
137  uword *p = hash_get (bdm->bd_index_by_bd_id, bd_id);
138  if (p)
139  {
140  verbose = 1;
141  bd_index = p[0];
142  }
143  else
144  {
145  vlib_cli_output (vm, "no such bridge domain id");
146  return 0;
147  }
148  }
149 
150  for (i = 0; i < h->nbuckets; i++)
151  {
152  b = &h->buckets[i];
153  if (b->offset == 0)
154  continue;
155  v = BV (clib_bihash_get_value) (h, b->offset);
156  for (j = 0; j < (1 << b->log2_pages); j++)
157  {
158  for (k = 0; k < BIHASH_KVP_PER_PAGE; k++)
159  {
160  if (v->kvp[k].key == ~0ULL && v->kvp[k].value == ~0ULL)
161  continue;
162 
163  if (verbose && first_entry)
164  {
165  first_entry = 0;
166  vlib_cli_output (vm,
167  "%=19s%=7s%=30s%=7s%=8s%=8s%=5s%=9s%=11s",
168  "Mac Address", "BD Idx", "Interface",
169  "Index", "static", "filter", "bvi",
170  "refresh", "timestamp");
171  }
172 
173  key.raw = v->kvp[k].key;
174  result.raw = v->kvp[k].value;
175 
176  if (verbose
177  & ((bd_index >> 31) || (bd_index == key.fields.bd_index)))
178  {
179  vlib_cli_output (vm,
180  "%=19U%=7d%=30U%=7d%=8d%=8d%=5d%=9d%=11X",
182  key.fields.bd_index,
184  msm->vnet_main, result.fields.sw_if_index,
185  result.fields.sw_if_index == ~0
186  ? -1 : result.fields.sw_if_index,
187  result.fields.static_mac,
188  result.fields.filter,
189  result.fields.bvi,
190  result.fields.refresh,
191  result.fields.timestamp);
192  }
193  total_entries++;
194  }
195  v++;
196  }
197  }
198 
199  if (total_entries == 0)
200  vlib_cli_output (vm, "no l2fib entries");
201  else
202  vlib_cli_output (vm, "%lld l2fib entries", total_entries);
203 
204  if (raw)
205  vlib_cli_output (vm, "Raw Hash Table:\n%U\n",
206  BV (format_bihash), h, 1 /* verbose */ );
207 
208  return 0;
209 }
210 
211 /*?
212  * This command dispays the MAC Address entries of the L2 FIB table.
213  * Output can be filtered to just get the number of MAC Addresses or display
214  * each MAC Address for all bridge domains or just a single bridge domain.
215  *
216  * @cliexpar
217  * Example of how to display the number of MAC Address entries in the L2
218  * FIB table:
219  * @cliexstart{show l2fib}
220  * 3 l2fib entries
221  * @cliexend
222  * Example of how to display all the MAC Address entries in the L2
223  * FIB table:
224  * @cliexstart{show l2fib verbose}
225  * Mac Address BD Idx Interface Index static filter bvi refresh timestamp
226  * 52:54:00:53:18:33 1 GigabitEthernet0/8/0.200 3 0 0 0 0 0
227  * 52:54:00:53:18:55 1 GigabitEthernet0/8/0.200 3 1 0 0 0 0
228  * 52:54:00:53:18:77 1 N/A -1 1 1 0 0 0
229  * 3 l2fib entries
230  * @cliexend
231 ?*/
232 /* *INDENT-OFF* */
233 VLIB_CLI_COMMAND (show_l2fib_cli, static) = {
234  .path = "show l2fib",
235  .short_help = "show l2fib [verbose | bd_id <nn> | bd_index <nn> | raw]",
236  .function = show_l2fib,
237 };
238 /* *INDENT-ON* */
239 
240 
241 /* Remove all entries from the l2fib */
242 void
243 l2fib_clear_table (uint keep_static)
244 {
245  l2fib_main_t *mp = &l2fib_main;
246 
247  if (keep_static)
248  {
249  /* TODO: remove only non-static entries */
250  }
251  else
252  {
253  /* Remove all entries */
254  BV (clib_bihash_free) (&mp->mac_table);
255  BV (clib_bihash_init) (&mp->mac_table, "l2fib mac table",
257  }
258 
260 }
261 
262 /** Clear all entries in L2FIB.
263  * @TODO: Later we may want a way to remove only the non-static entries
264  */
265 static clib_error_t *
267  unformat_input_t * input, vlib_cli_command_t * cmd)
268 {
269  l2fib_clear_table (0);
270  return 0;
271 }
272 
273 /*?
274  * This command clears all the MAC Address entries from the L2 FIB table.
275  *
276  * @cliexpar
277  * Example of how to clear the L2 FIB Table:
278  * @cliexcmd{clear l2fib}
279  * Example to show the L2 FIB Table has been cleared:
280  * @cliexstart{show l2fib verbose}
281  * no l2fib entries
282  * @cliexend
283 ?*/
284 /* *INDENT-OFF* */
285 VLIB_CLI_COMMAND (clear_l2fib_cli, static) = {
286  .path = "clear l2fib",
287  .short_help = "clear l2fib",
288  .function = clear_l2fib,
289 };
290 /* *INDENT-ON* */
291 
292 
293 /**
294  * Add an entry to the l2fib.
295  * If the entry already exists then overwrite it
296  */
297 void
299  u32 bd_index,
300  u32 sw_if_index, u32 static_mac, u32 filter_mac, u32 bvi_mac)
301 {
302  l2fib_entry_key_t key;
303  l2fib_entry_result_t result;
304  __attribute__ ((unused)) u32 bucket_contents;
305  l2fib_main_t *mp = &l2fib_main;
306  BVT (clib_bihash_kv) kv;
307 
308  /* set up key */
309  key.raw = l2fib_make_key ((u8 *) & mac, bd_index);
310 
311  /* set up result */
312  result.raw = 0; /* clear all fields */
313  result.fields.sw_if_index = sw_if_index;
314  result.fields.static_mac = static_mac;
315  result.fields.filter = filter_mac;
316  result.fields.bvi = bvi_mac;
317 
318  kv.key = key.raw;
319  kv.value = result.raw;
320 
321  BV (clib_bihash_add_del) (&mp->mac_table, &kv, 1 /* is_add */ );
322 
323  /* increment counter if dynamically learned mac */
324  if (result.fields.static_mac)
325  {
327  }
328 }
329 
330 /**
331  * Add an entry to the L2FIB.
332  * The CLI format is:
333  * l2fib add <mac> <bd> <intf> [static] [bvi]
334  * l2fib add <mac> <bd> filter
335  * Note that filter and bvi entries are always static
336  */
337 static clib_error_t *
339  unformat_input_t * input, vlib_cli_command_t * cmd)
340 {
341  bd_main_t *bdm = &bd_main;
342  vnet_main_t *vnm = vnet_get_main ();
343  clib_error_t *error = 0;
344  u64 mac;
345  u32 bd_id;
346  u32 bd_index;
347  u32 sw_if_index = ~0;
348  u32 filter_mac = 0;
349  u32 static_mac = 0;
350  u32 bvi_mac = 0;
351  uword *p;
352 
353  if (!unformat_user (input, unformat_ethernet_address, &mac))
354  {
355  error = clib_error_return (0, "expected mac address `%U'",
356  format_unformat_error, input);
357  goto done;
358  }
359 
360  if (!unformat (input, "%d", &bd_id))
361  {
362  error = clib_error_return (0, "expected bridge domain ID `%U'",
363  format_unformat_error, input);
364  goto done;
365  }
366 
367  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
368  if (!p)
369  {
370  error = clib_error_return (0, "bridge domain ID %d invalid", bd_id);
371  goto done;
372  }
373  bd_index = p[0];
374 
375  if (unformat (input, "filter"))
376  {
377  filter_mac = 1;
378  static_mac = 1;
379 
380  }
381  else
382  {
383 
384  if (!unformat_user
385  (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
386  {
387  error = clib_error_return (0, "unknown interface `%U'",
388  format_unformat_error, input);
389  goto done;
390  }
391  if (unformat (input, "static"))
392  {
393  static_mac = 1;
394  }
395  else if (unformat (input, "bvi"))
396  {
397  bvi_mac = 1;
398  static_mac = 1;
399  }
400  }
401 
402  l2fib_add_entry (mac, bd_index, sw_if_index, static_mac, filter_mac,
403  bvi_mac);
404 
405 done:
406  return error;
407 }
408 
409 /*?
410  * This command adds a MAC Address entry to the L2 FIB table
411  * of an existing bridge-domain. The MAC Address can be static
412  * or dynamic. This command also allows a filter to be added,
413  * such that packets with given MAC Addresses (source mac or
414  * destination mac match) are dropped.
415  *
416  * @cliexpar
417  * Example of how to add a dynamic MAC Address entry to the L2 FIB table
418  * of a bridge-domain (where 200 is the bridge-domain-id):
419  * @cliexcmd{l2fib add 52:54:00:53:18:33 200 GigabitEthernet0/8/0.200}
420  * Example of how to add a static MAC Address entry to the L2 FIB table
421  * of a bridge-domain (where 200 is the bridge-domain-id):
422  * @cliexcmd{l2fib add 52:54:00:53:18:55 200 GigabitEthernet0/8/0.200 static}
423  * Example of how to add a filter such that a packet with the given MAC
424  * Address will be dropped in a given bridge-domain (where 200 is the
425  * bridge-domain-id):
426  * @cliexcmd{l2fib add 52:54:00:53:18:77 200 filter}
427  * Example of show command of the provisioned MAC Addresses and filters:
428  * @cliexstart{show l2fib verbose}
429  * Mac Address BD Idx Interface Index static filter bvi refresh timestamp
430  * 52:54:00:53:18:33 1 GigabitEthernet0/8/0.200 3 0 0 0 0 0
431  * 52:54:00:53:18:55 1 GigabitEthernet0/8/0.200 3 1 0 0 0 0
432  * 52:54:00:53:18:77 1 N/A -1 1 1 0 0 0
433  * 3 l2fib entries
434  * @cliexend
435 ?*/
436 /* *INDENT-OFF* */
437 VLIB_CLI_COMMAND (l2fib_add_cli, static) = {
438  .path = "l2fib add",
439  .short_help = "l2fib add <mac> <bridge-domain-id> filter | <intf> [static | bvi]",
440  .function = l2fib_add,
441 };
442 /* *INDENT-ON* */
443 
444 
445 static clib_error_t *
447  unformat_input_t * input, vlib_cli_command_t * cmd)
448 {
449  clib_error_t *error = 0;
450  u64 mac, save_mac;
451  u32 bd_index = 0;
452  u32 sw_if_index = 8;
453  u32 filter_mac = 0;
454  u32 bvi_mac = 0;
455  u32 is_add = 0;
456  u32 is_del = 0;
457  u32 is_check = 0;
458  u32 count = 1;
459  int mac_set = 0;
460  int i;
461 
463  {
464  if (unformat (input, "mac %U", unformat_ethernet_address, &mac))
465  mac_set = 1;
466  else if (unformat (input, "add"))
467  is_add = 1;
468  else if (unformat (input, "del"))
469  is_del = 1;
470  else if (unformat (input, "check"))
471  is_check = 1;
472  else if (unformat (input, "count %d", &count))
473  ;
474  else
475  break;
476  }
477 
478  if (mac_set == 0)
479  return clib_error_return (0, "mac not set");
480 
481  if (is_add == 0 && is_del == 0 && is_check == 0)
482  return clib_error_return (0,
483  "noop: pick at least one of (add,del,check)");
484 
485  save_mac = mac;
486 
487  if (is_add)
488  {
489  for (i = 0; i < count; i++)
490  {
491  u64 tmp;
492  l2fib_add_entry (mac, bd_index, sw_if_index, mac,
493  filter_mac, bvi_mac);
494  tmp = clib_net_to_host_u64 (mac);
495  tmp >>= 16;
496  tmp++;
497  tmp <<= 16;
498  mac = clib_host_to_net_u64 (tmp);
499  }
500  }
501 
502  if (is_check)
503  {
504  BVT (clib_bihash_kv) kv;
505  l2fib_main_t *mp = &l2fib_main;
506 
507  mac = save_mac;
508 
509  for (i = 0; i < count; i++)
510  {
511  u64 tmp;
512  kv.key = l2fib_make_key ((u8 *) & mac, bd_index);
513  if (BV (clib_bihash_search) (&mp->mac_table, &kv, &kv))
514  {
515  clib_warning ("key %U AWOL", format_ethernet_address, &mac);
516  break;
517  }
518  tmp = clib_net_to_host_u64 (mac);
519  tmp >>= 16;
520  tmp++;
521  tmp <<= 16;
522  mac = clib_host_to_net_u64 (tmp);
523  }
524  }
525 
526  if (is_del)
527  {
528  for (i = 0; i < count; i++)
529  {
530  u64 tmp;
531 
532  l2fib_del_entry (mac, bd_index);
533 
534  tmp = clib_net_to_host_u64 (mac);
535  tmp >>= 16;
536  tmp++;
537  tmp <<= 16;
538  mac = clib_host_to_net_u64 (tmp);
539  }
540  }
541 
542  return error;
543 }
544 
545 /*?
546  * The set of '<em>test l2fib</em>' commands allow the L2 FIB table of the default
547  * bridge domain (bridge-domain-id of 0) to be modified.
548  *
549  * @cliexpar
550  * @parblock
551  * Example of how to add a set of 4 sequential MAC Address entries to L2
552  * FIB table of the default bridge-domain:
553  * @cliexcmd{test l2fib add mac 52:54:00:53:00:00 count 4}
554  *
555  * Show the set of 4 sequential MAC Address entries that were added:
556  * @cliexstart{show l2fib verbose}
557  * Mac Address BD Idx Interface Index static filter bvi refresh timestamp
558  * 52:54:00:53:00:00 0 GigabitEthernet0/8/0.300 8 0 0 0 0 0
559  * 52:54:00:53:00:01 0 GigabitEthernet0/8/0.300 8 0 0 0 0 0
560  * 52:54:00:53:00:03 0 GigabitEthernet0/8/0.300 8 0 0 0 0 0
561  * 52:54:00:53:00:02 0 GigabitEthernet0/8/0.300 8 0 0 0 0 0
562  * 4 l2fib entries
563  * @cliexend
564  *
565  * Example of how to check that the set of 4 sequential MAC Address
566  * entries were added to L2 FIB table of the default
567  * bridge-domain. Used a count of 5 to produce an error:
568  *
569  * @cliexcmd{test l2fib check mac 52:54:00:53:00:00 count 5}
570  * The output of the check command is in the log files. Log file
571  * location may vary based on your OS and Version:
572  *
573  * <b><em># tail -f /var/log/messages | grep l2fib_test_command_fn</em></b>
574  *
575  * Sep 7 17:15:24 localhost vnet[4952]: l2fib_test_command_fn:446: key 52:54:00:53:00:04 AWOL
576  *
577  * Example of how to delete a set of 4 sequential MAC Address entries
578  * from L2 FIB table of the default bridge-domain:
579  * @cliexcmd{test l2fib del mac 52:54:00:53:00:00 count 4}
580  * @endparblock
581 ?*/
582 /* *INDENT-OFF* */
583 VLIB_CLI_COMMAND (l2fib_test_command, static) = {
584  .path = "test l2fib",
585  .short_help = "test l2fib [add|del|check] mac <base-addr> count <nn>",
586  .function = l2fib_test_command_fn,
587 };
588 /* *INDENT-ON* */
589 
590 
591 /**
592  * Delete an entry from the l2fib.
593  * Return 0 if the entry was deleted, or 1 if it was not found
594  */
595 u32
596 l2fib_del_entry (u64 mac, u32 bd_index)
597 {
598 
599  l2fib_entry_result_t result;
600  l2fib_main_t *mp = &l2fib_main;
601  BVT (clib_bihash_kv) kv;
602 
603  /* set up key */
604  kv.key = l2fib_make_key ((u8 *) & mac, bd_index);
605 
606  if (BV (clib_bihash_search) (&mp->mac_table, &kv, &kv))
607  return 1;
608 
609  result.raw = kv.value;
610 
611  /* decrement counter if dynamically learned mac */
612  if (result.fields.static_mac)
613  {
615  {
617  }
618  }
619 
620  /* Remove entry from hash table */
621  BV (clib_bihash_add_del) (&mp->mac_table, &kv, 0 /* is_add */ );
622  return 0;
623 }
624 
625 /**
626  * Delete an entry from the L2FIB.
627  * The CLI format is:
628  * l2fib del <mac> <bd-id>
629  */
630 static clib_error_t *
632  unformat_input_t * input, vlib_cli_command_t * cmd)
633 {
634  bd_main_t *bdm = &bd_main;
635  clib_error_t *error = 0;
636  u64 mac;
637  u32 bd_id;
638  u32 bd_index;
639  uword *p;
640 
641  if (!unformat_user (input, unformat_ethernet_address, &mac))
642  {
643  error = clib_error_return (0, "expected mac address `%U'",
644  format_unformat_error, input);
645  goto done;
646  }
647 
648  if (!unformat (input, "%d", &bd_id))
649  {
650  error = clib_error_return (0, "expected bridge domain ID `%U'",
651  format_unformat_error, input);
652  goto done;
653  }
654 
655  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
656  if (!p)
657  {
658  error = clib_error_return (0, "bridge domain ID %d invalid", bd_id);
659  goto done;
660  }
661  bd_index = p[0];
662 
663  /* Delete the entry */
664  if (l2fib_del_entry (mac, bd_index))
665  {
666  error = clib_error_return (0, "mac entry not found");
667  goto done;
668  }
669 
670 done:
671  return error;
672 }
673 
674 /*?
675  * This command deletes an existing MAC Address entry from the L2 FIB
676  * table of an existing bridge-domain.
677  *
678  * @cliexpar
679  * 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):
680  * @cliexcmd{l2fib del 52:54:00:53:18:33 200}
681 ?*/
682 /* *INDENT-OFF* */
683 VLIB_CLI_COMMAND (l2fib_del_cli, static) = {
684  .path = "l2fib del",
685  .short_help = "l2fib del <mac> <bridge-domain-id>",
686  .function = l2fib_del,
687 };
688 /* *INDENT-ON* */
689 
690 
691 BVT (clib_bihash) * get_mac_table (void)
692 {
693  l2fib_main_t *mp = &l2fib_main;
694  return &mp->mac_table;
695 }
696 
697 clib_error_t *
699 {
700  l2fib_main_t *mp = &l2fib_main;
701  l2fib_entry_key_t test_key;
702  u8 test_mac[6];
703 
704  mp->vlib_main = vm;
705  mp->vnet_main = vnet_get_main ();
706 
707  /* Create the hash table */
708  BV (clib_bihash_init) (&mp->mac_table, "l2fib mac table",
710 
711  /* verify the key constructor is good, since it is endian-sensitive */
712  memset (test_mac, 0, sizeof (test_mac));
713  test_mac[0] = 0x11;
714  test_key.raw = 0;
715  test_key.raw = l2fib_make_key ((u8 *) & test_mac, 0x1234);
716  ASSERT (test_key.fields.mac[0] == 0x11);
717  ASSERT (test_key.fields.bd_index == 0x1234);
718 
719  return 0;
720 }
721 
723 
724 /*
725  * fd.io coding-style-patch-verification: ON
726  *
727  * Local Variables:
728  * eval: (c-set-style "gnu")
729  * End:
730  */
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:446
u32 global_learn_count
Definition: l2_learn.h:32
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
u8 * format_vnet_sw_if_index_name_with_NA(u8 *s, va_list *args)
Format sw_if_index.
Definition: l2_fib.c:59
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
clib_bihash_bucket_t
Definition: bihash_doc.h:65
void clib_bihash_free(clib_bihash *h)
Destroy a bounded index extensible hash table.
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
u32 l2fib_del_entry(u64 mac, u32 bd_index)
Delete an entry from the l2fib.
Definition: l2_fib.c:596
clib_error_t * l2fib_init(vlib_main_t *vm)
Definition: l2_fib.c:698
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
struct l2fib_entry_result_t::@182::@184 fields
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
#define L2FIB_MEMORY_SIZE
Definition: l2_fib.h:28
unformat_function_t unformat_vnet_sw_interface
Definition: l2_fib.h:54
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:631
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
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
#define clib_warning(format, args...)
Definition: error.h:59
unsigned long u64
Definition: types.h:89
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:977
int vlib_main(vlib_main_t *volatile vm, unformat_input_t *input)
Definition: main.c:1573
uword * bd_index_by_bd_id
Definition: l2_bd.h:27
#define hash_get(h, key)
Definition: hash.h:248
format_function_t format_vnet_sw_interface_name
#define BIHASH_KVP_PER_PAGE
Definition: bihash_24_8.h:18
vnet_main_t vnet_main
Definition: misc.c:43
#define L2FIB_NUM_BUCKETS
Definition: l2_fib.h:27
void clib_bihash_init(clib_bihash *h, char *name, u32 nbuckets, uword memory_size)
initialize a bounded index extensible hash table
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
l2fib_main_t l2fib_main
Definition: l2_fib.c:54
u64 raw
Definition: l2_fib.h:70
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:266
BVT(clib_bihash)
Definition: l2_fib.c:691
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:112
void l2fib_clear_table(uint keep_static)
Definition: l2_fib.c:243
struct l2fib_entry_key_t::@178::@180 fields
void l2fib_add_entry(u64 mac, u32 bd_index, u32 sw_if_index, u32 static_mac, u32 filter_mac, u32 bvi_mac)
Add an entry to the l2fib.
Definition: l2_fib.c:298
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
Definition: format.c:245
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
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:33
u64 uword
Definition: types.h:112
template key/value backing page structure
Definition: bihash_doc.h:44
unsigned char u8
Definition: types.h:56
static u64 l2fib_make_key(u8 *mac_address, u16 bd_index)
Definition: l2_fib.h:95
void l2fib_table_dump(u32 bd_index, l2fib_entry_key_t **l2fe_key, l2fib_entry_result_t **l2fe_res)
Definition: l2_fib.c:72
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
l2learn_main_t l2learn_main
Definition: l2_learn.h:46
static void * clib_bihash_get_value(clib_bihash *h, uword offset)
Get pointer to value page given its clib mheap offset.
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
bd_main_t bd_main
Definition: l2_bd.c:43
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:338
u64 raw
Definition: l2_fib.h:47