]> git.proxmox.com Git - mirror_frr.git/blob - sharpd/sharp_vty.c
Merge pull request #8441 from mjstapp/fix_topo_pylint1
[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 #include "link_state.h"
33
34 #include "sharpd/sharp_globals.h"
35 #include "sharpd/sharp_zebra.h"
36 #include "sharpd/sharp_nht.h"
37 #include "sharpd/sharp_vty.h"
38 #ifndef VTYSH_EXTRACT_PL
39 #include "sharpd/sharp_vty_clippy.c"
40 #endif
41
42 DEFPY(watch_redistribute, watch_redistribute_cmd,
43 "sharp watch [vrf NAME$vrf_name] redistribute " FRR_REDIST_STR_SHARPD,
44 "Sharp routing Protocol\n"
45 "Watch for changes\n"
46 "The vrf we would like to watch if non-default\n"
47 "The NAME of the vrf\n"
48 "Redistribute into Sharp\n"
49 FRR_REDIST_HELP_STR_SHARPD)
50 {
51 struct vrf *vrf;
52 int source;
53
54 if (!vrf_name)
55 vrf_name = VRF_DEFAULT_NAME;
56 vrf = vrf_lookup_by_name(vrf_name);
57 if (!vrf) {
58 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
59 vrf_name);
60 return CMD_WARNING;
61 }
62
63 source = proto_redistnum(AFI_IP, argv[argc-1]->text);
64 sharp_redistribute_vrf(vrf, source);
65
66 return CMD_SUCCESS;
67 }
68
69 DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
70 "sharp watch [vrf NAME$vrf_name] <nexthop$n X:X::X:X$nhop|import$import X:X::X:X/M$inhop> [connected$connected]",
71 "Sharp routing Protocol\n"
72 "Watch for changes\n"
73 "The vrf we would like to watch if non-default\n"
74 "The NAME of the vrf\n"
75 "Watch for nexthop changes\n"
76 "The v6 nexthop to signal for watching\n"
77 "Watch for import check changes\n"
78 "The v6 prefix to signal for watching\n"
79 "Should the route be connected\n")
80 {
81 struct vrf *vrf;
82 struct prefix p;
83 bool type_import;
84
85 if (!vrf_name)
86 vrf_name = VRF_DEFAULT_NAME;
87 vrf = vrf_lookup_by_name(vrf_name);
88 if (!vrf) {
89 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
90 vrf_name);
91 return CMD_WARNING;
92 }
93
94 memset(&p, 0, sizeof(p));
95
96 if (n) {
97 type_import = false;
98 p.prefixlen = 128;
99 memcpy(&p.u.prefix6, &nhop, 16);
100 p.family = AF_INET6;
101 } else {
102 type_import = true;
103 p = *(const struct prefix *)inhop;
104 }
105
106 sharp_nh_tracker_get(&p);
107 sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
108 true, !!connected);
109
110 return CMD_SUCCESS;
111 }
112
113 DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
114 "sharp watch [vrf NAME$vrf_name] <nexthop$n A.B.C.D$nhop|import$import A.B.C.D/M$inhop> [connected$connected]",
115 "Sharp routing Protocol\n"
116 "Watch for changes\n"
117 "The vrf we would like to watch if non-default\n"
118 "The NAME of the vrf\n"
119 "Watch for nexthop changes\n"
120 "The v4 address to signal for watching\n"
121 "Watch for import check changes\n"
122 "The v4 prefix for import check to watch\n"
123 "Should the route be connected\n")
124 {
125 struct vrf *vrf;
126 struct prefix p;
127 bool type_import;
128
129 if (!vrf_name)
130 vrf_name = VRF_DEFAULT_NAME;
131 vrf = vrf_lookup_by_name(vrf_name);
132 if (!vrf) {
133 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
134 vrf_name);
135 return CMD_WARNING;
136 }
137
138 memset(&p, 0, sizeof(p));
139
140 if (n) {
141 type_import = false;
142 p.prefixlen = 32;
143 p.u.prefix4 = nhop;
144 p.family = AF_INET;
145 }
146 else {
147 type_import = true;
148 p = *(const struct prefix *)inhop;
149 }
150
151 sharp_nh_tracker_get(&p);
152 sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
153 true, !!connected);
154
155 return CMD_SUCCESS;
156 }
157
158 DEFPY(sharp_nht_data_dump,
159 sharp_nht_data_dump_cmd,
160 "sharp data nexthop",
161 "Sharp routing Protocol\n"
162 "Data about what is going on\n"
163 "Nexthop information\n")
164 {
165 sharp_nh_tracker_dump(vty);
166
167 return CMD_SUCCESS;
168 }
169
170 DEFPY (install_routes_data_dump,
171 install_routes_data_dump_cmd,
172 "sharp data route",
173 "Sharp routing Protocol\n"
174 "Data about what is going on\n"
175 "Route Install/Removal Information\n")
176 {
177 struct timeval r;
178
179 timersub(&sg.r.t_end, &sg.r.t_start, &r);
180 vty_out(vty, "Prefix: %pFX Total: %u %u %u Time: %jd.%ld\n",
181 &sg.r.orig_prefix, sg.r.total_routes, sg.r.installed_routes,
182 sg.r.removed_routes, (intmax_t)r.tv_sec, (long)r.tv_usec);
183
184 return CMD_SUCCESS;
185 }
186
187 DEFPY (install_routes,
188 install_routes_cmd,
189 "sharp install routes [vrf NAME$vrf_name]\
190 <A.B.C.D$start4|X:X::X:X$start6>\
191 <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|\
192 nexthop-group NHGNAME$nexthop_group>\
193 [backup$backup <A.B.C.D$backup_nexthop4|X:X::X:X$backup_nexthop6>] \
194 (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt] [opaque WORD]",
195 "Sharp routing Protocol\n"
196 "install some routes\n"
197 "Routes to install\n"
198 "The vrf we would like to install into if non-default\n"
199 "The NAME of the vrf\n"
200 "v4 Address to start /32 generation at\n"
201 "v6 Address to start /32 generation at\n"
202 "Nexthop to use(Can be an IPv4 or IPv6 address)\n"
203 "V4 Nexthop address to use\n"
204 "V6 Nexthop address to use\n"
205 "Nexthop-Group to use\n"
206 "The Name of the nexthop-group\n"
207 "Backup nexthop to use(Can be an IPv4 or IPv6 address)\n"
208 "Backup V4 Nexthop address to use\n"
209 "Backup V6 Nexthop address to use\n"
210 "How many to create\n"
211 "Instance to use\n"
212 "Instance\n"
213 "Should we repeat this command\n"
214 "How many times to repeat this command\n"
215 "What opaque data to send down\n"
216 "The opaque data\n")
217 {
218 struct vrf *vrf;
219 struct prefix prefix;
220 uint32_t rts;
221 uint32_t nhgid = 0;
222
223 sg.r.total_routes = routes;
224 sg.r.installed_routes = 0;
225
226 if (rpt >= 2)
227 sg.r.repeat = rpt * 2;
228 else
229 sg.r.repeat = 0;
230
231 memset(&prefix, 0, sizeof(prefix));
232 memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
233 memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
234 memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
235 memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
236 memset(&sg.r.backup_nhop_group, 0, sizeof(sg.r.nhop_group));
237
238 if (start4.s_addr != INADDR_ANY) {
239 prefix.family = AF_INET;
240 prefix.prefixlen = 32;
241 prefix.u.prefix4 = start4;
242 } else {
243 prefix.family = AF_INET6;
244 prefix.prefixlen = 128;
245 prefix.u.prefix6 = start6;
246 }
247 sg.r.orig_prefix = prefix;
248
249 if (!vrf_name)
250 vrf_name = VRF_DEFAULT_NAME;
251
252 vrf = vrf_lookup_by_name(vrf_name);
253 if (!vrf) {
254 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
255 vrf_name);
256 return CMD_WARNING;
257 }
258
259 /* Explicit backup not available with named nexthop-group */
260 if (backup && nexthop_group) {
261 vty_out(vty, "%% Invalid: cannot specify both nexthop-group and backup\n");
262 return CMD_WARNING;
263 }
264
265 if (nexthop_group) {
266 struct nexthop_group_cmd *nhgc = nhgc_find(nexthop_group);
267 if (!nhgc) {
268 vty_out(vty,
269 "Specified Nexthop Group: %s does not exist\n",
270 nexthop_group);
271 return CMD_WARNING;
272 }
273
274 nhgid = sharp_nhgroup_get_id(nexthop_group);
275 sg.r.nhgid = nhgid;
276 sg.r.nhop_group.nexthop = nhgc->nhg.nexthop;
277
278 /* Use group's backup nexthop info if present */
279 if (nhgc->backup_list_name[0]) {
280 struct nexthop_group_cmd *bnhgc =
281 nhgc_find(nhgc->backup_list_name);
282
283 if (!bnhgc) {
284 vty_out(vty, "%% Backup group %s not found for group %s\n",
285 nhgc->backup_list_name,
286 nhgc->name);
287 return CMD_WARNING;
288 }
289
290 sg.r.backup_nhop.vrf_id = vrf->vrf_id;
291 sg.r.backup_nhop_group.nexthop = bnhgc->nhg.nexthop;
292 }
293 } else {
294 if (nexthop4.s_addr != INADDR_ANY) {
295 sg.r.nhop.gate.ipv4 = nexthop4;
296 sg.r.nhop.type = NEXTHOP_TYPE_IPV4;
297 } else {
298 sg.r.nhop.gate.ipv6 = nexthop6;
299 sg.r.nhop.type = NEXTHOP_TYPE_IPV6;
300 }
301
302 sg.r.nhop.vrf_id = vrf->vrf_id;
303 sg.r.nhop_group.nexthop = &sg.r.nhop;
304 }
305
306 /* Use single backup nexthop if specified */
307 if (backup) {
308 /* Set flag and index in primary nexthop */
309 SET_FLAG(sg.r.nhop.flags, NEXTHOP_FLAG_HAS_BACKUP);
310 sg.r.nhop.backup_num = 1;
311 sg.r.nhop.backup_idx[0] = 0;
312
313 if (backup_nexthop4.s_addr != INADDR_ANY) {
314 sg.r.backup_nhop.gate.ipv4 = backup_nexthop4;
315 sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV4;
316 } else {
317 sg.r.backup_nhop.gate.ipv6 = backup_nexthop6;
318 sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV6;
319 }
320
321 sg.r.backup_nhop.vrf_id = vrf->vrf_id;
322 sg.r.backup_nhop_group.nexthop = &sg.r.backup_nhop;
323 }
324
325 if (opaque)
326 strlcpy(sg.r.opaque, opaque, ZAPI_MESSAGE_OPAQUE_LENGTH);
327 else
328 sg.r.opaque[0] = '\0';
329
330 sg.r.inst = instance;
331 sg.r.vrf_id = vrf->vrf_id;
332 rts = routes;
333 sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst, nhgid,
334 &sg.r.nhop_group, &sg.r.backup_nhop_group,
335 rts, sg.r.opaque);
336
337 return CMD_SUCCESS;
338 }
339
340 DEFPY(vrf_label, vrf_label_cmd,
341 "sharp label <ip$ipv4|ipv6$ipv6> vrf NAME$vrf_name label (0-100000)$label",
342 "Sharp Routing Protocol\n"
343 "Give a vrf a label\n"
344 "Pop and forward for IPv4\n"
345 "Pop and forward for IPv6\n"
346 VRF_CMD_HELP_STR
347 "The label to use, 0 specifies remove the label installed from previous\n"
348 "Specified range to use\n")
349 {
350 struct vrf *vrf;
351 afi_t afi = (ipv4) ? AFI_IP : AFI_IP6;
352
353 if (strcmp(vrf_name, "default") == 0)
354 vrf = vrf_lookup_by_id(VRF_DEFAULT);
355 else
356 vrf = vrf_lookup_by_name(vrf_name);
357
358 if (!vrf) {
359 vty_out(vty, "Unable to find vrf you silly head");
360 return CMD_WARNING_CONFIG_FAILED;
361 }
362
363 if (label == 0)
364 label = MPLS_LABEL_NONE;
365
366 vrf_label_add(vrf->vrf_id, afi, label);
367 return CMD_SUCCESS;
368 }
369
370 DEFPY (remove_routes,
371 remove_routes_cmd,
372 "sharp remove routes [vrf NAME$vrf_name] <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]",
373 "Sharp Routing Protocol\n"
374 "Remove some routes\n"
375 "Routes to remove\n"
376 "The vrf we would like to remove from if non-default\n"
377 "The NAME of the vrf\n"
378 "v4 Starting spot\n"
379 "v6 Starting spot\n"
380 "Routes to uninstall\n"
381 "instance to use\n"
382 "Value of instance\n")
383 {
384 struct vrf *vrf;
385 struct prefix prefix;
386
387 sg.r.total_routes = routes;
388 sg.r.removed_routes = 0;
389 uint32_t rts;
390
391 memset(&prefix, 0, sizeof(prefix));
392
393 if (start4.s_addr != INADDR_ANY) {
394 prefix.family = AF_INET;
395 prefix.prefixlen = 32;
396 prefix.u.prefix4 = start4;
397 } else {
398 prefix.family = AF_INET6;
399 prefix.prefixlen = 128;
400 prefix.u.prefix6 = start6;
401 }
402
403 vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
404 if (!vrf) {
405 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
406 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
407 return CMD_WARNING;
408 }
409
410 sg.r.inst = instance;
411 sg.r.vrf_id = vrf->vrf_id;
412 rts = routes;
413 sharp_remove_routes_helper(&prefix, sg.r.vrf_id,
414 sg.r.inst, rts);
415
416 return CMD_SUCCESS;
417 }
418
419 DEFUN_NOSH (show_debugging_sharpd,
420 show_debugging_sharpd_cmd,
421 "show debugging [sharp]",
422 SHOW_STR
423 DEBUG_STR
424 "Sharp Information\n")
425 {
426 vty_out(vty, "Sharp debugging status:\n");
427
428 return CMD_SUCCESS;
429 }
430
431 DEFPY (sharp_lsp_prefix_v4, sharp_lsp_prefix_v4_cmd,
432 "sharp lsp [update]$update (0-100000)$inlabel\
433 nexthop-group NHGNAME$nhgname\
434 [prefix A.B.C.D/M$pfx\
435 " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]",
436 "Sharp Routing Protocol\n"
437 "Add an LSP\n"
438 "Update an LSP\n"
439 "The ingress label to use\n"
440 "Use nexthops from a nexthop-group\n"
441 "The nexthop-group name\n"
442 "Label a prefix\n"
443 "The v4 prefix to label\n"
444 FRR_IP_REDIST_HELP_STR_ZEBRA
445 "Instance to use\n"
446 "Instance\n")
447 {
448 struct nexthop_group_cmd *nhgc = NULL;
449 struct nexthop_group_cmd *backup_nhgc = NULL;
450 struct nexthop_group *backup_nhg = NULL;
451 struct prefix p = {};
452 int type = 0;
453 bool update_p;
454
455 update_p = (update != NULL);
456
457 /* We're offered a v4 prefix */
458 if (pfx->family > 0 && type_str) {
459 p.family = pfx->family;
460 p.prefixlen = pfx->prefixlen;
461 p.u.prefix4 = pfx->prefix;
462
463 type = proto_redistnum(AFI_IP, type_str);
464 if (type < 0) {
465 vty_out(vty, "%% Unknown route type '%s'\n", type_str);
466 return CMD_WARNING;
467 }
468 } else if (pfx->family > 0 || type_str) {
469 vty_out(vty, "%% Must supply both prefix and type\n");
470 return CMD_WARNING;
471 }
472
473 nhgc = nhgc_find(nhgname);
474 if (!nhgc) {
475 vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
476 nhgname);
477 return CMD_WARNING;
478 }
479
480 if (nhgc->nhg.nexthop == NULL) {
481 vty_out(vty, "%% Nexthop-group '%s' is empty\n", nhgname);
482 return CMD_WARNING;
483 }
484
485 /* Use group's backup nexthop info if present */
486 if (nhgc->backup_list_name[0]) {
487 backup_nhgc = nhgc_find(nhgc->backup_list_name);
488
489 if (!backup_nhgc) {
490 vty_out(vty,
491 "%% Backup group %s not found for group %s\n",
492 nhgc->backup_list_name,
493 nhgname);
494 return CMD_WARNING;
495 }
496 backup_nhg = &(backup_nhgc->nhg);
497 }
498
499 if (sharp_install_lsps_helper(true /*install*/, update_p,
500 pfx->family > 0 ? &p : NULL,
501 type, instance, inlabel,
502 &(nhgc->nhg), backup_nhg) == 0)
503 return CMD_SUCCESS;
504 else {
505 vty_out(vty, "%% LSP install failed!\n");
506 return CMD_WARNING;
507 }
508 }
509
510 DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd,
511 "sharp remove lsp \
512 (0-100000)$inlabel\
513 [nexthop-group NHGNAME$nhgname] \
514 [prefix A.B.C.D/M$pfx\
515 " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]",
516 "Sharp Routing Protocol\n"
517 "Remove data\n"
518 "Remove an LSP\n"
519 "The ingress label\n"
520 "Use nexthops from a nexthop-group\n"
521 "The nexthop-group name\n"
522 "Specify a v4 prefix\n"
523 "The v4 prefix to label\n"
524 FRR_IP_REDIST_HELP_STR_ZEBRA
525 "Routing instance\n"
526 "Instance to use\n")
527 {
528 struct nexthop_group_cmd *nhgc = NULL;
529 struct prefix p = {};
530 int type = 0;
531 struct nexthop_group *nhg = NULL;
532
533 /* We're offered a v4 prefix */
534 if (pfx->family > 0 && type_str) {
535 p.family = pfx->family;
536 p.prefixlen = pfx->prefixlen;
537 p.u.prefix4 = pfx->prefix;
538
539 type = proto_redistnum(AFI_IP, type_str);
540 if (type < 0) {
541 vty_out(vty, "%% Unknown route type '%s'\n", type_str);
542 return CMD_WARNING;
543 }
544 } else if (pfx->family > 0 || type_str) {
545 vty_out(vty, "%% Must supply both prefix and type\n");
546 return CMD_WARNING;
547 }
548
549 if (nhgname) {
550 nhgc = nhgc_find(nhgname);
551 if (!nhgc) {
552 vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
553 nhgname);
554 return CMD_WARNING;
555 }
556
557 if (nhgc->nhg.nexthop == NULL) {
558 vty_out(vty, "%% Nexthop-group '%s' is empty\n",
559 nhgname);
560 return CMD_WARNING;
561 }
562 nhg = &(nhgc->nhg);
563 }
564
565 if (sharp_install_lsps_helper(false /*!install*/, false,
566 pfx->family > 0 ? &p : NULL,
567 type, instance, inlabel, nhg, NULL) == 0)
568 return CMD_SUCCESS;
569 else {
570 vty_out(vty, "%% LSP remove failed!\n");
571 return CMD_WARNING;
572 }
573 }
574
575 DEFPY (logpump,
576 logpump_cmd,
577 "sharp logpump duration (1-60) frequency (1-1000000) burst (1-1000)",
578 "Sharp Routing Protocol\n"
579 "Generate bulk log messages for testing\n"
580 "Duration of run (s)\n"
581 "Duration of run (s)\n"
582 "Frequency of bursts (s^-1)\n"
583 "Frequency of bursts (s^-1)\n"
584 "Number of log messages per each burst\n"
585 "Number of log messages per each burst\n")
586 {
587 sharp_logpump_run(vty, duration, frequency, burst);
588 return CMD_SUCCESS;
589 }
590
591 DEFPY (create_session,
592 create_session_cmd,
593 "sharp create session (1-1024)",
594 "Sharp Routing Protocol\n"
595 "Create data\n"
596 "Create a test session\n"
597 "Session ID\n")
598 {
599 if (sharp_zclient_create(session) != 0) {
600 vty_out(vty, "%% Client session error\n");
601 return CMD_WARNING;
602 }
603
604 return CMD_SUCCESS;
605 }
606
607 DEFPY (remove_session,
608 remove_session_cmd,
609 "sharp remove session (1-1024)",
610 "Sharp Routing Protocol\n"
611 "Remove data\n"
612 "Remove a test session\n"
613 "Session ID\n")
614 {
615 sharp_zclient_delete(session);
616 return CMD_SUCCESS;
617 }
618
619 DEFPY (send_opaque,
620 send_opaque_cmd,
621 "sharp send opaque type (1-255) (1-1000)$count",
622 SHARP_STR
623 "Send messages for testing\n"
624 "Send opaque messages\n"
625 "Type code to send\n"
626 "Type code to send\n"
627 "Number of messages to send\n")
628 {
629 sharp_opaque_send(type, 0, 0, 0, count);
630 return CMD_SUCCESS;
631 }
632
633 DEFPY (send_opaque_unicast,
634 send_opaque_unicast_cmd,
635 "sharp send opaque unicast type (1-255) \
636 " FRR_IP_REDIST_STR_ZEBRA "$proto_str \
637 [{instance (0-1000) | session (1-1000)}] (1-1000)$count",
638 SHARP_STR
639 "Send messages for testing\n"
640 "Send opaque messages\n"
641 "Send unicast messages\n"
642 "Type code to send\n"
643 "Type code to send\n"
644 FRR_IP_REDIST_HELP_STR_ZEBRA
645 "Daemon instance\n"
646 "Daemon instance\n"
647 "Session ID\n"
648 "Session ID\n"
649 "Number of messages to send\n")
650 {
651 uint32_t proto;
652
653 proto = proto_redistnum(AFI_IP, proto_str);
654
655 sharp_opaque_send(type, proto, instance, session, count);
656
657 return CMD_SUCCESS;
658 }
659
660 DEFPY (send_opaque_reg,
661 send_opaque_reg_cmd,
662 "sharp send opaque <reg$reg | unreg> \
663 " FRR_IP_REDIST_STR_ZEBRA "$proto_str \
664 [{instance (0-1000) | session (1-1000)}] type (1-1000)",
665 SHARP_STR
666 "Send messages for testing\n"
667 "Send opaque messages\n"
668 "Send opaque registration\n"
669 "Send opaque unregistration\n"
670 FRR_IP_REDIST_HELP_STR_ZEBRA
671 "Daemon instance\n"
672 "Daemon instance\n"
673 "Session ID\n"
674 "Session ID\n"
675 "Opaque sub-type code\n"
676 "Opaque sub-type code\n")
677 {
678 int proto;
679
680 proto = proto_redistnum(AFI_IP, proto_str);
681
682 sharp_opaque_reg_send((reg != NULL), proto, instance, session, type);
683 return CMD_SUCCESS;
684 }
685
686 DEFPY (neigh_discover,
687 neigh_discover_cmd,
688 "sharp neigh discover [vrf NAME$vrf_name] <A.B.C.D$dst4|X:X::X:X$dst6> IFNAME$ifname",
689 SHARP_STR
690 "Discover neighbours\n"
691 "Send an ARP/NDP request\n"
692 VRF_CMD_HELP_STR
693 "v4 Destination address\n"
694 "v6 Destination address\n"
695 "Interface name\n")
696 {
697 struct vrf *vrf;
698 struct interface *ifp;
699 struct prefix prefix;
700
701 memset(&prefix, 0, sizeof(prefix));
702
703 if (dst4.s_addr != INADDR_ANY) {
704 prefix.family = AF_INET;
705 prefix.prefixlen = 32;
706 prefix.u.prefix4 = dst4;
707 } else {
708 prefix.family = AF_INET6;
709 prefix.prefixlen = 128;
710 prefix.u.prefix6 = dst6;
711 }
712
713 vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
714 if (!vrf) {
715 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
716 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
717 return CMD_WARNING;
718 }
719
720 ifp = if_lookup_by_name_vrf(ifname, vrf);
721 if (ifp == NULL) {
722 vty_out(vty, "%% Can't find interface %s\n", ifname);
723 return CMD_WARNING;
724 }
725
726 sharp_zebra_send_arp(ifp, &prefix);
727
728 return CMD_SUCCESS;
729 }
730
731 DEFPY (import_te,
732 import_te_cmd,
733 "sharp import-te",
734 SHARP_STR
735 "Import Traffic Engineering\n")
736 {
737 sg.ted = ls_ted_new(1, "Sharp", 0);
738 sharp_zebra_register_te();
739
740 return CMD_SUCCESS;
741 }
742
743 DEFUN (show_sharp_ted,
744 show_sharp_ted_cmd,
745 "show sharp ted [<vertex [A.B.C.D]|edge [A.B.C.D]|subnet [A.B.C.D/M]>] [verbose|json]",
746 SHOW_STR
747 SHARP_STR
748 "Traffic Engineering Database\n"
749 "MPLS-TE Vertex\n"
750 "MPLS-TE router ID (as an IP address)\n"
751 "MPLS-TE Edge\n"
752 "MPLS-TE Edge ID (as an IP address)\n"
753 "MPLS-TE Subnet\n"
754 "MPLS-TE Subnet ID (as an IP prefix)\n"
755 "Verbose output\n"
756 JSON_STR)
757 {
758 int idx = 0;
759 struct in_addr ip_addr;
760 struct prefix pref;
761 struct ls_vertex *vertex;
762 struct ls_edge *edge;
763 struct ls_subnet *subnet;
764 uint64_t key;
765 bool verbose = false;
766 bool uj = use_json(argc, argv);
767 json_object *json = NULL;
768
769 if (sg.ted == NULL) {
770 vty_out(vty, "MPLS-TE import is not enabled\n");
771 return CMD_WARNING;
772 }
773
774 if (uj)
775 json = json_object_new_object();
776
777 if (argv[argc - 1]->arg && strmatch(argv[argc - 1]->text, "verbose"))
778 verbose = true;
779
780 if (argv_find(argv, argc, "vertex", &idx)) {
781 /* Show Vertex */
782 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
783 if (!inet_aton(argv[idx + 1]->arg, &ip_addr)) {
784 vty_out(vty,
785 "Specified Router ID %s is invalid\n",
786 argv[idx + 1]->arg);
787 return CMD_WARNING_CONFIG_FAILED;
788 }
789 /* Get the Vertex from the Link State Database */
790 key = ((uint64_t)ip_addr.s_addr) & 0xffffffff;
791 vertex = ls_find_vertex_by_key(sg.ted, key);
792 if (!vertex) {
793 vty_out(vty, "No vertex found for ID %pI4\n",
794 &ip_addr);
795 return CMD_WARNING;
796 }
797 } else
798 vertex = NULL;
799
800 if (vertex)
801 ls_show_vertex(vertex, vty, json, verbose);
802 else
803 ls_show_vertices(sg.ted, vty, json, verbose);
804
805 } else if (argv_find(argv, argc, "edge", &idx)) {
806 /* Show Edge */
807 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
808 if (!inet_aton(argv[idx]->arg, &ip_addr)) {
809 vty_out(vty,
810 "Specified Edge ID %s is invalid\n",
811 argv[idx]->arg);
812 return CMD_WARNING_CONFIG_FAILED;
813 }
814 /* Get the Edge from the Link State Database */
815 key = ((uint64_t)ip_addr.s_addr) & 0xffffffff;
816 edge = ls_find_edge_by_key(sg.ted, key);
817 if (!edge) {
818 vty_out(vty, "No edge found for ID %pI4\n",
819 &ip_addr);
820 return CMD_WARNING;
821 }
822 } else
823 edge = NULL;
824
825 if (edge)
826 ls_show_edge(edge, vty, json, verbose);
827 else
828 ls_show_edges(sg.ted, vty, json, verbose);
829
830 } else if (argv_find(argv, argc, "subnet", &idx)) {
831 /* Show Subnet */
832 if (argv_find(argv, argc, "A.B.C.D/M", &idx)) {
833 if (!str2prefix(argv[idx]->arg, &pref)) {
834 vty_out(vty, "Invalid prefix format %s\n",
835 argv[idx]->arg);
836 return CMD_WARNING_CONFIG_FAILED;
837 }
838 /* Get the Subnet from the Link State Database */
839 subnet = ls_find_subnet(sg.ted, pref);
840 if (!subnet) {
841 vty_out(vty, "No subnet found for ID %pFX\n",
842 &pref);
843 return CMD_WARNING;
844 }
845 } else
846 subnet = NULL;
847
848 if (subnet)
849 ls_show_subnet(subnet, vty, json, verbose);
850 else
851 ls_show_subnets(sg.ted, vty, json, verbose);
852
853 } else {
854 /* Show the complete TED */
855 ls_show_ted(sg.ted, vty, json, verbose);
856 }
857
858 if (uj) {
859 vty_out(vty, "%s\n",
860 json_object_to_json_string_ext(
861 json, JSON_C_TO_STRING_PRETTY));
862 json_object_free(json);
863 }
864 return CMD_SUCCESS;
865 }
866
867 void sharp_vty_init(void)
868 {
869 install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
870 install_element(ENABLE_NODE, &install_routes_cmd);
871 install_element(ENABLE_NODE, &remove_routes_cmd);
872 install_element(ENABLE_NODE, &vrf_label_cmd);
873 install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd);
874 install_element(ENABLE_NODE, &watch_redistribute_cmd);
875 install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
876 install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
877 install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd);
878 install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd);
879 install_element(ENABLE_NODE, &logpump_cmd);
880 install_element(ENABLE_NODE, &create_session_cmd);
881 install_element(ENABLE_NODE, &remove_session_cmd);
882 install_element(ENABLE_NODE, &send_opaque_cmd);
883 install_element(ENABLE_NODE, &send_opaque_unicast_cmd);
884 install_element(ENABLE_NODE, &send_opaque_reg_cmd);
885 install_element(ENABLE_NODE, &neigh_discover_cmd);
886 install_element(ENABLE_NODE, &import_te_cmd);
887
888 install_element(ENABLE_NODE, &show_debugging_sharpd_cmd);
889 install_element(ENABLE_NODE, &show_sharp_ted_cmd);
890
891 return;
892 }