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