blob: 58998a6576cb4095abba6e205af4fa7837a822d2 [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 REPLY_MACRO2 (VL_API_MPLS_ROUTE_ADD_DEL_REPLY,
203 ({
204 rmp->stats_index = htonl (stats_index);
205 }));
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100206}
207
Neale Ranns15002542017-09-10 04:39:11 -0700208void
Neale Ranns2297af02017-09-12 09:45:04 -0700209mpls_table_create (u32 table_id, u8 is_api, const u8 * name)
Neale Ranns15002542017-09-10 04:39:11 -0700210{
Neale Ranns15002542017-09-10 04:39:11 -0700211 /*
212 * The MPLS defult table must also be explicitly created via the API.
213 * So in contrast to IP, it gets no special treatment here.
214 */
215
216 /*
217 * The API holds only one lock on the table.
218 * i.e. it can be added many times via the API but needs to be
219 * deleted only once.
220 */
Neale Ranns2297af02017-09-12 09:45:04 -0700221 fib_table_find_or_create_and_lock_w_name (FIB_PROTOCOL_MPLS,
222 table_id,
223 (is_api ?
224 FIB_SOURCE_API :
225 FIB_SOURCE_CLI), name);
Neale Ranns15002542017-09-10 04:39:11 -0700226}
227
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100228static void
229vl_api_mpls_tunnel_add_del_t_handler (vl_api_mpls_tunnel_add_del_t * mp)
230{
Neale Ranns097fa662018-05-01 05:17:55 -0700231 u32 tunnel_sw_if_index = ~0, tunnel_index = ~0;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100232 vl_api_mpls_tunnel_add_del_reply_t *rmp;
Neale Ranns097fa662018-05-01 05:17:55 -0700233 fib_route_path_t *rpath, *rpaths = NULL;
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700234 int ii, rv = 0;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800235
Neale Ranns097fa662018-05-01 05:17:55 -0700236 vec_validate (rpaths, mp->mt_tunnel.mt_n_paths - 1);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100237
Neale Ranns097fa662018-05-01 05:17:55 -0700238 for (ii = 0; ii < mp->mt_tunnel.mt_n_paths; ii++)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800239 {
Neale Ranns097fa662018-05-01 05:17:55 -0700240 rpath = &rpaths[ii];
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800241
Neale Ranns097fa662018-05-01 05:17:55 -0700242 rv = fib_api_path_decode (&mp->mt_tunnel.mt_paths[ii], rpath);
243
244 if (0 != rv)
245 goto out;
Neale Ranns7c922dc2018-08-30 06:12:27 -0700246 }
Neale Ranns097fa662018-05-01 05:17:55 -0700247 tunnel_sw_if_index = ntohl (mp->mt_tunnel.mt_sw_if_index);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800248
249 if (mp->mt_is_add)
250 {
251 if (~0 == tunnel_sw_if_index)
Neale Ranns097fa662018-05-01 05:17:55 -0700252 tunnel_sw_if_index =
253 vnet_mpls_tunnel_create (mp->mt_tunnel.mt_l2_only,
IJsbrand Wijnands39ae0a02020-03-05 10:56:26 -0800254 mp->mt_tunnel.mt_is_multicast,
255 mp->mt_tunnel.mt_tag);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800256 vnet_mpls_tunnel_path_add (tunnel_sw_if_index, rpaths);
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700257
258 tunnel_index = vnet_mpls_tunnel_get_index (tunnel_sw_if_index);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100259 }
260 else
261 {
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700262 tunnel_index = vnet_mpls_tunnel_get_index (tunnel_sw_if_index);
Neale Ranns097fa662018-05-01 05:17:55 -0700263 tunnel_sw_if_index = ntohl (mp->mt_tunnel.mt_sw_if_index);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800264 if (!vnet_mpls_tunnel_path_remove (tunnel_sw_if_index, rpaths))
265 vnet_mpls_tunnel_del (tunnel_sw_if_index);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100266 }
267
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800268 vec_free (rpaths);
269
John Lo06fda9c2018-10-03 16:32:44 -0400270out:
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100271 REPLY_MACRO2(VL_API_MPLS_TUNNEL_ADD_DEL_REPLY,
272 ({
273 rmp->sw_if_index = ntohl(tunnel_sw_if_index);
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700274 rmp->tunnel_index = ntohl(tunnel_index);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100275 }));
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100276}
277
Neale Rannsb8d44812017-11-10 06:53:54 -0800278static void
279 vl_api_sw_interface_set_mpls_enable_t_handler
280 (vl_api_sw_interface_set_mpls_enable_t * mp)
281{
282 vl_api_sw_interface_set_mpls_enable_reply_t *rmp;
283 int rv = 0;
284
285 VALIDATE_SW_IF_INDEX (mp);
286
Nathan Skrzypczak275bd792021-09-17 17:29:14 +0200287 rv = mpls_sw_interface_enable_disable (&mpls_main, ntohl (mp->sw_if_index),
288 mp->enable);
Neale Rannsb8d44812017-11-10 06:53:54 -0800289
290 BAD_SW_IF_INDEX_LABEL;
291 REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY);
292}
293
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100294typedef struct mpls_tunnel_send_walk_ctx_t_
295{
Florin Coras6c4dae22018-01-09 06:39:23 -0800296 vl_api_registration_t *reg;
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700297 u32 sw_if_index;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100298 u32 context;
299} mpls_tunnel_send_walk_ctx_t;
300
301static void
302send_mpls_tunnel_entry (u32 mti, void *arg)
303{
304 mpls_tunnel_send_walk_ctx_t *ctx;
305 vl_api_mpls_tunnel_details_t *mp;
Neale Ranns097fa662018-05-01 05:17:55 -0700306 fib_path_encode_ctx_t path_ctx = {
307 .rpaths = NULL,
308 };
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100309 const mpls_tunnel_t *mt;
Neale Ranns097fa662018-05-01 05:17:55 -0700310 fib_route_path_t *rpath;
Neale Ranns31ed7442018-02-23 05:29:09 -0800311 vl_api_fib_path_t *fp;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800312 u32 n;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100313
314 ctx = arg;
315
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700316 mt = mpls_tunnel_get (mti);
317
318 if (~0 != ctx->sw_if_index && mt->mt_sw_if_index != ctx->sw_if_index)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100319 return;
320
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800321 n = fib_path_list_get_n_paths (mt->mt_path_list);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100322
Neale Ranns31ed7442018-02-23 05:29:09 -0800323 mp = vl_msg_api_alloc (sizeof (*mp) + n * sizeof (vl_api_fib_path_t));
Dave Barachb7b92992018-10-17 10:38:51 -0400324 clib_memset (mp, 0, sizeof (*mp) + n * sizeof (vl_api_fib_path_t));
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800325
Filip Tehlarda5088c2021-06-22 22:01:19 +0000326 mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_MPLS_TUNNEL_DETAILS);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100327 mp->context = ctx->context;
328
IJsbrand Wijnandsbf103d92019-10-28 17:19:27 +0100329 mp->mt_tunnel.mt_n_paths = n;
Neale Ranns097fa662018-05-01 05:17:55 -0700330 mp->mt_tunnel.mt_sw_if_index = ntohl (mt->mt_sw_if_index);
331 mp->mt_tunnel.mt_tunnel_index = ntohl (mti);
332 mp->mt_tunnel.mt_l2_only = ! !(MPLS_TUNNEL_FLAG_L2 & mt->mt_flags);
333 mp->mt_tunnel.mt_is_multicast = ! !(MPLS_TUNNEL_FLAG_MCAST & mt->mt_flags);
IJsbrand Wijnands39ae0a02020-03-05 10:56:26 -0800334 memcpy (mp->mt_tunnel.mt_tag, mt->mt_tag, sizeof (mp->mt_tunnel.mt_tag));
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800335
Neale Ranns775f73c2018-12-20 03:01:49 -0800336 fib_path_list_walk_w_ext (mt->mt_path_list,
Neale Ranns097fa662018-05-01 05:17:55 -0700337 &mt->mt_path_exts, fib_path_encode, &path_ctx);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800338
Neale Ranns097fa662018-05-01 05:17:55 -0700339 fp = mp->mt_tunnel.mt_paths;
340 vec_foreach (rpath, path_ctx.rpaths)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800341 {
Neale Ranns097fa662018-05-01 05:17:55 -0700342 fib_api_path_encode (rpath, fp);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800343 fp++;
344 }
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100345
Florin Coras6c4dae22018-01-09 06:39:23 -0800346 vl_api_send_msg (ctx->reg, (u8 *) mp);
Neale Ranns097fa662018-05-01 05:17:55 -0700347
348 vec_free (path_ctx.rpaths);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100349}
350
351static void
352vl_api_mpls_tunnel_dump_t_handler (vl_api_mpls_tunnel_dump_t * mp)
353{
Florin Coras6c4dae22018-01-09 06:39:23 -0800354 vl_api_registration_t *reg;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100355
Florin Coras6c4dae22018-01-09 06:39:23 -0800356 reg = vl_api_client_index_to_registration (mp->client_index);
357 if (!reg)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100358 return;
359
360 mpls_tunnel_send_walk_ctx_t ctx = {
Florin Coras6c4dae22018-01-09 06:39:23 -0800361 .reg = reg,
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700362 .sw_if_index = ntohl (mp->sw_if_index),
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100363 .context = mp->context,
364 };
365 mpls_tunnel_walk (send_mpls_tunnel_entry, &ctx);
366}
367
368static void
Neale Ranns097fa662018-05-01 05:17:55 -0700369send_mpls_table_details (vpe_api_main_t * am,
370 vl_api_registration_t * reg,
371 u32 context, const fib_table_t * table)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100372{
Neale Ranns097fa662018-05-01 05:17:55 -0700373 vl_api_mpls_table_details_t *mp;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100374
Neale Ranns097fa662018-05-01 05:17:55 -0700375 mp = vl_msg_api_alloc (sizeof (*mp));
376 memset (mp, 0, sizeof (*mp));
Filip Tehlarda5088c2021-06-22 22:01:19 +0000377 mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_MPLS_TABLE_DETAILS);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100378 mp->context = context;
379
Neale Ranns097fa662018-05-01 05:17:55 -0700380 mp->mt_table.mt_table_id = htonl (table->ft_table_id);
381 memcpy (mp->mt_table.mt_name,
382 table->ft_desc,
383 clib_min (vec_len (table->ft_desc), sizeof (mp->mt_table.mt_name)));
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100384
Florin Coras6c4dae22018-01-09 06:39:23 -0800385 vl_api_send_msg (reg, (u8 *) mp);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100386}
387
Neale Ranns097fa662018-05-01 05:17:55 -0700388static void
389vl_api_mpls_table_dump_t_handler (vl_api_mpls_table_dump_t * mp)
390{
391 vpe_api_main_t *am = &vpe_api_main;
392 vl_api_registration_t *reg;
393 mpls_main_t *mm = &mpls_main;
394 fib_table_t *fib_table;
395
396 reg = vl_api_client_index_to_registration (mp->client_index);
397 if (!reg)
398 return;
399
Damjan Marionb2c31b62020-12-13 21:47:40 +0100400 pool_foreach (fib_table, mm->fibs)
401 {
Neale Ranns097fa662018-05-01 05:17:55 -0700402 send_mpls_table_details(am, reg, mp->context, fib_table);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100403 }
Neale Ranns097fa662018-05-01 05:17:55 -0700404}
405
406static void
Pim van Pelt8d61c592023-06-10 16:46:34 +0200407send_mpls_interface_details (vpe_api_main_t *am, vl_api_registration_t *reg,
408 u32 context, const u32 sw_if_index)
409{
410 vl_api_mpls_interface_details_t *mp;
411
412 mp = vl_msg_api_alloc_zero (sizeof (*mp));
413 mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_MPLS_INTERFACE_DETAILS);
414 mp->context = context;
415
416 mp->sw_if_index = htonl (sw_if_index);
417 vl_api_send_msg (reg, (u8 *) mp);
418}
419
420static void
421vl_api_mpls_interface_dump_t_handler (vl_api_mpls_interface_dump_t *mp)
422{
423 vpe_api_main_t *am = &vpe_api_main;
424 vl_api_registration_t *reg;
425 vnet_interface_main_t *im = &vnet_main.interface_main;
426 vnet_sw_interface_t *si;
427 u32 sw_if_index = ~0;
428
429 reg = vl_api_client_index_to_registration (mp->client_index);
430 if (!reg)
431 return;
432 sw_if_index = ntohl (mp->sw_if_index);
433
434 if (sw_if_index == ~0)
435 {
436 pool_foreach (si, im->sw_interfaces)
437 {
438 if (mpls_sw_interface_is_enabled (si->sw_if_index))
439 {
440 send_mpls_interface_details (am, reg, mp->context,
441 si->sw_if_index);
442 }
443 }
444 }
445 else
446 {
447 if (mpls_sw_interface_is_enabled (sw_if_index))
448 {
449 send_mpls_interface_details (am, reg, mp->context, sw_if_index);
450 }
451 }
452}
453
454static void
Neale Ranns097fa662018-05-01 05:17:55 -0700455send_mpls_route_details (vpe_api_main_t * am,
456 vl_api_registration_t * reg,
457 u32 context, fib_node_index_t fib_entry_index)
458{
459 fib_route_path_t *rpaths, *rpath;
460 vl_api_mpls_route_details_t *mp;
461 const fib_prefix_t *pfx;
462 vl_api_fib_path_t *fp;
463 int path_count;
464
465 rpaths = fib_entry_encode (fib_entry_index);
466 pfx = fib_entry_get_prefix (fib_entry_index);
467
468 path_count = vec_len (rpaths);
469 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
470 if (!mp)
471 return;
472 clib_memset (mp, 0, sizeof (*mp));
Filip Tehlarda5088c2021-06-22 22:01:19 +0000473 mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_MPLS_ROUTE_DETAILS);
Neale Ranns097fa662018-05-01 05:17:55 -0700474 mp->context = context;
475
476 mp->mr_route.mr_table_id =
477 htonl (fib_table_get_table_id
478 (fib_entry_get_fib_index (fib_entry_index), pfx->fp_proto));
479 mp->mr_route.mr_eos = pfx->fp_eos;
480 mp->mr_route.mr_eos_proto = pfx->fp_payload_proto;
481 mp->mr_route.mr_label = htonl (pfx->fp_label);
482
483 mp->mr_route.mr_n_paths = path_count;
484 fp = mp->mr_route.mr_paths;
485 vec_foreach (rpath, rpaths)
486 {
487 fib_api_path_encode (rpath, fp);
488 fp++;
489 }
490
491 vec_free (rpaths);
492 vl_api_send_msg (reg, (u8 *) mp);
493}
494
495typedef struct vl_api_mpls_route_dump_table_walk_ctx_t_
Neale Rannsa3af3372017-03-28 03:49:52 -0700496{
497 fib_node_index_t *lfeis;
Neale Ranns097fa662018-05-01 05:17:55 -0700498} vl_api_mpls_route_dump_table_walk_ctx_t;
Neale Rannsa3af3372017-03-28 03:49:52 -0700499
Neale Ranns89541992017-04-06 04:41:02 -0700500static fib_table_walk_rc_t
Neale Ranns097fa662018-05-01 05:17:55 -0700501vl_api_mpls_route_dump_table_walk (fib_node_index_t fei, void *arg)
Neale Rannsa3af3372017-03-28 03:49:52 -0700502{
Neale Ranns097fa662018-05-01 05:17:55 -0700503 vl_api_mpls_route_dump_table_walk_ctx_t *ctx = arg;
Neale Rannsa3af3372017-03-28 03:49:52 -0700504
505 vec_add1 (ctx->lfeis, fei);
506
Neale Ranns89541992017-04-06 04:41:02 -0700507 return (FIB_TABLE_WALK_CONTINUE);
Neale Rannsa3af3372017-03-28 03:49:52 -0700508}
509
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100510static void
Neale Ranns097fa662018-05-01 05:17:55 -0700511vl_api_mpls_route_dump_t_handler (vl_api_mpls_route_dump_t * mp)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100512{
513 vpe_api_main_t *am = &vpe_api_main;
Florin Coras6c4dae22018-01-09 06:39:23 -0800514 vl_api_registration_t *reg;
Neale Rannsa3af3372017-03-28 03:49:52 -0700515 fib_node_index_t *lfeip = NULL;
Neale Ranns097fa662018-05-01 05:17:55 -0700516 vl_api_mpls_route_dump_table_walk_ctx_t ctx = {
Neale Rannsa3af3372017-03-28 03:49:52 -0700517 .lfeis = NULL,
518 };
Neale Ranns097fa662018-05-01 05:17:55 -0700519 u32 fib_index;
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100520
Florin Coras6c4dae22018-01-09 06:39:23 -0800521 reg = vl_api_client_index_to_registration (mp->client_index);
522 if (!reg)
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100523 return;
524
Neale Ranns097fa662018-05-01 05:17:55 -0700525 fib_index = fib_table_find (FIB_PROTOCOL_MPLS,
526 ntohl (mp->table.mt_table_id));
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100527
Neale Ranns097fa662018-05-01 05:17:55 -0700528 if (INDEX_INVALID != fib_index)
529 {
530 fib_table_walk (fib_index,
531 FIB_PROTOCOL_MPLS,
532 vl_api_mpls_route_dump_table_walk, &ctx);
533 vec_sort_with_function (ctx.lfeis, fib_entry_cmp_for_sort);
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100534
Neale Ranns097fa662018-05-01 05:17:55 -0700535 vec_foreach (lfeip, ctx.lfeis)
536 {
537 send_mpls_route_details (am, reg, mp->context, *lfeip);
538 }
539
540 vec_free (ctx.lfeis);
541 }
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100542}
543
Filip Tehlarda5088c2021-06-22 22:01:19 +0000544#include <vnet/mpls/mpls.api.c>
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100545static clib_error_t *
546mpls_api_hookup (vlib_main_t * vm)
547{
Dave Barach39d69112019-11-27 11:42:13 -0500548 api_main_t *am = vlibapi_get_main ();
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100549
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100550 /*
551 * Trace space for 8 MPLS encap labels
552 */
Damjan Marioncada9eb2022-05-18 22:16:11 +0200553 vl_api_increase_msg_trace_size (am, VL_API_MPLS_TUNNEL_ADD_DEL,
554 8 * sizeof (u32));
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100555
556 /*
557 * Set up the (msg_name, crc, message-id) table
558 */
Filip Tehlarda5088c2021-06-22 22:01:19 +0000559 REPLY_MSG_ID_BASE = setup_message_id_table ();
Pavel Kotucek0f971d82017-01-03 10:48:54 +0100560
561 return 0;
562}
563
564VLIB_API_INIT_FUNCTION (mpls_api_hookup);
565
566/*
567 * fd.io coding-style-patch-verification: ON
568 *
569 * Local Variables:
570 * eval: (c-set-style "gnu")
571 * End:
572 */