]> git.proxmox.com Git - mirror_frr.git/blob - sharpd/sharp_vty.c
Merge pull request #7736 from ton31337/fix/s_addr_INADDR_ANY
[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 "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 struct timeval r;
150
151 timersub(&sg.r.t_end, &sg.r.t_start, &r);
152 vty_out(vty, "Prefix: %pFX Total: %u %u %u Time: %jd.%ld\n",
153 &sg.r.orig_prefix, sg.r.total_routes, sg.r.installed_routes,
154 sg.r.removed_routes, (intmax_t)r.tv_sec, (long)r.tv_usec);
155
156 return CMD_SUCCESS;
157 }
158
159 DEFPY (install_routes,
160 install_routes_cmd,
161 "sharp install routes [vrf NAME$vrf_name]\
162 <A.B.C.D$start4|X:X::X:X$start6>\
163 <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|\
164 nexthop-group NHGNAME$nexthop_group>\
165 [backup$backup <A.B.C.D$backup_nexthop4|X:X::X:X$backup_nexthop6>] \
166 (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt] [opaque WORD]",
167 "Sharp routing Protocol\n"
168 "install some routes\n"
169 "Routes to install\n"
170 "The vrf we would like to install into if non-default\n"
171 "The NAME of the vrf\n"
172 "v4 Address to start /32 generation at\n"
173 "v6 Address to start /32 generation at\n"
174 "Nexthop to use(Can be an IPv4 or IPv6 address)\n"
175 "V4 Nexthop address to use\n"
176 "V6 Nexthop address to use\n"
177 "Nexthop-Group to use\n"
178 "The Name of the nexthop-group\n"
179 "Backup nexthop to use(Can be an IPv4 or IPv6 address)\n"
180 "Backup V4 Nexthop address to use\n"
181 "Backup V6 Nexthop address to use\n"
182 "How many to create\n"
183 "Instance to use\n"
184 "Instance\n"
185 "Should we repeat this command\n"
186 "How many times to repeat this command\n"
187 "What opaque data to send down\n"
188 "The opaque data\n")
189 {
190 struct vrf *vrf;
191 struct prefix prefix;
192 uint32_t rts;
193 uint32_t nhgid = 0;
194
195 sg.r.total_routes = routes;
196 sg.r.installed_routes = 0;
197
198 if (rpt >= 2)
199 sg.r.repeat = rpt * 2;
200 else
201 sg.r.repeat = 0;
202
203 memset(&prefix, 0, sizeof(prefix));
204 memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
205 memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
206 memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
207 memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
208 memset(&sg.r.backup_nhop_group, 0, sizeof(sg.r.nhop_group));
209
210 if (start4.s_addr != INADDR_ANY) {
211 prefix.family = AF_INET;
212 prefix.prefixlen = 32;
213 prefix.u.prefix4 = start4;
214 } else {
215 prefix.family = AF_INET6;
216 prefix.prefixlen = 128;
217 prefix.u.prefix6 = start6;
218 }
219 sg.r.orig_prefix = prefix;
220
221 if (!vrf_name)
222 vrf_name = VRF_DEFAULT_NAME;
223
224 vrf = vrf_lookup_by_name(vrf_name);
225 if (!vrf) {
226 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
227 vrf_name);
228 return CMD_WARNING;
229 }
230
231 /* Explicit backup not available with named nexthop-group */
232 if (backup && nexthop_group) {
233 vty_out(vty, "%% Invalid: cannot specify both nexthop-group and backup\n");
234 return CMD_WARNING;
235 }
236
237 if (nexthop_group) {
238 struct nexthop_group_cmd *nhgc = nhgc_find(nexthop_group);
239 if (!nhgc) {
240 vty_out(vty,
241 "Specified Nexthop Group: %s does not exist\n",
242 nexthop_group);
243 return CMD_WARNING;
244 }
245
246 nhgid = sharp_nhgroup_get_id(nexthop_group);
247 sg.r.nhgid = nhgid;
248 sg.r.nhop_group.nexthop = nhgc->nhg.nexthop;
249
250 /* Use group's backup nexthop info if present */
251 if (nhgc->backup_list_name[0]) {
252 struct nexthop_group_cmd *bnhgc =
253 nhgc_find(nhgc->backup_list_name);
254
255 if (!bnhgc) {
256 vty_out(vty, "%% Backup group %s not found for group %s\n",
257 nhgc->backup_list_name,
258 nhgc->name);
259 return CMD_WARNING;
260 }
261
262 sg.r.backup_nhop.vrf_id = vrf->vrf_id;
263 sg.r.backup_nhop_group.nexthop = bnhgc->nhg.nexthop;
264 }
265 } else {
266 if (nexthop4.s_addr != INADDR_ANY) {
267 sg.r.nhop.gate.ipv4 = nexthop4;
268 sg.r.nhop.type = NEXTHOP_TYPE_IPV4;
269 } else {
270 sg.r.nhop.gate.ipv6 = nexthop6;
271 sg.r.nhop.type = NEXTHOP_TYPE_IPV6;
272 }
273
274 sg.r.nhop.vrf_id = vrf->vrf_id;
275 sg.r.nhop_group.nexthop = &sg.r.nhop;
276 }
277
278 /* Use single backup nexthop if specified */
279 if (backup) {
280 /* Set flag and index in primary nexthop */
281 SET_FLAG(sg.r.nhop.flags, NEXTHOP_FLAG_HAS_BACKUP);
282 sg.r.nhop.backup_num = 1;
283 sg.r.nhop.backup_idx[0] = 0;
284
285 if (backup_nexthop4.s_addr != INADDR_ANY) {
286 sg.r.backup_nhop.gate.ipv4 = backup_nexthop4;
287 sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV4;
288 } else {
289 sg.r.backup_nhop.gate.ipv6 = backup_nexthop6;
290 sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV6;
291 }
292
293 sg.r.backup_nhop.vrf_id = vrf->vrf_id;
294 sg.r.backup_nhop_group.nexthop = &sg.r.backup_nhop;
295 }
296
297 if (opaque)
298 strlcpy(sg.r.opaque, opaque, ZAPI_MESSAGE_OPAQUE_LENGTH);
299 else
300 sg.r.opaque[0] = '\0';
301
302 sg.r.inst = instance;
303 sg.r.vrf_id = vrf->vrf_id;
304 rts = routes;
305 sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst, nhgid,
306 &sg.r.nhop_group, &sg.r.backup_nhop_group,
307 rts, sg.r.opaque);
308
309 return CMD_SUCCESS;
310 }
311
312 DEFPY(vrf_label, vrf_label_cmd,
313 "sharp label <ip$ipv4|ipv6$ipv6> vrf NAME$vrf_name label (0-100000)$label",
314 "Sharp Routing Protocol\n"
315 "Give a vrf a label\n"
316 "Pop and forward for IPv4\n"
317 "Pop and forward for IPv6\n"
318 VRF_CMD_HELP_STR
319 "The label to use, 0 specifies remove the label installed from previous\n"
320 "Specified range to use\n")
321 {
322 struct vrf *vrf;
323 afi_t afi = (ipv4) ? AFI_IP : AFI_IP6;
324
325 if (strcmp(vrf_name, "default") == 0)
326 vrf = vrf_lookup_by_id(VRF_DEFAULT);
327 else
328 vrf = vrf_lookup_by_name(vrf_name);
329
330 if (!vrf) {
331 vty_out(vty, "Unable to find vrf you silly head");
332 return CMD_WARNING_CONFIG_FAILED;
333 }
334
335 if (label == 0)
336 label = MPLS_LABEL_NONE;
337
338 vrf_label_add(vrf->vrf_id, afi, label);
339 return CMD_SUCCESS;
340 }
341
342 DEFPY (remove_routes,
343 remove_routes_cmd,
344 "sharp remove routes [vrf NAME$vrf_name] <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]",
345 "Sharp Routing Protocol\n"
346 "Remove some routes\n"
347 "Routes to remove\n"
348 "The vrf we would like to remove from if non-default\n"
349 "The NAME of the vrf\n"
350 "v4 Starting spot\n"
351 "v6 Starting spot\n"
352 "Routes to uninstall\n"
353 "instance to use\n"
354 "Value of instance\n")
355 {
356 struct vrf *vrf;
357 struct prefix prefix;
358
359 sg.r.total_routes = routes;
360 sg.r.removed_routes = 0;
361 uint32_t rts;
362
363 memset(&prefix, 0, sizeof(prefix));
364
365 if (start4.s_addr != INADDR_ANY) {
366 prefix.family = AF_INET;
367 prefix.prefixlen = 32;
368 prefix.u.prefix4 = start4;
369 } else {
370 prefix.family = AF_INET6;
371 prefix.prefixlen = 128;
372 prefix.u.prefix6 = start6;
373 }
374
375 vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
376 if (!vrf) {
377 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
378 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
379 return CMD_WARNING;
380 }
381
382 sg.r.inst = instance;
383 sg.r.vrf_id = vrf->vrf_id;
384 rts = routes;
385 sharp_remove_routes_helper(&prefix, sg.r.vrf_id,
386 sg.r.inst, rts);
387
388 return CMD_SUCCESS;
389 }
390
391 DEFUN_NOSH (show_debugging_sharpd,
392 show_debugging_sharpd_cmd,
393 "show debugging [sharp]",
394 SHOW_STR
395 DEBUG_STR
396 "Sharp Information\n")
397 {
398 vty_out(vty, "Sharp debugging status:\n");
399
400 return CMD_SUCCESS;
401 }
402
403 DEFPY (sharp_lsp_prefix_v4, sharp_lsp_prefix_v4_cmd,
404 "sharp lsp [update]$update (0-100000)$inlabel\
405 nexthop-group NHGNAME$nhgname\
406 [prefix A.B.C.D/M$pfx\
407 " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]",
408 "Sharp Routing Protocol\n"
409 "Add an LSP\n"
410 "Update an LSP\n"
411 "The ingress label to use\n"
412 "Use nexthops from a nexthop-group\n"
413 "The nexthop-group name\n"
414 "Label a prefix\n"
415 "The v4 prefix to label\n"
416 FRR_IP_REDIST_HELP_STR_ZEBRA
417 "Instance to use\n"
418 "Instance\n")
419 {
420 struct nexthop_group_cmd *nhgc = NULL;
421 struct nexthop_group_cmd *backup_nhgc = NULL;
422 struct nexthop_group *backup_nhg = NULL;
423 struct prefix p = {};
424 int type = 0;
425 bool update_p;
426
427 update_p = (update != NULL);
428
429 /* We're offered a v4 prefix */
430 if (pfx->family > 0 && type_str) {
431 p.family = pfx->family;
432 p.prefixlen = pfx->prefixlen;
433 p.u.prefix4 = pfx->prefix;
434
435 type = proto_redistnum(AFI_IP, type_str);
436 if (type < 0) {
437 vty_out(vty, "%% Unknown route type '%s'\n", type_str);
438 return CMD_WARNING;
439 }
440 } else if (pfx->family > 0 || type_str) {
441 vty_out(vty, "%% Must supply both prefix and type\n");
442 return CMD_WARNING;
443 }
444
445 nhgc = nhgc_find(nhgname);
446 if (!nhgc) {
447 vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
448 nhgname);
449 return CMD_WARNING;
450 }
451
452 if (nhgc->nhg.nexthop == NULL) {
453 vty_out(vty, "%% Nexthop-group '%s' is empty\n", nhgname);
454 return CMD_WARNING;
455 }
456
457 /* Use group's backup nexthop info if present */
458 if (nhgc->backup_list_name[0]) {
459 backup_nhgc = nhgc_find(nhgc->backup_list_name);
460
461 if (!backup_nhgc) {
462 vty_out(vty,
463 "%% Backup group %s not found for group %s\n",
464 nhgc->backup_list_name,
465 nhgname);
466 return CMD_WARNING;
467 }
468 backup_nhg = &(backup_nhgc->nhg);
469 }
470
471 if (sharp_install_lsps_helper(true /*install*/, update_p,
472 pfx->family > 0 ? &p : NULL,
473 type, instance, inlabel,
474 &(nhgc->nhg), backup_nhg) == 0)
475 return CMD_SUCCESS;
476 else {
477 vty_out(vty, "%% LSP install failed!\n");
478 return CMD_WARNING;
479 }
480 }
481
482 DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd,
483 "sharp remove lsp \
484 (0-100000)$inlabel\
485 [nexthop-group NHGNAME$nhgname] \
486 [prefix A.B.C.D/M$pfx\
487 " FRR_IP_REDIST_STR_SHARPD "$type_str [instance (0-255)$instance]]",
488 "Sharp Routing Protocol\n"
489 "Remove data\n"
490 "Remove an LSP\n"
491 "The ingress label\n"
492 "Use nexthops from a nexthop-group\n"
493 "The nexthop-group name\n"
494 "Specify a v4 prefix\n"
495 "The v4 prefix to label\n"
496 FRR_IP_REDIST_HELP_STR_SHARPD
497 "Routing instance\n"
498 "Instance to use\n")
499 {
500 struct nexthop_group_cmd *nhgc = NULL;
501 struct prefix p = {};
502 int type = 0;
503 struct nexthop_group *nhg = NULL;
504
505 /* We're offered a v4 prefix */
506 if (pfx->family > 0 && type_str) {
507 p.family = pfx->family;
508 p.prefixlen = pfx->prefixlen;
509 p.u.prefix4 = pfx->prefix;
510
511 type = proto_redistnum(AFI_IP, type_str);
512 if (type < 0) {
513 vty_out(vty, "%% Unknown route type '%s'\n", type_str);
514 return CMD_WARNING;
515 }
516 } else if (pfx->family > 0 || type_str) {
517 vty_out(vty, "%% Must supply both prefix and type\n");
518 return CMD_WARNING;
519 }
520
521 if (nhgname) {
522 nhgc = nhgc_find(nhgname);
523 if (!nhgc) {
524 vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
525 nhgname);
526 return CMD_WARNING;
527 }
528
529 if (nhgc->nhg.nexthop == NULL) {
530 vty_out(vty, "%% Nexthop-group '%s' is empty\n",
531 nhgname);
532 return CMD_WARNING;
533 }
534 nhg = &(nhgc->nhg);
535 }
536
537 if (sharp_install_lsps_helper(false /*!install*/, false,
538 pfx->family > 0 ? &p : NULL,
539 type, instance, inlabel, nhg, NULL) == 0)
540 return CMD_SUCCESS;
541 else {
542 vty_out(vty, "%% LSP remove failed!\n");
543 return CMD_WARNING;
544 }
545 }
546
547 DEFPY (logpump,
548 logpump_cmd,
549 "sharp logpump duration (1-60) frequency (1-1000000) burst (1-1000)",
550 "Sharp Routing Protocol\n"
551 "Generate bulk log messages for testing\n"
552 "Duration of run (s)\n"
553 "Duration of run (s)\n"
554 "Frequency of bursts (s^-1)\n"
555 "Frequency of bursts (s^-1)\n"
556 "Number of log messages per each burst\n"
557 "Number of log messages per each burst\n")
558 {
559 sharp_logpump_run(vty, duration, frequency, burst);
560 return CMD_SUCCESS;
561 }
562
563 DEFPY (create_session,
564 create_session_cmd,
565 "sharp create session (1-1024)",
566 "Sharp Routing Protocol\n"
567 "Create data\n"
568 "Create a test session\n"
569 "Session ID\n")
570 {
571 if (sharp_zclient_create(session) != 0) {
572 vty_out(vty, "%% Client session error\n");
573 return CMD_WARNING;
574 }
575
576 return CMD_SUCCESS;
577 }
578
579 DEFPY (remove_session,
580 remove_session_cmd,
581 "sharp remove session (1-1024)",
582 "Sharp Routing Protocol\n"
583 "Remove data\n"
584 "Remove a test session\n"
585 "Session ID\n")
586 {
587 sharp_zclient_delete(session);
588 return CMD_SUCCESS;
589 }
590
591 DEFPY (send_opaque,
592 send_opaque_cmd,
593 "sharp send opaque type (1-255) (1-1000)$count",
594 SHARP_STR
595 "Send messages for testing\n"
596 "Send opaque messages\n"
597 "Type code to send\n"
598 "Type code to send\n"
599 "Number of messages to send\n")
600 {
601 sharp_opaque_send(type, 0, 0, 0, count);
602 return CMD_SUCCESS;
603 }
604
605 DEFPY (send_opaque_unicast,
606 send_opaque_unicast_cmd,
607 "sharp send opaque unicast type (1-255) \
608 " FRR_IP_REDIST_STR_ZEBRA "$proto_str \
609 [{instance (0-1000) | session (1-1000)}] (1-1000)$count",
610 SHARP_STR
611 "Send messages for testing\n"
612 "Send opaque messages\n"
613 "Send unicast messages\n"
614 "Type code to send\n"
615 "Type code to send\n"
616 FRR_IP_REDIST_HELP_STR_ZEBRA
617 "Daemon instance\n"
618 "Daemon instance\n"
619 "Session ID\n"
620 "Session ID\n"
621 "Number of messages to send\n")
622 {
623 uint32_t proto;
624
625 proto = proto_redistnum(AFI_IP, proto_str);
626
627 sharp_opaque_send(type, proto, instance, session, count);
628
629 return CMD_SUCCESS;
630 }
631
632 DEFPY (send_opaque_reg,
633 send_opaque_reg_cmd,
634 "sharp send opaque <reg$reg | unreg> \
635 " FRR_IP_REDIST_STR_ZEBRA "$proto_str \
636 [{instance (0-1000) | session (1-1000)}] type (1-1000)",
637 SHARP_STR
638 "Send messages for testing\n"
639 "Send opaque messages\n"
640 "Send opaque registration\n"
641 "Send opaque unregistration\n"
642 FRR_IP_REDIST_HELP_STR_ZEBRA
643 "Daemon instance\n"
644 "Daemon instance\n"
645 "Session ID\n"
646 "Session ID\n"
647 "Opaque sub-type code\n"
648 "Opaque sub-type code\n")
649 {
650 int proto;
651
652 proto = proto_redistnum(AFI_IP, proto_str);
653
654 sharp_opaque_reg_send((reg != NULL), proto, instance, session, type);
655 return CMD_SUCCESS;
656 }
657
658 DEFPY (neigh_discover,
659 neigh_discover_cmd,
660 "sharp neigh discover [vrf NAME$vrf_name] <A.B.C.D$dst4|X:X::X:X$dst6> IFNAME$ifname",
661 SHARP_STR
662 "Discover neighbours\n"
663 "Send an ARP/NDP request\n"
664 VRF_CMD_HELP_STR
665 "v4 Destination address\n"
666 "v6 Destination address\n"
667 "Interface name\n")
668 {
669 struct vrf *vrf;
670 struct interface *ifp;
671 struct prefix prefix;
672
673 memset(&prefix, 0, sizeof(prefix));
674
675 if (dst4.s_addr != INADDR_ANY) {
676 prefix.family = AF_INET;
677 prefix.prefixlen = 32;
678 prefix.u.prefix4 = dst4;
679 } else {
680 prefix.family = AF_INET6;
681 prefix.prefixlen = 128;
682 prefix.u.prefix6 = dst6;
683 }
684
685 vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
686 if (!vrf) {
687 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
688 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
689 return CMD_WARNING;
690 }
691
692 ifp = if_lookup_by_name_vrf(ifname, vrf);
693 if (ifp == NULL) {
694 vty_out(vty, "%% Can't find interface %s\n", ifname);
695 return CMD_WARNING;
696 }
697
698 sharp_zebra_send_arp(ifp, &prefix);
699
700 return CMD_SUCCESS;
701 }
702
703 void sharp_vty_init(void)
704 {
705 install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
706 install_element(ENABLE_NODE, &install_routes_cmd);
707 install_element(ENABLE_NODE, &remove_routes_cmd);
708 install_element(ENABLE_NODE, &vrf_label_cmd);
709 install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd);
710 install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
711 install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
712 install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd);
713 install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd);
714 install_element(ENABLE_NODE, &logpump_cmd);
715 install_element(ENABLE_NODE, &create_session_cmd);
716 install_element(ENABLE_NODE, &remove_session_cmd);
717 install_element(ENABLE_NODE, &send_opaque_cmd);
718 install_element(ENABLE_NODE, &send_opaque_unicast_cmd);
719 install_element(ENABLE_NODE, &send_opaque_reg_cmd);
720 install_element(ENABLE_NODE, &neigh_discover_cmd);
721
722 install_element(ENABLE_NODE, &show_debugging_sharpd_cmd);
723
724 return;
725 }