c11 safe string handling support
[vpp.git] / src / vnet / classify / classify_api.c
1 /*
2  *------------------------------------------------------------------
3  * classify_api.c - classify 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
26 #include <vnet/classify/vnet_classify.h>
27 #include <vnet/classify/in_out_acl.h>
28 #include <vnet/classify/policer_classify.h>
29 #include <vnet/classify/flow_classify.h>
30 #include <vnet/l2/l2_classify.h>
31
32 #include <vnet/vnet_msg_enum.h>
33
34 #define vl_typedefs             /* define message structures */
35 #include <vnet/vnet_all_api_h.h>
36 #undef vl_typedefs
37
38 #define vl_endianfun            /* define message structures */
39 #include <vnet/vnet_all_api_h.h>
40 #undef vl_endianfun
41
42 /* instantiate all the print functions we know about */
43 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
44 #define vl_printfun
45 #include <vnet/vnet_all_api_h.h>
46 #undef vl_printfun
47
48 #include <vlibapi/api_helper_macros.h>
49
50 #define foreach_vpe_api_msg                                             \
51 _(CLASSIFY_ADD_DEL_TABLE, classify_add_del_table)                       \
52 _(CLASSIFY_ADD_DEL_SESSION, classify_add_del_session)                   \
53 _(CLASSIFY_TABLE_IDS,classify_table_ids)                                \
54 _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface)             \
55 _(CLASSIFY_TABLE_INFO,classify_table_info)                              \
56 _(CLASSIFY_SESSION_DUMP,classify_session_dump)                          \
57 _(POLICER_CLASSIFY_SET_INTERFACE, policer_classify_set_interface)       \
58 _(POLICER_CLASSIFY_DUMP, policer_classify_dump)                         \
59 _(FLOW_CLASSIFY_SET_INTERFACE, flow_classify_set_interface)             \
60 _(FLOW_CLASSIFY_DUMP, flow_classify_dump)                               \
61 _(INPUT_ACL_SET_INTERFACE, input_acl_set_interface)                     \
62 _(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table)     \
63 _(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables)   \
64 _(OUTPUT_ACL_SET_INTERFACE, output_acl_set_interface)
65
66 #define foreach_classify_add_del_table_field    \
67 _(table_index)                                  \
68 _(nbuckets)                                     \
69 _(memory_size)                                  \
70 _(skip_n_vectors)                               \
71 _(match_n_vectors)                              \
72 _(next_table_index)                             \
73 _(miss_next_index)                              \
74 _(current_data_flag)                            \
75 _(current_data_offset)                          \
76 _(mask_len)
77
78 static void vl_api_classify_add_del_table_t_handler
79   (vl_api_classify_add_del_table_t * mp)
80 {
81   vl_api_classify_add_del_table_reply_t *rmp;
82   vnet_classify_main_t *cm = &vnet_classify_main;
83   vnet_classify_table_t *t;
84   int rv;
85
86 #define _(a) u32 a;
87   foreach_classify_add_del_table_field;
88 #undef _
89
90 #define _(a) a = ntohl(mp->a);
91   foreach_classify_add_del_table_field;
92 #undef _
93
94   if (mask_len != match_n_vectors * sizeof (u32x4))
95     {
96       rv = VNET_API_ERROR_INVALID_VALUE;
97       goto out;
98     }
99
100   /* The underlying API fails silently, on purpose, so check here */
101   if (mp->is_add == 0)          /* delete */
102     {
103       if (pool_is_free_index (cm->tables, table_index))
104         {
105           rv = VNET_API_ERROR_NO_SUCH_TABLE;
106           goto out;
107         }
108     }
109   else                          /* add or update */
110     {
111       if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
112         table_index = ~0;
113     }
114
115   rv = vnet_classify_add_del_table
116     (cm, mp->mask, nbuckets, memory_size,
117      skip_n_vectors, match_n_vectors,
118      next_table_index, miss_next_index, &table_index,
119      current_data_flag, current_data_offset, mp->is_add, mp->del_chain);
120
121 out:
122   /* *INDENT-OFF* */
123   REPLY_MACRO2(VL_API_CLASSIFY_ADD_DEL_TABLE_REPLY,
124   ({
125     if (rv == 0 && mp->is_add)
126       {
127         t = pool_elt_at_index (cm->tables, table_index);
128         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
129         rmp->match_n_vectors = ntohl(t->match_n_vectors);
130         rmp->new_table_index = ntohl(table_index);
131       }
132     else
133       {
134         rmp->skip_n_vectors = ~0;
135         rmp->match_n_vectors = ~0;
136         rmp->new_table_index = ~0;
137       }
138   }));
139   /* *INDENT-ON* */
140 }
141
142 static void vl_api_classify_add_del_session_t_handler
143   (vl_api_classify_add_del_session_t * mp)
144 {
145   vnet_classify_main_t *cm = &vnet_classify_main;
146   vl_api_classify_add_del_session_reply_t *rmp;
147   int rv;
148   u32 table_index, hit_next_index, opaque_index, metadata, match_len;
149   i32 advance;
150   u8 action;
151   vnet_classify_table_t *t;
152
153   table_index = ntohl (mp->table_index);
154   hit_next_index = ntohl (mp->hit_next_index);
155   opaque_index = ntohl (mp->opaque_index);
156   advance = ntohl (mp->advance);
157   action = mp->action;
158   metadata = ntohl (mp->metadata);
159   match_len = ntohl (mp->match_len);
160
161   if (pool_is_free_index (cm->tables, table_index))
162     {
163       rv = VNET_API_ERROR_NO_SUCH_TABLE;
164       goto out;
165     }
166
167   t = pool_elt_at_index (cm->tables, table_index);
168
169   if (match_len != (t->skip_n_vectors + t->match_n_vectors) * sizeof (u32x4))
170     {
171       rv = VNET_API_ERROR_INVALID_VALUE;
172       goto out;
173     }
174
175   rv = vnet_classify_add_del_session
176     (cm, table_index, mp->match, hit_next_index, opaque_index,
177      advance, action, metadata, mp->is_add);
178
179 out:
180   REPLY_MACRO (VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
181 }
182
183 static void
184   vl_api_policer_classify_set_interface_t_handler
185   (vl_api_policer_classify_set_interface_t * mp)
186 {
187   vlib_main_t *vm = vlib_get_main ();
188   vl_api_policer_classify_set_interface_reply_t *rmp;
189   int rv;
190   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
191
192   ip4_table_index = ntohl (mp->ip4_table_index);
193   ip6_table_index = ntohl (mp->ip6_table_index);
194   l2_table_index = ntohl (mp->l2_table_index);
195   sw_if_index = ntohl (mp->sw_if_index);
196
197   VALIDATE_SW_IF_INDEX (mp);
198
199   rv = vnet_set_policer_classify_intfc (vm, sw_if_index, ip4_table_index,
200                                         ip6_table_index, l2_table_index,
201                                         mp->is_add);
202
203   BAD_SW_IF_INDEX_LABEL;
204
205   REPLY_MACRO (VL_API_POLICER_CLASSIFY_SET_INTERFACE_REPLY);
206 }
207
208 static void
209 send_policer_classify_details (u32 sw_if_index,
210                                u32 table_index, vl_api_registration_t * reg,
211                                u32 context)
212 {
213   vl_api_policer_classify_details_t *mp;
214
215   mp = vl_msg_api_alloc (sizeof (*mp));
216   clib_memset (mp, 0, sizeof (*mp));
217   mp->_vl_msg_id = ntohs (VL_API_POLICER_CLASSIFY_DETAILS);
218   mp->context = context;
219   mp->sw_if_index = htonl (sw_if_index);
220   mp->table_index = htonl (table_index);
221
222   vl_api_send_msg (reg, (u8 *) mp);
223 }
224
225 static void
226 vl_api_policer_classify_dump_t_handler (vl_api_policer_classify_dump_t * mp)
227 {
228   vl_api_registration_t *reg;
229   policer_classify_main_t *pcm = &policer_classify_main;
230   u32 *vec_tbl;
231   int i;
232
233   reg = vl_api_client_index_to_registration (mp->client_index);
234   if (!reg)
235     return;
236
237   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
238
239   if (vec_len (vec_tbl))
240     {
241       for (i = 0; i < vec_len (vec_tbl); i++)
242         {
243           if (vec_elt (vec_tbl, i) == ~0)
244             continue;
245
246           send_policer_classify_details (i, vec_elt (vec_tbl, i), reg,
247                                          mp->context);
248         }
249     }
250 }
251
252 static void
253 vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp)
254 {
255   vl_api_registration_t *reg;
256
257   reg = vl_api_client_index_to_registration (mp->client_index);
258   if (!reg)
259     return;
260
261   vnet_classify_main_t *cm = &vnet_classify_main;
262   vnet_classify_table_t *t;
263   u32 *table_ids = 0;
264   u32 count;
265
266    /* *INDENT-OFF* */
267    pool_foreach (t, cm->tables,
268    ({
269      vec_add1 (table_ids, ntohl(t - cm->tables));
270    }));
271    /* *INDENT-ON* */
272   count = vec_len (table_ids);
273
274   vl_api_classify_table_ids_reply_t *rmp;
275   rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
276   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY);
277   rmp->context = mp->context;
278   rmp->count = ntohl (count);
279   clib_memcpy (rmp->ids, table_ids, count * sizeof (u32));
280   rmp->retval = 0;
281
282   vl_api_send_msg (reg, (u8 *) rmp);
283
284   vec_free (table_ids);
285 }
286
287 static void
288   vl_api_classify_table_by_interface_t_handler
289   (vl_api_classify_table_by_interface_t * mp)
290 {
291   vl_api_classify_table_by_interface_reply_t *rmp;
292   int rv = 0;
293
294   u32 sw_if_index = ntohl (mp->sw_if_index);
295   u32 *acl = 0;
296
297   vec_validate (acl, IN_OUT_ACL_N_TABLES - 1);
298   vec_set (acl, ~0);
299
300   VALIDATE_SW_IF_INDEX (mp);
301
302   in_out_acl_main_t *am = &in_out_acl_main;
303
304   int if_idx;
305   u32 type;
306
307   for (type = 0; type < IN_OUT_ACL_N_TABLES; type++)
308     {
309       u32 *vec_tbl =
310         am->classify_table_index_by_sw_if_index[IN_OUT_ACL_INPUT_TABLE_GROUP]
311         [type];
312       if (vec_len (vec_tbl))
313         {
314           for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
315             {
316               if (vec_elt (vec_tbl, if_idx) == ~0 || sw_if_index != if_idx)
317                 {
318                   continue;
319                 }
320               acl[type] = vec_elt (vec_tbl, if_idx);
321             }
322         }
323     }
324
325   BAD_SW_IF_INDEX_LABEL;
326
327    /* *INDENT-OFF* */
328    REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
329    ({
330      rmp->sw_if_index = ntohl(sw_if_index);
331      rmp->l2_table_id = ntohl(acl[IN_OUT_ACL_TABLE_L2]);
332      rmp->ip4_table_id = ntohl(acl[IN_OUT_ACL_TABLE_IP4]);
333      rmp->ip6_table_id = ntohl(acl[IN_OUT_ACL_TABLE_IP6]);
334    }));
335    /* *INDENT-ON* */
336   vec_free (acl);
337 }
338
339 static void
340 vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t * mp)
341 {
342   vl_api_registration_t *reg;
343
344   reg = vl_api_client_index_to_registration (mp->client_index);
345   if (!reg)
346     return;
347
348   vl_api_classify_table_info_reply_t *rmp = 0;
349
350   vnet_classify_main_t *cm = &vnet_classify_main;
351   u32 table_id = ntohl (mp->table_id);
352   vnet_classify_table_t *t;
353
354    /* *INDENT-OFF* */
355    pool_foreach (t, cm->tables,
356    ({
357      if (table_id == t - cm->tables)
358        {
359          rmp = vl_msg_api_alloc_as_if_client
360            (sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
361          rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
362          rmp->context = mp->context;
363          rmp->table_id = ntohl(table_id);
364          rmp->nbuckets = ntohl(t->nbuckets);
365          rmp->match_n_vectors = ntohl(t->match_n_vectors);
366          rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
367          rmp->active_sessions = ntohl(t->active_elements);
368          rmp->next_table_index = ntohl(t->next_table_index);
369          rmp->miss_next_index = ntohl(t->miss_next_index);
370          rmp->mask_length = ntohl(t->match_n_vectors * sizeof (u32x4));
371          clib_memcpy(rmp->mask, t->mask, t->match_n_vectors * sizeof(u32x4));
372          rmp->retval = 0;
373          break;
374        }
375    }));
376    /* *INDENT-ON* */
377
378   if (rmp == 0)
379     {
380       rmp = vl_msg_api_alloc (sizeof (*rmp));
381       rmp->_vl_msg_id = ntohs ((VL_API_CLASSIFY_TABLE_INFO_REPLY));
382       rmp->context = mp->context;
383       rmp->retval = ntohl (VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
384     }
385
386   vl_api_send_msg (reg, (u8 *) rmp);
387 }
388
389 static void
390 send_classify_session_details (vl_api_registration_t * reg,
391                                u32 table_id,
392                                u32 match_length,
393                                vnet_classify_entry_t * e, u32 context)
394 {
395   vl_api_classify_session_details_t *rmp;
396
397   rmp = vl_msg_api_alloc (sizeof (*rmp));
398   clib_memset (rmp, 0, sizeof (*rmp));
399   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_SESSION_DETAILS);
400   rmp->context = context;
401   rmp->table_id = ntohl (table_id);
402   rmp->hit_next_index = ntohl (e->next_index);
403   rmp->advance = ntohl (e->advance);
404   rmp->opaque_index = ntohl (e->opaque_index);
405   rmp->match_length = ntohl (match_length);
406   clib_memcpy (rmp->match, e->key, match_length);
407
408   vl_api_send_msg (reg, (u8 *) rmp);
409 }
410
411 static void
412 vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp)
413 {
414   vnet_classify_main_t *cm = &vnet_classify_main;
415   vl_api_registration_t *reg;
416
417   u32 table_id = ntohl (mp->table_id);
418   vnet_classify_table_t *t;
419
420   reg = vl_api_client_index_to_registration (mp->client_index);
421   if (!reg)
422     return;
423
424   /* *INDENT-OFF* */
425   pool_foreach (t, cm->tables,
426   ({
427     if (table_id == t - cm->tables)
428       {
429         vnet_classify_bucket_t * b;
430         vnet_classify_entry_t * v, * save_v;
431         int i, j, k;
432
433         for (i = 0; i < t->nbuckets; i++)
434           {
435             b = &t->buckets [i];
436             if (b->offset == 0)
437               continue;
438
439             save_v = vnet_classify_get_entry (t, b->offset);
440             for (j = 0; j < (1<<b->log2_pages); j++)
441               {
442                 for (k = 0; k < t->entries_per_page; k++)
443                   {
444                     v = vnet_classify_entry_at_index
445                       (t, save_v, j*t->entries_per_page + k);
446                     if (vnet_classify_entry_is_free (v))
447                       continue;
448
449                     send_classify_session_details
450                       (reg, table_id, t->match_n_vectors * sizeof (u32x4),
451                        v, mp->context);
452                   }
453               }
454           }
455         break;
456       }
457   }));
458   /* *INDENT-ON* */
459 }
460
461 static void
462   vl_api_flow_classify_set_interface_t_handler
463   (vl_api_flow_classify_set_interface_t * mp)
464 {
465   vlib_main_t *vm = vlib_get_main ();
466   vl_api_flow_classify_set_interface_reply_t *rmp;
467   int rv;
468   u32 sw_if_index, ip4_table_index, ip6_table_index;
469
470   ip4_table_index = ntohl (mp->ip4_table_index);
471   ip6_table_index = ntohl (mp->ip6_table_index);
472   sw_if_index = ntohl (mp->sw_if_index);
473
474   VALIDATE_SW_IF_INDEX (mp);
475
476   rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index,
477                                      ip6_table_index, mp->is_add);
478
479   BAD_SW_IF_INDEX_LABEL;
480
481   REPLY_MACRO (VL_API_FLOW_CLASSIFY_SET_INTERFACE_REPLY);
482 }
483
484 static void
485 send_flow_classify_details (u32 sw_if_index,
486                             u32 table_index, vl_api_registration_t * reg,
487                             u32 context)
488 {
489   vl_api_flow_classify_details_t *mp;
490
491   mp = vl_msg_api_alloc (sizeof (*mp));
492   clib_memset (mp, 0, sizeof (*mp));
493   mp->_vl_msg_id = ntohs (VL_API_FLOW_CLASSIFY_DETAILS);
494   mp->context = context;
495   mp->sw_if_index = htonl (sw_if_index);
496   mp->table_index = htonl (table_index);
497
498   vl_api_send_msg (reg, (u8 *) mp);
499 }
500
501 static void
502 vl_api_flow_classify_dump_t_handler (vl_api_flow_classify_dump_t * mp)
503 {
504   vl_api_registration_t *reg;
505   flow_classify_main_t *pcm = &flow_classify_main;
506   u32 *vec_tbl;
507   int i;
508
509   reg = vl_api_client_index_to_registration (mp->client_index);
510   if (!reg)
511     return;
512
513   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
514
515   if (vec_len (vec_tbl))
516     {
517       for (i = 0; i < vec_len (vec_tbl); i++)
518         {
519           if (vec_elt (vec_tbl, i) == ~0)
520             continue;
521
522           send_flow_classify_details (i, vec_elt (vec_tbl, i), reg,
523                                       mp->context);
524         }
525     }
526 }
527
528 static void vl_api_classify_set_interface_ip_table_t_handler
529   (vl_api_classify_set_interface_ip_table_t * mp)
530 {
531   vlib_main_t *vm = vlib_get_main ();
532   vl_api_classify_set_interface_ip_table_reply_t *rmp;
533   int rv;
534
535   VALIDATE_SW_IF_INDEX (mp);
536
537   u32 table_index = ntohl (mp->table_index);
538   u32 sw_if_index = ntohl (mp->sw_if_index);
539
540   if (mp->is_ipv6)
541     rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
542   else
543     rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
544
545   BAD_SW_IF_INDEX_LABEL;
546
547   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
548 }
549
550 static void vl_api_classify_set_interface_l2_tables_t_handler
551   (vl_api_classify_set_interface_l2_tables_t * mp)
552 {
553   vl_api_classify_set_interface_l2_tables_reply_t *rmp;
554   int rv;
555   u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
556   int enable;
557
558   ip4_table_index = ntohl (mp->ip4_table_index);
559   ip6_table_index = ntohl (mp->ip6_table_index);
560   other_table_index = ntohl (mp->other_table_index);
561   sw_if_index = ntohl (mp->sw_if_index);
562
563   VALIDATE_SW_IF_INDEX (mp);
564
565   if (mp->is_input)
566     rv = vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
567                                             ip6_table_index,
568                                             other_table_index);
569   else
570     rv = vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
571                                              ip6_table_index,
572                                              other_table_index);
573
574   if (rv == 0)
575     {
576       if (ip4_table_index != ~0 || ip6_table_index != ~0
577           || other_table_index != ~0)
578         enable = 1;
579       else
580         enable = 0;
581
582       if (mp->is_input)
583         vnet_l2_input_classify_enable_disable (sw_if_index, enable);
584       else
585         vnet_l2_output_classify_enable_disable (sw_if_index, enable);
586     }
587
588   BAD_SW_IF_INDEX_LABEL;
589
590   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
591 }
592
593 static void vl_api_input_acl_set_interface_t_handler
594   (vl_api_input_acl_set_interface_t * mp)
595 {
596   vlib_main_t *vm = vlib_get_main ();
597   vl_api_input_acl_set_interface_reply_t *rmp;
598   int rv;
599
600   VALIDATE_SW_IF_INDEX (mp);
601
602   u32 ip4_table_index = ntohl (mp->ip4_table_index);
603   u32 ip6_table_index = ntohl (mp->ip6_table_index);
604   u32 l2_table_index = ntohl (mp->l2_table_index);
605   u32 sw_if_index = ntohl (mp->sw_if_index);
606
607   rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
608                                  ip6_table_index, l2_table_index, mp->is_add);
609
610   BAD_SW_IF_INDEX_LABEL;
611
612   REPLY_MACRO (VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
613 }
614
615 static void vl_api_output_acl_set_interface_t_handler
616   (vl_api_output_acl_set_interface_t * mp)
617 {
618   vlib_main_t *vm = vlib_get_main ();
619   vl_api_output_acl_set_interface_reply_t *rmp;
620   int rv;
621
622   VALIDATE_SW_IF_INDEX (mp);
623
624   u32 ip4_table_index = ntohl (mp->ip4_table_index);
625   u32 ip6_table_index = ntohl (mp->ip6_table_index);
626   u32 l2_table_index = ntohl (mp->l2_table_index);
627   u32 sw_if_index = ntohl (mp->sw_if_index);
628
629   rv = vnet_set_output_acl_intfc (vm, sw_if_index, ip4_table_index,
630                                   ip6_table_index, l2_table_index,
631                                   mp->is_add);
632
633   BAD_SW_IF_INDEX_LABEL;
634
635   REPLY_MACRO (VL_API_OUTPUT_ACL_SET_INTERFACE_REPLY);
636 }
637
638 /*
639  * classify_api_hookup
640  * Add vpe's API message handlers to the table.
641  * vlib has alread mapped shared memory and
642  * added the client registration handlers.
643  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
644  */
645 #define vl_msg_name_crc_list
646 #include <vnet/vnet_all_api_h.h>
647 #undef vl_msg_name_crc_list
648
649 static void
650 setup_message_id_table (api_main_t * am)
651 {
652 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
653   foreach_vl_msg_name_crc_classify;
654 #undef _
655 }
656
657 static clib_error_t *
658 classify_api_hookup (vlib_main_t * vm)
659 {
660   api_main_t *am = &api_main;
661
662 #define _(N,n)                                                  \
663     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
664                            vl_api_##n##_t_handler,              \
665                            vl_noop_handler,                     \
666                            vl_api_##n##_t_endian,               \
667                            vl_api_##n##_t_print,                \
668                            sizeof(vl_api_##n##_t), 1);
669   foreach_vpe_api_msg;
670 #undef _
671
672   /*
673    * Set up the (msg_name, crc, message-id) table
674    */
675   setup_message_id_table (am);
676
677   return 0;
678 }
679
680 VLIB_API_INIT_FUNCTION (classify_api_hookup);
681
682 /*
683  * fd.io coding-style-patch-verification: ON
684  *
685  * Local Variables:
686  * eval: (c-set-style "gnu")
687  * End:
688  */