blob: e89732f0d10f83ba6b7d7510e7963d3c6b022588 [file] [log] [blame]
Pavel Kotucek0f971d82017-01-03 10:48:54 +01001/*
2 *------------------------------------------------------------------
3 * mpls_api.c - mpls 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/mpls/mpls.h>
26#include <vnet/mpls/mpls_tunnel.h>
27#include <vnet/fib/fib_table.h>
28#include <vnet/fib/fib_api.h>
Neale Rannsa3af3372017-03-28 03:49:52 -070029#include <vnet/fib/mpls_fib.h>
Neale Ranns0f26c5a2017-03-01 15:12:11 -080030#include <vnet/fib/fib_path_list.h>
Neale Ranns097fa662018-05-01 05:17:55 -070031#include <vnet/ip/ip_types_api.h>
Pavel Kotucek0f971d82017-01-03 10:48:54 +010032
Filip Tehlarda5088c2021-06-22 22:01:19 +000033#include <vnet/format_fns.h>
34#include <vnet/mpls/mpls.api_enum.h>
35#include <vnet/mpls/mpls.api_types.h>
Pavel Kotucek0f971d82017-01-03 10:48:54 +010036
Filip Tehlarda5088c2021-06-22 22:01:19 +000037#define REPLY_MSG_ID_BASE mpls_main.msg_id_base
Pavel Kotucek0f971d82017-01-03 10:48:54 +010038#include <vlibapi/api_helper_macros.h>
39
Neale Ranns28ab9cc2017-08-14 07:18:42 -070040void
Neale Ranns15002542017-09-10 04:39:11 -070041mpls_table_delete (u32 table_id, u8 is_api)
42{
43 u32 fib_index;
44
45 /*
46 * The MPLS defult table must also be explicitly created via the API.
47 * So in contrast to IP, it gets no special treatment here.
48 *
49 * The API holds only one lock on the table.
50 * i.e. it can be added many times via the API but needs to be
51 * deleted only once.
52 */
53 fib_index = fib_table_find (FIB_PROTOCOL_MPLS, table_id);
54
55 if (~0 != fib_index)
56 {
57 fib_table_unlock (fib_index,
58 FIB_PROTOCOL_MPLS,
59 (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI));
60 }
61}
62
63void
Neale Ranns28ab9cc2017-08-14 07:18:42 -070064vl_api_mpls_table_add_del_t_handler (vl_api_mpls_table_add_del_t * mp)
65{
66 vl_api_mpls_table_add_del_reply_t *rmp;
67 vnet_main_t *vnm;
68 int rv = 0;
69
70 vnm = vnet_get_main ();
71 vnm->api_errno = 0;
72
Neale Ranns15002542017-09-10 04:39:11 -070073 if (mp->mt_is_add)
Neale Ranns097fa662018-05-01 05:17:55 -070074 mpls_table_create (ntohl (mp->mt_table.mt_table_id),
75 1, mp->mt_table.mt_name);
Neale Ranns15002542017-09-10 04:39:11 -070076 else
Neale Ranns097fa662018-05-01 05:17:55 -070077 mpls_table_delete (ntohl (mp->mt_table.mt_table_id), 1);
Neale Ranns15002542017-09-10 04:39:11 -070078
Chris Lukeb2bcad62017-09-18 08:51:22 -040079 // NB: Nothing sets rv; none of the above returns an error
Neale Ranns15002542017-09-10 04:39:11 -070080
Neale Ranns28ab9cc2017-08-14 07:18:42 -070081 REPLY_MACRO (VL_API_MPLS_TABLE_ADD_DEL_REPLY);
82}
83
Pavel Kotucek0f971d82017-01-03 10:48:54 +010084static int
85mpls_ip_bind_unbind_handler (vnet_main_t * vnm,
86 vl_api_mpls_ip_bind_unbind_t * mp)
87{
88 u32 mpls_fib_index, ip_fib_index;
Neale Ranns097fa662018-05-01 05:17:55 -070089 fib_prefix_t pfx;
Pavel Kotucek0f971d82017-01-03 10:48:54 +010090
91 mpls_fib_index =
92 fib_table_find (FIB_PROTOCOL_MPLS, ntohl (mp->mb_mpls_table_id));
93
94 if (~0 == mpls_fib_index)
95 {
Neale Ranns15002542017-09-10 04:39:11 -070096 return VNET_API_ERROR_NO_SUCH_FIB;
Pavel Kotucek0f971d82017-01-03 10:48:54 +010097 }
98
Neale Ranns097fa662018-05-01 05:17:55 -070099 ip_prefix_decode (&mp->mb_prefix, &pfx);
100
101 ip_fib_index = fib_table_find (pfx.fp_proto, ntohl (mp->mb_ip_table_id));
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100102 if (~0 == ip_fib_index)
103 return VNET_API_ERROR_NO_SUCH_FIB;
104
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100105 if (mp->mb_is_bind)
106 fib_table_entry_local_label_add (ip_fib_index, &pfx,
107 ntohl (mp->mb_label));
108 else
109 fib_table_entry_local_label_remove (ip_fib_index, &pfx,
110 ntohl (mp->mb_label));
111
112 return (0);
113}
114
115void
116vl_api_mpls_ip_bind_unbind_t_handler (vl_api_mpls_ip_bind_unbind_t * mp)
117{
118 vl_api_mpls_ip_bind_unbind_reply_t *rmp;
119 vnet_main_t *vnm;
120 int rv;
121
122 vnm = vnet_get_main ();
123 vnm->api_errno = 0;
124
125 rv = mpls_ip_bind_unbind_handler (vnm, mp);
126 rv = (rv == 0) ? vnm->api_errno : rv;
127
128 REPLY_MACRO (VL_API_MPLS_IP_BIND_UNBIND_REPLY);
129}
130
131static int
132mpls_route_add_del_t_handler (vnet_main_t * vnm,
Neale Ranns008dbe12018-09-07 09:32:36 -0700133 vl_api_mpls_route_add_del_t * mp,
134 u32 * stats_index)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100135{
Neale Ranns097fa662018-05-01 05:17:55 -0700136 fib_route_path_t *rpaths = NULL, *rpath;
137 vl_api_fib_path_t *apath;
138 u32 fib_index;
139 int rv, ii;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100140
141 fib_prefix_t pfx = {
142 .fp_len = 21,
143 .fp_proto = FIB_PROTOCOL_MPLS,
Neale Ranns097fa662018-05-01 05:17:55 -0700144 .fp_eos = mp->mr_route.mr_eos,
145 .fp_label = ntohl (mp->mr_route.mr_label),
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100146 };
147 if (pfx.fp_eos)
148 {
Neale Ranns097fa662018-05-01 05:17:55 -0700149 pfx.fp_payload_proto = mp->mr_route.mr_eos_proto;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100150 }
151 else
152 {
153 pfx.fp_payload_proto = DPO_PROTO_MPLS;
154 }
155
Neale Ranns097fa662018-05-01 05:17:55 -0700156 rv = fib_api_table_id_decode (FIB_PROTOCOL_MPLS,
157 ntohl (mp->mr_route.mr_table_id), &fib_index);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100158 if (0 != rv)
Neale Ranns097fa662018-05-01 05:17:55 -0700159 goto out;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100160
Neale Ranns097fa662018-05-01 05:17:55 -0700161 vec_validate (rpaths, mp->mr_route.mr_n_paths - 1);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100162
Neale Ranns097fa662018-05-01 05:17:55 -0700163 for (ii = 0; ii < mp->mr_route.mr_n_paths; ii++)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100164 {
Neale Ranns097fa662018-05-01 05:17:55 -0700165 apath = &mp->mr_route.mr_paths[ii];
166 rpath = &rpaths[ii];
167
168 rv = fib_api_path_decode (apath, rpath);
169
170 if (0 != rv)
171 goto out;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100172 }
173
Neale Ranns976b2592019-12-04 06:11:00 +0000174 rv = fib_api_route_add_del (
175 mp->mr_is_add, mp->mr_is_multipath, fib_index, &pfx, FIB_SOURCE_API,
176 (mp->mr_route.mr_is_multicast ? FIB_ENTRY_FLAG_MULTICAST :
177 FIB_ENTRY_FLAG_NONE),
178 rpaths);
Neale Ranns008dbe12018-09-07 09:32:36 -0700179
180 if (mp->mr_is_add && 0 == rv)
181 *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx);
182
Neale Ranns097fa662018-05-01 05:17:55 -0700183out:
184 vec_free (rpaths);
185
Neale Ranns008dbe12018-09-07 09:32:36 -0700186 return (rv);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100187}
188
189void
190vl_api_mpls_route_add_del_t_handler (vl_api_mpls_route_add_del_t * mp)
191{
192 vl_api_mpls_route_add_del_reply_t *rmp;
193 vnet_main_t *vnm;
Neale Ranns008dbe12018-09-07 09:32:36 -0700194 u32 stats_index;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100195 int rv;
196
197 vnm = vnet_get_main ();
Neale Ranns008dbe12018-09-07 09:32:36 -0700198 stats_index = ~0;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100199
Neale Ranns008dbe12018-09-07 09:32:36 -0700200 rv = mpls_route_add_del_t_handler (vnm, mp, &stats_index);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100201
Neale Ranns008dbe12018-09-07 09:32:36 -0700202 /* *INDENT-OFF* */
203 REPLY_MACRO2 (VL_API_MPLS_ROUTE_ADD_DEL_REPLY,
204 ({
205 rmp->stats_index = htonl (stats_index);
206 }));
207 /* *INDENT-ON* */
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100208}
209
Neale Ranns15002542017-09-10 04:39:11 -0700210void
Neale Ranns2297af02017-09-12 09:45:04 -0700211mpls_table_create (u32 table_id, u8 is_api, const u8 * name)
Neale Ranns15002542017-09-10 04:39:11 -0700212{
213 u32 fib_index;
214
215 /*
216 * The MPLS defult table must also be explicitly created via the API.
217 * So in contrast to IP, it gets no special treatment here.
218 */
219
220 /*
221 * The API holds only one lock on the table.
222 * i.e. it can be added many times via the API but needs to be
223 * deleted only once.
224 */
225 fib_index = fib_table_find (FIB_PROTOCOL_MPLS, table_id);
226
227 if (~0 == fib_index)
228 {
Neale Ranns2297af02017-09-12 09:45:04 -0700229 fib_table_find_or_create_and_lock_w_name (FIB_PROTOCOL_MPLS,
230 table_id,
231 (is_api ?
232 FIB_SOURCE_API :
233 FIB_SOURCE_CLI), name);
Neale Ranns15002542017-09-10 04:39:11 -0700234 }
235}
236
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100237static void
238vl_api_mpls_tunnel_add_del_t_handler (vl_api_mpls_tunnel_add_del_t * mp)
239{
Neale Ranns097fa662018-05-01 05:17:55 -0700240 u32 tunnel_sw_if_index = ~0, tunnel_index = ~0;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100241 vl_api_mpls_tunnel_add_del_reply_t *rmp;
Neale Ranns097fa662018-05-01 05:17:55 -0700242 fib_route_path_t *rpath, *rpaths = NULL;
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700243 int ii, rv = 0;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800244
Neale Ranns097fa662018-05-01 05:17:55 -0700245 vec_validate (rpaths, mp->mt_tunnel.mt_n_paths - 1);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100246
Neale Ranns097fa662018-05-01 05:17:55 -0700247 for (ii = 0; ii < mp->mt_tunnel.mt_n_paths; ii++)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800248 {
Neale Ranns097fa662018-05-01 05:17:55 -0700249 rpath = &rpaths[ii];
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800250
Neale Ranns097fa662018-05-01 05:17:55 -0700251 rv = fib_api_path_decode (&mp->mt_tunnel.mt_paths[ii], rpath);
252
253 if (0 != rv)
254 goto out;
Neale Ranns7c922dc2018-08-30 06:12:27 -0700255 }
Neale Ranns097fa662018-05-01 05:17:55 -0700256 tunnel_sw_if_index = ntohl (mp->mt_tunnel.mt_sw_if_index);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800257
258 if (mp->mt_is_add)
259 {
260 if (~0 == tunnel_sw_if_index)
Neale Ranns097fa662018-05-01 05:17:55 -0700261 tunnel_sw_if_index =
262 vnet_mpls_tunnel_create (mp->mt_tunnel.mt_l2_only,
IJsbrand Wijnands39ae0a02020-03-05 10:56:26 -0800263 mp->mt_tunnel.mt_is_multicast,
264 mp->mt_tunnel.mt_tag);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800265 vnet_mpls_tunnel_path_add (tunnel_sw_if_index, rpaths);
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700266
267 tunnel_index = vnet_mpls_tunnel_get_index (tunnel_sw_if_index);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100268 }
269 else
270 {
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700271 tunnel_index = vnet_mpls_tunnel_get_index (tunnel_sw_if_index);
Neale Ranns097fa662018-05-01 05:17:55 -0700272 tunnel_sw_if_index = ntohl (mp->mt_tunnel.mt_sw_if_index);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800273 if (!vnet_mpls_tunnel_path_remove (tunnel_sw_if_index, rpaths))
274 vnet_mpls_tunnel_del (tunnel_sw_if_index);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100275 }
276
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800277 vec_free (rpaths);
278
John Lo06fda9c2018-10-03 16:32:44 -0400279out:
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100280 /* *INDENT-OFF* */
281 REPLY_MACRO2(VL_API_MPLS_TUNNEL_ADD_DEL_REPLY,
282 ({
283 rmp->sw_if_index = ntohl(tunnel_sw_if_index);
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700284 rmp->tunnel_index = ntohl(tunnel_index);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100285 }));
286 /* *INDENT-ON* */
287}
288
Neale Rannsb8d44812017-11-10 06:53:54 -0800289static void
290 vl_api_sw_interface_set_mpls_enable_t_handler
291 (vl_api_sw_interface_set_mpls_enable_t * mp)
292{
293 vl_api_sw_interface_set_mpls_enable_reply_t *rmp;
294 int rv = 0;
295
296 VALIDATE_SW_IF_INDEX (mp);
297
298 rv = mpls_sw_interface_enable_disable (&mpls_main,
299 ntohl (mp->sw_if_index),
300 mp->enable, 1);
301
302 BAD_SW_IF_INDEX_LABEL;
303 REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY);
304}
305
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100306typedef struct mpls_tunnel_send_walk_ctx_t_
307{
Florin Coras6c4dae22018-01-09 06:39:23 -0800308 vl_api_registration_t *reg;
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700309 u32 sw_if_index;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100310 u32 context;
311} mpls_tunnel_send_walk_ctx_t;
312
313static void
314send_mpls_tunnel_entry (u32 mti, void *arg)
315{
316 mpls_tunnel_send_walk_ctx_t *ctx;
317 vl_api_mpls_tunnel_details_t *mp;
Neale Ranns097fa662018-05-01 05:17:55 -0700318 fib_path_encode_ctx_t path_ctx = {
319 .rpaths = NULL,
320 };
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100321 const mpls_tunnel_t *mt;
Neale Ranns097fa662018-05-01 05:17:55 -0700322 fib_route_path_t *rpath;
Neale Ranns31ed7442018-02-23 05:29:09 -0800323 vl_api_fib_path_t *fp;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800324 u32 n;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100325
326 ctx = arg;
327
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700328 mt = mpls_tunnel_get (mti);
329
330 if (~0 != ctx->sw_if_index && mt->mt_sw_if_index != ctx->sw_if_index)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100331 return;
332
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800333 n = fib_path_list_get_n_paths (mt->mt_path_list);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100334
Neale Ranns31ed7442018-02-23 05:29:09 -0800335 mp = vl_msg_api_alloc (sizeof (*mp) + n * sizeof (vl_api_fib_path_t));
Dave Barachb7b92992018-10-17 10:38:51 -0400336 clib_memset (mp, 0, sizeof (*mp) + n * sizeof (vl_api_fib_path_t));
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800337
Filip Tehlarda5088c2021-06-22 22:01:19 +0000338 mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_MPLS_TUNNEL_DETAILS);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100339 mp->context = ctx->context;
340
IJsbrand Wijnandsbf103d92019-10-28 17:19:27 +0100341 mp->mt_tunnel.mt_n_paths = n;
Neale Ranns097fa662018-05-01 05:17:55 -0700342 mp->mt_tunnel.mt_sw_if_index = ntohl (mt->mt_sw_if_index);
343 mp->mt_tunnel.mt_tunnel_index = ntohl (mti);
344 mp->mt_tunnel.mt_l2_only = ! !(MPLS_TUNNEL_FLAG_L2 & mt->mt_flags);
345 mp->mt_tunnel.mt_is_multicast = ! !(MPLS_TUNNEL_FLAG_MCAST & mt->mt_flags);
IJsbrand Wijnands39ae0a02020-03-05 10:56:26 -0800346 memcpy (mp->mt_tunnel.mt_tag, mt->mt_tag, sizeof (mp->mt_tunnel.mt_tag));
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800347
Neale Ranns775f73c2018-12-20 03:01:49 -0800348 fib_path_list_walk_w_ext (mt->mt_path_list,
Neale Ranns097fa662018-05-01 05:17:55 -0700349 &mt->mt_path_exts, fib_path_encode, &path_ctx);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800350
Neale Ranns097fa662018-05-01 05:17:55 -0700351 fp = mp->mt_tunnel.mt_paths;
352 vec_foreach (rpath, path_ctx.rpaths)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800353 {
Neale Ranns097fa662018-05-01 05:17:55 -0700354 fib_api_path_encode (rpath, fp);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800355 fp++;
356 }
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100357
Florin Coras6c4dae22018-01-09 06:39:23 -0800358 vl_api_send_msg (ctx->reg, (u8 *) mp);
Neale Ranns097fa662018-05-01 05:17:55 -0700359
360 vec_free (path_ctx.rpaths);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100361}
362
363static void
364vl_api_mpls_tunnel_dump_t_handler (vl_api_mpls_tunnel_dump_t * mp)
365{
Florin Coras6c4dae22018-01-09 06:39:23 -0800366 vl_api_registration_t *reg;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100367
Florin Coras6c4dae22018-01-09 06:39:23 -0800368 reg = vl_api_client_index_to_registration (mp->client_index);
369 if (!reg)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100370 return;
371
372 mpls_tunnel_send_walk_ctx_t ctx = {
Florin Coras6c4dae22018-01-09 06:39:23 -0800373 .reg = reg,
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700374 .sw_if_index = ntohl (mp->sw_if_index),
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100375 .context = mp->context,
376 };
377 mpls_tunnel_walk (send_mpls_tunnel_entry, &ctx);
378}
379
380static void
Neale Ranns097fa662018-05-01 05:17:55 -0700381send_mpls_table_details (vpe_api_main_t * am,
382 vl_api_registration_t * reg,
383 u32 context, const fib_table_t * table)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100384{
Neale Ranns097fa662018-05-01 05:17:55 -0700385 vl_api_mpls_table_details_t *mp;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100386
Neale Ranns097fa662018-05-01 05:17:55 -0700387 mp = vl_msg_api_alloc (sizeof (*mp));
388 memset (mp, 0, sizeof (*mp));
Filip Tehlarda5088c2021-06-22 22:01:19 +0000389 mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_MPLS_TABLE_DETAILS);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100390 mp->context = context;
391
Neale Ranns097fa662018-05-01 05:17:55 -0700392 mp->mt_table.mt_table_id = htonl (table->ft_table_id);
393 memcpy (mp->mt_table.mt_name,
394 table->ft_desc,
395 clib_min (vec_len (table->ft_desc), sizeof (mp->mt_table.mt_name)));
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100396
Florin Coras6c4dae22018-01-09 06:39:23 -0800397 vl_api_send_msg (reg, (u8 *) mp);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100398}
399
Neale Ranns097fa662018-05-01 05:17:55 -0700400static void
401vl_api_mpls_table_dump_t_handler (vl_api_mpls_table_dump_t * mp)
402{
403 vpe_api_main_t *am = &vpe_api_main;
404 vl_api_registration_t *reg;
405 mpls_main_t *mm = &mpls_main;
406 fib_table_t *fib_table;
407
408 reg = vl_api_client_index_to_registration (mp->client_index);
409 if (!reg)
410 return;
411
412 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100413 pool_foreach (fib_table, mm->fibs)
414 {
Neale Ranns097fa662018-05-01 05:17:55 -0700415 send_mpls_table_details(am, reg, mp->context, fib_table);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100416 }
Neale Ranns097fa662018-05-01 05:17:55 -0700417 /* *INDENT-ON* */
418}
419
420static void
421send_mpls_route_details (vpe_api_main_t * am,
422 vl_api_registration_t * reg,
423 u32 context, fib_node_index_t fib_entry_index)
424{
425 fib_route_path_t *rpaths, *rpath;
426 vl_api_mpls_route_details_t *mp;
427 const fib_prefix_t *pfx;
428 vl_api_fib_path_t *fp;
429 int path_count;
430
431 rpaths = fib_entry_encode (fib_entry_index);
432 pfx = fib_entry_get_prefix (fib_entry_index);
433
434 path_count = vec_len (rpaths);
435 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
436 if (!mp)
437 return;
438 clib_memset (mp, 0, sizeof (*mp));
Filip Tehlarda5088c2021-06-22 22:01:19 +0000439 mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_MPLS_ROUTE_DETAILS);
Neale Ranns097fa662018-05-01 05:17:55 -0700440 mp->context = context;
441
442 mp->mr_route.mr_table_id =
443 htonl (fib_table_get_table_id
444 (fib_entry_get_fib_index (fib_entry_index), pfx->fp_proto));
445 mp->mr_route.mr_eos = pfx->fp_eos;
446 mp->mr_route.mr_eos_proto = pfx->fp_payload_proto;
447 mp->mr_route.mr_label = htonl (pfx->fp_label);
448
449 mp->mr_route.mr_n_paths = path_count;
450 fp = mp->mr_route.mr_paths;
451 vec_foreach (rpath, rpaths)
452 {
453 fib_api_path_encode (rpath, fp);
454 fp++;
455 }
456
457 vec_free (rpaths);
458 vl_api_send_msg (reg, (u8 *) mp);
459}
460
461typedef struct vl_api_mpls_route_dump_table_walk_ctx_t_
Neale Rannsa3af3372017-03-28 03:49:52 -0700462{
463 fib_node_index_t *lfeis;
Neale Ranns097fa662018-05-01 05:17:55 -0700464} vl_api_mpls_route_dump_table_walk_ctx_t;
Neale Rannsa3af3372017-03-28 03:49:52 -0700465
Neale Ranns89541992017-04-06 04:41:02 -0700466static fib_table_walk_rc_t
Neale Ranns097fa662018-05-01 05:17:55 -0700467vl_api_mpls_route_dump_table_walk (fib_node_index_t fei, void *arg)
Neale Rannsa3af3372017-03-28 03:49:52 -0700468{
Neale Ranns097fa662018-05-01 05:17:55 -0700469 vl_api_mpls_route_dump_table_walk_ctx_t *ctx = arg;
Neale Rannsa3af3372017-03-28 03:49:52 -0700470
471 vec_add1 (ctx->lfeis, fei);
472
Neale Ranns89541992017-04-06 04:41:02 -0700473 return (FIB_TABLE_WALK_CONTINUE);
Neale Rannsa3af3372017-03-28 03:49:52 -0700474}
475
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100476static void
Neale Ranns097fa662018-05-01 05:17:55 -0700477vl_api_mpls_route_dump_t_handler (vl_api_mpls_route_dump_t * mp)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100478{
479 vpe_api_main_t *am = &vpe_api_main;
Florin Coras6c4dae22018-01-09 06:39:23 -0800480 vl_api_registration_t *reg;
Neale Rannsa3af3372017-03-28 03:49:52 -0700481 fib_node_index_t *lfeip = NULL;
Neale Ranns097fa662018-05-01 05:17:55 -0700482 vl_api_mpls_route_dump_table_walk_ctx_t ctx = {
Neale Rannsa3af3372017-03-28 03:49:52 -0700483 .lfeis = NULL,
484 };
Neale Ranns097fa662018-05-01 05:17:55 -0700485 u32 fib_index;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100486
Florin Coras6c4dae22018-01-09 06:39:23 -0800487 reg = vl_api_client_index_to_registration (mp->client_index);
488 if (!reg)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100489 return;
490
Neale Ranns097fa662018-05-01 05:17:55 -0700491 fib_index = fib_table_find (FIB_PROTOCOL_MPLS,
492 ntohl (mp->table.mt_table_id));
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100493
Neale Ranns097fa662018-05-01 05:17:55 -0700494 if (INDEX_INVALID != fib_index)
495 {
496 fib_table_walk (fib_index,
497 FIB_PROTOCOL_MPLS,
498 vl_api_mpls_route_dump_table_walk, &ctx);
499 vec_sort_with_function (ctx.lfeis, fib_entry_cmp_for_sort);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100500
Neale Ranns097fa662018-05-01 05:17:55 -0700501 vec_foreach (lfeip, ctx.lfeis)
502 {
503 send_mpls_route_details (am, reg, mp->context, *lfeip);
504 }
505
506 vec_free (ctx.lfeis);
507 }
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100508}
509
Filip Tehlarda5088c2021-06-22 22:01:19 +0000510#include <vnet/mpls/mpls.api.c>
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100511static clib_error_t *
512mpls_api_hookup (vlib_main_t * vm)
513{
Dave Barach39d69112019-11-27 11:42:13 -0500514 api_main_t *am = vlibapi_get_main ();
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100515
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100516 /*
517 * Trace space for 8 MPLS encap labels
518 */
519 am->api_trace_cfg[VL_API_MPLS_TUNNEL_ADD_DEL].size += 8 * sizeof (u32);
520
521 /*
522 * Set up the (msg_name, crc, message-id) table
523 */
Filip Tehlarda5088c2021-06-22 22:01:19 +0000524 REPLY_MSG_ID_BASE = setup_message_id_table ();
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100525
526 return 0;
527}
528
529VLIB_API_INIT_FUNCTION (mpls_api_hookup);
530
531/*
532 * fd.io coding-style-patch-verification: ON
533 *
534 * Local Variables:
535 * eval: (c-set-style "gnu")
536 * End:
537 */