blob: 5f371ccd6ee9ffdbd6b65cba3eeda934a4a4e111 [file] [log] [blame]
Matus Fabianf468e232016-12-02 06:00:53 -08001/*
2 *------------------------------------------------------------------
3 * l2_api.c - layer 2 forwarding api
4 *
5 * Copyright (c) 2016 Cisco and/or its affiliates.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
18 */
19
20#include <vnet/vnet.h>
21#include <vlibmemory/api.h>
22
23#include <vnet/interface.h>
24#include <vnet/api_errno.h>
25#include <vnet/l2/l2_input.h>
Pavel Kotucek0f971d82017-01-03 10:48:54 +010026#include <vnet/l2/l2_fib.h>
Pavel Kotucekadec5872017-01-25 08:50:53 +010027#include <vnet/l2/l2_vtr.h>
Matus Fabianf468e232016-12-02 06:00:53 -080028
29#include <vnet/vnet_msg_enum.h>
30
31#define vl_typedefs /* define message structures */
32#include <vnet/vnet_all_api_h.h>
33#undef vl_typedefs
34
35#define vl_endianfun /* define message structures */
36#include <vnet/vnet_all_api_h.h>
37#undef vl_endianfun
38
39/* instantiate all the print functions we know about */
40#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
41#define vl_printfun
42#include <vnet/vnet_all_api_h.h>
43#undef vl_printfun
44
45#include <vlibapi/api_helper_macros.h>
46
Pavel Kotucek0f971d82017-01-03 10:48:54 +010047#define foreach_vpe_api_msg \
48_(L2_XCONNECT_DUMP, l2_xconnect_dump) \
49_(L2_FIB_CLEAR_TABLE, l2_fib_clear_table) \
50_(L2_FIB_TABLE_DUMP, l2_fib_table_dump) \
Eyal Bari7537e712017-04-27 14:07:55 +030051_(L2FIB_FLUSH_ALL, l2fib_flush_all) \
Eyal Barif24991c2017-04-05 05:33:21 +030052_(L2FIB_FLUSH_INT, l2fib_flush_int) \
53_(L2FIB_FLUSH_BD, l2fib_flush_bd) \
Pavel Kotucek0f971d82017-01-03 10:48:54 +010054_(L2FIB_ADD_DEL, l2fib_add_del) \
55_(L2_FLAGS, l2_flags) \
56_(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del) \
57_(BRIDGE_DOMAIN_DUMP, bridge_domain_dump) \
Pavel Kotucekadec5872017-01-25 08:50:53 +010058_(BRIDGE_FLAGS, bridge_flags) \
59_(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite) \
Eyal Barifead6702017-04-04 04:46:32 +030060_(L2_INTERFACE_PBB_TAG_REWRITE, l2_interface_pbb_tag_rewrite) \
61_(BRIDGE_DOMAIN_SET_MAC_AGE, bridge_domain_set_mac_age)
Matus Fabianf468e232016-12-02 06:00:53 -080062
63static void
64send_l2_xconnect_details (unix_shared_memory_queue_t * q, u32 context,
65 u32 rx_sw_if_index, u32 tx_sw_if_index)
66{
67 vl_api_l2_xconnect_details_t *mp;
68
69 mp = vl_msg_api_alloc (sizeof (*mp));
70 memset (mp, 0, sizeof (*mp));
71 mp->_vl_msg_id = ntohs (VL_API_L2_XCONNECT_DETAILS);
72 mp->context = context;
73 mp->rx_sw_if_index = htonl (rx_sw_if_index);
74 mp->tx_sw_if_index = htonl (tx_sw_if_index);
75
76 vl_msg_api_send_shmem (q, (u8 *) & mp);
77}
78
79static void
80vl_api_l2_xconnect_dump_t_handler (vl_api_l2_xconnect_dump_t * mp)
81{
82 unix_shared_memory_queue_t *q;
83 vnet_main_t *vnm = vnet_get_main ();
84 vnet_interface_main_t *im = &vnm->interface_main;
85 l2input_main_t *l2im = &l2input_main;
86 vnet_sw_interface_t *swif;
87 l2_input_config_t *config;
88
89 q = vl_api_client_index_to_input_queue (mp->client_index);
90 if (q == 0)
91 return;
92
93 /* *INDENT-OFF* */
94 pool_foreach (swif, im->sw_interfaces,
95 ({
96 config = vec_elt_at_index (l2im->configs, swif->sw_if_index);
97 if (config->xconnect)
98 send_l2_xconnect_details (q, mp->context, swif->sw_if_index,
99 config->output_sw_if_index);
100 }));
101 /* *INDENT-ON* */
102}
103
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100104static void
105vl_api_l2_fib_clear_table_t_handler (vl_api_l2_fib_clear_table_t * mp)
106{
107 int rv = 0;
108 vl_api_l2_fib_clear_table_reply_t *rmp;
109
Eyal Bari7537e712017-04-27 14:07:55 +0300110 /* Clear all MACs including static MACs */
111 l2fib_clear_table ();
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100112
113 REPLY_MACRO (VL_API_L2_FIB_CLEAR_TABLE_REPLY);
114}
115
116static void
117send_l2fib_table_entry (vpe_api_main_t * am,
118 unix_shared_memory_queue_t * q,
119 l2fib_entry_key_t * l2fe_key,
120 l2fib_entry_result_t * l2fe_res, u32 context)
121{
122 vl_api_l2_fib_table_entry_t *mp;
123
124 mp = vl_msg_api_alloc (sizeof (*mp));
125 memset (mp, 0, sizeof (*mp));
126 mp->_vl_msg_id = ntohs (VL_API_L2_FIB_TABLE_ENTRY);
127
128 mp->bd_id =
129 ntohl (l2input_main.bd_configs[l2fe_key->fields.bd_index].bd_id);
130
131 mp->mac = l2fib_make_key (l2fe_key->fields.mac, 0);
132 mp->sw_if_index = ntohl (l2fe_res->fields.sw_if_index);
133 mp->static_mac = l2fe_res->fields.static_mac;
134 mp->filter_mac = l2fe_res->fields.filter;
135 mp->bvi_mac = l2fe_res->fields.bvi;
136 mp->context = context;
137
138 vl_msg_api_send_shmem (q, (u8 *) & mp);
139}
140
141static void
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100142vl_api_l2_fib_table_dump_t_handler (vl_api_l2_fib_table_dump_t * mp)
143{
144 vpe_api_main_t *am = &vpe_api_main;
145 bd_main_t *bdm = &bd_main;
146 l2fib_entry_key_t *l2fe_key = NULL;
147 l2fib_entry_result_t *l2fe_res = NULL;
148 u32 ni, bd_id = ntohl (mp->bd_id);
149 u32 bd_index;
150 unix_shared_memory_queue_t *q;
151 uword *p;
152
153 q = vl_api_client_index_to_input_queue (mp->client_index);
154 if (q == 0)
155 return;
156
157 /* see l2fib_table_dump: ~0 means "any" */
158 if (bd_id == ~0)
159 bd_index = ~0;
160 else
161 {
162 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
163 if (p == 0)
164 return;
165
166 bd_index = p[0];
167 }
168
169 l2fib_table_dump (bd_index, &l2fe_key, &l2fe_res);
170
171 vec_foreach_index (ni, l2fe_key)
172 {
173 send_l2fib_table_entry (am, q, vec_elt_at_index (l2fe_key, ni),
174 vec_elt_at_index (l2fe_res, ni), mp->context);
175 }
176 vec_free (l2fe_key);
177 vec_free (l2fe_res);
178}
179
180static void
181vl_api_l2fib_add_del_t_handler (vl_api_l2fib_add_del_t * mp)
182{
183 bd_main_t *bdm = &bd_main;
184 l2input_main_t *l2im = &l2input_main;
185 vl_api_l2fib_add_del_reply_t *rmp;
186 int rv = 0;
187 u64 mac = 0;
188 u32 sw_if_index = ntohl (mp->sw_if_index);
189 u32 bd_id = ntohl (mp->bd_id);
190 u32 bd_index;
191 u32 static_mac;
192 u32 filter_mac;
193 u32 bvi_mac;
194 uword *p;
195
196 mac = mp->mac;
197
198 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
199 if (!p)
200 {
201 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
202 goto bad_sw_if_index;
203 }
204 bd_index = p[0];
205
206 if (mp->is_add)
207 {
208 filter_mac = mp->filter_mac ? 1 : 0;
209 if (filter_mac == 0)
210 {
211 VALIDATE_SW_IF_INDEX (mp);
212 if (vec_len (l2im->configs) <= sw_if_index)
213 {
214 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
215 goto bad_sw_if_index;
216 }
217 else
218 {
219 l2_input_config_t *config;
220 config = vec_elt_at_index (l2im->configs, sw_if_index);
221 if (config->bridge == 0)
222 {
223 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
224 goto bad_sw_if_index;
225 }
226 }
227 }
228 static_mac = mp->static_mac ? 1 : 0;
229 bvi_mac = mp->bvi_mac ? 1 : 0;
230 l2fib_add_entry (mac, bd_index, sw_if_index, static_mac, filter_mac,
231 bvi_mac);
232 }
233 else
234 {
235 l2fib_del_entry (mac, bd_index);
236 }
237
238 BAD_SW_IF_INDEX_LABEL;
239
240 REPLY_MACRO (VL_API_L2FIB_ADD_DEL_REPLY);
241}
242
243static void
Eyal Barif24991c2017-04-05 05:33:21 +0300244vl_api_l2fib_flush_int_t_handler (vl_api_l2fib_flush_int_t * mp)
245{
246 int rv = 0;
247 vlib_main_t *vm = vlib_get_main ();
248 vl_api_l2fib_flush_int_reply_t *rmp;
249
250 VALIDATE_SW_IF_INDEX (mp);
251
252 u32 sw_if_index = ntohl (mp->sw_if_index);
253 l2fib_flush_int_mac (vm, sw_if_index);
254
255 BAD_SW_IF_INDEX_LABEL;
256 REPLY_MACRO (VL_API_L2FIB_FLUSH_INT_REPLY);
257}
258
259static void
Eyal Bari7537e712017-04-27 14:07:55 +0300260vl_api_l2fib_flush_all_t_handler (vl_api_l2fib_flush_all_t * mp)
261{
262 int rv = 0;
263 vl_api_l2fib_flush_all_reply_t *rmp;
264
265 l2fib_flush_all_mac (vlib_get_main ());
266 REPLY_MACRO (VL_API_L2FIB_FLUSH_ALL_REPLY);
267}
268
269static void
Eyal Barif24991c2017-04-05 05:33:21 +0300270vl_api_l2fib_flush_bd_t_handler (vl_api_l2fib_flush_bd_t * mp)
271{
272 int rv = 0;
273 vlib_main_t *vm = vlib_get_main ();
274 bd_main_t *bdm = &bd_main;
275 vl_api_l2fib_flush_bd_reply_t *rmp;
276
277 u32 bd_id = ntohl (mp->bd_id);
278 uword *p = hash_get (bdm->bd_index_by_bd_id, bd_id);
279 if (p == 0)
280 {
281 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
282 goto out;
283 }
284 l2fib_flush_bd_mac (vm, *p);
285out:
286 REPLY_MACRO (VL_API_L2FIB_FLUSH_BD_REPLY);
287}
288
289static void
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100290vl_api_l2_flags_t_handler (vl_api_l2_flags_t * mp)
291{
292 vl_api_l2_flags_reply_t *rmp;
293 int rv = 0;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100294 u32 rbm = 0;
295
296 VALIDATE_SW_IF_INDEX (mp);
297
Eyal Barifead6702017-04-04 04:46:32 +0300298 u32 sw_if_index = ntohl (mp->sw_if_index);
299 u32 flags = ntohl (mp->feature_bitmap) & L2INPUT_VALID_MASK;
300 rbm = l2input_intf_bitmap_enable (sw_if_index, flags, mp->is_set);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100301
302 BAD_SW_IF_INDEX_LABEL;
303
304 /* *INDENT-OFF* */
305 REPLY_MACRO2(VL_API_L2_FLAGS_REPLY,
306 ({
307 rmp->resulting_feature_bitmap = ntohl(rbm);
308 }));
309 /* *INDENT-ON* */
310}
311
312static void
Eyal Barifead6702017-04-04 04:46:32 +0300313vl_api_bridge_domain_set_mac_age_t_handler (vl_api_bridge_domain_set_mac_age_t
314 * mp)
315{
316 vlib_main_t *vm = vlib_get_main ();
317 bd_main_t *bdm = &bd_main;
318 vl_api_bridge_domain_set_mac_age_reply_t *rmp;
319 int rv = 0;
320 u32 bd_id = ntohl (mp->bd_id);
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500321 uword *p;
322
323 if (bd_id == 0)
324 {
325 rv = VNET_API_ERROR_BD_NOT_MODIFIABLE;
326 goto out;
327 }
328
329 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
Eyal Barifead6702017-04-04 04:46:32 +0300330 if (p == 0)
331 {
332 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
333 goto out;
334 }
335 bd_set_mac_age (vm, *p, mp->mac_age);
336out:
337 REPLY_MACRO (VL_API_BRIDGE_DOMAIN_SET_MAC_AGE_REPLY);
338}
339
340static void
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100341vl_api_bridge_domain_add_del_t_handler (vl_api_bridge_domain_add_del_t * mp)
342{
Eyal Barib1352ed2017-04-07 23:14:17 +0300343 l2_bridge_domain_add_del_args_t a = {
344 .is_add = mp->is_add,
345 .flood = mp->flood,
346 .uu_flood = mp->uu_flood,
347 .forward = mp->forward,
348 .learn = mp->learn,
349 .arp_term = mp->arp_term,
350 .mac_age = mp->mac_age,
351 .bd_id = ntohl (mp->bd_id),
352 };
353
354 int rv = bd_add_del (&a);
355
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100356 vl_api_bridge_domain_add_del_reply_t *rmp;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100357 REPLY_MACRO (VL_API_BRIDGE_DOMAIN_ADD_DEL_REPLY);
358}
359
360static void
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100361send_bridge_domain_details (unix_shared_memory_queue_t * q,
362 l2_bridge_domain_t * bd_config,
363 u32 n_sw_ifs, u32 context)
364{
365 vl_api_bridge_domain_details_t *mp;
366
367 mp = vl_msg_api_alloc (sizeof (*mp));
368 memset (mp, 0, sizeof (*mp));
369 mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_DETAILS);
370 mp->bd_id = ntohl (bd_config->bd_id);
371 mp->flood = bd_feature_flood (bd_config);
372 mp->uu_flood = bd_feature_uu_flood (bd_config);
373 mp->forward = bd_feature_forward (bd_config);
374 mp->learn = bd_feature_learn (bd_config);
375 mp->arp_term = bd_feature_arp_term (bd_config);
376 mp->bvi_sw_if_index = ntohl (bd_config->bvi_sw_if_index);
377 mp->mac_age = bd_config->mac_age;
378 mp->n_sw_ifs = ntohl (n_sw_ifs);
379 mp->context = context;
380
381 vl_msg_api_send_shmem (q, (u8 *) & mp);
382}
383
384static void
385send_bd_sw_if_details (l2input_main_t * l2im,
386 unix_shared_memory_queue_t * q,
387 l2_flood_member_t * member, u32 bd_id, u32 context)
388{
389 vl_api_bridge_domain_sw_if_details_t *mp;
390 l2_input_config_t *input_cfg;
391
392 mp = vl_msg_api_alloc (sizeof (*mp));
393 memset (mp, 0, sizeof (*mp));
394 mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_SW_IF_DETAILS);
395 mp->bd_id = ntohl (bd_id);
396 mp->sw_if_index = ntohl (member->sw_if_index);
397 input_cfg = vec_elt_at_index (l2im->configs, member->sw_if_index);
398 mp->shg = input_cfg->shg;
399 mp->context = context;
400
401 vl_msg_api_send_shmem (q, (u8 *) & mp);
402}
403
404static void
405vl_api_bridge_domain_dump_t_handler (vl_api_bridge_domain_dump_t * mp)
406{
407 bd_main_t *bdm = &bd_main;
408 l2input_main_t *l2im = &l2input_main;
409 unix_shared_memory_queue_t *q;
410 l2_bridge_domain_t *bd_config;
411 u32 bd_id, bd_index;
412 u32 end;
413
414 q = vl_api_client_index_to_input_queue (mp->client_index);
415
416 if (q == 0)
417 return;
418
419 bd_id = ntohl (mp->bd_id);
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500420 if (bd_id == 0)
421 return;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100422
Eyal Barib1352ed2017-04-07 23:14:17 +0300423 bd_index = (bd_id == ~0) ? 0 : bd_find_index (bdm, bd_id);
424 ASSERT (bd_index != ~0);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100425 end = (bd_id == ~0) ? vec_len (l2im->bd_configs) : bd_index + 1;
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500426
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100427 for (; bd_index < end; bd_index++)
428 {
429 bd_config = l2input_bd_config_from_index (l2im, bd_index);
430 /* skip dummy bd_id 0 */
431 if (bd_config && (bd_config->bd_id > 0))
432 {
433 u32 n_sw_ifs;
434 l2_flood_member_t *m;
435
436 n_sw_ifs = vec_len (bd_config->members);
437 send_bridge_domain_details (q, bd_config, n_sw_ifs, mp->context);
438
439 vec_foreach (m, bd_config->members)
440 {
441 send_bd_sw_if_details (l2im, q, m, bd_config->bd_id, mp->context);
442 }
443 }
444 }
445}
446
447static void
448vl_api_bridge_flags_t_handler (vl_api_bridge_flags_t * mp)
449{
450 vlib_main_t *vm = vlib_get_main ();
451 bd_main_t *bdm = &bd_main;
452 vl_api_bridge_flags_reply_t *rmp;
453 int rv = 0;
454 u32 bd_id = ntohl (mp->bd_id);
455 u32 bd_index;
456 u32 flags = ntohl (mp->feature_bitmap);
457 uword *p;
458
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500459 if (bd_id == 0)
460 {
461 rv = VNET_API_ERROR_BD_NOT_MODIFIABLE;
462 goto out;
463 }
464
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100465 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
466 if (p == 0)
467 {
468 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
469 goto out;
470 }
471
472 bd_index = p[0];
473
474 bd_set_flags (vm, bd_index, flags, mp->is_set);
475
476out:
477 /* *INDENT-OFF* */
478 REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY,
479 ({
480 rmp->resulting_feature_bitmap = ntohl(flags);
481 }));
482 /* *INDENT-ON* */
483}
Matus Fabianf468e232016-12-02 06:00:53 -0800484
Pavel Kotucekadec5872017-01-25 08:50:53 +0100485static void
486 vl_api_l2_interface_vlan_tag_rewrite_t_handler
487 (vl_api_l2_interface_vlan_tag_rewrite_t * mp)
488{
489 int rv = 0;
490 vl_api_l2_interface_vlan_tag_rewrite_reply_t *rmp;
491 vnet_main_t *vnm = vnet_get_main ();
492 vlib_main_t *vm = vlib_get_main ();
493 u32 vtr_op;
494
495 VALIDATE_SW_IF_INDEX (mp);
496
497 vtr_op = ntohl (mp->vtr_op);
498
499 /* The L2 code is unsuspicious */
500 switch (vtr_op)
501 {
502 case L2_VTR_DISABLED:
503 case L2_VTR_PUSH_1:
504 case L2_VTR_PUSH_2:
505 case L2_VTR_POP_1:
506 case L2_VTR_POP_2:
507 case L2_VTR_TRANSLATE_1_1:
508 case L2_VTR_TRANSLATE_1_2:
509 case L2_VTR_TRANSLATE_2_1:
510 case L2_VTR_TRANSLATE_2_2:
511 break;
512
513 default:
514 rv = VNET_API_ERROR_INVALID_VALUE;
515 goto bad_sw_if_index;
516 }
517
518 rv = l2vtr_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
519 ntohl (mp->push_dot1q), ntohl (mp->tag1),
520 ntohl (mp->tag2));
521
522 BAD_SW_IF_INDEX_LABEL;
523
524 REPLY_MACRO (VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
525}
526
527static void
528 vl_api_l2_interface_pbb_tag_rewrite_t_handler
529 (vl_api_l2_interface_pbb_tag_rewrite_t * mp)
530{
531 vl_api_l2_interface_pbb_tag_rewrite_reply_t *rmp;
532 vnet_main_t *vnm = vnet_get_main ();
533 vlib_main_t *vm = vlib_get_main ();
534 u32 vtr_op;
535 int rv = 0;
536
537 VALIDATE_SW_IF_INDEX (mp);
538
539 vtr_op = ntohl (mp->vtr_op);
540
541 switch (vtr_op)
542 {
543 case L2_VTR_DISABLED:
544 case L2_VTR_PUSH_2:
545 case L2_VTR_POP_2:
546 case L2_VTR_TRANSLATE_2_1:
547 break;
548
549 default:
550 rv = VNET_API_ERROR_INVALID_VALUE;
551 goto bad_sw_if_index;
552 }
553
554 rv = l2pbb_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
555 mp->b_dmac, mp->b_smac, ntohs (mp->b_vlanid),
556 ntohl (mp->i_sid), ntohs (mp->outer_tag));
557
558 BAD_SW_IF_INDEX_LABEL;
559
560 REPLY_MACRO (VL_API_L2_INTERFACE_PBB_TAG_REWRITE_REPLY);
561}
562
Matus Fabianf468e232016-12-02 06:00:53 -0800563/*
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100564 * l2_api_hookup
Matus Fabianf468e232016-12-02 06:00:53 -0800565 * Add vpe's API message handlers to the table.
566 * vlib has alread mapped shared memory and
567 * added the client registration handlers.
568 * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
569 */
570#define vl_msg_name_crc_list
571#include <vnet/vnet_all_api_h.h>
572#undef vl_msg_name_crc_list
573
574static void
575setup_message_id_table (api_main_t * am)
576{
577#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
578 foreach_vl_msg_name_crc_l2;
579#undef _
580}
581
582static clib_error_t *
583l2_api_hookup (vlib_main_t * vm)
584{
585 api_main_t *am = &api_main;
586
587#define _(N,n) \
588 vl_msg_api_set_handlers(VL_API_##N, #n, \
589 vl_api_##n##_t_handler, \
590 vl_noop_handler, \
591 vl_api_##n##_t_endian, \
592 vl_api_##n##_t_print, \
593 sizeof(vl_api_##n##_t), 1);
594 foreach_vpe_api_msg;
595#undef _
596
597 /*
598 * Set up the (msg_name, crc, message-id) table
599 */
600 setup_message_id_table (am);
601
602 return 0;
603}
604
605VLIB_API_INIT_FUNCTION (l2_api_hookup);
606
607/*
608 * fd.io coding-style-patch-verification: ON
609 *
610 * Local Variables:
611 * eval: (c-set-style "gnu")
612 * End:
613 */