]> git.proxmox.com Git - mirror_frr.git/blob - sharpd/sharp_vty.c
Merge pull request #6221 from opensourcerouting/defaults-fix-version-cmp
[mirror_frr.git] / sharpd / sharp_vty.c
1 /*
2 * SHARP - vty code
3 * Copyright (C) Cumulus Networks, Inc.
4 * Donald Sharp
5 *
6 * This file is part of FRR.
7 *
8 * FRR is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * FRR is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22 #include <zebra.h>
23
24 #include "vty.h"
25 #include "command.h"
26 #include "prefix.h"
27 #include "nexthop.h"
28 #include "log.h"
29 #include "vrf.h"
30 #include "zclient.h"
31 #include "nexthop_group.h"
32
33 #include "sharpd/sharp_globals.h"
34 #include "sharpd/sharp_zebra.h"
35 #include "sharpd/sharp_nht.h"
36 #include "sharpd/sharp_vty.h"
37 #ifndef VTYSH_EXTRACT_PL
38 #include "sharpd/sharp_vty_clippy.c"
39 #endif
40
41 DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
42 "sharp watch [vrf NAME$vrf_name] <nexthop$n X:X::X:X$nhop|import$import X:X::X:X/M$inhop> [connected$connected]",
43 "Sharp routing Protocol\n"
44 "Watch for changes\n"
45 "The vrf we would like to watch if non-default\n"
46 "The NAME of the vrf\n"
47 "Watch for nexthop changes\n"
48 "The v6 nexthop to signal for watching\n"
49 "Watch for import check changes\n"
50 "The v6 prefix to signal for watching\n"
51 "Should the route be connected\n")
52 {
53 struct vrf *vrf;
54 struct prefix p;
55 bool type_import;
56
57 if (!vrf_name)
58 vrf_name = VRF_DEFAULT_NAME;
59 vrf = vrf_lookup_by_name(vrf_name);
60 if (!vrf) {
61 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
62 vrf_name);
63 return CMD_WARNING;
64 }
65
66 memset(&p, 0, sizeof(p));
67
68 if (n) {
69 type_import = false;
70 p.prefixlen = 128;
71 memcpy(&p.u.prefix6, &nhop, 16);
72 p.family = AF_INET6;
73 } else {
74 type_import = true;
75 p = *(const struct prefix *)inhop;
76 }
77
78 sharp_nh_tracker_get(&p);
79 sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
80 true, !!connected);
81
82 return CMD_SUCCESS;
83 }
84
85 DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
86 "sharp watch [vrf NAME$vrf_name] <nexthop$n A.B.C.D$nhop|import$import A.B.C.D/M$inhop> [connected$connected]",
87 "Sharp routing Protocol\n"
88 "Watch for changes\n"
89 "The vrf we would like to watch if non-default\n"
90 "The NAME of the vrf\n"
91 "Watch for nexthop changes\n"
92 "The v4 address to signal for watching\n"
93 "Watch for import check changes\n"
94 "The v4 prefix for import check to watch\n"
95 "Should the route be connected\n")
96 {
97 struct vrf *vrf;
98 struct prefix p;
99 bool type_import;
100
101 if (!vrf_name)
102 vrf_name = VRF_DEFAULT_NAME;
103 vrf = vrf_lookup_by_name(vrf_name);
104 if (!vrf) {
105 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
106 vrf_name);
107 return CMD_WARNING;
108 }
109
110 memset(&p, 0, sizeof(p));
111
112 if (n) {
113 type_import = false;
114 p.prefixlen = 32;
115 p.u.prefix4 = nhop;
116 p.family = AF_INET;
117 }
118 else {
119 type_import = true;
120 p = *(const struct prefix *)inhop;
121 }
122
123 sharp_nh_tracker_get(&p);
124 sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
125 true, !!connected);
126
127 return CMD_SUCCESS;
128 }
129
130 DEFPY(sharp_nht_data_dump,
131 sharp_nht_data_dump_cmd,
132 "sharp data nexthop",
133 "Sharp routing Protocol\n"
134 "Nexthop information\n"
135 "Data Dump\n")
136 {
137 sharp_nh_tracker_dump(vty);
138
139 return CMD_SUCCESS;
140 }
141
142 DEFPY (install_routes_data_dump,
143 install_routes_data_dump_cmd,
144 "sharp data route",
145 "Sharp routing Protocol\n"
146 "Data about what is going on\n"
147 "Route Install/Removal Information\n")
148 {
149 char buf[PREFIX_STRLEN];
150 struct timeval r;
151
152 timersub(&sg.r.t_end, &sg.r.t_start, &r);
153 vty_out(vty, "Prefix: %s Total: %u %u %u Time: %jd.%ld\n",
154 prefix2str(&sg.r.orig_prefix, buf, sizeof(buf)),
155 sg.r.total_routes,
156 sg.r.installed_routes,
157 sg.r.removed_routes,
158 (intmax_t)r.tv_sec, (long)r.tv_usec);
159
160 return CMD_SUCCESS;
161 }
162
163 DEFPY (install_routes,
164 install_routes_cmd,
165 "sharp install routes [vrf NAME$vrf_name]\
166 <A.B.C.D$start4|X:X::X:X$start6>\
167 <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|\
168 nexthop-group NHGNAME$nexthop_group>\
169 [backup$backup <A.B.C.D$backup_nexthop4|X:X::X:X$backup_nexthop6>] \
170 (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]",
171 "Sharp routing Protocol\n"
172 "install some routes\n"
173 "Routes to install\n"
174 "The vrf we would like to install into if non-default\n"
175 "The NAME of the vrf\n"
176 "v4 Address to start /32 generation at\n"
177 "v6 Address to start /32 generation at\n"
178 "Nexthop to use(Can be an IPv4 or IPv6 address)\n"
179 "V4 Nexthop address to use\n"
180 "V6 Nexthop address to use\n"
181 "Nexthop-Group to use\n"
182 "The Name of the nexthop-group\n"
183 "Backup nexthop to use(Can be an IPv4 or IPv6 address)\n"
184 "Backup V4 Nexthop address to use\n"
185 "Backup V6 Nexthop address to use\n"
186 "How many to create\n"
187 "Instance to use\n"
188 "Instance\n"
189 "Should we repeat this command\n"
190 "How many times to repeat this command\n")
191 {
192 struct vrf *vrf;
193 struct prefix prefix;
194 uint32_t rts;
195
196 sg.r.total_routes = routes;
197 sg.r.installed_routes = 0;
198
199 if (rpt >= 2)
200 sg.r.repeat = rpt * 2;
201 else
202 sg.r.repeat = 0;
203
204 memset(&prefix, 0, sizeof(prefix));
205 memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
206 memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
207 memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
208 memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
209 memset(&sg.r.backup_nhop_group, 0, sizeof(sg.r.nhop_group));
210
211 if (start4.s_addr != 0) {
212 prefix.family = AF_INET;
213 prefix.prefixlen = 32;
214 prefix.u.prefix4 = start4;
215 } else {
216 prefix.family = AF_INET6;
217 prefix.prefixlen = 128;
218 prefix.u.prefix6 = start6;
219 }
220 sg.r.orig_prefix = prefix;
221
222 if (!vrf_name)
223 vrf_name = VRF_DEFAULT_NAME;
224
225 vrf = vrf_lookup_by_name(vrf_name);
226 if (!vrf) {
227 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
228 vrf_name);
229 return CMD_WARNING;
230 }
231
232 /* Explicit backup not available with named nexthop-group */
233 if (backup && nexthop_group) {
234 vty_out(vty, "%% Invalid: cannot specify both nexthop-group and backup\n");
235 return CMD_WARNING;
236 }
237
238 if (nexthop_group) {
239 struct nexthop_group_cmd *nhgc = nhgc_find(nexthop_group);
240 if (!nhgc) {
241 vty_out(vty,
242 "Specified Nexthop Group: %s does not exist\n",
243 nexthop_group);
244 return CMD_WARNING;
245 }
246
247 sg.r.nhop_group.nexthop = nhgc->nhg.nexthop;
248
249 /* Use group's backup nexthop info if present */
250 if (nhgc->backup_list_name[0]) {
251 struct nexthop_group_cmd *bnhgc =
252 nhgc_find(nhgc->backup_list_name);
253
254 if (!bnhgc) {
255 vty_out(vty, "%% Backup group %s not found for group %s\n",
256 nhgc->backup_list_name,
257 nhgc->name);
258 return CMD_WARNING;
259 }
260
261 sg.r.backup_nhop.vrf_id = vrf->vrf_id;
262 sg.r.backup_nhop_group.nexthop = bnhgc->nhg.nexthop;
263 }
264 } else {
265 if (nexthop4.s_addr != INADDR_ANY) {
266 sg.r.nhop.gate.ipv4 = nexthop4;
267 sg.r.nhop.type = NEXTHOP_TYPE_IPV4;
268 } else {
269 sg.r.nhop.gate.ipv6 = nexthop6;
270 sg.r.nhop.type = NEXTHOP_TYPE_IPV6;
271 }
272
273 sg.r.nhop.vrf_id = vrf->vrf_id;
274 sg.r.nhop_group.nexthop = &sg.r.nhop;
275 }
276
277 /* Use single backup nexthop if specified */
278 if (backup) {
279 /* Set flag and index in primary nexthop */
280 SET_FLAG(sg.r.nhop.flags, NEXTHOP_FLAG_HAS_BACKUP);
281 sg.r.nhop.backup_idx = 0;
282
283 if (backup_nexthop4.s_addr != INADDR_ANY) {
284 sg.r.backup_nhop.gate.ipv4 = backup_nexthop4;
285 sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV4;
286 } else {
287 sg.r.backup_nhop.gate.ipv6 = backup_nexthop6;
288 sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV6;
289 }
290
291 sg.r.backup_nhop.vrf_id = vrf->vrf_id;
292 sg.r.backup_nhop_group.nexthop = &sg.r.backup_nhop;
293 }
294
295 sg.r.inst = instance;
296 sg.r.vrf_id = vrf->vrf_id;
297 rts = routes;
298 sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst,
299 &sg.r.nhop_group, &sg.r.backup_nhop_group,
300 rts);
301
302 return CMD_SUCCESS;
303 }
304
305 DEFPY(vrf_label, vrf_label_cmd,
306 "sharp label <ip$ipv4|ipv6$ipv6> vrf NAME$vrf_name label (0-100000)$label",
307 "Sharp Routing Protocol\n"
308 "Give a vrf a label\n"
309 "Pop and forward for IPv4\n"
310 "Pop and forward for IPv6\n"
311 VRF_CMD_HELP_STR
312 "The label to use, 0 specifies remove the label installed from previous\n"
313 "Specified range to use\n")
314 {
315 struct vrf *vrf;
316 afi_t afi = (ipv4) ? AFI_IP : AFI_IP6;
317
318 if (strcmp(vrf_name, "default") == 0)
319 vrf = vrf_lookup_by_id(VRF_DEFAULT);
320 else
321 vrf = vrf_lookup_by_name(vrf_name);
322
323 if (!vrf) {
324 vty_out(vty, "Unable to find vrf you silly head");
325 return CMD_WARNING_CONFIG_FAILED;
326 }
327
328 if (label == 0)
329 label = MPLS_LABEL_NONE;
330
331 vrf_label_add(vrf->vrf_id, afi, label);
332 return CMD_SUCCESS;
333 }
334
335 DEFPY (remove_routes,
336 remove_routes_cmd,
337 "sharp remove routes [vrf NAME$vrf_name] <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]",
338 "Sharp Routing Protocol\n"
339 "Remove some routes\n"
340 "Routes to remove\n"
341 "The vrf we would like to remove from if non-default\n"
342 "The NAME of the vrf\n"
343 "v4 Starting spot\n"
344 "v6 Starting spot\n"
345 "Routes to uninstall\n"
346 "instance to use\n"
347 "Value of instance\n")
348 {
349 struct vrf *vrf;
350 struct prefix prefix;
351
352 sg.r.total_routes = routes;
353 sg.r.removed_routes = 0;
354 uint32_t rts;
355
356 memset(&prefix, 0, sizeof(prefix));
357
358 if (start4.s_addr != 0) {
359 prefix.family = AF_INET;
360 prefix.prefixlen = 32;
361 prefix.u.prefix4 = start4;
362 } else {
363 prefix.family = AF_INET6;
364 prefix.prefixlen = 128;
365 prefix.u.prefix6 = start6;
366 }
367
368 vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
369 if (!vrf) {
370 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
371 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
372 return CMD_WARNING;
373 }
374
375 sg.r.inst = instance;
376 sg.r.vrf_id = vrf->vrf_id;
377 rts = routes;
378 sharp_remove_routes_helper(&prefix, sg.r.vrf_id,
379 sg.r.inst, rts);
380
381 return CMD_SUCCESS;
382 }
383
384 DEFUN_NOSH (show_debugging_sharpd,
385 show_debugging_sharpd_cmd,
386 "show debugging [sharp]",
387 SHOW_STR
388 DEBUG_STR
389 "Sharp Information\n")
390 {
391 vty_out(vty, "Sharp debugging status:\n");
392
393 return CMD_SUCCESS;
394 }
395
396 DEFPY(sharp_lsp_prefix_v4, sharp_lsp_prefix_v4_cmd,
397 "sharp lsp (0-100000)$inlabel\
398 nexthop-group NHGNAME$nhgname\
399 [prefix A.B.C.D/M$pfx\
400 " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]",
401 "Sharp Routing Protocol\n"
402 "Add an LSP\n"
403 "The ingress label to use\n"
404 "Use nexthops from a nexthop-group\n"
405 "The nexthop-group name\n"
406 "Label a prefix\n"
407 "The v4 prefix to label\n"
408 FRR_IP_REDIST_HELP_STR_ZEBRA
409 "Instance to use\n"
410 "Instance\n")
411 {
412 struct nexthop_group_cmd *nhgc = NULL;
413 struct prefix p = {};
414 int type = 0;
415
416 /* We're offered a v4 prefix */
417 if (pfx->family > 0 && type_str) {
418 p.family = pfx->family;
419 p.prefixlen = pfx->prefixlen;
420 p.u.prefix4 = pfx->prefix;
421
422 type = proto_redistnum(AFI_IP, type_str);
423 if (type < 0) {
424 vty_out(vty, "%% Unknown route type '%s'\n", type_str);
425 return CMD_WARNING;
426 }
427 } else if (pfx->family > 0 || type_str) {
428 vty_out(vty, "%% Must supply both prefix and type\n");
429 return CMD_WARNING;
430 }
431
432 nhgc = nhgc_find(nhgname);
433 if (!nhgc) {
434 vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
435 nhgname);
436 return CMD_WARNING;
437 }
438
439 if (nhgc->nhg.nexthop == NULL) {
440 vty_out(vty, "%% Nexthop-group '%s' is empty\n", nhgname);
441 return CMD_WARNING;
442 }
443
444 if (sharp_install_lsps_helper(true, pfx->family > 0 ? &p : NULL,
445 type, instance, inlabel,
446 &(nhgc->nhg)) == 0)
447 return CMD_SUCCESS;
448 else {
449 vty_out(vty, "%% LSP install failed!\n");
450 return CMD_WARNING;
451 }
452 }
453
454 DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd,
455 "sharp remove lsp \
456 (0-100000)$inlabel\
457 nexthop-group NHGNAME$nhgname\
458 [prefix A.B.C.D/M$pfx\
459 " FRR_IP_REDIST_STR_SHARPD "$type_str [instance (0-255)$instance]]",
460 "Sharp Routing Protocol\n"
461 "Remove data\n"
462 "Remove an LSP\n"
463 "The ingress label\n"
464 "Use nexthops from a nexthop-group\n"
465 "The nexthop-group name\n"
466 "Specify a v4 prefix\n"
467 "The v4 prefix to label\n"
468 FRR_IP_REDIST_HELP_STR_SHARPD
469 "Routing instance\n"
470 "Instance to use\n")
471 {
472 struct nexthop_group_cmd *nhgc = NULL;
473 struct prefix p = {};
474 int type = 0;
475
476 /* We're offered a v4 prefix */
477 if (pfx->family > 0 && type_str) {
478 p.family = pfx->family;
479 p.prefixlen = pfx->prefixlen;
480 p.u.prefix4 = pfx->prefix;
481
482 type = proto_redistnum(AFI_IP, type_str);
483 if (type < 0) {
484 vty_out(vty, "%% Unknown route type '%s'\n", type_str);
485 return CMD_WARNING;
486 }
487 } else if (pfx->family > 0 || type_str) {
488 vty_out(vty, "%% Must supply both prefix and type\n");
489 return CMD_WARNING;
490 }
491
492 nhgc = nhgc_find(nhgname);
493 if (!nhgc) {
494 vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
495 nhgname);
496 return CMD_WARNING;
497 }
498
499 if (nhgc->nhg.nexthop == NULL) {
500 vty_out(vty, "%% Nexthop-group '%s' is empty\n", nhgname);
501 return CMD_WARNING;
502 }
503
504 if (sharp_install_lsps_helper(false, pfx->family > 0 ? &p : NULL,
505 type, instance, inlabel,
506 &(nhgc->nhg)) == 0)
507 return CMD_SUCCESS;
508 else {
509 vty_out(vty, "%% LSP remove failed!\n");
510 return CMD_WARNING;
511 }
512 }
513
514 DEFPY (logpump,
515 logpump_cmd,
516 "sharp logpump duration (1-60) frequency (1-1000000) burst (1-1000)",
517 "Sharp Routing Protocol\n"
518 "Generate bulk log messages for testing\n"
519 "Duration of run (s)\n"
520 "Duration of run (s)\n"
521 "Frequency of bursts (s^-1)\n"
522 "Frequency of bursts (s^-1)\n"
523 "Number of log messages per each burst\n"
524 "Number of log messages per each burst\n")
525 {
526 sharp_logpump_run(vty, duration, frequency, burst);
527 return CMD_SUCCESS;
528 }
529
530 void sharp_vty_init(void)
531 {
532 install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
533 install_element(ENABLE_NODE, &install_routes_cmd);
534 install_element(ENABLE_NODE, &remove_routes_cmd);
535 install_element(ENABLE_NODE, &vrf_label_cmd);
536 install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd);
537 install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
538 install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
539 install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd);
540 install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd);
541 install_element(ENABLE_NODE, &logpump_cmd);
542
543 install_element(VIEW_NODE, &show_debugging_sharpd_cmd);
544
545 return;
546 }