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