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