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