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