blob: fac52827e1db11d728675de2c72aff4e7599994d [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{
Neale Ranns15002542017-09-10 04:39:11 -0700213 /*
214 * The MPLS defult table must also be explicitly created via the API.
215 * So in contrast to IP, it gets no special treatment here.
216 */
217
218 /*
219 * The API holds only one lock on the table.
220 * i.e. it can be added many times via the API but needs to be
221 * deleted only once.
222 */
Neale Ranns2297af02017-09-12 09:45:04 -0700223 fib_table_find_or_create_and_lock_w_name (FIB_PROTOCOL_MPLS,
224 table_id,
225 (is_api ?
226 FIB_SOURCE_API :
227 FIB_SOURCE_CLI), name);
Neale Ranns15002542017-09-10 04:39:11 -0700228}
229
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100230static void
231vl_api_mpls_tunnel_add_del_t_handler (vl_api_mpls_tunnel_add_del_t * mp)
232{
Neale Ranns097fa662018-05-01 05:17:55 -0700233 u32 tunnel_sw_if_index = ~0, tunnel_index = ~0;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100234 vl_api_mpls_tunnel_add_del_reply_t *rmp;
Neale Ranns097fa662018-05-01 05:17:55 -0700235 fib_route_path_t *rpath, *rpaths = NULL;
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700236 int ii, rv = 0;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800237
Neale Ranns097fa662018-05-01 05:17:55 -0700238 vec_validate (rpaths, mp->mt_tunnel.mt_n_paths - 1);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100239
Neale Ranns097fa662018-05-01 05:17:55 -0700240 for (ii = 0; ii < mp->mt_tunnel.mt_n_paths; ii++)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800241 {
Neale Ranns097fa662018-05-01 05:17:55 -0700242 rpath = &rpaths[ii];
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800243
Neale Ranns097fa662018-05-01 05:17:55 -0700244 rv = fib_api_path_decode (&mp->mt_tunnel.mt_paths[ii], rpath);
245
246 if (0 != rv)
247 goto out;
Neale Ranns7c922dc2018-08-30 06:12:27 -0700248 }
Neale Ranns097fa662018-05-01 05:17:55 -0700249 tunnel_sw_if_index = ntohl (mp->mt_tunnel.mt_sw_if_index);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800250
251 if (mp->mt_is_add)
252 {
253 if (~0 == tunnel_sw_if_index)
Neale Ranns097fa662018-05-01 05:17:55 -0700254 tunnel_sw_if_index =
255 vnet_mpls_tunnel_create (mp->mt_tunnel.mt_l2_only,
IJsbrand Wijnands39ae0a02020-03-05 10:56:26 -0800256 mp->mt_tunnel.mt_is_multicast,
257 mp->mt_tunnel.mt_tag);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800258 vnet_mpls_tunnel_path_add (tunnel_sw_if_index, rpaths);
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700259
260 tunnel_index = vnet_mpls_tunnel_get_index (tunnel_sw_if_index);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100261 }
262 else
263 {
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700264 tunnel_index = vnet_mpls_tunnel_get_index (tunnel_sw_if_index);
Neale Ranns097fa662018-05-01 05:17:55 -0700265 tunnel_sw_if_index = ntohl (mp->mt_tunnel.mt_sw_if_index);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800266 if (!vnet_mpls_tunnel_path_remove (tunnel_sw_if_index, rpaths))
267 vnet_mpls_tunnel_del (tunnel_sw_if_index);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100268 }
269
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800270 vec_free (rpaths);
271
John Lo06fda9c2018-10-03 16:32:44 -0400272out:
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100273 /* *INDENT-OFF* */
274 REPLY_MACRO2(VL_API_MPLS_TUNNEL_ADD_DEL_REPLY,
275 ({
276 rmp->sw_if_index = ntohl(tunnel_sw_if_index);
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700277 rmp->tunnel_index = ntohl(tunnel_index);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100278 }));
279 /* *INDENT-ON* */
280}
281
Neale Rannsb8d44812017-11-10 06:53:54 -0800282static void
283 vl_api_sw_interface_set_mpls_enable_t_handler
284 (vl_api_sw_interface_set_mpls_enable_t * mp)
285{
286 vl_api_sw_interface_set_mpls_enable_reply_t *rmp;
287 int rv = 0;
288
289 VALIDATE_SW_IF_INDEX (mp);
290
Nathan Skrzypczak275bd792021-09-17 17:29:14 +0200291 rv = mpls_sw_interface_enable_disable (&mpls_main, ntohl (mp->sw_if_index),
292 mp->enable);
Neale Rannsb8d44812017-11-10 06:53:54 -0800293
294 BAD_SW_IF_INDEX_LABEL;
295 REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY);
296}
297
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100298typedef struct mpls_tunnel_send_walk_ctx_t_
299{
Florin Coras6c4dae22018-01-09 06:39:23 -0800300 vl_api_registration_t *reg;
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700301 u32 sw_if_index;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100302 u32 context;
303} mpls_tunnel_send_walk_ctx_t;
304
305static void
306send_mpls_tunnel_entry (u32 mti, void *arg)
307{
308 mpls_tunnel_send_walk_ctx_t *ctx;
309 vl_api_mpls_tunnel_details_t *mp;
Neale Ranns097fa662018-05-01 05:17:55 -0700310 fib_path_encode_ctx_t path_ctx = {
311 .rpaths = NULL,
312 };
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100313 const mpls_tunnel_t *mt;
Neale Ranns097fa662018-05-01 05:17:55 -0700314 fib_route_path_t *rpath;
Neale Ranns31ed7442018-02-23 05:29:09 -0800315 vl_api_fib_path_t *fp;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800316 u32 n;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100317
318 ctx = arg;
319
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700320 mt = mpls_tunnel_get (mti);
321
322 if (~0 != ctx->sw_if_index && mt->mt_sw_if_index != ctx->sw_if_index)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100323 return;
324
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800325 n = fib_path_list_get_n_paths (mt->mt_path_list);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100326
Neale Ranns31ed7442018-02-23 05:29:09 -0800327 mp = vl_msg_api_alloc (sizeof (*mp) + n * sizeof (vl_api_fib_path_t));
Dave Barachb7b92992018-10-17 10:38:51 -0400328 clib_memset (mp, 0, sizeof (*mp) + n * sizeof (vl_api_fib_path_t));
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800329
Filip Tehlarda5088c2021-06-22 22:01:19 +0000330 mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_MPLS_TUNNEL_DETAILS);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100331 mp->context = ctx->context;
332
IJsbrand Wijnandsbf103d92019-10-28 17:19:27 +0100333 mp->mt_tunnel.mt_n_paths = n;
Neale Ranns097fa662018-05-01 05:17:55 -0700334 mp->mt_tunnel.mt_sw_if_index = ntohl (mt->mt_sw_if_index);
335 mp->mt_tunnel.mt_tunnel_index = ntohl (mti);
336 mp->mt_tunnel.mt_l2_only = ! !(MPLS_TUNNEL_FLAG_L2 & mt->mt_flags);
337 mp->mt_tunnel.mt_is_multicast = ! !(MPLS_TUNNEL_FLAG_MCAST & mt->mt_flags);
IJsbrand Wijnands39ae0a02020-03-05 10:56:26 -0800338 memcpy (mp->mt_tunnel.mt_tag, mt->mt_tag, sizeof (mp->mt_tunnel.mt_tag));
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800339
Neale Ranns775f73c2018-12-20 03:01:49 -0800340 fib_path_list_walk_w_ext (mt->mt_path_list,
Neale Ranns097fa662018-05-01 05:17:55 -0700341 &mt->mt_path_exts, fib_path_encode, &path_ctx);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800342
Neale Ranns097fa662018-05-01 05:17:55 -0700343 fp = mp->mt_tunnel.mt_paths;
344 vec_foreach (rpath, path_ctx.rpaths)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800345 {
Neale Ranns097fa662018-05-01 05:17:55 -0700346 fib_api_path_encode (rpath, fp);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800347 fp++;
348 }
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100349
Florin Coras6c4dae22018-01-09 06:39:23 -0800350 vl_api_send_msg (ctx->reg, (u8 *) mp);
Neale Ranns097fa662018-05-01 05:17:55 -0700351
352 vec_free (path_ctx.rpaths);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100353}
354
355static void
356vl_api_mpls_tunnel_dump_t_handler (vl_api_mpls_tunnel_dump_t * mp)
357{
Florin Coras6c4dae22018-01-09 06:39:23 -0800358 vl_api_registration_t *reg;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100359
Florin Coras6c4dae22018-01-09 06:39:23 -0800360 reg = vl_api_client_index_to_registration (mp->client_index);
361 if (!reg)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100362 return;
363
364 mpls_tunnel_send_walk_ctx_t ctx = {
Florin Coras6c4dae22018-01-09 06:39:23 -0800365 .reg = reg,
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700366 .sw_if_index = ntohl (mp->sw_if_index),
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100367 .context = mp->context,
368 };
369 mpls_tunnel_walk (send_mpls_tunnel_entry, &ctx);
370}
371
372static void
Neale Ranns097fa662018-05-01 05:17:55 -0700373send_mpls_table_details (vpe_api_main_t * am,
374 vl_api_registration_t * reg,
375 u32 context, const fib_table_t * table)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100376{
Neale Ranns097fa662018-05-01 05:17:55 -0700377 vl_api_mpls_table_details_t *mp;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100378
Neale Ranns097fa662018-05-01 05:17:55 -0700379 mp = vl_msg_api_alloc (sizeof (*mp));
380 memset (mp, 0, sizeof (*mp));
Filip Tehlarda5088c2021-06-22 22:01:19 +0000381 mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_MPLS_TABLE_DETAILS);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100382 mp->context = context;
383
Neale Ranns097fa662018-05-01 05:17:55 -0700384 mp->mt_table.mt_table_id = htonl (table->ft_table_id);
385 memcpy (mp->mt_table.mt_name,
386 table->ft_desc,
387 clib_min (vec_len (table->ft_desc), sizeof (mp->mt_table.mt_name)));
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100388
Florin Coras6c4dae22018-01-09 06:39:23 -0800389 vl_api_send_msg (reg, (u8 *) mp);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100390}
391
Neale Ranns097fa662018-05-01 05:17:55 -0700392static void
393vl_api_mpls_table_dump_t_handler (vl_api_mpls_table_dump_t * mp)
394{
395 vpe_api_main_t *am = &vpe_api_main;
396 vl_api_registration_t *reg;
397 mpls_main_t *mm = &mpls_main;
398 fib_table_t *fib_table;
399
400 reg = vl_api_client_index_to_registration (mp->client_index);
401 if (!reg)
402 return;
403
404 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100405 pool_foreach (fib_table, mm->fibs)
406 {
Neale Ranns097fa662018-05-01 05:17:55 -0700407 send_mpls_table_details(am, reg, mp->context, fib_table);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100408 }
Neale Ranns097fa662018-05-01 05:17:55 -0700409 /* *INDENT-ON* */
410}
411
412static void
413send_mpls_route_details (vpe_api_main_t * am,
414 vl_api_registration_t * reg,
415 u32 context, fib_node_index_t fib_entry_index)
416{
417 fib_route_path_t *rpaths, *rpath;
418 vl_api_mpls_route_details_t *mp;
419 const fib_prefix_t *pfx;
420 vl_api_fib_path_t *fp;
421 int path_count;
422
423 rpaths = fib_entry_encode (fib_entry_index);
424 pfx = fib_entry_get_prefix (fib_entry_index);
425
426 path_count = vec_len (rpaths);
427 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
428 if (!mp)
429 return;
430 clib_memset (mp, 0, sizeof (*mp));
Filip Tehlarda5088c2021-06-22 22:01:19 +0000431 mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_MPLS_ROUTE_DETAILS);
Neale Ranns097fa662018-05-01 05:17:55 -0700432 mp->context = context;
433
434 mp->mr_route.mr_table_id =
435 htonl (fib_table_get_table_id
436 (fib_entry_get_fib_index (fib_entry_index), pfx->fp_proto));
437 mp->mr_route.mr_eos = pfx->fp_eos;
438 mp->mr_route.mr_eos_proto = pfx->fp_payload_proto;
439 mp->mr_route.mr_label = htonl (pfx->fp_label);
440
441 mp->mr_route.mr_n_paths = path_count;
442 fp = mp->mr_route.mr_paths;
443 vec_foreach (rpath, rpaths)
444 {
445 fib_api_path_encode (rpath, fp);
446 fp++;
447 }
448
449 vec_free (rpaths);
450 vl_api_send_msg (reg, (u8 *) mp);
451}
452
453typedef struct vl_api_mpls_route_dump_table_walk_ctx_t_
Neale Rannsa3af3372017-03-28 03:49:52 -0700454{
455 fib_node_index_t *lfeis;
Neale Ranns097fa662018-05-01 05:17:55 -0700456} vl_api_mpls_route_dump_table_walk_ctx_t;
Neale Rannsa3af3372017-03-28 03:49:52 -0700457
Neale Ranns89541992017-04-06 04:41:02 -0700458static fib_table_walk_rc_t
Neale Ranns097fa662018-05-01 05:17:55 -0700459vl_api_mpls_route_dump_table_walk (fib_node_index_t fei, void *arg)
Neale Rannsa3af3372017-03-28 03:49:52 -0700460{
Neale Ranns097fa662018-05-01 05:17:55 -0700461 vl_api_mpls_route_dump_table_walk_ctx_t *ctx = arg;
Neale Rannsa3af3372017-03-28 03:49:52 -0700462
463 vec_add1 (ctx->lfeis, fei);
464
Neale Ranns89541992017-04-06 04:41:02 -0700465 return (FIB_TABLE_WALK_CONTINUE);
Neale Rannsa3af3372017-03-28 03:49:52 -0700466}
467
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100468static void
Neale Ranns097fa662018-05-01 05:17:55 -0700469vl_api_mpls_route_dump_t_handler (vl_api_mpls_route_dump_t * mp)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100470{
471 vpe_api_main_t *am = &vpe_api_main;
Florin Coras6c4dae22018-01-09 06:39:23 -0800472 vl_api_registration_t *reg;
Neale Rannsa3af3372017-03-28 03:49:52 -0700473 fib_node_index_t *lfeip = NULL;
Neale Ranns097fa662018-05-01 05:17:55 -0700474 vl_api_mpls_route_dump_table_walk_ctx_t ctx = {
Neale Rannsa3af3372017-03-28 03:49:52 -0700475 .lfeis = NULL,
476 };
Neale Ranns097fa662018-05-01 05:17:55 -0700477 u32 fib_index;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100478
Florin Coras6c4dae22018-01-09 06:39:23 -0800479 reg = vl_api_client_index_to_registration (mp->client_index);
480 if (!reg)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100481 return;
482
Neale Ranns097fa662018-05-01 05:17:55 -0700483 fib_index = fib_table_find (FIB_PROTOCOL_MPLS,
484 ntohl (mp->table.mt_table_id));
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100485
Neale Ranns097fa662018-05-01 05:17:55 -0700486 if (INDEX_INVALID != fib_index)
487 {
488 fib_table_walk (fib_index,
489 FIB_PROTOCOL_MPLS,
490 vl_api_mpls_route_dump_table_walk, &ctx);
491 vec_sort_with_function (ctx.lfeis, fib_entry_cmp_for_sort);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100492
Neale Ranns097fa662018-05-01 05:17:55 -0700493 vec_foreach (lfeip, ctx.lfeis)
494 {
495 send_mpls_route_details (am, reg, mp->context, *lfeip);
496 }
497
498 vec_free (ctx.lfeis);
499 }
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100500}
501
Filip Tehlarda5088c2021-06-22 22:01:19 +0000502#include <vnet/mpls/mpls.api.c>
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100503static clib_error_t *
504mpls_api_hookup (vlib_main_t * vm)
505{
Dave Barach39d69112019-11-27 11:42:13 -0500506 api_main_t *am = vlibapi_get_main ();
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100507
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100508 /*
509 * Trace space for 8 MPLS encap labels
510 */
Damjan Marioncada9eb2022-05-18 22:16:11 +0200511 vl_api_increase_msg_trace_size (am, VL_API_MPLS_TUNNEL_ADD_DEL,
512 8 * sizeof (u32));
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100513
514 /*
515 * Set up the (msg_name, crc, message-id) table
516 */
Filip Tehlarda5088c2021-06-22 22:01:19 +0000517 REPLY_MSG_ID_BASE = setup_message_id_table ();
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100518
519 return 0;
520}
521
522VLIB_API_INIT_FUNCTION (mpls_api_hookup);
523
524/*
525 * fd.io coding-style-patch-verification: ON
526 *
527 * Local Variables:
528 * eval: (c-set-style "gnu")
529 * End:
530 */