1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Zebra MPLS VTY functions
3 * Copyright (C) 2002 Kunihiro Ishiguro
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"
26 static 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
,
31 struct zebra_vrf
*zvrf
;
33 enum nexthop_types_t gtype
;
36 mpls_label_t in_label
, out_label
;
40 "%% MPLS not turned on in kernel, ignoring command\n");
41 return CMD_WARNING_CONFIG_FAILED
;
44 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
46 vty_out(vty
, "%% Default VRF does not exist\n");
47 return CMD_WARNING_CONFIG_FAILED
;
51 vty_out(vty
, "%% No Label Information\n");
52 return CMD_WARNING_CONFIG_FAILED
;
55 out_label
= MPLS_LABEL_IMPLICIT_NULL
; /* as initialization */
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
;
64 vty_out(vty
, "%% No Nexthop Information\n");
65 return CMD_WARNING_CONFIG_FAILED
;
68 vty_out(vty
, "%% No Outgoing label Information\n");
69 return CMD_WARNING_CONFIG_FAILED
;
74 gtype
= NEXTHOP_TYPE_BLACKHOLE
; /* as initialization */
77 /* Gateway is a IPv4 or IPv6 nexthop. */
78 ret
= inet_pton(AF_INET6
, gate_str
, &gate
.ipv6
);
80 gtype
= NEXTHOP_TYPE_IPV6
;
82 ret
= inet_pton(AF_INET
, gate_str
, &gate
.ipv4
);
84 gtype
= NEXTHOP_TYPE_IPV4
;
86 vty_out(vty
, "%% Invalid nexthop\n");
87 return CMD_WARNING_CONFIG_FAILED
;
93 if (outlabel_str
[0] == 'i')
94 out_label
= MPLS_LABEL_IMPLICIT_NULL
;
95 else if (outlabel_str
[0] == 'e' && gtype
== NEXTHOP_TYPE_IPV4
)
96 out_label
= MPLS_LABEL_IPV4_EXPLICIT_NULL
;
97 else if (outlabel_str
[0] == 'e' && gtype
== NEXTHOP_TYPE_IPV6
)
98 out_label
= MPLS_LABEL_IPV6_EXPLICIT_NULL
;
100 out_label
= atoi(outlabel_str
);
104 #if defined(HAVE_CUMULUS)
105 /* Check that label value is consistent. */
106 if (!zebra_mpls_lsp_label_consistent(zvrf
, in_label
, out_label
,
108 vty_out(vty
, "%% Label value not consistent\n");
109 return CMD_WARNING_CONFIG_FAILED
;
111 #endif /* HAVE_CUMULUS */
113 ret
= zebra_mpls_static_lsp_add(zvrf
, in_label
, out_label
,
116 ret
= zebra_mpls_static_lsp_del(zvrf
, in_label
, gtype
, &gate
,
120 vty_out(vty
, "%% LSP cannot be %s\n",
121 add_cmd
? "added" : "deleted");
122 return CMD_WARNING_CONFIG_FAILED
;
128 DEFUN (mpls_transit_lsp
,
129 mpls_transit_lsp_cmd
,
130 "mpls lsp (16-1048575) <A.B.C.D|X:X::X:X> <(16-1048575)|explicit-null|implicit-null>",
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"
137 "Use Explicit-Null label\n"
138 "Use Implicit-Null label\n")
140 return zebra_mpls_transit_lsp(vty
, 1, argv
[2]->arg
, argv
[3]->arg
,
144 DEFUN (no_mpls_transit_lsp
,
145 no_mpls_transit_lsp_cmd
,
146 "no mpls lsp (16-1048575) <A.B.C.D|X:X::X:X>",
149 "Establish label switched path\n"
150 "Incoming MPLS label\n"
151 "IPv4 gateway address\n"
152 "IPv6 gateway address\n")
154 return zebra_mpls_transit_lsp(vty
, 0, argv
[3]->arg
, argv
[4]->arg
, NULL
,
158 ALIAS(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>",
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")
169 DEFUN (no_mpls_transit_lsp_all
,
170 no_mpls_transit_lsp_all_cmd
,
171 "no mpls lsp (16-1048575)",
174 "Establish label switched path\n"
175 "Incoming MPLS label\n")
177 return zebra_mpls_transit_lsp(vty
, 0, argv
[3]->arg
, NULL
, NULL
, NULL
);
180 static int zebra_mpls_bind(struct vty
*vty
, int add_cmd
, const char *prefix
,
181 const char *label_str
)
183 struct zebra_vrf
*zvrf
;
188 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
190 vty_out(vty
, "%% Default VRF does not exist\n");
191 return CMD_WARNING_CONFIG_FAILED
;
194 memset(&p
, 0, sizeof(p
));
195 ret
= str2prefix(prefix
, &p
);
197 vty_out(vty
, "%% Malformed address\n");
198 return CMD_WARNING_CONFIG_FAILED
;
203 vty_out(vty
, "%% No label binding specified\n");
204 return CMD_WARNING_CONFIG_FAILED
;
207 if (!strcmp(label_str
, "implicit-null"))
208 label
= MPLS_LABEL_IMPLICIT_NULL
;
209 else if (!strcmp(label_str
, "explicit-null")) {
210 if (p
.family
== AF_INET
)
211 label
= MPLS_LABEL_IPV4_EXPLICIT_NULL
;
213 label
= MPLS_LABEL_IPV6_EXPLICIT_NULL
;
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
;
220 if (zebra_mpls_label_already_bound(zvrf
, label
)) {
222 "%% Label already bound to a FEC\n");
223 return CMD_WARNING_CONFIG_FAILED
;
227 ret
= zebra_mpls_static_fec_add(zvrf
, &p
, label
);
229 ret
= zebra_mpls_static_fec_del(zvrf
, &p
);
232 vty_out(vty
, "%% FEC to label binding cannot be %s\n",
233 add_cmd
? "added" : "deleted");
234 return CMD_WARNING_CONFIG_FAILED
;
240 DEFUN (mpls_label_bind
,
242 "mpls label bind <A.B.C.D/M|X:X::X:X/M> <(16-1048575)|implicit-null|explicit-null>",
244 "Label configuration\n"
245 "Establish FEC to label binding\n"
248 "MPLS Label to bind\n"
249 "Use Implicit-Null Label\n"
250 "Use Explicit-Null Label\n")
252 return zebra_mpls_bind(vty
, 1, argv
[3]->arg
, argv
[4]->arg
);
255 DEFUN (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>]",
260 "Label configuration\n"
261 "Establish FEC to label binding\n"
264 "MPLS Label to bind\n"
265 "Use Implicit-Null Label\n")
267 return zebra_mpls_bind(vty
, 0, argv
[4]->arg
, NULL
);
270 /* MPLS LSP configuration write function. */
271 static int zebra_mpls_config(struct vty
*vty
)
274 struct zebra_vrf
*zvrf
;
276 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
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
);
286 DEFUN (show_mpls_fec
,
288 "show mpls fec [<A.B.C.D/M|X:X::X:X/M>]",
292 "FEC to display information about\n"
293 "FEC to display information about\n")
295 struct zebra_vrf
*zvrf
;
299 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
304 zebra_mpls_print_fec_table(vty
, zvrf
);
306 memset(&p
, 0, sizeof(struct prefix
));
307 ret
= str2prefix(argv
[3]->arg
, &p
);
309 vty_out(vty
, "%% Malformed address\n");
312 zebra_mpls_print_fec(vty
, zvrf
, &p
);
318 DEFUN (show_mpls_table
,
320 "show mpls table [json]",
326 struct zebra_vrf
*zvrf
;
327 bool uj
= use_json(argc
, argv
);
329 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
330 zebra_mpls_print_lsp_table(vty
, zvrf
, uj
);
334 DEFUN (show_mpls_table_lsp
,
335 show_mpls_table_lsp_cmd
,
336 "show mpls table (16-1048575) [json]",
340 "LSP to display information about\n"
344 struct zebra_vrf
*zvrf
;
345 bool uj
= use_json(argc
, argv
);
347 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
348 label
= atoi(argv
[3]->arg
);
349 zebra_mpls_print_lsp(vty
, zvrf
, label
, uj
);
353 DEFUN (show_mpls_status
,
354 show_mpls_status_cmd
,
360 vty_out(vty
, "MPLS support enabled: %s\n",
361 (mpls_enabled
) ? "yes"
362 : "no (mpls kernel extensions not detected)");
366 static int zebra_mpls_global_block(struct vty
*vty
, int add_cmd
,
367 const char *start_label_str
,
368 const char *end_label_str
)
371 uint32_t start_label
;
373 struct zebra_vrf
*zvrf
;
375 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
377 vty_out(vty
, "%% Default VRF does not exist\n");
378 return CMD_WARNING_CONFIG_FAILED
;
382 if (!start_label_str
|| !end_label_str
) {
383 vty_out(vty
, "%% Labels not specified\n");
384 return CMD_WARNING_CONFIG_FAILED
;
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
;
394 if (end_label
< start_label
) {
395 vty_out(vty
, "%% End label is less than Start label\n");
396 return CMD_WARNING_CONFIG_FAILED
;
399 ret
= zebra_mpls_label_block_add(zvrf
, start_label
, end_label
);
401 ret
= zebra_mpls_label_block_del(zvrf
);
404 vty_out(vty
, "%% Global label block could not be %s\n",
405 add_cmd
? "added" : "deleted");
406 return CMD_WARNING_CONFIG_FAILED
;
412 DEFUN (mpls_label_global_block
,
413 mpls_label_global_block_cmd
,
414 "mpls label global-block (16-1048575) (16-1048575)",
416 "Label configuration\n"
417 "Configure global label block\n"
421 return zebra_mpls_global_block(vty
, 1, argv
[3]->arg
, argv
[4]->arg
);
424 DEFUN (no_mpls_label_global_block
,
425 no_mpls_label_global_block_cmd
,
426 "no mpls label global-block [(16-1048575) (16-1048575)]",
429 "Label configuration\n"
430 "Configure global label block\n"
434 return zebra_mpls_global_block(vty
, 0, NULL
, NULL
);
437 static int zebra_mpls_config(struct vty
*vty
);
438 /* MPLS node for MPLS LSP. */
439 static struct cmd_node mpls_node
= {
443 .config_write
= zebra_mpls_config
,
447 void zebra_mpls_vty_init(void)
449 install_element(VIEW_NODE
, &show_mpls_status_cmd
);
451 install_node(&mpls_node
);
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
);
458 install_element(CONFIG_NODE
, &mpls_label_bind_cmd
);
459 install_element(CONFIG_NODE
, &no_mpls_label_bind_cmd
);
461 install_element(CONFIG_NODE
, &mpls_label_global_block_cmd
);
462 install_element(CONFIG_NODE
, &no_mpls_label_global_block_cmd
);
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
);