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