]> git.proxmox.com Git - mirror_frr.git/blob - sharpd/sharp_vty.c
tools: improve explanation of 'wrap' options
[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 "linklist.h"
33 #include "link_state.h"
34 #include "cspf.h"
35
36 #include "sharpd/sharp_globals.h"
37 #include "sharpd/sharp_zebra.h"
38 #include "sharpd/sharp_nht.h"
39 #include "sharpd/sharp_vty.h"
40 #ifndef VTYSH_EXTRACT_PL
41 #include "sharpd/sharp_vty_clippy.c"
42 #endif
43
44 DEFINE_MTYPE_STATIC(SHARPD, SRV6_LOCATOR, "SRv6 Locator");
45
46 DEFPY(watch_redistribute, watch_redistribute_cmd,
47 "sharp watch [vrf NAME$vrf_name] redistribute " FRR_REDIST_STR_SHARPD,
48 "Sharp routing Protocol\n"
49 "Watch for changes\n"
50 "The vrf we would like to watch if non-default\n"
51 "The NAME of the vrf\n"
52 "Redistribute into Sharp\n"
53 FRR_REDIST_HELP_STR_SHARPD)
54 {
55 struct vrf *vrf;
56 int source;
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 source = proto_redistnum(AFI_IP, argv[argc-1]->text);
68 sharp_redistribute_vrf(vrf, source);
69
70 return CMD_SUCCESS;
71 }
72
73 DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
74 "sharp watch [vrf NAME$vrf_name] <nexthop$n X:X::X:X$nhop|import$import X:X::X:X/M$inhop> [connected$connected]",
75 "Sharp routing Protocol\n"
76 "Watch for changes\n"
77 "The vrf we would like to watch if non-default\n"
78 "The NAME of the vrf\n"
79 "Watch for nexthop changes\n"
80 "The v6 nexthop to signal for watching\n"
81 "Watch for import check changes\n"
82 "The v6 prefix to signal for watching\n"
83 "Should the route be connected\n")
84 {
85 struct vrf *vrf;
86 struct prefix p;
87 bool type_import;
88
89 if (!vrf_name)
90 vrf_name = VRF_DEFAULT_NAME;
91 vrf = vrf_lookup_by_name(vrf_name);
92 if (!vrf) {
93 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
94 vrf_name);
95 return CMD_WARNING;
96 }
97
98 memset(&p, 0, sizeof(p));
99
100 if (n) {
101 type_import = false;
102 p.prefixlen = IPV6_MAX_BITLEN;
103 memcpy(&p.u.prefix6, &nhop, IPV6_MAX_BYTELEN);
104 p.family = AF_INET6;
105 } else {
106 type_import = true;
107 prefix_copy(&p, inhop);
108 }
109
110 sharp_nh_tracker_get(&p);
111 sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
112 true, !!connected);
113
114 return CMD_SUCCESS;
115 }
116
117 DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
118 "sharp watch [vrf NAME$vrf_name] <nexthop$n A.B.C.D$nhop|import$import A.B.C.D/M$inhop> [connected$connected]",
119 "Sharp routing Protocol\n"
120 "Watch for changes\n"
121 "The vrf we would like to watch if non-default\n"
122 "The NAME of the vrf\n"
123 "Watch for nexthop changes\n"
124 "The v4 address to signal for watching\n"
125 "Watch for import check changes\n"
126 "The v4 prefix for import check to watch\n"
127 "Should the route be connected\n")
128 {
129 struct vrf *vrf;
130 struct prefix p;
131 bool type_import;
132
133 if (!vrf_name)
134 vrf_name = VRF_DEFAULT_NAME;
135 vrf = vrf_lookup_by_name(vrf_name);
136 if (!vrf) {
137 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
138 vrf_name);
139 return CMD_WARNING;
140 }
141
142 memset(&p, 0, sizeof(p));
143
144 if (n) {
145 type_import = false;
146 p.prefixlen = IPV4_MAX_BITLEN;
147 p.u.prefix4 = nhop;
148 p.family = AF_INET;
149 }
150 else {
151 type_import = true;
152 prefix_copy(&p, inhop);
153 }
154
155 sharp_nh_tracker_get(&p);
156 sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
157 true, !!connected);
158
159 return CMD_SUCCESS;
160 }
161
162 DEFPY(sharp_nht_data_dump,
163 sharp_nht_data_dump_cmd,
164 "sharp data nexthop",
165 "Sharp routing Protocol\n"
166 "Data about what is going on\n"
167 "Nexthop information\n")
168 {
169 sharp_nh_tracker_dump(vty);
170
171 return CMD_SUCCESS;
172 }
173
174 DEFPY (install_routes_data_dump,
175 install_routes_data_dump_cmd,
176 "sharp data route",
177 "Sharp routing Protocol\n"
178 "Data about what is going on\n"
179 "Route Install/Removal Information\n")
180 {
181 struct timeval r;
182
183 timersub(&sg.r.t_end, &sg.r.t_start, &r);
184 vty_out(vty, "Prefix: %pFX Total: %u %u %u Time: %jd.%ld\n",
185 &sg.r.orig_prefix, sg.r.total_routes, sg.r.installed_routes,
186 sg.r.removed_routes, (intmax_t)r.tv_sec, (long)r.tv_usec);
187
188 return CMD_SUCCESS;
189 }
190
191 DEFPY (install_routes,
192 install_routes_cmd,
193 "sharp install routes [vrf NAME$vrf_name]\
194 <A.B.C.D$start4|X:X::X:X$start6>\
195 <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|\
196 nexthop-group NHGNAME$nexthop_group>\
197 [backup$backup <A.B.C.D$backup_nexthop4|X:X::X:X$backup_nexthop6>] \
198 (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt] [opaque WORD]",
199 "Sharp routing Protocol\n"
200 "install some routes\n"
201 "Routes to install\n"
202 "The vrf we would like to install into if non-default\n"
203 "The NAME of the vrf\n"
204 "v4 Address to start /32 generation at\n"
205 "v6 Address to start /32 generation at\n"
206 "Nexthop to use(Can be an IPv4 or IPv6 address)\n"
207 "V4 Nexthop address to use\n"
208 "V6 Nexthop address to use\n"
209 "Nexthop-Group to use\n"
210 "The Name of the nexthop-group\n"
211 "Backup nexthop to use(Can be an IPv4 or IPv6 address)\n"
212 "Backup V4 Nexthop address to use\n"
213 "Backup V6 Nexthop address to use\n"
214 "How many to create\n"
215 "Instance to use\n"
216 "Instance\n"
217 "Should we repeat this command\n"
218 "How many times to repeat this command\n"
219 "What opaque data to send down\n"
220 "The opaque data\n")
221 {
222 struct vrf *vrf;
223 struct prefix prefix;
224 uint32_t rts;
225 uint32_t nhgid = 0;
226
227 sg.r.total_routes = routes;
228 sg.r.installed_routes = 0;
229
230 if (rpt >= 2)
231 sg.r.repeat = rpt * 2;
232 else
233 sg.r.repeat = 0;
234
235 memset(&prefix, 0, sizeof(prefix));
236 memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
237 memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
238 memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
239 memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
240 memset(&sg.r.backup_nhop_group, 0, sizeof(sg.r.nhop_group));
241
242 if (start4.s_addr != INADDR_ANY) {
243 prefix.family = AF_INET;
244 prefix.prefixlen = IPV4_MAX_BITLEN;
245 prefix.u.prefix4 = start4;
246 } else {
247 prefix.family = AF_INET6;
248 prefix.prefixlen = IPV6_MAX_BITLEN;
249 prefix.u.prefix6 = start6;
250 }
251 sg.r.orig_prefix = prefix;
252
253 if (!vrf_name)
254 vrf_name = VRF_DEFAULT_NAME;
255
256 vrf = vrf_lookup_by_name(vrf_name);
257 if (!vrf) {
258 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
259 vrf_name);
260 return CMD_WARNING;
261 }
262
263 /* Explicit backup not available with named nexthop-group */
264 if (backup && nexthop_group) {
265 vty_out(vty, "%% Invalid: cannot specify both nexthop-group and backup\n");
266 return CMD_WARNING;
267 }
268
269 if (nexthop_group) {
270 struct nexthop_group_cmd *nhgc = nhgc_find(nexthop_group);
271 if (!nhgc) {
272 vty_out(vty,
273 "Specified Nexthop Group: %s does not exist\n",
274 nexthop_group);
275 return CMD_WARNING;
276 }
277
278 nhgid = sharp_nhgroup_get_id(nexthop_group);
279 sg.r.nhgid = nhgid;
280 sg.r.nhop_group.nexthop = nhgc->nhg.nexthop;
281
282 /* Use group's backup nexthop info if present */
283 if (nhgc->backup_list_name[0]) {
284 struct nexthop_group_cmd *bnhgc =
285 nhgc_find(nhgc->backup_list_name);
286
287 if (!bnhgc) {
288 vty_out(vty, "%% Backup group %s not found for group %s\n",
289 nhgc->backup_list_name,
290 nhgc->name);
291 return CMD_WARNING;
292 }
293
294 sg.r.backup_nhop.vrf_id = vrf->vrf_id;
295 sg.r.backup_nhop_group.nexthop = bnhgc->nhg.nexthop;
296 }
297 } else {
298 if (nexthop4.s_addr != INADDR_ANY) {
299 sg.r.nhop.gate.ipv4 = nexthop4;
300 sg.r.nhop.type = NEXTHOP_TYPE_IPV4;
301 } else {
302 sg.r.nhop.gate.ipv6 = nexthop6;
303 sg.r.nhop.type = NEXTHOP_TYPE_IPV6;
304 }
305
306 sg.r.nhop.vrf_id = vrf->vrf_id;
307 sg.r.nhop_group.nexthop = &sg.r.nhop;
308 }
309
310 /* Use single backup nexthop if specified */
311 if (backup) {
312 /* Set flag and index in primary nexthop */
313 SET_FLAG(sg.r.nhop.flags, NEXTHOP_FLAG_HAS_BACKUP);
314 sg.r.nhop.backup_num = 1;
315 sg.r.nhop.backup_idx[0] = 0;
316
317 if (backup_nexthop4.s_addr != INADDR_ANY) {
318 sg.r.backup_nhop.gate.ipv4 = backup_nexthop4;
319 sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV4;
320 } else {
321 sg.r.backup_nhop.gate.ipv6 = backup_nexthop6;
322 sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV6;
323 }
324
325 sg.r.backup_nhop.vrf_id = vrf->vrf_id;
326 sg.r.backup_nhop_group.nexthop = &sg.r.backup_nhop;
327 }
328
329 if (opaque)
330 strlcpy(sg.r.opaque, opaque, ZAPI_MESSAGE_OPAQUE_LENGTH);
331 else
332 sg.r.opaque[0] = '\0';
333
334 sg.r.inst = instance;
335 sg.r.vrf_id = vrf->vrf_id;
336 rts = routes;
337 sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst, nhgid,
338 &sg.r.nhop_group, &sg.r.backup_nhop_group,
339 rts, 0, sg.r.opaque);
340
341 return CMD_SUCCESS;
342 }
343
344 DEFPY (install_seg6_routes,
345 install_seg6_routes_cmd,
346 "sharp install seg6-routes [vrf NAME$vrf_name]\
347 <A.B.C.D$start4|X:X::X:X$start6>\
348 nexthop-seg6 X:X::X:X$seg6_nh6 encap X:X::X:X$seg6_seg\
349 (1-1000000)$routes [repeat (2-1000)$rpt]",
350 "Sharp routing Protocol\n"
351 "install some routes\n"
352 "Routes to install\n"
353 "The vrf we would like to install into if non-default\n"
354 "The NAME of the vrf\n"
355 "v4 Address to start /32 generation at\n"
356 "v6 Address to start /32 generation at\n"
357 "Nexthop-seg6 to use\n"
358 "V6 Nexthop address to use\n"
359 "Encap mode\n"
360 "Segment List to use\n"
361 "How many to create\n"
362 "Should we repeat this command\n"
363 "How many times to repeat this command\n")
364 {
365 struct vrf *vrf;
366 struct prefix prefix;
367 uint32_t route_flags = 0;
368
369 sg.r.total_routes = routes;
370 sg.r.installed_routes = 0;
371
372 if (rpt >= 2)
373 sg.r.repeat = rpt * 2;
374 else
375 sg.r.repeat = 0;
376
377 memset(&prefix, 0, sizeof(prefix));
378 memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
379 memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
380 memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
381 memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
382 memset(&sg.r.backup_nhop_group, 0, sizeof(sg.r.nhop_group));
383 sg.r.opaque[0] = '\0';
384 sg.r.inst = 0;
385
386 if (start4.s_addr != INADDR_ANY) {
387 prefix.family = AF_INET;
388 prefix.prefixlen = IPV4_MAX_BITLEN;
389 prefix.u.prefix4 = start4;
390 } else {
391 prefix.family = AF_INET6;
392 prefix.prefixlen = IPV6_MAX_BITLEN;
393 prefix.u.prefix6 = start6;
394 }
395 sg.r.orig_prefix = prefix;
396
397 if (!vrf_name)
398 vrf_name = VRF_DEFAULT_NAME;
399
400 vrf = vrf_lookup_by_name(vrf_name);
401 if (!vrf) {
402 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
403 vrf_name);
404 return CMD_WARNING;
405 }
406
407 sg.r.nhop.type = NEXTHOP_TYPE_IPV6;
408 sg.r.nhop.gate.ipv6 = seg6_nh6;
409 sg.r.nhop.vrf_id = vrf->vrf_id;
410 sg.r.nhop_group.nexthop = &sg.r.nhop;
411 nexthop_add_srv6_seg6(&sg.r.nhop, &seg6_seg);
412
413 sg.r.vrf_id = vrf->vrf_id;
414 sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst, 0,
415 &sg.r.nhop_group, &sg.r.backup_nhop_group,
416 routes, route_flags, sg.r.opaque);
417
418 return CMD_SUCCESS;
419 }
420
421 DEFPY (install_seg6local_routes,
422 install_seg6local_routes_cmd,
423 "sharp install seg6local-routes [vrf NAME$vrf_name]\
424 X:X::X:X$start6\
425 nexthop-seg6local NAME$seg6l_oif\
426 <End$seg6l_end|\
427 End_X$seg6l_endx X:X::X:X$seg6l_endx_nh6|\
428 End_T$seg6l_endt (1-4294967295)$seg6l_endt_table|\
429 End_DX4$seg6l_enddx4 A.B.C.D$seg6l_enddx4_nh4|\
430 End_DT6$seg6l_enddt6 (1-4294967295)$seg6l_enddt6_table|\
431 End_DT4$seg6l_enddt4 (1-4294967295)$seg6l_enddt4_table>\
432 (1-1000000)$routes [repeat (2-1000)$rpt]",
433 "Sharp routing Protocol\n"
434 "install some routes\n"
435 "Routes to install\n"
436 "The vrf we would like to install into if non-default\n"
437 "The NAME of the vrf\n"
438 "v6 Address to start /32 generation at\n"
439 "Nexthop-seg6local to use\n"
440 "Output device to use\n"
441 "SRv6 End function to use\n"
442 "SRv6 End.X function to use\n"
443 "V6 Nexthop address to use\n"
444 "SRv6 End.T function to use\n"
445 "Redirect table id to use\n"
446 "SRv6 End.DX4 function to use\n"
447 "V4 Nexthop address to use\n"
448 "SRv6 End.DT6 function to use\n"
449 "Redirect table id to use\n"
450 "SRv6 End.DT4 function to use\n"
451 "Redirect table id to use\n"
452 "How many to create\n"
453 "Should we repeat this command\n"
454 "How many times to repeat this command\n")
455 {
456 struct vrf *vrf;
457 uint32_t route_flags = 0;
458 struct seg6local_context ctx = {};
459 enum seg6local_action_t action;
460
461 sg.r.total_routes = routes;
462 sg.r.installed_routes = 0;
463
464 if (rpt >= 2)
465 sg.r.repeat = rpt * 2;
466 else
467 sg.r.repeat = 0;
468
469 memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
470 memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
471 memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
472 memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
473 memset(&sg.r.backup_nhop_group, 0, sizeof(sg.r.nhop_group));
474 sg.r.opaque[0] = '\0';
475 sg.r.inst = 0;
476 sg.r.orig_prefix.family = AF_INET6;
477 sg.r.orig_prefix.prefixlen = 128;
478 sg.r.orig_prefix.u.prefix6 = start6;
479
480 if (!vrf_name)
481 vrf_name = VRF_DEFAULT_NAME;
482
483 vrf = vrf_lookup_by_name(vrf_name);
484 if (!vrf) {
485 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
486 vrf_name);
487 return CMD_WARNING;
488 }
489
490 if (seg6l_enddx4) {
491 action = ZEBRA_SEG6_LOCAL_ACTION_END_DX4;
492 ctx.nh4 = seg6l_enddx4_nh4;
493 } else if (seg6l_endx) {
494 action = ZEBRA_SEG6_LOCAL_ACTION_END_X;
495 ctx.nh6 = seg6l_endx_nh6;
496 } else if (seg6l_endt) {
497 action = ZEBRA_SEG6_LOCAL_ACTION_END_T;
498 ctx.table = seg6l_endt_table;
499 } else if (seg6l_enddt6) {
500 action = ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
501 ctx.table = seg6l_enddt6_table;
502 } else if (seg6l_enddt4) {
503 action = ZEBRA_SEG6_LOCAL_ACTION_END_DT4;
504 ctx.table = seg6l_enddt4_table;
505 } else {
506 action = ZEBRA_SEG6_LOCAL_ACTION_END;
507 }
508
509 sg.r.nhop.type = NEXTHOP_TYPE_IFINDEX;
510 sg.r.nhop.ifindex = ifname2ifindex(seg6l_oif, vrf->vrf_id);
511 sg.r.nhop.vrf_id = vrf->vrf_id;
512 sg.r.nhop_group.nexthop = &sg.r.nhop;
513 nexthop_add_srv6_seg6local(&sg.r.nhop, action, &ctx);
514
515 sg.r.vrf_id = vrf->vrf_id;
516 sharp_install_routes_helper(&sg.r.orig_prefix, sg.r.vrf_id, sg.r.inst,
517 0, &sg.r.nhop_group,
518 &sg.r.backup_nhop_group, routes,
519 route_flags, sg.r.opaque);
520
521 return CMD_SUCCESS;
522 }
523
524 DEFPY(vrf_label, vrf_label_cmd,
525 "sharp label <ip$ipv4|ipv6$ipv6> vrf NAME$vrf_name label (0-100000)$label",
526 "Sharp Routing Protocol\n"
527 "Give a vrf a label\n"
528 "Pop and forward for IPv4\n"
529 "Pop and forward for IPv6\n"
530 VRF_CMD_HELP_STR
531 "The label to use, 0 specifies remove the label installed from previous\n"
532 "Specified range to use\n")
533 {
534 struct vrf *vrf;
535 afi_t afi = (ipv4) ? AFI_IP : AFI_IP6;
536
537 if (strcmp(vrf_name, "default") == 0)
538 vrf = vrf_lookup_by_id(VRF_DEFAULT);
539 else
540 vrf = vrf_lookup_by_name(vrf_name);
541
542 if (!vrf) {
543 vty_out(vty, "Unable to find vrf you silly head\n");
544 return CMD_WARNING_CONFIG_FAILED;
545 }
546
547 if (label == 0)
548 label = MPLS_LABEL_NONE;
549
550 vrf_label_add(vrf->vrf_id, afi, label);
551 return CMD_SUCCESS;
552 }
553
554 DEFPY (remove_routes,
555 remove_routes_cmd,
556 "sharp remove routes [vrf NAME$vrf_name] <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]",
557 "Sharp Routing Protocol\n"
558 "Remove some routes\n"
559 "Routes to remove\n"
560 "The vrf we would like to remove from if non-default\n"
561 "The NAME of the vrf\n"
562 "v4 Starting spot\n"
563 "v6 Starting spot\n"
564 "Routes to uninstall\n"
565 "instance to use\n"
566 "Value of instance\n")
567 {
568 struct vrf *vrf;
569 struct prefix prefix;
570
571 sg.r.total_routes = routes;
572 sg.r.removed_routes = 0;
573 uint32_t rts;
574
575 memset(&prefix, 0, sizeof(prefix));
576
577 if (start4.s_addr != INADDR_ANY) {
578 prefix.family = AF_INET;
579 prefix.prefixlen = IPV4_MAX_BITLEN;
580 prefix.u.prefix4 = start4;
581 } else {
582 prefix.family = AF_INET6;
583 prefix.prefixlen = IPV6_MAX_BITLEN;
584 prefix.u.prefix6 = start6;
585 }
586
587 vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
588 if (!vrf) {
589 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
590 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
591 return CMD_WARNING;
592 }
593
594 sg.r.inst = instance;
595 sg.r.vrf_id = vrf->vrf_id;
596 rts = routes;
597 sharp_remove_routes_helper(&prefix, sg.r.vrf_id,
598 sg.r.inst, rts);
599
600 return CMD_SUCCESS;
601 }
602
603 DEFUN_NOSH (show_debugging_sharpd,
604 show_debugging_sharpd_cmd,
605 "show debugging [sharp]",
606 SHOW_STR
607 DEBUG_STR
608 "Sharp Information\n")
609 {
610 vty_out(vty, "Sharp debugging status:\n");
611
612 return CMD_SUCCESS;
613 }
614
615 DEFPY (sharp_lsp_prefix_v4, sharp_lsp_prefix_v4_cmd,
616 "sharp lsp [update]$update (0-100000)$inlabel\
617 nexthop-group NHGNAME$nhgname\
618 [prefix A.B.C.D/M$pfx\
619 " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]",
620 "Sharp Routing Protocol\n"
621 "Add an LSP\n"
622 "Update an LSP\n"
623 "The ingress label to use\n"
624 "Use nexthops from a nexthop-group\n"
625 "The nexthop-group name\n"
626 "Label a prefix\n"
627 "The v4 prefix to label\n"
628 FRR_IP_REDIST_HELP_STR_ZEBRA
629 "Instance to use\n"
630 "Instance\n")
631 {
632 struct nexthop_group_cmd *nhgc = NULL;
633 struct nexthop_group_cmd *backup_nhgc = NULL;
634 struct nexthop_group *backup_nhg = NULL;
635 struct prefix p = {};
636 int type = 0;
637 bool update_p;
638
639 update_p = (update != NULL);
640
641 /* We're offered a v4 prefix */
642 if (pfx->family > 0 && type_str) {
643 p.family = pfx->family;
644 p.prefixlen = pfx->prefixlen;
645 p.u.prefix4 = pfx->prefix;
646
647 type = proto_redistnum(AFI_IP, type_str);
648 if (type < 0) {
649 vty_out(vty, "%% Unknown route type '%s'\n", type_str);
650 return CMD_WARNING;
651 }
652 } else if (pfx->family > 0 || type_str) {
653 vty_out(vty, "%% Must supply both prefix and type\n");
654 return CMD_WARNING;
655 }
656
657 nhgc = nhgc_find(nhgname);
658 if (!nhgc) {
659 vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
660 nhgname);
661 return CMD_WARNING;
662 }
663
664 if (nhgc->nhg.nexthop == NULL) {
665 vty_out(vty, "%% Nexthop-group '%s' is empty\n", nhgname);
666 return CMD_WARNING;
667 }
668
669 /* Use group's backup nexthop info if present */
670 if (nhgc->backup_list_name[0]) {
671 backup_nhgc = nhgc_find(nhgc->backup_list_name);
672
673 if (!backup_nhgc) {
674 vty_out(vty,
675 "%% Backup group %s not found for group %s\n",
676 nhgc->backup_list_name,
677 nhgname);
678 return CMD_WARNING;
679 }
680 backup_nhg = &(backup_nhgc->nhg);
681 }
682
683 if (sharp_install_lsps_helper(true /*install*/, update_p,
684 pfx->family > 0 ? &p : NULL,
685 type, instance, inlabel,
686 &(nhgc->nhg), backup_nhg) == 0)
687 return CMD_SUCCESS;
688 else {
689 vty_out(vty, "%% LSP install failed!\n");
690 return CMD_WARNING;
691 }
692 }
693
694 DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd,
695 "sharp remove lsp \
696 (0-100000)$inlabel\
697 [nexthop-group NHGNAME$nhgname] \
698 [prefix A.B.C.D/M$pfx\
699 " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]",
700 "Sharp Routing Protocol\n"
701 "Remove data\n"
702 "Remove an LSP\n"
703 "The ingress label\n"
704 "Use nexthops from a nexthop-group\n"
705 "The nexthop-group name\n"
706 "Specify a v4 prefix\n"
707 "The v4 prefix to label\n"
708 FRR_IP_REDIST_HELP_STR_ZEBRA
709 "Routing instance\n"
710 "Instance to use\n")
711 {
712 struct nexthop_group_cmd *nhgc = NULL;
713 struct prefix p = {};
714 int type = 0;
715 struct nexthop_group *nhg = NULL;
716
717 /* We're offered a v4 prefix */
718 if (pfx->family > 0 && type_str) {
719 p.family = pfx->family;
720 p.prefixlen = pfx->prefixlen;
721 p.u.prefix4 = pfx->prefix;
722
723 type = proto_redistnum(AFI_IP, type_str);
724 if (type < 0) {
725 vty_out(vty, "%% Unknown route type '%s'\n", type_str);
726 return CMD_WARNING;
727 }
728 } else if (pfx->family > 0 || type_str) {
729 vty_out(vty, "%% Must supply both prefix and type\n");
730 return CMD_WARNING;
731 }
732
733 if (nhgname) {
734 nhgc = nhgc_find(nhgname);
735 if (!nhgc) {
736 vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
737 nhgname);
738 return CMD_WARNING;
739 }
740
741 if (nhgc->nhg.nexthop == NULL) {
742 vty_out(vty, "%% Nexthop-group '%s' is empty\n",
743 nhgname);
744 return CMD_WARNING;
745 }
746 nhg = &(nhgc->nhg);
747 }
748
749 if (sharp_install_lsps_helper(false /*!install*/, false,
750 pfx->family > 0 ? &p : NULL,
751 type, instance, inlabel, nhg, NULL) == 0)
752 return CMD_SUCCESS;
753 else {
754 vty_out(vty, "%% LSP remove failed!\n");
755 return CMD_WARNING;
756 }
757 }
758
759 DEFPY (logpump,
760 logpump_cmd,
761 "sharp logpump duration (1-60) frequency (1-1000000) burst (1-1000)",
762 "Sharp Routing Protocol\n"
763 "Generate bulk log messages for testing\n"
764 "Duration of run (s)\n"
765 "Duration of run (s)\n"
766 "Frequency of bursts (s^-1)\n"
767 "Frequency of bursts (s^-1)\n"
768 "Number of log messages per each burst\n"
769 "Number of log messages per each burst\n")
770 {
771 sharp_logpump_run(vty, duration, frequency, burst);
772 return CMD_SUCCESS;
773 }
774
775 DEFPY (create_session,
776 create_session_cmd,
777 "sharp create session (1-1024)",
778 "Sharp Routing Protocol\n"
779 "Create data\n"
780 "Create a test session\n"
781 "Session ID\n")
782 {
783 if (sharp_zclient_create(session) != 0) {
784 vty_out(vty, "%% Client session error\n");
785 return CMD_WARNING;
786 }
787
788 return CMD_SUCCESS;
789 }
790
791 DEFPY (remove_session,
792 remove_session_cmd,
793 "sharp remove session (1-1024)",
794 "Sharp Routing Protocol\n"
795 "Remove data\n"
796 "Remove a test session\n"
797 "Session ID\n")
798 {
799 sharp_zclient_delete(session);
800 return CMD_SUCCESS;
801 }
802
803 DEFPY (send_opaque,
804 send_opaque_cmd,
805 "sharp send opaque type (1-255) (1-1000)$count",
806 SHARP_STR
807 "Send messages for testing\n"
808 "Send opaque messages\n"
809 "Type code to send\n"
810 "Type code to send\n"
811 "Number of messages to send\n")
812 {
813 sharp_opaque_send(type, 0, 0, 0, count);
814 return CMD_SUCCESS;
815 }
816
817 DEFPY (send_opaque_unicast,
818 send_opaque_unicast_cmd,
819 "sharp send opaque unicast type (1-255) \
820 " FRR_IP_REDIST_STR_ZEBRA "$proto_str \
821 [{instance (0-1000) | session (1-1000)}] (1-1000)$count",
822 SHARP_STR
823 "Send messages for testing\n"
824 "Send opaque messages\n"
825 "Send unicast messages\n"
826 "Type code to send\n"
827 "Type code to send\n"
828 FRR_IP_REDIST_HELP_STR_ZEBRA
829 "Daemon instance\n"
830 "Daemon instance\n"
831 "Session ID\n"
832 "Session ID\n"
833 "Number of messages to send\n")
834 {
835 uint32_t proto;
836
837 proto = proto_redistnum(AFI_IP, proto_str);
838
839 sharp_opaque_send(type, proto, instance, session, count);
840
841 return CMD_SUCCESS;
842 }
843
844 DEFPY (send_opaque_reg,
845 send_opaque_reg_cmd,
846 "sharp send opaque <reg$reg | unreg> \
847 " FRR_IP_REDIST_STR_ZEBRA "$proto_str \
848 [{instance (0-1000) | session (1-1000)}] type (1-1000)",
849 SHARP_STR
850 "Send messages for testing\n"
851 "Send opaque messages\n"
852 "Send opaque registration\n"
853 "Send opaque unregistration\n"
854 FRR_IP_REDIST_HELP_STR_ZEBRA
855 "Daemon instance\n"
856 "Daemon instance\n"
857 "Session ID\n"
858 "Session ID\n"
859 "Opaque sub-type code\n"
860 "Opaque sub-type code\n")
861 {
862 int proto;
863
864 proto = proto_redistnum(AFI_IP, proto_str);
865
866 sharp_opaque_reg_send((reg != NULL), proto, instance, session, type);
867 return CMD_SUCCESS;
868 }
869
870 DEFPY (neigh_discover,
871 neigh_discover_cmd,
872 "sharp neigh discover [vrf NAME$vrf_name] <A.B.C.D$dst4|X:X::X:X$dst6> IFNAME$ifname",
873 SHARP_STR
874 "Discover neighbours\n"
875 "Send an ARP/NDP request\n"
876 VRF_CMD_HELP_STR
877 "v4 Destination address\n"
878 "v6 Destination address\n"
879 "Interface name\n")
880 {
881 struct vrf *vrf;
882 struct interface *ifp;
883 struct prefix prefix;
884
885 memset(&prefix, 0, sizeof(prefix));
886
887 if (dst4.s_addr != INADDR_ANY) {
888 prefix.family = AF_INET;
889 prefix.prefixlen = IPV4_MAX_BITLEN;
890 prefix.u.prefix4 = dst4;
891 } else {
892 prefix.family = AF_INET6;
893 prefix.prefixlen = 128;
894 prefix.u.prefix6 = dst6;
895 }
896
897 vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
898 if (!vrf) {
899 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
900 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
901 return CMD_WARNING;
902 }
903
904 ifp = if_lookup_by_name_vrf(ifname, vrf);
905 if (ifp == NULL) {
906 vty_out(vty, "%% Can't find interface %s\n", ifname);
907 return CMD_WARNING;
908 }
909
910 sharp_zebra_send_arp(ifp, &prefix);
911
912 return CMD_SUCCESS;
913 }
914
915 DEFPY (import_te,
916 import_te_cmd,
917 "sharp import-te",
918 SHARP_STR
919 "Import Traffic Engineering\n")
920 {
921 sg.ted = ls_ted_new(1, "Sharp", 0);
922 sharp_zebra_register_te();
923
924 return CMD_SUCCESS;
925 }
926
927 DEFPY (sharp_srv6_manager_get_locator_chunk,
928 sharp_srv6_manager_get_locator_chunk_cmd,
929 "sharp srv6-manager get-locator-chunk NAME$locator_name",
930 SHARP_STR
931 "Segment-Routing IPv6\n"
932 "Get SRv6 locator-chunk\n"
933 "SRv6 Locator name\n")
934 {
935 int ret;
936 struct listnode *node;
937 struct sharp_srv6_locator *loc;
938 struct sharp_srv6_locator *loc_found = NULL;
939
940 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, node, loc)) {
941 if (strcmp(loc->name, locator_name))
942 continue;
943 loc_found = loc;
944 break;
945 }
946 if (!loc_found) {
947 loc = XCALLOC(MTYPE_SRV6_LOCATOR,
948 sizeof(struct sharp_srv6_locator));
949 loc->chunks = list_new();
950 snprintf(loc->name, SRV6_LOCNAME_SIZE, "%s", locator_name);
951 listnode_add(sg.srv6_locators, loc);
952 }
953
954 ret = sharp_zebra_srv6_manager_get_locator_chunk(locator_name);
955 if (ret < 0)
956 return CMD_WARNING_CONFIG_FAILED;
957
958 return CMD_SUCCESS;
959 }
960
961 DEFUN (show_sharp_ted,
962 show_sharp_ted_cmd,
963 "show sharp ted [<vertex [A.B.C.D]|edge [A.B.C.D]|subnet [A.B.C.D/M]>] [verbose|json]",
964 SHOW_STR
965 SHARP_STR
966 "Traffic Engineering Database\n"
967 "MPLS-TE Vertex\n"
968 "MPLS-TE router ID (as an IP address)\n"
969 "MPLS-TE Edge\n"
970 "MPLS-TE Edge ID (as an IP address)\n"
971 "MPLS-TE Subnet\n"
972 "MPLS-TE Subnet ID (as an IP prefix)\n"
973 "Verbose output\n"
974 JSON_STR)
975 {
976 int idx = 0;
977 struct in_addr ip_addr;
978 struct prefix pref;
979 struct ls_vertex *vertex;
980 struct ls_edge *edge;
981 struct ls_subnet *subnet;
982 uint64_t key;
983 bool verbose = false;
984 bool uj = use_json(argc, argv);
985 json_object *json = NULL;
986
987 if (sg.ted == NULL) {
988 vty_out(vty, "MPLS-TE import is not enabled\n");
989 return CMD_WARNING;
990 }
991
992 if (uj)
993 json = json_object_new_object();
994
995 if (argv[argc - 1]->arg && strmatch(argv[argc - 1]->text, "verbose"))
996 verbose = true;
997
998 if (argv_find(argv, argc, "vertex", &idx)) {
999 /* Show Vertex */
1000 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
1001 if (!inet_aton(argv[idx + 1]->arg, &ip_addr)) {
1002 vty_out(vty,
1003 "Specified Router ID %s is invalid\n",
1004 argv[idx + 1]->arg);
1005 return CMD_WARNING_CONFIG_FAILED;
1006 }
1007 /* Get the Vertex from the Link State Database */
1008 key = ((uint64_t)ip_addr.s_addr) & 0xffffffff;
1009 vertex = ls_find_vertex_by_key(sg.ted, key);
1010 if (!vertex) {
1011 vty_out(vty, "No vertex found for ID %pI4\n",
1012 &ip_addr);
1013 return CMD_WARNING;
1014 }
1015 } else
1016 vertex = NULL;
1017
1018 if (vertex)
1019 ls_show_vertex(vertex, vty, json, verbose);
1020 else
1021 ls_show_vertices(sg.ted, vty, json, verbose);
1022
1023 } else if (argv_find(argv, argc, "edge", &idx)) {
1024 /* Show Edge */
1025 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
1026 if (!inet_aton(argv[idx]->arg, &ip_addr)) {
1027 vty_out(vty,
1028 "Specified Edge ID %s is invalid\n",
1029 argv[idx]->arg);
1030 return CMD_WARNING_CONFIG_FAILED;
1031 }
1032 /* Get the Edge from the Link State Database */
1033 key = ((uint64_t)ip_addr.s_addr) & 0xffffffff;
1034 edge = ls_find_edge_by_key(sg.ted, key);
1035 if (!edge) {
1036 vty_out(vty, "No edge found for ID %pI4\n",
1037 &ip_addr);
1038 return CMD_WARNING;
1039 }
1040 } else
1041 edge = NULL;
1042
1043 if (edge)
1044 ls_show_edge(edge, vty, json, verbose);
1045 else
1046 ls_show_edges(sg.ted, vty, json, verbose);
1047
1048 } else if (argv_find(argv, argc, "subnet", &idx)) {
1049 /* Show Subnet */
1050 if (argv_find(argv, argc, "A.B.C.D/M", &idx)) {
1051 if (!str2prefix(argv[idx]->arg, &pref)) {
1052 vty_out(vty, "Invalid prefix format %s\n",
1053 argv[idx]->arg);
1054 return CMD_WARNING_CONFIG_FAILED;
1055 }
1056 /* Get the Subnet from the Link State Database */
1057 subnet = ls_find_subnet(sg.ted, pref);
1058 if (!subnet) {
1059 vty_out(vty, "No subnet found for ID %pFX\n",
1060 &pref);
1061 return CMD_WARNING;
1062 }
1063 } else
1064 subnet = NULL;
1065
1066 if (subnet)
1067 ls_show_subnet(subnet, vty, json, verbose);
1068 else
1069 ls_show_subnets(sg.ted, vty, json, verbose);
1070
1071 } else {
1072 /* Show the complete TED */
1073 ls_show_ted(sg.ted, vty, json, verbose);
1074 }
1075
1076 if (uj)
1077 vty_json(vty, json);
1078
1079 return CMD_SUCCESS;
1080 }
1081
1082 DEFPY (sharp_srv6_manager_release_locator_chunk,
1083 sharp_srv6_manager_release_locator_chunk_cmd,
1084 "sharp srv6-manager release-locator-chunk NAME$locator_name",
1085 SHARP_STR
1086 "Segment-Routing IPv6\n"
1087 "Release SRv6 locator-chunk\n"
1088 "SRv6 Locator name\n")
1089 {
1090 int ret;
1091 struct listnode *loc_node;
1092 struct sharp_srv6_locator *loc;
1093
1094 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, loc_node, loc)) {
1095 if (!strcmp(loc->name, locator_name)) {
1096 list_delete_all_node(loc->chunks);
1097 list_delete(&loc->chunks);
1098 listnode_delete(sg.srv6_locators, loc);
1099 break;
1100 }
1101 }
1102
1103 ret = sharp_zebra_srv6_manager_release_locator_chunk(locator_name);
1104 if (ret < 0)
1105 return CMD_WARNING_CONFIG_FAILED;
1106
1107 return CMD_SUCCESS;
1108 }
1109
1110 DEFPY (show_sharp_segment_routing_srv6,
1111 show_sharp_segment_routing_srv6_cmd,
1112 "show sharp segment-routing srv6 [json]",
1113 SHOW_STR
1114 SHARP_STR
1115 "Segment-Routing\n"
1116 "Segment-Routing IPv6\n"
1117 JSON_STR)
1118 {
1119 char str[256];
1120 struct listnode *loc_node;
1121 struct listnode *chunk_node;
1122 struct sharp_srv6_locator *loc;
1123 struct prefix_ipv6 *chunk;
1124 bool uj = use_json(argc, argv);
1125 json_object *jo_locs = NULL;
1126 json_object *jo_loc = NULL;
1127 json_object *jo_chunks = NULL;
1128
1129 if (uj) {
1130 jo_locs = json_object_new_array();
1131 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, loc_node, loc)) {
1132 jo_loc = json_object_new_object();
1133 json_object_array_add(jo_locs, jo_loc);
1134 json_object_string_add(jo_loc, "name", loc->name);
1135 jo_chunks = json_object_new_array();
1136 json_object_object_add(jo_loc, "chunks", jo_chunks);
1137 for (ALL_LIST_ELEMENTS_RO(loc->chunks, chunk_node,
1138 chunk)) {
1139 prefix2str(chunk, str, sizeof(str));
1140 json_array_string_add(jo_chunks, str);
1141 }
1142 }
1143
1144 vty_json(vty, jo_locs);
1145 } else {
1146 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, loc_node, loc)) {
1147 vty_out(vty, "Locator %s has %d prefix chunks\n",
1148 loc->name, listcount(loc->chunks));
1149 for (ALL_LIST_ELEMENTS_RO(loc->chunks, chunk_node,
1150 chunk)) {
1151 prefix2str(chunk, str, sizeof(str));
1152 vty_out(vty, " %s\n", str);
1153 }
1154 vty_out(vty, "\n");
1155 }
1156 }
1157
1158 return CMD_SUCCESS;
1159 }
1160
1161 DEFPY (show_sharp_cspf,
1162 show_sharp_cspf_cmd,
1163 "show sharp cspf source <A.B.C.D$src4|X:X::X:X$src6> \
1164 destination <A.B.C.D$dst4|X:X::X:X$dst6> \
1165 <metric|te-metric|delay> (0-16777215)$cost \
1166 [rsv-bw (0-7)$cos BANDWIDTH$bw]",
1167 SHOW_STR
1168 SHARP_STR
1169 "Constraint Shortest Path First path computation\n"
1170 "Source of the path\n"
1171 "IPv4 Source address in dot decimal A.B.C.D\n"
1172 "IPv6 Source address as X:X:X:X\n"
1173 "Destination of the path\n"
1174 "IPv4 Destination address in dot decimal A.B.C.D\n"
1175 "IPv6 Destination address as X:X:X:X\n"
1176 "Maximum Metric\n"
1177 "Maximum TE Metric\n"
1178 "Maxim Delay\n"
1179 "Value of Maximum cost\n"
1180 "Reserved Bandwidth of this path\n"
1181 "Class of Service or Priority level\n"
1182 "Bytes/second (IEEE floating point format)\n")
1183 {
1184
1185 struct cspf *algo;
1186 struct constraints csts;
1187 struct c_path *path;
1188 struct listnode *node;
1189 struct ls_edge *edge;
1190 int idx;
1191
1192 if (sg.ted == NULL) {
1193 vty_out(vty, "MPLS-TE import is not enabled\n");
1194 return CMD_WARNING;
1195 }
1196
1197 if ((src4.s_addr != INADDR_ANY && dst4.s_addr == INADDR_ANY) ||
1198 (src4.s_addr == INADDR_ANY && dst4.s_addr != INADDR_ANY)) {
1199 vty_out(vty, "Don't mix IPv4 and IPv6 addresses\n");
1200 return CMD_WARNING;
1201 }
1202
1203 idx = 6;
1204 memset(&csts, 0, sizeof(struct constraints));
1205 if (argv_find(argv, argc, "metric", &idx)) {
1206 csts.ctype = CSPF_METRIC;
1207 csts.cost = cost;
1208 }
1209 idx = 6;
1210 if (argv_find(argv, argc, "te-metric", &idx)) {
1211 csts.ctype = CSPF_TE_METRIC;
1212 csts.cost = cost;
1213 }
1214 idx = 6;
1215 if (argv_find(argv, argc, "delay", &idx)) {
1216 csts.ctype = CSPF_DELAY;
1217 csts.cost = cost;
1218 }
1219 if (argc > 9) {
1220 if (sscanf(bw, "%g", &csts.bw) != 1) {
1221 vty_out(vty, "Bandwidth constraints: fscanf: %s\n",
1222 safe_strerror(errno));
1223 return CMD_WARNING_CONFIG_FAILED;
1224 }
1225 csts.cos = cos;
1226 }
1227
1228 /* Initialize and call point-to-point Path computation */
1229 if (src4.s_addr != INADDR_ANY)
1230 algo = cspf_init_v4(NULL, sg.ted, src4, dst4, &csts);
1231 else
1232 algo = cspf_init_v6(NULL, sg.ted, src6, dst6, &csts);
1233 path = compute_p2p_path(algo, sg.ted);
1234 cspf_del(algo);
1235
1236 if (!path) {
1237 vty_out(vty, "Path computation failed without error\n");
1238 return CMD_SUCCESS;
1239 }
1240 if (path->status != SUCCESS) {
1241 vty_out(vty, "Path computation failed: %d\n", path->status);
1242 return CMD_SUCCESS;
1243 }
1244
1245 vty_out(vty, "Path computation success\n");
1246 vty_out(vty, "\tCost: %d\n", path->weight);
1247 vty_out(vty, "\tEdges:");
1248 for (ALL_LIST_ELEMENTS_RO(path->edges, node, edge)) {
1249 if (src4.s_addr != INADDR_ANY)
1250 vty_out(vty, " %pI4",
1251 &edge->attributes->standard.remote);
1252 else
1253 vty_out(vty, " %pI6",
1254 &edge->attributes->standard.remote6);
1255 }
1256 vty_out(vty, "\n");
1257
1258 return CMD_SUCCESS;
1259 }
1260
1261 static struct interface *if_lookup_vrf_all(const char *ifname)
1262 {
1263 struct interface *ifp;
1264 struct vrf *vrf;
1265
1266 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
1267 ifp = if_lookup_by_name(ifname, vrf->vrf_id);
1268 if (ifp)
1269 return ifp;
1270 }
1271
1272 return NULL;
1273 }
1274
1275 DEFPY (sharp_interface_protodown,
1276 sharp_interface_protodown_cmd,
1277 "sharp interface IFNAME$ifname protodown",
1278 SHARP_STR
1279 INTERFACE_STR
1280 IFNAME_STR
1281 "Set interface protodown\n")
1282 {
1283 struct interface *ifp;
1284
1285 ifp = if_lookup_vrf_all(ifname);
1286
1287 if (!ifp) {
1288 vty_out(vty, "%% Can't find interface %s\n", ifname);
1289 return CMD_WARNING;
1290 }
1291
1292 if (sharp_zebra_send_interface_protodown(ifp, true) != 0)
1293 return CMD_WARNING;
1294
1295 return CMD_SUCCESS;
1296 }
1297
1298 DEFPY (no_sharp_interface_protodown,
1299 no_sharp_interface_protodown_cmd,
1300 "no sharp interface IFNAME$ifname protodown",
1301 NO_STR
1302 SHARP_STR
1303 INTERFACE_STR
1304 IFNAME_STR
1305 "Set interface protodown\n")
1306 {
1307 struct interface *ifp;
1308
1309 ifp = if_lookup_vrf_all(ifname);
1310
1311 if (!ifp) {
1312 vty_out(vty, "%% Can't find interface %s\n", ifname);
1313 return CMD_WARNING;
1314 }
1315
1316 if (sharp_zebra_send_interface_protodown(ifp, false) != 0)
1317 return CMD_WARNING;
1318
1319 return CMD_SUCCESS;
1320 }
1321
1322 void sharp_vty_init(void)
1323 {
1324 install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
1325 install_element(ENABLE_NODE, &install_routes_cmd);
1326 install_element(ENABLE_NODE, &install_seg6_routes_cmd);
1327 install_element(ENABLE_NODE, &install_seg6local_routes_cmd);
1328 install_element(ENABLE_NODE, &remove_routes_cmd);
1329 install_element(ENABLE_NODE, &vrf_label_cmd);
1330 install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd);
1331 install_element(ENABLE_NODE, &watch_redistribute_cmd);
1332 install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
1333 install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
1334 install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd);
1335 install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd);
1336 install_element(ENABLE_NODE, &logpump_cmd);
1337 install_element(ENABLE_NODE, &create_session_cmd);
1338 install_element(ENABLE_NODE, &remove_session_cmd);
1339 install_element(ENABLE_NODE, &send_opaque_cmd);
1340 install_element(ENABLE_NODE, &send_opaque_unicast_cmd);
1341 install_element(ENABLE_NODE, &send_opaque_reg_cmd);
1342 install_element(ENABLE_NODE, &neigh_discover_cmd);
1343 install_element(ENABLE_NODE, &import_te_cmd);
1344
1345 install_element(ENABLE_NODE, &show_debugging_sharpd_cmd);
1346 install_element(ENABLE_NODE, &show_sharp_ted_cmd);
1347 install_element(ENABLE_NODE, &show_sharp_cspf_cmd);
1348
1349 install_element(ENABLE_NODE, &sharp_srv6_manager_get_locator_chunk_cmd);
1350 install_element(ENABLE_NODE,
1351 &sharp_srv6_manager_release_locator_chunk_cmd);
1352 install_element(ENABLE_NODE, &show_sharp_segment_routing_srv6_cmd);
1353
1354 install_element(ENABLE_NODE, &sharp_interface_protodown_cmd);
1355 install_element(ENABLE_NODE, &no_sharp_interface_protodown_cmd);
1356
1357 return;
1358 }