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