]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_mpls_vty.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / zebra / zebra_mpls_vty.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
41675b4c
RW
2/* Zebra MPLS VTY functions
3 * Copyright (C) 2002 Kunihiro Ishiguro
41675b4c
RW
4 */
5
6#include <zebra.h>
7
41675b4c
RW
8#include "memory.h"
9#include "if.h"
10#include "prefix.h"
11#include "command.h"
12#include "table.h"
13#include "rib.h"
14#include "nexthop.h"
15#include "vrf.h"
16#include "mpls.h"
17#include "lib/json.h"
18
19#include "zebra/zserv.h"
20#include "zebra/zebra_vrf.h"
21#include "zebra/zebra_mpls.h"
22#include "zebra/zebra_rnh.h"
23#include "zebra/redistribute.h"
24#include "zebra/zebra_routemap.h"
41675b4c 25
d62a17ae 26static int zebra_mpls_transit_lsp(struct vty *vty, int add_cmd,
27 const char *inlabel_str, const char *gate_str,
28 const char *outlabel_str,
29 const char *flag_str)
41675b4c 30{
d62a17ae 31 struct zebra_vrf *zvrf;
32 int ret;
33 enum nexthop_types_t gtype;
34 union g_addr gate;
35 mpls_label_t label;
36 mpls_label_t in_label, out_label;
37
38 if (!mpls_enabled) {
39 vty_out(vty,
40 "%% MPLS not turned on in kernel, ignoring command\n");
41 return CMD_WARNING_CONFIG_FAILED;
42 }
43
44 zvrf = vrf_info_lookup(VRF_DEFAULT);
45 if (!zvrf) {
46 vty_out(vty, "%% Default VRF does not exist\n");
47 return CMD_WARNING_CONFIG_FAILED;
48 }
49
50 if (!inlabel_str) {
51 vty_out(vty, "%% No Label Information\n");
52 return CMD_WARNING_CONFIG_FAILED;
53 }
54
70e98a7f 55 out_label = MPLS_LABEL_IMPLICIT_NULL; /* as initialization */
d62a17ae 56 label = atoi(inlabel_str);
57 if (!IS_MPLS_UNRESERVED_LABEL(label)) {
58 vty_out(vty, "%% Invalid label\n");
59 return CMD_WARNING_CONFIG_FAILED;
60 }
61
62 if (add_cmd) {
63 if (!gate_str) {
64 vty_out(vty, "%% No Nexthop Information\n");
65 return CMD_WARNING_CONFIG_FAILED;
66 }
67 if (!outlabel_str) {
68 vty_out(vty, "%% No Outgoing label Information\n");
69 return CMD_WARNING_CONFIG_FAILED;
70 }
71 }
72
73 in_label = label;
21683186 74 gtype = NEXTHOP_TYPE_BLACKHOLE; /* as initialization */
d62a17ae 75
21683186 76 if (gate_str) {
77 /* Gateway is a IPv4 or IPv6 nexthop. */
78 ret = inet_pton(AF_INET6, gate_str, &gate.ipv6);
a44e3106 79 if (ret == 1)
21683186 80 gtype = NEXTHOP_TYPE_IPV6;
d62a17ae 81 else {
21683186 82 ret = inet_pton(AF_INET, gate_str, &gate.ipv4);
83 if (ret == 1)
84 gtype = NEXTHOP_TYPE_IPV4;
85 else {
86 vty_out(vty, "%% Invalid nexthop\n");
87 return CMD_WARNING_CONFIG_FAILED;
88 }
d62a17ae 89 }
90 }
91
92 if (outlabel_str) {
93 if (outlabel_str[0] == 'i')
70e98a7f 94 out_label = MPLS_LABEL_IMPLICIT_NULL;
d62a17ae 95 else if (outlabel_str[0] == 'e' && gtype == NEXTHOP_TYPE_IPV4)
70e98a7f 96 out_label = MPLS_LABEL_IPV4_EXPLICIT_NULL;
d62a17ae 97 else if (outlabel_str[0] == 'e' && gtype == NEXTHOP_TYPE_IPV6)
70e98a7f 98 out_label = MPLS_LABEL_IPV6_EXPLICIT_NULL;
d62a17ae 99 else
100 out_label = atoi(outlabel_str);
101 }
102
103 if (add_cmd) {
41675b4c 104#if defined(HAVE_CUMULUS)
d62a17ae 105 /* Check that label value is consistent. */
106 if (!zebra_mpls_lsp_label_consistent(zvrf, in_label, out_label,
107 gtype, &gate, 0)) {
108 vty_out(vty, "%% Label value not consistent\n");
109 return CMD_WARNING_CONFIG_FAILED;
110 }
41675b4c
RW
111#endif /* HAVE_CUMULUS */
112
d62a17ae 113 ret = zebra_mpls_static_lsp_add(zvrf, in_label, out_label,
114 gtype, &gate, 0);
115 } else
116 ret = zebra_mpls_static_lsp_del(zvrf, in_label, gtype, &gate,
117 0);
41675b4c 118
a44e3106 119 if (ret != 0) {
d62a17ae 120 vty_out(vty, "%% LSP cannot be %s\n",
121 add_cmd ? "added" : "deleted");
122 return CMD_WARNING_CONFIG_FAILED;
123 }
41675b4c 124
d62a17ae 125 return CMD_SUCCESS;
41675b4c
RW
126}
127
128DEFUN (mpls_transit_lsp,
129 mpls_transit_lsp_cmd,
e52702f2 130 "mpls lsp (16-1048575) <A.B.C.D|X:X::X:X> <(16-1048575)|explicit-null|implicit-null>",
41675b4c
RW
131 MPLS_STR
132 "Establish label switched path\n"
133 "Incoming MPLS label\n"
134 "IPv4 gateway address\n"
135 "IPv6 gateway address\n"
136 "Outgoing MPLS label\n"
e64f3c32 137 "Use Explicit-Null label\n"
41675b4c
RW
138 "Use Implicit-Null label\n")
139{
d62a17ae 140 return zebra_mpls_transit_lsp(vty, 1, argv[2]->arg, argv[3]->arg,
141 argv[4]->arg, NULL);
41675b4c
RW
142}
143
144DEFUN (no_mpls_transit_lsp,
145 no_mpls_transit_lsp_cmd,
e52702f2 146 "no mpls lsp (16-1048575) <A.B.C.D|X:X::X:X>",
41675b4c
RW
147 NO_STR
148 MPLS_STR
149 "Establish label switched path\n"
150 "Incoming MPLS label\n"
151 "IPv4 gateway address\n"
152 "IPv6 gateway address\n")
153{
d62a17ae 154 return zebra_mpls_transit_lsp(vty, 0, argv[3]->arg, argv[4]->arg, NULL,
155 NULL);
41675b4c
RW
156}
157
d62a17ae 158ALIAS(no_mpls_transit_lsp, no_mpls_transit_lsp_out_label_cmd,
159 "no mpls lsp (16-1048575) <A.B.C.D|X:X::X:X> <(16-1048575)|explicit-null|implicit-null>",
160 NO_STR MPLS_STR
161 "Establish label switched path\n"
162 "Incoming MPLS label\n"
163 "IPv4 gateway address\n"
164 "IPv6 gateway address\n"
165 "Outgoing MPLS label\n"
166 "Use Explicit-Null label\n"
167 "Use Implicit-Null label\n")
168
41675b4c
RW
169DEFUN (no_mpls_transit_lsp_all,
170 no_mpls_transit_lsp_all_cmd,
e52702f2 171 "no mpls lsp (16-1048575)",
41675b4c
RW
172 NO_STR
173 MPLS_STR
174 "Establish label switched path\n"
175 "Incoming MPLS label\n")
176{
d62a17ae 177 return zebra_mpls_transit_lsp(vty, 0, argv[3]->arg, NULL, NULL, NULL);
41675b4c
RW
178}
179
d62a17ae 180static int zebra_mpls_bind(struct vty *vty, int add_cmd, const char *prefix,
181 const char *label_str)
f31e084c 182{
d62a17ae 183 struct zebra_vrf *zvrf;
184 struct prefix p;
d7c0a89a 185 uint32_t label;
d62a17ae 186 int ret;
187
188 zvrf = vrf_info_lookup(VRF_DEFAULT);
189 if (!zvrf) {
190 vty_out(vty, "%% Default VRF does not exist\n");
191 return CMD_WARNING_CONFIG_FAILED;
192 }
193
6006b807 194 memset(&p, 0, sizeof(p));
d62a17ae 195 ret = str2prefix(prefix, &p);
196 if (ret <= 0) {
197 vty_out(vty, "%% Malformed address\n");
198 return CMD_WARNING_CONFIG_FAILED;
199 }
200
201 if (add_cmd) {
202 if (!label_str) {
203 vty_out(vty, "%% No label binding specified\n");
204 return CMD_WARNING_CONFIG_FAILED;
205 }
206
207 if (!strcmp(label_str, "implicit-null"))
70e98a7f 208 label = MPLS_LABEL_IMPLICIT_NULL;
d62a17ae 209 else if (!strcmp(label_str, "explicit-null")) {
210 if (p.family == AF_INET)
70e98a7f 211 label = MPLS_LABEL_IPV4_EXPLICIT_NULL;
d62a17ae 212 else
70e98a7f 213 label = MPLS_LABEL_IPV6_EXPLICIT_NULL;
d62a17ae 214 } else {
215 label = atoi(label_str);
216 if (!IS_MPLS_UNRESERVED_LABEL(label)) {
217 vty_out(vty, "%% Invalid label\n");
218 return CMD_WARNING_CONFIG_FAILED;
219 }
220 if (zebra_mpls_label_already_bound(zvrf, label)) {
221 vty_out(vty,
222 "%% Label already bound to a FEC\n");
223 return CMD_WARNING_CONFIG_FAILED;
224 }
225 }
226
227 ret = zebra_mpls_static_fec_add(zvrf, &p, label);
228 } else
229 ret = zebra_mpls_static_fec_del(zvrf, &p);
230
231 if (ret) {
232 vty_out(vty, "%% FEC to label binding cannot be %s\n",
233 add_cmd ? "added" : "deleted");
234 return CMD_WARNING_CONFIG_FAILED;
235 }
236
237 return CMD_SUCCESS;
f31e084c
DS
238}
239
240DEFUN (mpls_label_bind,
241 mpls_label_bind_cmd,
bf995813 242 "mpls label bind <A.B.C.D/M|X:X::X:X/M> <(16-1048575)|implicit-null|explicit-null>",
f31e084c
DS
243 MPLS_STR
244 "Label configuration\n"
245 "Establish FEC to label binding\n"
246 "IPv4 prefix\n"
247 "IPv6 prefix\n"
248 "MPLS Label to bind\n"
bf995813
DS
249 "Use Implicit-Null Label\n"
250 "Use Explicit-Null Label\n")
f31e084c 251{
d62a17ae 252 return zebra_mpls_bind(vty, 1, argv[3]->arg, argv[4]->arg);
f31e084c
DS
253}
254
255DEFUN (no_mpls_label_bind,
256 no_mpls_label_bind_cmd,
257 "no mpls label bind <A.B.C.D/M|X:X::X:X/M> [<(16-1048575)|implicit-null>]",
258 NO_STR
259 MPLS_STR
260 "Label configuration\n"
261 "Establish FEC to label binding\n"
262 "IPv4 prefix\n"
263 "IPv6 prefix\n"
264 "MPLS Label to bind\n"
265 "Use Implicit-Null Label\n")
f31e084c 266{
d62a17ae 267 return zebra_mpls_bind(vty, 0, argv[4]->arg, NULL);
f31e084c
DS
268}
269
41675b4c 270/* MPLS LSP configuration write function. */
d62a17ae 271static int zebra_mpls_config(struct vty *vty)
41675b4c 272{
d62a17ae 273 int write = 0;
274 struct zebra_vrf *zvrf;
41675b4c 275
d62a17ae 276 zvrf = vrf_info_lookup(VRF_DEFAULT);
277 if (!zvrf)
278 return 0;
41675b4c 279
d62a17ae 280 write += zebra_mpls_write_lsp_config(vty, zvrf);
281 write += zebra_mpls_write_fec_config(vty, zvrf);
282 write += zebra_mpls_write_label_block_config(vty, zvrf);
283 return write;
41675b4c
RW
284}
285
f31e084c
DS
286DEFUN (show_mpls_fec,
287 show_mpls_fec_cmd,
288 "show mpls fec [<A.B.C.D/M|X:X::X:X/M>]",
289 SHOW_STR
290 MPLS_STR
291 "MPLS FEC table\n"
292 "FEC to display information about\n"
293 "FEC to display information about\n")
294{
d62a17ae 295 struct zebra_vrf *zvrf;
296 struct prefix p;
297 int ret;
298
299 zvrf = vrf_info_lookup(VRF_DEFAULT);
300 if (!zvrf)
301 return 0;
302
303 if (argc == 3)
304 zebra_mpls_print_fec_table(vty, zvrf);
305 else {
306 memset(&p, 0, sizeof(struct prefix));
307 ret = str2prefix(argv[3]->arg, &p);
308 if (ret <= 0) {
309 vty_out(vty, "%% Malformed address\n");
310 return CMD_WARNING;
311 }
312 zebra_mpls_print_fec(vty, zvrf, &p);
313 }
314
315 return CMD_SUCCESS;
f31e084c
DS
316}
317
41675b4c
RW
318DEFUN (show_mpls_table,
319 show_mpls_table_cmd,
e52702f2 320 "show mpls table [json]",
41675b4c
RW
321 SHOW_STR
322 MPLS_STR
323 "MPLS table\n"
9973d184 324 JSON_STR)
41675b4c 325{
d62a17ae 326 struct zebra_vrf *zvrf;
088f1098 327 bool uj = use_json(argc, argv);
41675b4c 328
d62a17ae 329 zvrf = vrf_info_lookup(VRF_DEFAULT);
330 zebra_mpls_print_lsp_table(vty, zvrf, uj);
331 return CMD_SUCCESS;
41675b4c
RW
332}
333
334DEFUN (show_mpls_table_lsp,
335 show_mpls_table_lsp_cmd,
e52702f2 336 "show mpls table (16-1048575) [json]",
41675b4c
RW
337 SHOW_STR
338 MPLS_STR
339 "MPLS table\n"
340 "LSP to display information about\n"
9973d184 341 JSON_STR)
41675b4c 342{
d7c0a89a 343 uint32_t label;
d62a17ae 344 struct zebra_vrf *zvrf;
088f1098 345 bool uj = use_json(argc, argv);
d62a17ae 346
347 zvrf = vrf_info_lookup(VRF_DEFAULT);
348 label = atoi(argv[3]->arg);
349 zebra_mpls_print_lsp(vty, zvrf, label, uj);
350 return CMD_SUCCESS;
41675b4c
RW
351}
352
fe6c7157
RW
353DEFUN (show_mpls_status,
354 show_mpls_status_cmd,
355 "show mpls status",
356 SHOW_STR
357 "MPLS information\n"
358 "MPLS status\n")
359{
d62a17ae 360 vty_out(vty, "MPLS support enabled: %s\n",
361 (mpls_enabled) ? "yes"
362 : "no (mpls kernel extensions not detected)");
363 return CMD_SUCCESS;
fe6c7157
RW
364}
365
d62a17ae 366static int zebra_mpls_global_block(struct vty *vty, int add_cmd,
367 const char *start_label_str,
368 const char *end_label_str)
1b6d5c7e 369{
d62a17ae 370 int ret;
d7c0a89a
QY
371 uint32_t start_label;
372 uint32_t end_label;
d62a17ae 373 struct zebra_vrf *zvrf;
374
375 zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
376 if (!zvrf) {
377 vty_out(vty, "%% Default VRF does not exist\n");
378 return CMD_WARNING_CONFIG_FAILED;
379 }
380
381 if (add_cmd) {
382 if (!start_label_str || !end_label_str) {
383 vty_out(vty, "%% Labels not specified\n");
384 return CMD_WARNING_CONFIG_FAILED;
385 }
386
387 start_label = atoi(start_label_str);
388 end_label = atoi(end_label_str);
389 if (!IS_MPLS_UNRESERVED_LABEL(start_label)
390 || !IS_MPLS_UNRESERVED_LABEL(end_label)) {
391 vty_out(vty, "%% Invalid label\n");
392 return CMD_WARNING_CONFIG_FAILED;
393 }
394 if (end_label < start_label) {
395 vty_out(vty, "%% End label is less than Start label\n");
396 return CMD_WARNING_CONFIG_FAILED;
397 }
398
399 ret = zebra_mpls_label_block_add(zvrf, start_label, end_label);
400 } else
401 ret = zebra_mpls_label_block_del(zvrf);
402
403 if (ret) {
404 vty_out(vty, "%% Global label block could not be %s\n",
405 add_cmd ? "added" : "deleted");
406 return CMD_WARNING_CONFIG_FAILED;
407 }
408
409 return CMD_SUCCESS;
1b6d5c7e
VV
410}
411
412DEFUN (mpls_label_global_block,
413 mpls_label_global_block_cmd,
414 "mpls label global-block (16-1048575) (16-1048575)",
415 MPLS_STR
416 "Label configuration\n"
417 "Configure global label block\n"
418 "Start label\n"
419 "End label\n")
420{
d62a17ae 421 return zebra_mpls_global_block(vty, 1, argv[3]->arg, argv[4]->arg);
1b6d5c7e
VV
422}
423
424DEFUN (no_mpls_label_global_block,
425 no_mpls_label_global_block_cmd,
426 "no mpls label global-block [(16-1048575) (16-1048575)]",
427 NO_STR
428 MPLS_STR
429 "Label configuration\n"
430 "Configure global label block\n"
431 "Start label\n"
432 "End label\n")
433{
d62a17ae 434 return zebra_mpls_global_block(vty, 0, NULL, NULL);
1b6d5c7e
VV
435}
436
612c2c15 437static int zebra_mpls_config(struct vty *vty);
41675b4c 438/* MPLS node for MPLS LSP. */
62b346ee 439static struct cmd_node mpls_node = {
f4b8291f 440 .name = "mpls",
62b346ee
DL
441 .node = MPLS_NODE,
442 .prompt = "",
612c2c15 443 .config_write = zebra_mpls_config,
62b346ee 444};
41675b4c
RW
445
446/* MPLS VTY. */
d62a17ae 447void zebra_mpls_vty_init(void)
41675b4c 448{
d62a17ae 449 install_element(VIEW_NODE, &show_mpls_status_cmd);
450
612c2c15 451 install_node(&mpls_node);
d62a17ae 452
d62a17ae 453 install_element(CONFIG_NODE, &mpls_transit_lsp_cmd);
454 install_element(CONFIG_NODE, &no_mpls_transit_lsp_cmd);
455 install_element(CONFIG_NODE, &no_mpls_transit_lsp_out_label_cmd);
456 install_element(CONFIG_NODE, &no_mpls_transit_lsp_all_cmd);
d97c792e 457
d62a17ae 458 install_element(CONFIG_NODE, &mpls_label_bind_cmd);
459 install_element(CONFIG_NODE, &no_mpls_label_bind_cmd);
460
461 install_element(CONFIG_NODE, &mpls_label_global_block_cmd);
462 install_element(CONFIG_NODE, &no_mpls_label_global_block_cmd);
463
464 install_element(VIEW_NODE, &show_mpls_table_cmd);
465 install_element(VIEW_NODE, &show_mpls_table_lsp_cmd);
466 install_element(VIEW_NODE, &show_mpls_fec_cmd);
41675b4c 467}