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 "Data about what is going on\n"
135 "Nexthop information\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_num = 1;
282 sg.r.nhop.backup_idx[0] = 0;
283
284 if (backup_nexthop4.s_addr != INADDR_ANY) {
285 sg.r.backup_nhop.gate.ipv4 = backup_nexthop4;
286 sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV4;
287 } else {
288 sg.r.backup_nhop.gate.ipv6 = backup_nexthop6;
289 sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV6;
290 }
291
292 sg.r.backup_nhop.vrf_id = vrf->vrf_id;
293 sg.r.backup_nhop_group.nexthop = &sg.r.backup_nhop;
294 }
295
296 sg.r.inst = instance;
297 sg.r.vrf_id = vrf->vrf_id;
298 rts = routes;
299 sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst,
300 &sg.r.nhop_group, &sg.r.backup_nhop_group,
301 rts);
302
303 return CMD_SUCCESS;
304 }
305
306 DEFPY(vrf_label, vrf_label_cmd,
307 "sharp label <ip$ipv4|ipv6$ipv6> vrf NAME$vrf_name label (0-100000)$label",
308 "Sharp Routing Protocol\n"
309 "Give a vrf a label\n"
310 "Pop and forward for IPv4\n"
311 "Pop and forward for IPv6\n"
312 VRF_CMD_HELP_STR
313 "The label to use, 0 specifies remove the label installed from previous\n"
314 "Specified range to use\n")
315 {
316 struct vrf *vrf;
317 afi_t afi = (ipv4) ? AFI_IP : AFI_IP6;
318
319 if (strcmp(vrf_name, "default") == 0)
320 vrf = vrf_lookup_by_id(VRF_DEFAULT);
321 else
322 vrf = vrf_lookup_by_name(vrf_name);
323
324 if (!vrf) {
325 vty_out(vty, "Unable to find vrf you silly head");
326 return CMD_WARNING_CONFIG_FAILED;
327 }
328
329 if (label == 0)
330 label = MPLS_LABEL_NONE;
331
332 vrf_label_add(vrf->vrf_id, afi, label);
333 return CMD_SUCCESS;
334 }
335
336 DEFPY (remove_routes,
337 remove_routes_cmd,
338 "sharp remove routes [vrf NAME$vrf_name] <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]",
339 "Sharp Routing Protocol\n"
340 "Remove some routes\n"
341 "Routes to remove\n"
342 "The vrf we would like to remove from if non-default\n"
343 "The NAME of the vrf\n"
344 "v4 Starting spot\n"
345 "v6 Starting spot\n"
346 "Routes to uninstall\n"
347 "instance to use\n"
348 "Value of instance\n")
349 {
350 struct vrf *vrf;
351 struct prefix prefix;
352
353 sg.r.total_routes = routes;
354 sg.r.removed_routes = 0;
355 uint32_t rts;
356
357 memset(&prefix, 0, sizeof(prefix));
358
359 if (start4.s_addr != 0) {
360 prefix.family = AF_INET;
361 prefix.prefixlen = 32;
362 prefix.u.prefix4 = start4;
363 } else {
364 prefix.family = AF_INET6;
365 prefix.prefixlen = 128;
366 prefix.u.prefix6 = start6;
367 }
368
369 vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
370 if (!vrf) {
371 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
372 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
373 return CMD_WARNING;
374 }
375
376 sg.r.inst = instance;
377 sg.r.vrf_id = vrf->vrf_id;
378 rts = routes;
379 sharp_remove_routes_helper(&prefix, sg.r.vrf_id,
380 sg.r.inst, rts);
381
382 return CMD_SUCCESS;
383 }
384
385 DEFUN_NOSH (show_debugging_sharpd,
386 show_debugging_sharpd_cmd,
387 "show debugging [sharp]",
388 SHOW_STR
389 DEBUG_STR
390 "Sharp Information\n")
391 {
392 vty_out(vty, "Sharp debugging status:\n");
393
394 return CMD_SUCCESS;
395 }
396
397 DEFPY (sharp_lsp_prefix_v4, sharp_lsp_prefix_v4_cmd,
398 "sharp lsp [update]$update (0-100000)$inlabel\
399 nexthop-group NHGNAME$nhgname\
400 [prefix A.B.C.D/M$pfx\
401 " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]",
402 "Sharp Routing Protocol\n"
403 "Add an LSP\n"
404 "Update an LSP\n"
405 "The ingress label to use\n"
406 "Use nexthops from a nexthop-group\n"
407 "The nexthop-group name\n"
408 "Label a prefix\n"
409 "The v4 prefix to label\n"
410 FRR_IP_REDIST_HELP_STR_ZEBRA
411 "Instance to use\n"
412 "Instance\n")
413 {
414 struct nexthop_group_cmd *nhgc = NULL;
415 struct nexthop_group_cmd *backup_nhgc = NULL;
416 struct nexthop_group *backup_nhg = NULL;
417 struct prefix p = {};
418 int type = 0;
419 bool update_p;
420
421 update_p = (update != NULL);
422
423 /* We're offered a v4 prefix */
424 if (pfx->family > 0 && type_str) {
425 p.family = pfx->family;
426 p.prefixlen = pfx->prefixlen;
427 p.u.prefix4 = pfx->prefix;
428
429 type = proto_redistnum(AFI_IP, type_str);
430 if (type < 0) {
431 vty_out(vty, "%% Unknown route type '%s'\n", type_str);
432 return CMD_WARNING;
433 }
434 } else if (pfx->family > 0 || type_str) {
435 vty_out(vty, "%% Must supply both prefix and type\n");
436 return CMD_WARNING;
437 }
438
439 nhgc = nhgc_find(nhgname);
440 if (!nhgc) {
441 vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
442 nhgname);
443 return CMD_WARNING;
444 }
445
446 if (nhgc->nhg.nexthop == NULL) {
447 vty_out(vty, "%% Nexthop-group '%s' is empty\n", nhgname);
448 return CMD_WARNING;
449 }
450
451 /* Use group's backup nexthop info if present */
452 if (nhgc->backup_list_name[0]) {
453 backup_nhgc = nhgc_find(nhgc->backup_list_name);
454
455 if (!backup_nhgc) {
456 vty_out(vty,
457 "%% Backup group %s not found for group %s\n",
458 nhgc->backup_list_name,
459 nhgname);
460 return CMD_WARNING;
461 }
462 backup_nhg = &(backup_nhgc->nhg);
463 }
464
465 if (sharp_install_lsps_helper(true /*install*/, update_p,
466 pfx->family > 0 ? &p : NULL,
467 type, instance, inlabel,
468 &(nhgc->nhg), backup_nhg) == 0)
469 return CMD_SUCCESS;
470 else {
471 vty_out(vty, "%% LSP install failed!\n");
472 return CMD_WARNING;
473 }
474 }
475
476 DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd,
477 "sharp remove lsp \
478 (0-100000)$inlabel\
479 [nexthop-group NHGNAME$nhgname] \
480 [prefix A.B.C.D/M$pfx\
481 " FRR_IP_REDIST_STR_SHARPD "$type_str [instance (0-255)$instance]]",
482 "Sharp Routing Protocol\n"
483 "Remove data\n"
484 "Remove an LSP\n"
485 "The ingress label\n"
486 "Use nexthops from a nexthop-group\n"
487 "The nexthop-group name\n"
488 "Specify a v4 prefix\n"
489 "The v4 prefix to label\n"
490 FRR_IP_REDIST_HELP_STR_SHARPD
491 "Routing instance\n"
492 "Instance to use\n")
493 {
494 struct nexthop_group_cmd *nhgc = NULL;
495 struct prefix p = {};
496 int type = 0;
497 struct nexthop_group *nhg = NULL;
498
499 /* We're offered a v4 prefix */
500 if (pfx->family > 0 && type_str) {
501 p.family = pfx->family;
502 p.prefixlen = pfx->prefixlen;
503 p.u.prefix4 = pfx->prefix;
504
505 type = proto_redistnum(AFI_IP, type_str);
506 if (type < 0) {
507 vty_out(vty, "%% Unknown route type '%s'\n", type_str);
508 return CMD_WARNING;
509 }
510 } else if (pfx->family > 0 || type_str) {
511 vty_out(vty, "%% Must supply both prefix and type\n");
512 return CMD_WARNING;
513 }
514
515 if (nhgname) {
516 nhgc = nhgc_find(nhgname);
517 if (!nhgc) {
518 vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
519 nhgname);
520 return CMD_WARNING;
521 }
522
523 if (nhgc->nhg.nexthop == NULL) {
524 vty_out(vty, "%% Nexthop-group '%s' is empty\n",
525 nhgname);
526 return CMD_WARNING;
527 }
528 nhg = &(nhgc->nhg);
529 }
530
531 if (sharp_install_lsps_helper(false /*!install*/, false,
532 pfx->family > 0 ? &p : NULL,
533 type, instance, inlabel, nhg, NULL) == 0)
534 return CMD_SUCCESS;
535 else {
536 vty_out(vty, "%% LSP remove failed!\n");
537 return CMD_WARNING;
538 }
539 }
540
541 DEFPY (logpump,
542 logpump_cmd,
543 "sharp logpump duration (1-60) frequency (1-1000000) burst (1-1000)",
544 "Sharp Routing Protocol\n"
545 "Generate bulk log messages for testing\n"
546 "Duration of run (s)\n"
547 "Duration of run (s)\n"
548 "Frequency of bursts (s^-1)\n"
549 "Frequency of bursts (s^-1)\n"
550 "Number of log messages per each burst\n"
551 "Number of log messages per each burst\n")
552 {
553 sharp_logpump_run(vty, duration, frequency, burst);
554 return CMD_SUCCESS;
555 }
556
557 DEFPY (create_session,
558 create_session_cmd,
559 "sharp create session (1-1024)",
560 "Sharp Routing Protocol\n"
561 "Create data\n"
562 "Create a test session\n"
563 "Session ID\n")
564 {
565 if (sharp_zclient_create(session) != 0) {
566 vty_out(vty, "%% Client session error\n");
567 return CMD_WARNING;
568 }
569
570 return CMD_SUCCESS;
571 }
572
573 DEFPY (remove_session,
574 remove_session_cmd,
575 "sharp remove session (1-1024)",
576 "Sharp Routing Protocol\n"
577 "Remove data\n"
578 "Remove a test session\n"
579 "Session ID\n")
580 {
581 sharp_zclient_delete(session);
582 return CMD_SUCCESS;
583 }
584
585 DEFPY (send_opaque,
586 send_opaque_cmd,
587 "sharp send opaque type (1-255) (1-1000)$count",
588 SHARP_STR
589 "Send messages for testing\n"
590 "Send opaque messages\n"
591 "Type code to send\n"
592 "Type code to send\n"
593 "Number of messages to send\n")
594 {
595 sharp_opaque_send(type, 0, 0, 0, count);
596 return CMD_SUCCESS;
597 }
598
599 DEFPY (send_opaque_unicast,
600 send_opaque_unicast_cmd,
601 "sharp send opaque unicast type (1-255) \
602 " FRR_IP_REDIST_STR_ZEBRA "$proto_str \
603 [{instance (0-1000) | session (1-1000)}] (1-1000)$count",
604 SHARP_STR
605 "Send messages for testing\n"
606 "Send opaque messages\n"
607 "Send unicast messages\n"
608 "Type code to send\n"
609 "Type code to send\n"
610 FRR_IP_REDIST_HELP_STR_ZEBRA
611 "Daemon instance\n"
612 "Daemon instance\n"
613 "Session ID\n"
614 "Session ID\n"
615 "Number of messages to send\n")
616 {
617 uint32_t proto;
618
619 proto = proto_redistnum(AFI_IP, proto_str);
620
621 sharp_opaque_send(type, proto, instance, session, count);
622
623 return CMD_SUCCESS;
624 }
625
626 DEFPY (send_opaque_reg,
627 send_opaque_reg_cmd,
628 "sharp send opaque <reg$reg | unreg> \
629 " FRR_IP_REDIST_STR_ZEBRA "$proto_str \
630 [{instance (0-1000) | session (1-1000)}] type (1-1000)",
631 SHARP_STR
632 "Send messages for testing\n"
633 "Send opaque messages\n"
634 "Send opaque registration\n"
635 "Send opaque unregistration\n"
636 FRR_IP_REDIST_HELP_STR_ZEBRA
637 "Daemon instance\n"
638 "Daemon instance\n"
639 "Session ID\n"
640 "Session ID\n"
641 "Opaque sub-type code\n"
642 "Opaque sub-type code\n")
643 {
644 int proto;
645
646 proto = proto_redistnum(AFI_IP, proto_str);
647
648 sharp_opaque_reg_send((reg != NULL), proto, instance, session, type);
649 return CMD_SUCCESS;
650 }
651
652 DEFPY (neigh_discover,
653 neigh_discover_cmd,
654 "sharp neigh discover [vrf NAME$vrf_name] <A.B.C.D$dst4|X:X::X:X$dst6> IFNAME$ifname",
655 SHARP_STR
656 "Discover neighbours\n"
657 "Send an ARP/NDP request\n"
658 VRF_CMD_HELP_STR
659 "v4 Destination address\n"
660 "v6 Destination address\n"
661 "Interface name\n")
662 {
663 struct vrf *vrf;
664 struct interface *ifp;
665 struct prefix prefix;
666
667 memset(&prefix, 0, sizeof(prefix));
668
669 if (dst4.s_addr != 0) {
670 prefix.family = AF_INET;
671 prefix.prefixlen = 32;
672 prefix.u.prefix4 = dst4;
673 } else {
674 prefix.family = AF_INET6;
675 prefix.prefixlen = 128;
676 prefix.u.prefix6 = dst6;
677 }
678
679 vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
680 if (!vrf) {
681 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
682 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
683 return CMD_WARNING;
684 }
685
686 ifp = if_lookup_by_name_vrf(ifname, vrf);
687 if (ifp == NULL) {
688 vty_out(vty, "%% Can't find interface %s\n", ifname);
689 return CMD_WARNING;
690 }
691
692 sharp_zebra_send_arp(ifp, &prefix);
693
694 return CMD_SUCCESS;
695 }
696
sharp_vty_init(void)697 void sharp_vty_init(void)
698 {
699 install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
700 install_element(ENABLE_NODE, &install_routes_cmd);
701 install_element(ENABLE_NODE, &remove_routes_cmd);
702 install_element(ENABLE_NODE, &vrf_label_cmd);
703 install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd);
704 install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
705 install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
706 install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd);
707 install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd);
708 install_element(ENABLE_NODE, &logpump_cmd);
709 install_element(ENABLE_NODE, &create_session_cmd);
710 install_element(ENABLE_NODE, &remove_session_cmd);
711 install_element(ENABLE_NODE, &send_opaque_cmd);
712 install_element(ENABLE_NODE, &send_opaque_unicast_cmd);
713 install_element(ENABLE_NODE, &send_opaque_reg_cmd);
714 install_element(ENABLE_NODE, &neigh_discover_cmd);
715
716 install_element(ENABLE_NODE, &show_debugging_sharpd_cmd);
717
718 return;
719 }
720