]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_mpls_vty.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / zebra / zebra_mpls_vty.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Zebra MPLS VTY functions
3 * Copyright (C) 2002 Kunihiro Ishiguro
4 */
5
6 #include <zebra.h>
7
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"
25
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,
29 const char *flag_str)
30 {
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
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;
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;
74 gtype = NEXTHOP_TYPE_BLACKHOLE; /* as initialization */
75
76 if (gate_str) {
77 /* Gateway is a IPv4 or IPv6 nexthop. */
78 ret = inet_pton(AF_INET6, gate_str, &gate.ipv6);
79 if (ret == 1)
80 gtype = NEXTHOP_TYPE_IPV6;
81 else {
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 }
89 }
90 }
91
92 if (outlabel_str) {
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;
99 else
100 out_label = atoi(outlabel_str);
101 }
102
103 if (add_cmd) {
104 #if defined(HAVE_CUMULUS)
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 }
111 #endif /* HAVE_CUMULUS */
112
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);
118
119 if (ret != 0) {
120 vty_out(vty, "%% LSP cannot be %s\n",
121 add_cmd ? "added" : "deleted");
122 return CMD_WARNING_CONFIG_FAILED;
123 }
124
125 return CMD_SUCCESS;
126 }
127
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>",
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"
137 "Use Explicit-Null label\n"
138 "Use Implicit-Null label\n")
139 {
140 return zebra_mpls_transit_lsp(vty, 1, argv[2]->arg, argv[3]->arg,
141 argv[4]->arg, NULL);
142 }
143
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>",
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 {
154 return zebra_mpls_transit_lsp(vty, 0, argv[3]->arg, argv[4]->arg, NULL,
155 NULL);
156 }
157
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>",
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
169 DEFUN (no_mpls_transit_lsp_all,
170 no_mpls_transit_lsp_all_cmd,
171 "no mpls lsp (16-1048575)",
172 NO_STR
173 MPLS_STR
174 "Establish label switched path\n"
175 "Incoming MPLS label\n")
176 {
177 return zebra_mpls_transit_lsp(vty, 0, argv[3]->arg, NULL, NULL, NULL);
178 }
179
180 static int zebra_mpls_bind(struct vty *vty, int add_cmd, const char *prefix,
181 const char *label_str)
182 {
183 struct zebra_vrf *zvrf;
184 struct prefix p;
185 uint32_t label;
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
194 memset(&p, 0, sizeof(p));
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"))
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;
212 else
213 label = MPLS_LABEL_IPV6_EXPLICIT_NULL;
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;
238 }
239
240 DEFUN (mpls_label_bind,
241 mpls_label_bind_cmd,
242 "mpls label bind <A.B.C.D/M|X:X::X:X/M> <(16-1048575)|implicit-null|explicit-null>",
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"
249 "Use Implicit-Null Label\n"
250 "Use Explicit-Null Label\n")
251 {
252 return zebra_mpls_bind(vty, 1, argv[3]->arg, argv[4]->arg);
253 }
254
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>]",
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")
266 {
267 return zebra_mpls_bind(vty, 0, argv[4]->arg, NULL);
268 }
269
270 /* MPLS LSP configuration write function. */
271 static int zebra_mpls_config(struct vty *vty)
272 {
273 int write = 0;
274 struct zebra_vrf *zvrf;
275
276 zvrf = vrf_info_lookup(VRF_DEFAULT);
277 if (!zvrf)
278 return 0;
279
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;
284 }
285
286 DEFUN (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 {
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;
316 }
317
318 DEFUN (show_mpls_table,
319 show_mpls_table_cmd,
320 "show mpls table [json]",
321 SHOW_STR
322 MPLS_STR
323 "MPLS table\n"
324 JSON_STR)
325 {
326 struct zebra_vrf *zvrf;
327 bool uj = use_json(argc, argv);
328
329 zvrf = vrf_info_lookup(VRF_DEFAULT);
330 zebra_mpls_print_lsp_table(vty, zvrf, uj);
331 return CMD_SUCCESS;
332 }
333
334 DEFUN (show_mpls_table_lsp,
335 show_mpls_table_lsp_cmd,
336 "show mpls table (16-1048575) [json]",
337 SHOW_STR
338 MPLS_STR
339 "MPLS table\n"
340 "LSP to display information about\n"
341 JSON_STR)
342 {
343 uint32_t label;
344 struct zebra_vrf *zvrf;
345 bool uj = use_json(argc, argv);
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;
351 }
352
353 DEFUN (show_mpls_status,
354 show_mpls_status_cmd,
355 "show mpls status",
356 SHOW_STR
357 "MPLS information\n"
358 "MPLS status\n")
359 {
360 vty_out(vty, "MPLS support enabled: %s\n",
361 (mpls_enabled) ? "yes"
362 : "no (mpls kernel extensions not detected)");
363 return CMD_SUCCESS;
364 }
365
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)
369 {
370 int ret;
371 uint32_t start_label;
372 uint32_t end_label;
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;
410 }
411
412 DEFUN (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 {
421 return zebra_mpls_global_block(vty, 1, argv[3]->arg, argv[4]->arg);
422 }
423
424 DEFUN (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 {
434 return zebra_mpls_global_block(vty, 0, NULL, NULL);
435 }
436
437 static int zebra_mpls_config(struct vty *vty);
438 /* MPLS node for MPLS LSP. */
439 static struct cmd_node mpls_node = {
440 .name = "mpls",
441 .node = MPLS_NODE,
442 .prompt = "",
443 .config_write = zebra_mpls_config,
444 };
445
446 /* MPLS VTY. */
447 void zebra_mpls_vty_init(void)
448 {
449 install_element(VIEW_NODE, &show_mpls_status_cmd);
450
451 install_node(&mpls_node);
452
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);
457
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);
467 }