blob: 606eaa612aed676066c3cbdd7e06d59605bed895 [file] [log] [blame]
Pavel Kotucek0f971d82017-01-03 10:48:54 +01001/*
2 *------------------------------------------------------------------
3 * sr_api.c - ipv6 segment routing 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>
Pablo Camarillo5d73eec2017-04-24 17:51:56 +020021#include <vnet/srv6/sr.h>
Pavel Kotucek0f971d82017-01-03 10:48:54 +010022#include <vlibmemory/api.h>
23
24#include <vnet/interface.h>
25#include <vnet/api_errno.h>
26#include <vnet/feature/feature.h>
Ahmed Abdelsalam13e6fce2019-12-08 12:58:27 +010027#include <vnet/fib/fib_table.h>
Pavel Kotucek0f971d82017-01-03 10:48:54 +010028
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
47#define foreach_vpe_api_msg \
Pablo Camarillofb380952016-12-07 18:34:18 +010048_(SR_LOCALSID_ADD_DEL, sr_localsid_add_del) \
Pablo Camarillo3337bd22018-06-19 15:49:02 +020049_(SR_POLICY_ADD, sr_policy_add) \
50_(SR_POLICY_MOD, sr_policy_mod) \
Pablo Camarillofb380952016-12-07 18:34:18 +010051_(SR_POLICY_DEL, sr_policy_del) \
Pablo Camarillo1a5e3012017-11-16 16:02:50 +010052_(SR_STEERING_ADD_DEL, sr_steering_add_del) \
53_(SR_SET_ENCAP_SOURCE, sr_set_encap_source) \
Ignas Bačiuseeb5fb32019-10-03 17:15:38 +030054_(SR_SET_ENCAP_HOP_LIMIT, sr_set_encap_hop_limit) \
Pablo Camarillo3337bd22018-06-19 15:49:02 +020055_(SR_LOCALSIDS_DUMP, sr_localsids_dump) \
56_(SR_POLICIES_DUMP, sr_policies_dump) \
57_(SR_STEERING_POL_DUMP, sr_steering_pol_dump)
Pavel Kotucek0f971d82017-01-03 10:48:54 +010058
Pablo Camarillofb380952016-12-07 18:34:18 +010059static void vl_api_sr_localsid_add_del_t_handler
60 (vl_api_sr_localsid_add_del_t * mp)
Pavel Kotucek0f971d82017-01-03 10:48:54 +010061{
Pablo Camarillofb380952016-12-07 18:34:18 +010062 vl_api_sr_localsid_add_del_reply_t *rmp;
Pavel Kotucek0f971d82017-01-03 10:48:54 +010063 int rv = 0;
Pablo Camarillofb380952016-12-07 18:34:18 +010064/*
65 * int sr_cli_localsid (char is_del, ip6_address_t *localsid_addr,
66 * char end_psp, u8 behavior, u32 sw_if_index, u32 vlan_index, u32 fib_table,
67 * ip46_address_t *nh_addr, void *ls_plugin_mem)
68 */
Pablo Camarillo3337bd22018-06-19 15:49:02 +020069 if (mp->behavior == SR_BEHAVIOR_X ||
70 mp->behavior == SR_BEHAVIOR_DX6 ||
71 mp->behavior == SR_BEHAVIOR_DX4 || mp->behavior == SR_BEHAVIOR_DX2)
72 VALIDATE_SW_IF_INDEX (mp);
Chris Luke879ace32017-09-26 13:15:16 -040073
Pablo Camarillo3337bd22018-06-19 15:49:02 +020074 ip46_address_t prefix;
75
Dave Barachb7b92992018-10-17 10:38:51 -040076 clib_memset (&prefix, 0, sizeof (ip46_address_t));
Pablo Camarillo3337bd22018-06-19 15:49:02 +020077 if ((mp->nh_addr4[0] | mp->nh_addr4[1] | mp->
78 nh_addr4[2] | mp->nh_addr4[3]) != 0)
79 memcpy (&prefix.ip4, mp->nh_addr4, sizeof (prefix.ip4));
80 else
81 memcpy (&prefix.ip6, mp->nh_addr6, sizeof (prefix.ip6));
Chris Luke879ace32017-09-26 13:15:16 -040082
Pablo Camarillofb380952016-12-07 18:34:18 +010083 rv = sr_cli_localsid (mp->is_del,
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -080084 (ip6_address_t *) & mp->localsid, 0,
Pablo Camarillofb380952016-12-07 18:34:18 +010085 mp->end_psp,
86 mp->behavior,
87 ntohl (mp->sw_if_index),
88 ntohl (mp->vlan_index),
Pablo Camarillo3337bd22018-06-19 15:49:02 +020089 ntohl (mp->fib_table), &prefix, NULL);
Pablo Camarillofb380952016-12-07 18:34:18 +010090
Chris Luke879ace32017-09-26 13:15:16 -040091 BAD_SW_IF_INDEX_LABEL;
Pablo Camarillofb380952016-12-07 18:34:18 +010092 REPLY_MACRO (VL_API_SR_LOCALSID_ADD_DEL_REPLY);
93}
94
95static void
96vl_api_sr_policy_add_t_handler (vl_api_sr_policy_add_t * mp)
97{
98 vl_api_sr_policy_add_reply_t *rmp;
Pavel Kotucek0f971d82017-01-03 10:48:54 +010099 ip6_address_t *segments = 0, *seg;
Pablo Camarillo3337bd22018-06-19 15:49:02 +0200100 ip6_address_t *this_address = (ip6_address_t *) mp->sids.sids;
Pablo Camarillofb380952016-12-07 18:34:18 +0100101
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100102 int i;
Pablo Camarillo3337bd22018-06-19 15:49:02 +0200103 for (i = 0; i < mp->sids.num_sids; i++)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100104 {
105 vec_add2 (segments, seg, 1);
106 clib_memcpy (seg->as_u8, this_address->as_u8, sizeof (*this_address));
107 this_address++;
108 }
Pablo Camarillofb380952016-12-07 18:34:18 +0100109
110/*
111 * sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments,
Tetsuya Murakami70d8ef82019-12-04 18:57:46 -0800112 * u32 weight, u8 behavior, u32 fib_table, u8 is_encap,
113 * u16 behavior, void *plugin_mem)
Pablo Camarillofb380952016-12-07 18:34:18 +0100114 */
115 int rv = 0;
116 rv = sr_policy_add ((ip6_address_t *) & mp->bsid_addr,
117 segments,
Pablo Camarillo3337bd22018-06-19 15:49:02 +0200118 ntohl (mp->sids.weight),
Tetsuya Murakami70d8ef82019-12-04 18:57:46 -0800119 mp->type, ntohl (mp->fib_table), mp->is_encap, 0, NULL);
John Lod23d39c2018-09-13 15:08:08 -0400120 vec_free (segments);
Pablo Camarillofb380952016-12-07 18:34:18 +0100121
122 REPLY_MACRO (VL_API_SR_POLICY_ADD_REPLY);
123}
124
125static void
126vl_api_sr_policy_mod_t_handler (vl_api_sr_policy_mod_t * mp)
127{
128 vl_api_sr_policy_mod_reply_t *rmp;
129
130 ip6_address_t *segments = 0, *seg;
Pablo Camarillo3337bd22018-06-19 15:49:02 +0200131 ip6_address_t *this_address = (ip6_address_t *) mp->sids.sids;
Pablo Camarillofb380952016-12-07 18:34:18 +0100132
133 int i;
Pablo Camarillo3337bd22018-06-19 15:49:02 +0200134 for (i = 0; i < mp->sids.num_sids; i++)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100135 {
Pablo Camarillofb380952016-12-07 18:34:18 +0100136 vec_add2 (segments, seg, 1);
137 clib_memcpy (seg->as_u8, this_address->as_u8, sizeof (*this_address));
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100138 this_address++;
139 }
140
Pablo Camarillofb380952016-12-07 18:34:18 +0100141 int rv = 0;
142/*
143 * int
144 * sr_policy_mod(ip6_address_t *bsid, u32 index, u32 fib_table,
145 * u8 operation, ip6_address_t *segments, u32 sl_index,
146 * u32 weight, u8 is_encap)
147 */
148 rv = sr_policy_mod ((ip6_address_t *) & mp->bsid_addr,
149 ntohl (mp->sr_policy_index),
150 ntohl (mp->fib_table),
151 mp->operation,
Pablo Camarillo3337bd22018-06-19 15:49:02 +0200152 segments, ntohl (mp->sl_index),
153 ntohl (mp->sids.weight));
John Lod23d39c2018-09-13 15:08:08 -0400154 vec_free (segments);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100155
Pablo Camarillofb380952016-12-07 18:34:18 +0100156 REPLY_MACRO (VL_API_SR_POLICY_MOD_REPLY);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100157}
158
Pablo Camarillofb380952016-12-07 18:34:18 +0100159static void
160vl_api_sr_policy_del_t_handler (vl_api_sr_policy_del_t * mp)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100161{
Pablo Camarillofb380952016-12-07 18:34:18 +0100162 vl_api_sr_policy_del_reply_t *rmp;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100163 int rv = 0;
Pablo Camarillofb380952016-12-07 18:34:18 +0100164/*
165 * int
166 * sr_policy_del (ip6_address_t *bsid, u32 index)
167 */
168 rv = sr_policy_del ((ip6_address_t *) & mp->bsid_addr,
169 ntohl (mp->sr_policy_index));
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100170
Pablo Camarillofb380952016-12-07 18:34:18 +0100171 REPLY_MACRO (VL_API_SR_POLICY_DEL_REPLY);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100172}
173
Pablo Camarillo1a5e3012017-11-16 16:02:50 +0100174static void
175vl_api_sr_set_encap_source_t_handler (vl_api_sr_set_encap_source_t * mp)
176{
177 vl_api_sr_set_encap_source_reply_t *rmp;
178 int rv = 0;
179 sr_set_source ((ip6_address_t *) & mp->encaps_source);
180
Vratko Polak1096b462019-08-21 18:40:03 +0200181 REPLY_MACRO (VL_API_SR_SET_ENCAP_SOURCE_REPLY);
Pablo Camarillo1a5e3012017-11-16 16:02:50 +0100182}
183
Ignas Bačiuseeb5fb32019-10-03 17:15:38 +0300184static void
185vl_api_sr_set_encap_hop_limit_t_handler (vl_api_sr_set_encap_hop_limit_t * mp)
186{
187 vl_api_sr_set_encap_hop_limit_reply_t *rmp;
188 int rv = 0;
189
190 if (mp->hop_limit == 0)
191 rv = VNET_API_ERROR_INVALID_VALUE;
192 else
193 sr_set_hop_limit (mp->hop_limit);
194
195 REPLY_MACRO (VL_API_SR_SET_ENCAP_HOP_LIMIT_REPLY);
196}
197
Pablo Camarillofb380952016-12-07 18:34:18 +0100198static void vl_api_sr_steering_add_del_t_handler
199 (vl_api_sr_steering_add_del_t * mp)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100200{
Pablo Camarillofb380952016-12-07 18:34:18 +0100201 vl_api_sr_steering_add_del_reply_t *rmp;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100202 int rv = 0;
Pablo Camarillofb380952016-12-07 18:34:18 +0100203/*
204 * int
205 * sr_steering_policy(int is_del, ip6_address_t *bsid, u32 sr_policy_index,
206 * u32 table_id, ip46_address_t *prefix, u32 mask_width, u32 sw_if_index,
207 * u8 traffic_type)
208 */
Pablo Camarillo3337bd22018-06-19 15:49:02 +0200209 if (mp->traffic_type == SR_STEER_L2)
210 VALIDATE_SW_IF_INDEX (mp);
Chris Luke879ace32017-09-26 13:15:16 -0400211
Pablo Camarillofb380952016-12-07 18:34:18 +0100212 rv = sr_steering_policy (mp->is_del,
213 (ip6_address_t *) & mp->bsid_addr,
214 ntohl (mp->sr_policy_index),
215 ntohl (mp->table_id),
216 (ip46_address_t *) & mp->prefix_addr,
217 ntohl (mp->mask_width),
218 ntohl (mp->sw_if_index), mp->traffic_type);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100219
Chris Luke879ace32017-09-26 13:15:16 -0400220 BAD_SW_IF_INDEX_LABEL;
Pablo Camarillofb380952016-12-07 18:34:18 +0100221 REPLY_MACRO (VL_API_SR_STEERING_ADD_DEL_REPLY);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100222}
223
Pablo Camarillo1a5e3012017-11-16 16:02:50 +0100224static void send_sr_localsid_details
Florin Coras6c4dae22018-01-09 06:39:23 -0800225 (ip6_sr_localsid_t * t, vl_api_registration_t * reg, u32 context)
Pablo Camarillo1a5e3012017-11-16 16:02:50 +0100226{
227 vl_api_sr_localsids_details_t *rmp;
228
229 rmp = vl_msg_api_alloc (sizeof (*rmp));
Dave Barachb7b92992018-10-17 10:38:51 -0400230 clib_memset (rmp, 0, sizeof (*rmp));
Pablo Camarillo1a5e3012017-11-16 16:02:50 +0100231 rmp->_vl_msg_id = ntohs (VL_API_SR_LOCALSIDS_DETAILS);
Pablo Camarillo3337bd22018-06-19 15:49:02 +0200232 clib_memcpy (rmp->addr.addr, &t->localsid, sizeof (ip6_address_t));
Pablo Camarillo1a5e3012017-11-16 16:02:50 +0100233 rmp->end_psp = t->end_psp;
234 rmp->behavior = htons (t->behavior);
235 rmp->fib_table = htonl (t->fib_table);
Pablo Camarillo3337bd22018-06-19 15:49:02 +0200236 rmp->vlan_index = htonl (t->vlan_index);
237 if (ip46_address_is_ip4 (&t->next_hop))
238 clib_memcpy (rmp->xconnect_nh_addr4, &t->next_hop.ip4,
239 sizeof (ip4_address_t));
240 else
241 clib_memcpy (rmp->xconnect_nh_addr6, &t->next_hop.ip6,
242 sizeof (ip6_address_t));
Ahmed Abdelsalam13e6fce2019-12-08 12:58:27 +0100243
244 if (t->behavior == SR_BEHAVIOR_T || t->behavior == SR_BEHAVIOR_DT6)
245 rmp->xconnect_iface_or_vrf_table =
246 htonl (fib_table_get_table_id (t->sw_if_index, FIB_PROTOCOL_IP6));
247 else if (t->behavior == SR_BEHAVIOR_DT4)
248 rmp->xconnect_iface_or_vrf_table =
249 htonl (fib_table_get_table_id (t->sw_if_index, FIB_PROTOCOL_IP4));
250 else
251 rmp->xconnect_iface_or_vrf_table = htonl (t->sw_if_index);
252
Pablo Camarillo1a5e3012017-11-16 16:02:50 +0100253 rmp->context = context;
254
Florin Coras6c4dae22018-01-09 06:39:23 -0800255 vl_api_send_msg (reg, (u8 *) rmp);
Pablo Camarillo1a5e3012017-11-16 16:02:50 +0100256}
257
258static void vl_api_sr_localsids_dump_t_handler
259 (vl_api_sr_localsids_dump_t * mp)
260{
Florin Coras6c4dae22018-01-09 06:39:23 -0800261 vl_api_registration_t *reg;
Pablo Camarillo1a5e3012017-11-16 16:02:50 +0100262 ip6_sr_main_t *sm = &sr_main;
263 ip6_sr_localsid_t *t;
264
Florin Coras6c4dae22018-01-09 06:39:23 -0800265 reg = vl_api_client_index_to_registration (mp->client_index);
266 if (!reg)
267 return;
Pablo Camarillo1a5e3012017-11-16 16:02:50 +0100268
269 /* *INDENT-OFF* */
270 pool_foreach (t, sm->localsids,
271 ({
Florin Coras6c4dae22018-01-09 06:39:23 -0800272 send_sr_localsid_details(t, reg, mp->context);
Pablo Camarillo1a5e3012017-11-16 16:02:50 +0100273 }));
274 /* *INDENT-ON* */
275}
276
Pablo Camarillo3337bd22018-06-19 15:49:02 +0200277static void send_sr_policies_details
278 (ip6_sr_policy_t * t, vl_api_registration_t * reg, u32 context)
279{
280 vl_api_sr_policies_details_t *rmp;
281 ip6_sr_main_t *sm = &sr_main;
282
283 u32 *sl_index;
284 ip6_sr_sl_t *segment_list = 0;
285 vl_api_srv6_sid_list_t *write_sid_list;
286
287 rmp = vl_msg_api_alloc (sizeof (*rmp) +
288 vec_len (t->segments_lists) *
289 sizeof (vl_api_srv6_sid_list_t));
Dave Barachb7b92992018-10-17 10:38:51 -0400290 clib_memset (rmp, 0,
291 (sizeof (*rmp) +
292 vec_len (t->segments_lists) *
293 sizeof (vl_api_srv6_sid_list_t)));
Pablo Camarillo3337bd22018-06-19 15:49:02 +0200294
295 rmp->_vl_msg_id = ntohs (VL_API_SR_POLICIES_DETAILS);
296 clib_memcpy (rmp->bsid.addr, &t->bsid, sizeof (ip6_address_t));
297 rmp->is_encap = t->is_encap;
298 rmp->type = t->type;
299 rmp->fib_table = htonl (t->fib_table);
300 rmp->num_sid_lists = vec_len (t->segments_lists);
301
302 /* Fill in all the segments lists */
303 vec_foreach (sl_index, t->segments_lists)
304 {
305 segment_list = pool_elt_at_index (sm->sid_lists, *sl_index);
306 write_sid_list = &rmp->sid_lists[sl_index - t->segments_lists];
307 write_sid_list->num_sids = vec_len (segment_list->segments);
308 write_sid_list->weight = htonl (segment_list->weight);
309 clib_memcpy (write_sid_list->sids, segment_list->segments,
310 vec_len (segment_list->segments) * sizeof (ip6_address_t));
311 }
312
313 rmp->context = context;
314 vl_api_send_msg (reg, (u8 *) rmp);
315}
316
317static void
318vl_api_sr_policies_dump_t_handler (vl_api_sr_policies_dump_t * mp)
319{
320 vl_api_registration_t *reg;
321 ip6_sr_main_t *sm = &sr_main;
322 ip6_sr_policy_t *t;
323
324 reg = vl_api_client_index_to_registration (mp->client_index);
325 if (!reg)
326 return;
327
328 /* *INDENT-OFF* */
329 pool_foreach (t, sm->sr_policies,
330 ({
331 send_sr_policies_details(t, reg, mp->context);
332 }));
333 /* *INDENT-ON* */
334}
335
336static void send_sr_steering_pol_details
337 (ip6_sr_steering_policy_t * t, vl_api_registration_t * reg, u32 context)
338{
339 vl_api_sr_steering_pol_details_t *rmp;
340 ip6_sr_main_t *sm = &sr_main;
341
342 rmp = vl_msg_api_alloc (sizeof (*rmp));
Dave Barachb7b92992018-10-17 10:38:51 -0400343 clib_memset (rmp, 0, sizeof (*rmp));
Pablo Camarillo3337bd22018-06-19 15:49:02 +0200344 rmp->_vl_msg_id = ntohs (VL_API_SR_STEERING_POL_DETAILS);
345
346 //Get the SR policy BSID
347 ip6_sr_policy_t *p;
348 p = pool_elt_at_index (sm->sr_policies, t->sr_policy);
349 clib_memcpy (rmp->bsid.addr, &p->bsid, sizeof (ip6_address_t));
350
351 //Get the steering
352 rmp->traffic_type = t->classify.traffic_type;
353 rmp->fib_table = htonl (t->classify.l3.fib_table);
354 rmp->mask_width = htonl (t->classify.l3.mask_width);
355 if (ip46_address_is_ip4 (&t->classify.l3.prefix))
356 clib_memcpy (rmp->prefix_addr, &t->classify.l3.prefix.ip4,
357 sizeof (ip4_address_t));
358 else
359 clib_memcpy (rmp->prefix_addr, &t->classify.l3.prefix.ip6,
360 sizeof (ip6_address_t));
361
362 rmp->sw_if_index = htonl (t->classify.l2.sw_if_index);
363
364 rmp->context = context;
365 vl_api_send_msg (reg, (u8 *) rmp);
366}
367
368static void vl_api_sr_steering_pol_dump_t_handler
369 (vl_api_sr_policies_dump_t * mp)
370{
371 vl_api_registration_t *reg;
372 ip6_sr_main_t *sm = &sr_main;
373 ip6_sr_steering_policy_t *t;
374
375 reg = vl_api_client_index_to_registration (mp->client_index);
376 if (!reg)
377 return;
378
379 /* *INDENT-OFF* */
380 pool_foreach (t, sm->steer_policies,
381 ({
382 send_sr_steering_pol_details(t, reg, mp->context);
383 }));
384 /* *INDENT-ON* */
385}
Pablo Camarillo1a5e3012017-11-16 16:02:50 +0100386
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100387/*
388 * sr_api_hookup
389 * Add vpe's API message handlers to the table.
Jim Thompsonf324dec2019-04-08 03:22:21 -0500390 * vlib has already mapped shared memory and
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100391 * added the client registration handlers.
392 * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
393 */
394#define vl_msg_name_crc_list
395#include <vnet/vnet_all_api_h.h>
396#undef vl_msg_name_crc_list
397
398static void
399setup_message_id_table (api_main_t * am)
400{
401#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
402 foreach_vl_msg_name_crc_sr;
403#undef _
404}
405
406static clib_error_t *
407sr_api_hookup (vlib_main_t * vm)
408{
Dave Barach39d69112019-11-27 11:42:13 -0500409 api_main_t *am = vlibapi_get_main ();
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100410
411#define _(N,n) \
412 vl_msg_api_set_handlers(VL_API_##N, #n, \
413 vl_api_##n##_t_handler, \
414 vl_noop_handler, \
415 vl_api_##n##_t_endian, \
416 vl_api_##n##_t_print, \
417 sizeof(vl_api_##n##_t), 1);
418 foreach_vpe_api_msg;
419#undef _
420
421 /*
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100422 * Set up the (msg_name, crc, message-id) table
423 */
424 setup_message_id_table (am);
425
426 return 0;
427}
428
429VLIB_API_INIT_FUNCTION (sr_api_hookup);
430
431/*
432 * fd.io coding-style-patch-verification: ON
433 *
434 * Local Variables:
435 * eval: (c-set-style "gnu")
436 * End:
437 */