]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_cmd.c
Merge pull request #9682 from adrianomarto/mesh-group-fix
[mirror_frr.git] / pimd / pim_cmd.c
1 /*
2 * PIM for Quagga
3 * Copyright (C) 2008 Everton da Silva Marques
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include <zebra.h>
21
22 #include "lib/json.h"
23 #include "command.h"
24 #include "if.h"
25 #include "prefix.h"
26 #include "zclient.h"
27 #include "plist.h"
28 #include "hash.h"
29 #include "nexthop.h"
30 #include "vrf.h"
31 #include "ferr.h"
32
33 #include "pimd.h"
34 #include "pim_mroute.h"
35 #include "pim_cmd.h"
36 #include "pim_iface.h"
37 #include "pim_vty.h"
38 #include "pim_mroute.h"
39 #include "pim_str.h"
40 #include "pim_igmp.h"
41 #include "pim_igmpv3.h"
42 #include "pim_sock.h"
43 #include "pim_time.h"
44 #include "pim_util.h"
45 #include "pim_oil.h"
46 #include "pim_neighbor.h"
47 #include "pim_pim.h"
48 #include "pim_ifchannel.h"
49 #include "pim_hello.h"
50 #include "pim_msg.h"
51 #include "pim_upstream.h"
52 #include "pim_rpf.h"
53 #include "pim_macro.h"
54 #include "pim_ssmpingd.h"
55 #include "pim_zebra.h"
56 #include "pim_static.h"
57 #include "pim_rp.h"
58 #include "pim_zlookup.h"
59 #include "pim_msdp.h"
60 #include "pim_ssm.h"
61 #include "pim_nht.h"
62 #include "pim_bfd.h"
63 #include "pim_vxlan.h"
64 #include "pim_mlag.h"
65 #include "bfd.h"
66 #include "pim_bsm.h"
67 #include "lib/northbound_cli.h"
68 #include "pim_errors.h"
69 #include "pim_nb.h"
70
71 #ifndef VTYSH_EXTRACT_PL
72 #include "pimd/pim_cmd_clippy.c"
73 #endif
74
75 static struct cmd_node debug_node = {
76 .name = "debug",
77 .node = DEBUG_NODE,
78 .prompt = "",
79 .config_write = pim_debug_config_write,
80 };
81
82 static struct vrf *pim_cmd_lookup_vrf(struct vty *vty, struct cmd_token *argv[],
83 const int argc, int *idx)
84 {
85 struct vrf *vrf;
86
87 if (argv_find(argv, argc, "NAME", idx))
88 vrf = vrf_lookup_by_name(argv[*idx]->arg);
89 else
90 vrf = vrf_lookup_by_id(VRF_DEFAULT);
91
92 if (!vrf)
93 vty_out(vty, "Specified VRF: %s does not exist\n",
94 argv[*idx]->arg);
95
96 return vrf;
97 }
98
99 static void pim_show_assert_helper(struct vty *vty,
100 struct pim_interface *pim_ifp,
101 struct pim_ifchannel *ch, time_t now)
102 {
103 char ch_src_str[INET_ADDRSTRLEN];
104 char ch_grp_str[INET_ADDRSTRLEN];
105 char winner_str[INET_ADDRSTRLEN];
106 struct in_addr ifaddr;
107 char uptime[10];
108 char timer[10];
109 char buf[PREFIX_STRLEN];
110
111 ifaddr = pim_ifp->primary_address;
112
113 pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str));
114 pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str));
115 pim_inet4_dump("<assrt_win?>", ch->ifassert_winner, winner_str,
116 sizeof(winner_str));
117
118 pim_time_uptime(uptime, sizeof(uptime), now - ch->ifassert_creation);
119 pim_time_timer_to_mmss(timer, sizeof(timer), ch->t_ifassert_timer);
120
121 vty_out(vty, "%-16s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n",
122 ch->interface->name,
123 inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)), ch_src_str,
124 ch_grp_str, pim_ifchannel_ifassert_name(ch->ifassert_state),
125 winner_str, uptime, timer);
126 }
127
128 static void pim_show_assert(struct pim_instance *pim, struct vty *vty)
129 {
130 struct pim_interface *pim_ifp;
131 struct pim_ifchannel *ch;
132 struct interface *ifp;
133 time_t now;
134
135 now = pim_time_monotonic_sec();
136
137 vty_out(vty,
138 "Interface Address Source Group State Winner Uptime Timer\n");
139
140 FOR_ALL_INTERFACES (pim->vrf, ifp) {
141 pim_ifp = ifp->info;
142 if (!pim_ifp)
143 continue;
144
145 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
146 pim_show_assert_helper(vty, pim_ifp, ch, now);
147 } /* scan interface channels */
148 }
149 }
150
151 static void pim_show_assert_internal_helper(struct vty *vty,
152 struct pim_interface *pim_ifp,
153 struct pim_ifchannel *ch)
154 {
155 char ch_src_str[INET_ADDRSTRLEN];
156 char ch_grp_str[INET_ADDRSTRLEN];
157 struct in_addr ifaddr;
158 char buf[PREFIX_STRLEN];
159
160 ifaddr = pim_ifp->primary_address;
161
162 pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str));
163 pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str));
164 vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n",
165 ch->interface->name,
166 inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)),
167 ch_src_str, ch_grp_str,
168 PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no",
169 pim_macro_ch_could_assert_eval(ch) ? "yes" : "no",
170 PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags) ? "yes"
171 : "no",
172 pim_macro_assert_tracking_desired_eval(ch) ? "yes" : "no");
173 }
174
175 static void pim_show_assert_internal(struct pim_instance *pim, struct vty *vty)
176 {
177 struct pim_interface *pim_ifp;
178 struct pim_ifchannel *ch;
179 struct interface *ifp;
180
181 vty_out(vty,
182 "CA: CouldAssert\n"
183 "ECA: Evaluate CouldAssert\n"
184 "ATD: AssertTrackingDesired\n"
185 "eATD: Evaluate AssertTrackingDesired\n\n");
186
187 vty_out(vty,
188 "Interface Address Source Group CA eCA ATD eATD\n");
189 FOR_ALL_INTERFACES (pim->vrf, ifp) {
190 pim_ifp = ifp->info;
191 if (!pim_ifp)
192 continue;
193
194 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
195 pim_show_assert_internal_helper(vty, pim_ifp, ch);
196 } /* scan interface channels */
197 }
198 }
199
200 static void pim_show_assert_metric_helper(struct vty *vty,
201 struct pim_interface *pim_ifp,
202 struct pim_ifchannel *ch)
203 {
204 char ch_src_str[INET_ADDRSTRLEN];
205 char ch_grp_str[INET_ADDRSTRLEN];
206 char addr_str[INET_ADDRSTRLEN];
207 struct pim_assert_metric am;
208 struct in_addr ifaddr;
209 char buf[PREFIX_STRLEN];
210
211 ifaddr = pim_ifp->primary_address;
212
213 am = pim_macro_spt_assert_metric(&ch->upstream->rpf,
214 pim_ifp->primary_address);
215
216 pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str));
217 pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str));
218 pim_inet4_dump("<addr?>", am.ip_address, addr_str, sizeof(addr_str));
219
220 vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %4u %6u %-15s\n",
221 ch->interface->name,
222 inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)),
223 ch_src_str, ch_grp_str, am.rpt_bit_flag ? "yes" : "no",
224 am.metric_preference, am.route_metric, addr_str);
225 }
226
227 static void pim_show_assert_metric(struct pim_instance *pim, struct vty *vty)
228 {
229 struct pim_interface *pim_ifp;
230 struct pim_ifchannel *ch;
231 struct interface *ifp;
232
233 vty_out(vty,
234 "Interface Address Source Group RPT Pref Metric Address \n");
235
236 FOR_ALL_INTERFACES (pim->vrf, ifp) {
237 pim_ifp = ifp->info;
238 if (!pim_ifp)
239 continue;
240
241 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
242 pim_show_assert_metric_helper(vty, pim_ifp, ch);
243 } /* scan interface channels */
244 }
245 }
246
247 static void pim_show_assert_winner_metric_helper(struct vty *vty,
248 struct pim_interface *pim_ifp,
249 struct pim_ifchannel *ch)
250 {
251 char ch_src_str[INET_ADDRSTRLEN];
252 char ch_grp_str[INET_ADDRSTRLEN];
253 char addr_str[INET_ADDRSTRLEN];
254 struct pim_assert_metric *am;
255 struct in_addr ifaddr;
256 char pref_str[16];
257 char metr_str[16];
258 char buf[PREFIX_STRLEN];
259
260 ifaddr = pim_ifp->primary_address;
261
262 am = &ch->ifassert_winner_metric;
263
264 pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str));
265 pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str));
266 pim_inet4_dump("<addr?>", am->ip_address, addr_str, sizeof(addr_str));
267
268 if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX)
269 snprintf(pref_str, sizeof(pref_str), "INFI");
270 else
271 snprintf(pref_str, sizeof(pref_str), "%4u",
272 am->metric_preference);
273
274 if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX)
275 snprintf(metr_str, sizeof(metr_str), "INFI");
276 else
277 snprintf(metr_str, sizeof(metr_str), "%6u", am->route_metric);
278
279 vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n",
280 ch->interface->name,
281 inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)), ch_src_str,
282 ch_grp_str, am->rpt_bit_flag ? "yes" : "no", pref_str, metr_str,
283 addr_str);
284 }
285
286 static void pim_show_assert_winner_metric(struct pim_instance *pim,
287 struct vty *vty)
288 {
289 struct pim_interface *pim_ifp;
290 struct pim_ifchannel *ch;
291 struct interface *ifp;
292
293 vty_out(vty,
294 "Interface Address Source Group RPT Pref Metric Address \n");
295
296 FOR_ALL_INTERFACES (pim->vrf, ifp) {
297 pim_ifp = ifp->info;
298 if (!pim_ifp)
299 continue;
300
301 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
302 pim_show_assert_winner_metric_helper(vty, pim_ifp, ch);
303 } /* scan interface channels */
304 }
305 }
306
307 static void json_object_pim_ifp_add(struct json_object *json,
308 struct interface *ifp)
309 {
310 struct pim_interface *pim_ifp;
311 char buf[PREFIX_STRLEN];
312
313 pim_ifp = ifp->info;
314 json_object_string_add(json, "name", ifp->name);
315 json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down");
316 json_object_string_add(json, "address",
317 inet_ntop(AF_INET, &pim_ifp->primary_address,
318 buf, sizeof(buf)));
319 json_object_int_add(json, "index", ifp->ifindex);
320
321 if (if_is_multicast(ifp))
322 json_object_boolean_true_add(json, "flagMulticast");
323
324 if (if_is_broadcast(ifp))
325 json_object_boolean_true_add(json, "flagBroadcast");
326
327 if (ifp->flags & IFF_ALLMULTI)
328 json_object_boolean_true_add(json, "flagAllMulticast");
329
330 if (ifp->flags & IFF_PROMISC)
331 json_object_boolean_true_add(json, "flagPromiscuous");
332
333 if (PIM_IF_IS_DELETED(ifp))
334 json_object_boolean_true_add(json, "flagDeleted");
335
336 if (pim_if_lan_delay_enabled(ifp))
337 json_object_boolean_true_add(json, "lanDelayEnabled");
338 }
339
340 static void pim_show_membership_helper(struct vty *vty,
341 struct pim_interface *pim_ifp,
342 struct pim_ifchannel *ch,
343 struct json_object *json)
344 {
345 char ch_src_str[INET_ADDRSTRLEN];
346 char ch_grp_str[INET_ADDRSTRLEN];
347 json_object *json_iface = NULL;
348 json_object *json_row = NULL;
349
350 pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str));
351 pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str));
352
353 json_object_object_get_ex(json, ch->interface->name, &json_iface);
354 if (!json_iface) {
355 json_iface = json_object_new_object();
356 json_object_pim_ifp_add(json_iface, ch->interface);
357 json_object_object_add(json, ch->interface->name, json_iface);
358 }
359
360 json_row = json_object_new_object();
361 json_object_string_add(json_row, "source", ch_src_str);
362 json_object_string_add(json_row, "group", ch_grp_str);
363 json_object_string_add(json_row, "localMembership",
364 ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO
365 ? "NOINFO"
366 : "INCLUDE");
367 json_object_object_add(json_iface, ch_grp_str, json_row);
368 }
369 static void pim_show_membership(struct pim_instance *pim, struct vty *vty,
370 bool uj)
371 {
372 struct pim_interface *pim_ifp;
373 struct pim_ifchannel *ch;
374 struct interface *ifp;
375 enum json_type type;
376 json_object *json = NULL;
377 json_object *json_tmp = NULL;
378
379 json = json_object_new_object();
380
381 FOR_ALL_INTERFACES (pim->vrf, ifp) {
382 pim_ifp = ifp->info;
383 if (!pim_ifp)
384 continue;
385
386 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
387 pim_show_membership_helper(vty, pim_ifp, ch, json);
388 } /* scan interface channels */
389 }
390
391 if (uj) {
392 vty_out(vty, "%s\n", json_object_to_json_string_ext(
393 json, JSON_C_TO_STRING_PRETTY));
394 } else {
395 vty_out(vty,
396 "Interface Address Source Group Membership\n");
397
398 /*
399 * Example of the json data we are traversing
400 *
401 * {
402 * "swp3":{
403 * "name":"swp3",
404 * "state":"up",
405 * "address":"10.1.20.1",
406 * "index":5,
407 * "flagMulticast":true,
408 * "flagBroadcast":true,
409 * "lanDelayEnabled":true,
410 * "226.10.10.10":{
411 * "source":"*",
412 * "group":"226.10.10.10",
413 * "localMembership":"INCLUDE"
414 * }
415 * }
416 * }
417 */
418
419 /* foreach interface */
420 json_object_object_foreach(json, key, val)
421 {
422
423 /* Find all of the keys where the val is an object. In
424 * the example
425 * above the only one is 226.10.10.10
426 */
427 json_object_object_foreach(val, if_field_key,
428 if_field_val)
429 {
430 type = json_object_get_type(if_field_val);
431
432 if (type == json_type_object) {
433 vty_out(vty, "%-16s ", key);
434
435 json_object_object_get_ex(
436 val, "address", &json_tmp);
437 vty_out(vty, "%-15s ",
438 json_object_get_string(
439 json_tmp));
440
441 json_object_object_get_ex(if_field_val,
442 "source",
443 &json_tmp);
444 vty_out(vty, "%-15s ",
445 json_object_get_string(
446 json_tmp));
447
448 /* Group */
449 vty_out(vty, "%-15s ", if_field_key);
450
451 json_object_object_get_ex(
452 if_field_val, "localMembership",
453 &json_tmp);
454 vty_out(vty, "%-10s\n",
455 json_object_get_string(
456 json_tmp));
457 }
458 }
459 }
460 }
461
462 json_object_free(json);
463 }
464
465 static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp,
466 int mloop)
467 {
468 vty_out(vty, "Flags\n");
469 vty_out(vty, "-----\n");
470 vty_out(vty, "All Multicast : %s\n",
471 (ifp->flags & IFF_ALLMULTI) ? "yes" : "no");
472 vty_out(vty, "Broadcast : %s\n",
473 if_is_broadcast(ifp) ? "yes" : "no");
474 vty_out(vty, "Deleted : %s\n",
475 PIM_IF_IS_DELETED(ifp) ? "yes" : "no");
476 vty_out(vty, "Interface Index : %d\n", ifp->ifindex);
477 vty_out(vty, "Multicast : %s\n",
478 if_is_multicast(ifp) ? "yes" : "no");
479 vty_out(vty, "Multicast Loop : %d\n", mloop);
480 vty_out(vty, "Promiscuous : %s\n",
481 (ifp->flags & IFF_PROMISC) ? "yes" : "no");
482 vty_out(vty, "\n");
483 vty_out(vty, "\n");
484 }
485
486 static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
487 bool uj)
488 {
489 struct interface *ifp;
490 time_t now;
491 char buf[PREFIX_STRLEN];
492 char quer_buf[PREFIX_STRLEN];
493 json_object *json = NULL;
494 json_object *json_row = NULL;
495
496 now = pim_time_monotonic_sec();
497
498 if (uj)
499 json = json_object_new_object();
500 else
501 vty_out(vty,
502 "Interface State Address V Querier QuerierIp Query Timer Uptime\n");
503
504 FOR_ALL_INTERFACES (pim->vrf, ifp) {
505 struct pim_interface *pim_ifp;
506 struct listnode *sock_node;
507 struct igmp_sock *igmp;
508
509 pim_ifp = ifp->info;
510
511 if (!pim_ifp)
512 continue;
513
514 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
515 igmp)) {
516 char uptime[10];
517 char query_hhmmss[10];
518
519 pim_time_uptime(uptime, sizeof(uptime),
520 now - igmp->sock_creation);
521 pim_time_timer_to_hhmmss(query_hhmmss,
522 sizeof(query_hhmmss),
523 igmp->t_igmp_query_timer);
524
525 if (uj) {
526 json_row = json_object_new_object();
527 json_object_pim_ifp_add(json_row, ifp);
528 json_object_string_add(json_row, "upTime",
529 uptime);
530 json_object_int_add(json_row, "version",
531 pim_ifp->igmp_version);
532
533 if (igmp->t_igmp_query_timer) {
534 json_object_boolean_true_add(json_row,
535 "querier");
536 json_object_string_add(json_row,
537 "queryTimer",
538 query_hhmmss);
539 }
540 json_object_string_add(
541 json_row, "querierIp",
542 inet_ntop(AF_INET, &igmp->querier_addr,
543 quer_buf, sizeof(quer_buf)));
544
545 json_object_object_add(json, ifp->name,
546 json_row);
547
548 if (igmp->mtrace_only) {
549 json_object_boolean_true_add(
550 json_row, "mtraceOnly");
551 }
552 } else {
553 vty_out(vty,
554 "%-16s %5s %15s %d %7s %17pI4 %11s %8s\n",
555 ifp->name,
556 if_is_up(ifp)
557 ? (igmp->mtrace_only ? "mtrc"
558 : "up")
559 : "down",
560 inet_ntop(AF_INET, &igmp->ifaddr, buf,
561 sizeof(buf)),
562 pim_ifp->igmp_version,
563 igmp->t_igmp_query_timer ? "local"
564 : "other",
565 &igmp->querier_addr, query_hhmmss,
566 uptime);
567 }
568 }
569 }
570
571 if (uj) {
572 vty_out(vty, "%s\n", json_object_to_json_string_ext(
573 json, JSON_C_TO_STRING_PRETTY));
574 json_object_free(json);
575 }
576 }
577
578 static void igmp_show_interfaces_single(struct pim_instance *pim,
579 struct vty *vty, const char *ifname,
580 bool uj)
581 {
582 struct igmp_sock *igmp;
583 struct interface *ifp;
584 struct listnode *sock_node;
585 struct pim_interface *pim_ifp;
586 char uptime[10];
587 char quer_buf[PREFIX_STRLEN];
588 char query_hhmmss[10];
589 char other_hhmmss[10];
590 int found_ifname = 0;
591 int sqi;
592 int mloop = 0;
593 long gmi_msec; /* Group Membership Interval */
594 long lmqt_msec;
595 long ohpi_msec;
596 long oqpi_msec; /* Other Querier Present Interval */
597 long qri_msec;
598 time_t now;
599 int lmqc;
600
601 json_object *json = NULL;
602 json_object *json_row = NULL;
603
604 if (uj)
605 json = json_object_new_object();
606
607 now = pim_time_monotonic_sec();
608
609 FOR_ALL_INTERFACES (pim->vrf, ifp) {
610 pim_ifp = ifp->info;
611
612 if (!pim_ifp)
613 continue;
614
615 if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
616 continue;
617
618 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
619 igmp)) {
620 found_ifname = 1;
621 pim_time_uptime(uptime, sizeof(uptime),
622 now - igmp->sock_creation);
623 pim_time_timer_to_hhmmss(query_hhmmss,
624 sizeof(query_hhmmss),
625 igmp->t_igmp_query_timer);
626 pim_time_timer_to_hhmmss(other_hhmmss,
627 sizeof(other_hhmmss),
628 igmp->t_other_querier_timer);
629
630 gmi_msec = PIM_IGMP_GMI_MSEC(
631 igmp->querier_robustness_variable,
632 igmp->querier_query_interval,
633 pim_ifp->igmp_query_max_response_time_dsec);
634
635 sqi = PIM_IGMP_SQI(
636 pim_ifp->igmp_default_query_interval);
637
638 oqpi_msec = PIM_IGMP_OQPI_MSEC(
639 igmp->querier_robustness_variable,
640 igmp->querier_query_interval,
641 pim_ifp->igmp_query_max_response_time_dsec);
642
643 lmqt_msec = PIM_IGMP_LMQT_MSEC(
644 pim_ifp->igmp_specific_query_max_response_time_dsec,
645 pim_ifp->igmp_last_member_query_count);
646
647 ohpi_msec =
648 PIM_IGMP_OHPI_DSEC(
649 igmp->querier_robustness_variable,
650 igmp->querier_query_interval,
651 pim_ifp->igmp_query_max_response_time_dsec)
652 * 100;
653
654 qri_msec = pim_ifp->igmp_query_max_response_time_dsec
655 * 100;
656 if (pim_ifp->pim_sock_fd >= 0)
657 mloop = pim_socket_mcastloop_get(
658 pim_ifp->pim_sock_fd);
659 else
660 mloop = 0;
661 lmqc = pim_ifp->igmp_last_member_query_count;
662
663 if (uj) {
664 json_row = json_object_new_object();
665 json_object_pim_ifp_add(json_row, ifp);
666 json_object_string_add(json_row, "upTime",
667 uptime);
668 json_object_string_add(json_row, "querier",
669 igmp->t_igmp_query_timer
670 ? "local"
671 : "other");
672 json_object_string_add(
673 json_row, "querierIp",
674 inet_ntop(AF_INET, &igmp->querier_addr,
675 quer_buf, sizeof(quer_buf)));
676 json_object_int_add(json_row, "queryStartCount",
677 igmp->startup_query_count);
678 json_object_string_add(json_row,
679 "queryQueryTimer",
680 query_hhmmss);
681 json_object_string_add(json_row,
682 "queryOtherTimer",
683 other_hhmmss);
684 json_object_int_add(json_row, "version",
685 pim_ifp->igmp_version);
686 json_object_int_add(
687 json_row,
688 "timerGroupMembershipIntervalMsec",
689 gmi_msec);
690 json_object_int_add(json_row,
691 "lastMemberQueryCount",
692 lmqc);
693 json_object_int_add(json_row,
694 "timerLastMemberQueryMsec",
695 lmqt_msec);
696 json_object_int_add(
697 json_row,
698 "timerOlderHostPresentIntervalMsec",
699 ohpi_msec);
700 json_object_int_add(
701 json_row,
702 "timerOtherQuerierPresentIntervalMsec",
703 oqpi_msec);
704 json_object_int_add(
705 json_row, "timerQueryInterval",
706 igmp->querier_query_interval);
707 json_object_int_add(
708 json_row,
709 "timerQueryResponseIntervalMsec",
710 qri_msec);
711 json_object_int_add(
712 json_row, "timerRobustnessVariable",
713 igmp->querier_robustness_variable);
714 json_object_int_add(json_row,
715 "timerStartupQueryInterval",
716 sqi);
717
718 json_object_object_add(json, ifp->name,
719 json_row);
720
721 if (igmp->mtrace_only) {
722 json_object_boolean_true_add(
723 json_row, "mtraceOnly");
724 }
725 } else {
726 vty_out(vty, "Interface : %s\n", ifp->name);
727 vty_out(vty, "State : %s\n",
728 if_is_up(ifp) ? (igmp->mtrace_only ?
729 "mtrace"
730 : "up")
731 : "down");
732 vty_out(vty, "Address : %pI4\n",
733 &pim_ifp->primary_address);
734 vty_out(vty, "Uptime : %s\n", uptime);
735 vty_out(vty, "Version : %d\n",
736 pim_ifp->igmp_version);
737 vty_out(vty, "\n");
738 vty_out(vty, "\n");
739
740 vty_out(vty, "Querier\n");
741 vty_out(vty, "-------\n");
742 vty_out(vty, "Querier : %s\n",
743 igmp->t_igmp_query_timer ? "local"
744 : "other");
745 vty_out(vty, "QuerierIp : %pI4",
746 &igmp->querier_addr);
747 if (pim_ifp->primary_address.s_addr
748 == igmp->querier_addr.s_addr)
749 vty_out(vty, " (this router)\n");
750 else
751 vty_out(vty, "\n");
752
753 vty_out(vty, "Start Count : %d\n",
754 igmp->startup_query_count);
755 vty_out(vty, "Query Timer : %s\n",
756 query_hhmmss);
757 vty_out(vty, "Other Timer : %s\n",
758 other_hhmmss);
759 vty_out(vty, "\n");
760 vty_out(vty, "\n");
761
762 vty_out(vty, "Timers\n");
763 vty_out(vty, "------\n");
764 vty_out(vty,
765 "Group Membership Interval : %lis\n",
766 gmi_msec / 1000);
767 vty_out(vty,
768 "Last Member Query Count : %d\n",
769 lmqc);
770 vty_out(vty,
771 "Last Member Query Time : %lis\n",
772 lmqt_msec / 1000);
773 vty_out(vty,
774 "Older Host Present Interval : %lis\n",
775 ohpi_msec / 1000);
776 vty_out(vty,
777 "Other Querier Present Interval : %lis\n",
778 oqpi_msec / 1000);
779 vty_out(vty,
780 "Query Interval : %ds\n",
781 igmp->querier_query_interval);
782 vty_out(vty,
783 "Query Response Interval : %lis\n",
784 qri_msec / 1000);
785 vty_out(vty,
786 "Robustness Variable : %d\n",
787 igmp->querier_robustness_variable);
788 vty_out(vty,
789 "Startup Query Interval : %ds\n",
790 sqi);
791 vty_out(vty, "\n");
792 vty_out(vty, "\n");
793
794 pim_print_ifp_flags(vty, ifp, mloop);
795 }
796 }
797 }
798
799 if (uj) {
800 vty_out(vty, "%s\n", json_object_to_json_string_ext(
801 json, JSON_C_TO_STRING_PRETTY));
802 json_object_free(json);
803 } else {
804 if (!found_ifname)
805 vty_out(vty, "%% No such interface\n");
806 }
807 }
808
809 static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty,
810 bool uj)
811 {
812 struct interface *ifp;
813 time_t now;
814 json_object *json = NULL;
815 json_object *json_iface = NULL;
816 json_object *json_grp = NULL;
817 json_object *json_grp_arr = NULL;
818
819 now = pim_time_monotonic_sec();
820
821 if (uj) {
822 json = json_object_new_object();
823 json_object_string_add(json, "vrf",
824 vrf_id_to_name(pim->vrf->vrf_id));
825 } else {
826 vty_out(vty,
827 "Interface Address Source Group Socket Uptime \n");
828 }
829
830 FOR_ALL_INTERFACES (pim->vrf, ifp) {
831 struct pim_interface *pim_ifp;
832 struct listnode *join_node;
833 struct igmp_join *ij;
834 struct in_addr pri_addr;
835 char pri_addr_str[INET_ADDRSTRLEN];
836
837 pim_ifp = ifp->info;
838
839 if (!pim_ifp)
840 continue;
841
842 if (!pim_ifp->igmp_join_list)
843 continue;
844
845 pri_addr = pim_find_primary_addr(ifp);
846 pim_inet4_dump("<pri?>", pri_addr, pri_addr_str,
847 sizeof(pri_addr_str));
848
849 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, join_node,
850 ij)) {
851 char group_str[INET_ADDRSTRLEN];
852 char source_str[INET_ADDRSTRLEN];
853 char uptime[10];
854
855 pim_time_uptime(uptime, sizeof(uptime),
856 now - ij->sock_creation);
857 pim_inet4_dump("<grp?>", ij->group_addr, group_str,
858 sizeof(group_str));
859 pim_inet4_dump("<src?>", ij->source_addr, source_str,
860 sizeof(source_str));
861
862 if (uj) {
863 json_object_object_get_ex(json, ifp->name,
864 &json_iface);
865
866 if (!json_iface) {
867 json_iface = json_object_new_object();
868 json_object_string_add(
869 json_iface, "name", ifp->name);
870 json_object_object_add(json, ifp->name,
871 json_iface);
872 json_grp_arr = json_object_new_array();
873 json_object_object_add(json_iface,
874 "groups",
875 json_grp_arr);
876 }
877
878 json_grp = json_object_new_object();
879 json_object_string_add(json_grp, "source",
880 source_str);
881 json_object_string_add(json_grp, "group",
882 group_str);
883 json_object_string_add(json_grp, "primaryAddr",
884 pri_addr_str);
885 json_object_int_add(json_grp, "sockFd",
886 ij->sock_fd);
887 json_object_string_add(json_grp, "upTime",
888 uptime);
889 json_object_array_add(json_grp_arr, json_grp);
890 } else {
891 vty_out(vty,
892 "%-16s %-15s %-15s %-15s %6d %8s\n",
893 ifp->name, pri_addr_str, source_str,
894 group_str, ij->sock_fd, uptime);
895 }
896 } /* for (pim_ifp->igmp_join_list) */
897
898 } /* for (iflist) */
899
900 if (uj) {
901 vty_out(vty, "%s\n", json_object_to_json_string_ext(
902 json, JSON_C_TO_STRING_PRETTY));
903 json_object_free(json);
904 }
905 }
906
907 static void pim_show_interfaces_single(struct pim_instance *pim,
908 struct vty *vty, const char *ifname,
909 bool mlag, bool uj)
910 {
911 struct in_addr ifaddr;
912 struct interface *ifp;
913 struct listnode *neighnode;
914 struct pim_interface *pim_ifp;
915 struct pim_neighbor *neigh;
916 struct pim_upstream *up;
917 time_t now;
918 char dr_str[INET_ADDRSTRLEN];
919 char dr_uptime[10];
920 char expire[10];
921 char grp_str[INET_ADDRSTRLEN];
922 char hello_period[10];
923 char hello_timer[10];
924 char neigh_src_str[INET_ADDRSTRLEN];
925 char src_str[INET_ADDRSTRLEN];
926 char stat_uptime[10];
927 char uptime[10];
928 int mloop = 0;
929 int found_ifname = 0;
930 int print_header;
931 char buf[PREFIX_STRLEN];
932 json_object *json = NULL;
933 json_object *json_row = NULL;
934 json_object *json_pim_neighbor = NULL;
935 json_object *json_pim_neighbors = NULL;
936 json_object *json_group = NULL;
937 json_object *json_group_source = NULL;
938 json_object *json_fhr_sources = NULL;
939 struct pim_secondary_addr *sec_addr;
940 struct listnode *sec_node;
941
942 now = pim_time_monotonic_sec();
943
944 if (uj)
945 json = json_object_new_object();
946
947 FOR_ALL_INTERFACES (pim->vrf, ifp) {
948 pim_ifp = ifp->info;
949
950 if (!pim_ifp)
951 continue;
952
953 if (mlag == true && pim_ifp->activeactive == false)
954 continue;
955
956 if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
957 continue;
958
959 found_ifname = 1;
960 ifaddr = pim_ifp->primary_address;
961 pim_inet4_dump("<dr?>", pim_ifp->pim_dr_addr, dr_str,
962 sizeof(dr_str));
963 pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now,
964 pim_ifp->pim_dr_election_last);
965 pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer),
966 pim_ifp->t_pim_hello_timer);
967 pim_time_mmss(hello_period, sizeof(hello_period),
968 pim_ifp->pim_hello_period);
969 pim_time_uptime(stat_uptime, sizeof(stat_uptime),
970 now - pim_ifp->pim_ifstat_start);
971 if (pim_ifp->pim_sock_fd >= 0)
972 mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd);
973 else
974 mloop = 0;
975
976 if (uj) {
977 char pbuf[PREFIX2STR_BUFFER];
978 json_row = json_object_new_object();
979 json_object_pim_ifp_add(json_row, ifp);
980
981 if (pim_ifp->update_source.s_addr != INADDR_ANY) {
982 json_object_string_add(
983 json_row, "useSource",
984 inet_ntop(AF_INET,
985 &pim_ifp->update_source,
986 buf, sizeof(buf)));
987 }
988 if (pim_ifp->sec_addr_list) {
989 json_object *sec_list = NULL;
990
991 sec_list = json_object_new_array();
992 for (ALL_LIST_ELEMENTS_RO(
993 pim_ifp->sec_addr_list, sec_node,
994 sec_addr)) {
995 json_object_array_add(
996 sec_list,
997 json_object_new_string(
998 prefix2str(
999 &sec_addr->addr,
1000 pbuf,
1001 sizeof(pbuf))));
1002 }
1003 json_object_object_add(json_row,
1004 "secondaryAddressList",
1005 sec_list);
1006 }
1007
1008 // PIM neighbors
1009 if (pim_ifp->pim_neighbor_list->count) {
1010 json_pim_neighbors = json_object_new_object();
1011
1012 for (ALL_LIST_ELEMENTS_RO(
1013 pim_ifp->pim_neighbor_list,
1014 neighnode, neigh)) {
1015 json_pim_neighbor =
1016 json_object_new_object();
1017 pim_inet4_dump("<src?>",
1018 neigh->source_addr,
1019 neigh_src_str,
1020 sizeof(neigh_src_str));
1021 pim_time_uptime(uptime, sizeof(uptime),
1022 now - neigh->creation);
1023 pim_time_timer_to_hhmmss(
1024 expire, sizeof(expire),
1025 neigh->t_expire_timer);
1026
1027 json_object_string_add(
1028 json_pim_neighbor, "address",
1029 neigh_src_str);
1030 json_object_string_add(
1031 json_pim_neighbor, "upTime",
1032 uptime);
1033 json_object_string_add(
1034 json_pim_neighbor, "holdtime",
1035 expire);
1036
1037 json_object_object_add(
1038 json_pim_neighbors,
1039 neigh_src_str,
1040 json_pim_neighbor);
1041 }
1042
1043 json_object_object_add(json_row, "neighbors",
1044 json_pim_neighbors);
1045 }
1046
1047 json_object_string_add(json_row, "drAddress", dr_str);
1048 json_object_int_add(json_row, "drPriority",
1049 pim_ifp->pim_dr_priority);
1050 json_object_string_add(json_row, "drUptime", dr_uptime);
1051 json_object_int_add(json_row, "drElections",
1052 pim_ifp->pim_dr_election_count);
1053 json_object_int_add(json_row, "drChanges",
1054 pim_ifp->pim_dr_election_changes);
1055
1056 // FHR
1057 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
1058 if (ifp != up->rpf.source_nexthop.interface)
1059 continue;
1060
1061 if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
1062 continue;
1063
1064 if (!json_fhr_sources)
1065 json_fhr_sources =
1066 json_object_new_object();
1067
1068 pim_inet4_dump("<src?>", up->sg.src, src_str,
1069 sizeof(src_str));
1070 pim_inet4_dump("<grp?>", up->sg.grp, grp_str,
1071 sizeof(grp_str));
1072 pim_time_uptime(uptime, sizeof(uptime),
1073 now - up->state_transition);
1074
1075 /*
1076 * Does this group live in json_fhr_sources?
1077 * If not create it.
1078 */
1079 json_object_object_get_ex(json_fhr_sources,
1080 grp_str, &json_group);
1081
1082 if (!json_group) {
1083 json_group = json_object_new_object();
1084 json_object_object_add(json_fhr_sources,
1085 grp_str,
1086 json_group);
1087 }
1088
1089 json_group_source = json_object_new_object();
1090 json_object_string_add(json_group_source,
1091 "source", src_str);
1092 json_object_string_add(json_group_source,
1093 "group", grp_str);
1094 json_object_string_add(json_group_source,
1095 "upTime", uptime);
1096 json_object_object_add(json_group, src_str,
1097 json_group_source);
1098 }
1099
1100 if (json_fhr_sources) {
1101 json_object_object_add(json_row,
1102 "firstHopRouter",
1103 json_fhr_sources);
1104 }
1105
1106 json_object_int_add(json_row, "helloPeriod",
1107 pim_ifp->pim_hello_period);
1108 json_object_int_add(json_row, "holdTime",
1109 PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
1110 json_object_string_add(json_row, "helloTimer",
1111 hello_timer);
1112 json_object_string_add(json_row, "helloStatStart",
1113 stat_uptime);
1114 json_object_int_add(json_row, "helloReceived",
1115 pim_ifp->pim_ifstat_hello_recv);
1116 json_object_int_add(json_row, "helloReceivedFailed",
1117 pim_ifp->pim_ifstat_hello_recvfail);
1118 json_object_int_add(json_row, "helloSend",
1119 pim_ifp->pim_ifstat_hello_sent);
1120 json_object_int_add(json_row, "hellosendFailed",
1121 pim_ifp->pim_ifstat_hello_sendfail);
1122 json_object_int_add(json_row, "helloGenerationId",
1123 pim_ifp->pim_generation_id);
1124 json_object_int_add(json_row, "flagMulticastLoop",
1125 mloop);
1126
1127 json_object_int_add(
1128 json_row, "effectivePropagationDelay",
1129 pim_if_effective_propagation_delay_msec(ifp));
1130 json_object_int_add(
1131 json_row, "effectiveOverrideInterval",
1132 pim_if_effective_override_interval_msec(ifp));
1133 json_object_int_add(
1134 json_row, "joinPruneOverrideInterval",
1135 pim_if_jp_override_interval_msec(ifp));
1136
1137 json_object_int_add(
1138 json_row, "propagationDelay",
1139 pim_ifp->pim_propagation_delay_msec);
1140 json_object_int_add(
1141 json_row, "propagationDelayHighest",
1142 pim_ifp->pim_neighbors_highest_propagation_delay_msec);
1143 json_object_int_add(
1144 json_row, "overrideInterval",
1145 pim_ifp->pim_override_interval_msec);
1146 json_object_int_add(
1147 json_row, "overrideIntervalHighest",
1148 pim_ifp->pim_neighbors_highest_override_interval_msec);
1149 if (pim_ifp->bsm_enable)
1150 json_object_boolean_true_add(json_row,
1151 "bsmEnabled");
1152 if (pim_ifp->ucast_bsm_accept)
1153 json_object_boolean_true_add(json_row,
1154 "ucastBsmEnabled");
1155 json_object_object_add(json, ifp->name, json_row);
1156
1157 } else {
1158 vty_out(vty, "Interface : %s\n", ifp->name);
1159 vty_out(vty, "State : %s\n",
1160 if_is_up(ifp) ? "up" : "down");
1161 if (pim_ifp->update_source.s_addr != INADDR_ANY) {
1162 vty_out(vty, "Use Source : %pI4\n",
1163 &pim_ifp->update_source);
1164 }
1165 if (pim_ifp->sec_addr_list) {
1166 vty_out(vty, "Address : %pI4 (primary)\n",
1167 &ifaddr);
1168 for (ALL_LIST_ELEMENTS_RO(
1169 pim_ifp->sec_addr_list, sec_node,
1170 sec_addr))
1171 vty_out(vty, " %pFX\n",
1172 &sec_addr->addr);
1173 } else {
1174 vty_out(vty, "Address : %pI4\n",
1175 &ifaddr);
1176 }
1177 vty_out(vty, "\n");
1178
1179 // PIM neighbors
1180 print_header = 1;
1181
1182 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
1183 neighnode, neigh)) {
1184
1185 if (print_header) {
1186 vty_out(vty, "PIM Neighbors\n");
1187 vty_out(vty, "-------------\n");
1188 print_header = 0;
1189 }
1190
1191 pim_inet4_dump("<src?>", neigh->source_addr,
1192 neigh_src_str,
1193 sizeof(neigh_src_str));
1194 pim_time_uptime(uptime, sizeof(uptime),
1195 now - neigh->creation);
1196 pim_time_timer_to_hhmmss(expire, sizeof(expire),
1197 neigh->t_expire_timer);
1198 vty_out(vty,
1199 "%-15s : up for %s, holdtime expires in %s\n",
1200 neigh_src_str, uptime, expire);
1201 }
1202
1203 if (!print_header) {
1204 vty_out(vty, "\n");
1205 vty_out(vty, "\n");
1206 }
1207
1208 vty_out(vty, "Designated Router\n");
1209 vty_out(vty, "-----------------\n");
1210 vty_out(vty, "Address : %s\n", dr_str);
1211 vty_out(vty, "Priority : %u(%d)\n",
1212 pim_ifp->pim_dr_priority,
1213 pim_ifp->pim_dr_num_nondrpri_neighbors);
1214 vty_out(vty, "Uptime : %s\n", dr_uptime);
1215 vty_out(vty, "Elections : %d\n",
1216 pim_ifp->pim_dr_election_count);
1217 vty_out(vty, "Changes : %d\n",
1218 pim_ifp->pim_dr_election_changes);
1219 vty_out(vty, "\n");
1220 vty_out(vty, "\n");
1221
1222 // FHR
1223 print_header = 1;
1224 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
1225 if (!up->rpf.source_nexthop.interface)
1226 continue;
1227
1228 if (strcmp(ifp->name,
1229 up->rpf.source_nexthop
1230 .interface->name)
1231 != 0)
1232 continue;
1233
1234 if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
1235 continue;
1236
1237 if (print_header) {
1238 vty_out(vty,
1239 "FHR - First Hop Router\n");
1240 vty_out(vty,
1241 "----------------------\n");
1242 print_header = 0;
1243 }
1244
1245 pim_inet4_dump("<src?>", up->sg.src, src_str,
1246 sizeof(src_str));
1247 pim_inet4_dump("<grp?>", up->sg.grp, grp_str,
1248 sizeof(grp_str));
1249 pim_time_uptime(uptime, sizeof(uptime),
1250 now - up->state_transition);
1251 vty_out(vty,
1252 "%s : %s is a source, uptime is %s\n",
1253 grp_str, src_str, uptime);
1254 }
1255
1256 if (!print_header) {
1257 vty_out(vty, "\n");
1258 vty_out(vty, "\n");
1259 }
1260
1261 vty_out(vty, "Hellos\n");
1262 vty_out(vty, "------\n");
1263 vty_out(vty, "Period : %d\n",
1264 pim_ifp->pim_hello_period);
1265 vty_out(vty, "HoldTime : %d\n",
1266 PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
1267 vty_out(vty, "Timer : %s\n", hello_timer);
1268 vty_out(vty, "StatStart : %s\n", stat_uptime);
1269 vty_out(vty, "Receive : %d\n",
1270 pim_ifp->pim_ifstat_hello_recv);
1271 vty_out(vty, "Receive Failed : %d\n",
1272 pim_ifp->pim_ifstat_hello_recvfail);
1273 vty_out(vty, "Send : %d\n",
1274 pim_ifp->pim_ifstat_hello_sent);
1275 vty_out(vty, "Send Failed : %d\n",
1276 pim_ifp->pim_ifstat_hello_sendfail);
1277 vty_out(vty, "Generation ID : %08x\n",
1278 pim_ifp->pim_generation_id);
1279 vty_out(vty, "\n");
1280 vty_out(vty, "\n");
1281
1282 pim_print_ifp_flags(vty, ifp, mloop);
1283
1284 vty_out(vty, "Join Prune Interval\n");
1285 vty_out(vty, "-------------------\n");
1286 vty_out(vty, "LAN Delay : %s\n",
1287 pim_if_lan_delay_enabled(ifp) ? "yes" : "no");
1288 vty_out(vty, "Effective Propagation Delay : %d msec\n",
1289 pim_if_effective_propagation_delay_msec(ifp));
1290 vty_out(vty, "Effective Override Interval : %d msec\n",
1291 pim_if_effective_override_interval_msec(ifp));
1292 vty_out(vty, "Join Prune Override Interval : %d msec\n",
1293 pim_if_jp_override_interval_msec(ifp));
1294 vty_out(vty, "\n");
1295 vty_out(vty, "\n");
1296
1297 vty_out(vty, "LAN Prune Delay\n");
1298 vty_out(vty, "---------------\n");
1299 vty_out(vty, "Propagation Delay : %d msec\n",
1300 pim_ifp->pim_propagation_delay_msec);
1301 vty_out(vty, "Propagation Delay (Highest) : %d msec\n",
1302 pim_ifp->pim_neighbors_highest_propagation_delay_msec);
1303 vty_out(vty, "Override Interval : %d msec\n",
1304 pim_ifp->pim_override_interval_msec);
1305 vty_out(vty, "Override Interval (Highest) : %d msec\n",
1306 pim_ifp->pim_neighbors_highest_override_interval_msec);
1307 vty_out(vty, "\n");
1308 vty_out(vty, "\n");
1309
1310 vty_out(vty, "BSM Status\n");
1311 vty_out(vty, "----------\n");
1312 vty_out(vty, "Bsm Enabled : %s\n",
1313 pim_ifp->bsm_enable ? "yes" : "no");
1314 vty_out(vty, "Unicast Bsm Enabled : %s\n",
1315 pim_ifp->ucast_bsm_accept ? "yes" : "no");
1316 vty_out(vty, "\n");
1317 vty_out(vty, "\n");
1318 }
1319 }
1320
1321 if (uj) {
1322 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1323 json, JSON_C_TO_STRING_PRETTY));
1324 json_object_free(json);
1325 } else {
1326 if (!found_ifname)
1327 vty_out(vty, "%% No such interface\n");
1328 }
1329 }
1330
1331 static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
1332 const char *ifname, bool uj)
1333 {
1334 struct interface *ifp;
1335 struct igmp_stats rx_stats;
1336
1337 igmp_stats_init(&rx_stats);
1338
1339 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1340 struct pim_interface *pim_ifp;
1341 struct listnode *sock_node;
1342 struct igmp_sock *igmp;
1343
1344 pim_ifp = ifp->info;
1345
1346 if (!pim_ifp)
1347 continue;
1348
1349 if (ifname && strcmp(ifname, ifp->name))
1350 continue;
1351
1352 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
1353 igmp)) {
1354 igmp_stats_add(&rx_stats, &igmp->rx_stats);
1355 }
1356 }
1357 if (uj) {
1358 json_object *json = NULL;
1359 json_object *json_row = NULL;
1360
1361 json = json_object_new_object();
1362 json_row = json_object_new_object();
1363
1364 json_object_string_add(json_row, "name", ifname ? ifname :
1365 "global");
1366 json_object_int_add(json_row, "queryV1", rx_stats.query_v1);
1367 json_object_int_add(json_row, "queryV2", rx_stats.query_v2);
1368 json_object_int_add(json_row, "queryV3", rx_stats.query_v3);
1369 json_object_int_add(json_row, "leaveV3", rx_stats.leave_v2);
1370 json_object_int_add(json_row, "reportV1", rx_stats.report_v1);
1371 json_object_int_add(json_row, "reportV2", rx_stats.report_v2);
1372 json_object_int_add(json_row, "reportV3", rx_stats.report_v3);
1373 json_object_int_add(json_row, "mtraceResponse",
1374 rx_stats.mtrace_rsp);
1375 json_object_int_add(json_row, "mtraceRequest",
1376 rx_stats.mtrace_req);
1377 json_object_int_add(json_row, "unsupported",
1378 rx_stats.unsupported);
1379 json_object_object_add(json, ifname ? ifname : "global",
1380 json_row);
1381 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1382 json, JSON_C_TO_STRING_PRETTY));
1383 json_object_free(json);
1384 } else {
1385 vty_out(vty, "IGMP RX statistics\n");
1386 vty_out(vty, "Interface : %s\n",
1387 ifname ? ifname : "global");
1388 vty_out(vty, "V1 query : %u\n", rx_stats.query_v1);
1389 vty_out(vty, "V2 query : %u\n", rx_stats.query_v2);
1390 vty_out(vty, "V3 query : %u\n", rx_stats.query_v3);
1391 vty_out(vty, "V2 leave : %u\n", rx_stats.leave_v2);
1392 vty_out(vty, "V1 report : %u\n", rx_stats.report_v1);
1393 vty_out(vty, "V2 report : %u\n", rx_stats.report_v2);
1394 vty_out(vty, "V3 report : %u\n", rx_stats.report_v3);
1395 vty_out(vty, "mtrace response : %u\n", rx_stats.mtrace_rsp);
1396 vty_out(vty, "mtrace request : %u\n", rx_stats.mtrace_req);
1397 vty_out(vty, "unsupported : %u\n", rx_stats.unsupported);
1398 }
1399 }
1400
1401 static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
1402 bool mlag, bool uj)
1403 {
1404 struct interface *ifp;
1405 struct pim_interface *pim_ifp;
1406 struct pim_upstream *up;
1407 int fhr = 0;
1408 int pim_nbrs = 0;
1409 int pim_ifchannels = 0;
1410 char buf[PREFIX_STRLEN];
1411 json_object *json = NULL;
1412 json_object *json_row = NULL;
1413 json_object *json_tmp;
1414
1415 json = json_object_new_object();
1416
1417 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1418 pim_ifp = ifp->info;
1419
1420 if (!pim_ifp)
1421 continue;
1422
1423 if (mlag == true && pim_ifp->activeactive == false)
1424 continue;
1425
1426 pim_nbrs = pim_ifp->pim_neighbor_list->count;
1427 pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
1428 fhr = 0;
1429
1430 frr_each (rb_pim_upstream, &pim->upstream_head, up)
1431 if (ifp == up->rpf.source_nexthop.interface)
1432 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
1433 fhr++;
1434
1435 json_row = json_object_new_object();
1436 json_object_pim_ifp_add(json_row, ifp);
1437 json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
1438 json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
1439 json_object_int_add(json_row, "firstHopRouterCount", fhr);
1440 json_object_string_add(json_row, "pimDesignatedRouter",
1441 inet_ntop(AF_INET,
1442 &pim_ifp->pim_dr_addr, buf,
1443 sizeof(buf)));
1444
1445 if (pim_ifp->pim_dr_addr.s_addr
1446 == pim_ifp->primary_address.s_addr)
1447 json_object_boolean_true_add(
1448 json_row, "pimDesignatedRouterLocal");
1449
1450 json_object_object_add(json, ifp->name, json_row);
1451 }
1452
1453 if (uj) {
1454 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1455 json, JSON_C_TO_STRING_PRETTY));
1456 } else {
1457 vty_out(vty,
1458 "Interface State Address PIM Nbrs PIM DR FHR IfChannels\n");
1459
1460 json_object_object_foreach(json, key, val)
1461 {
1462 vty_out(vty, "%-16s ", key);
1463
1464 json_object_object_get_ex(val, "state", &json_tmp);
1465 vty_out(vty, "%5s ", json_object_get_string(json_tmp));
1466
1467 json_object_object_get_ex(val, "address", &json_tmp);
1468 vty_out(vty, "%15s ",
1469 json_object_get_string(json_tmp));
1470
1471 json_object_object_get_ex(val, "pimNeighbors",
1472 &json_tmp);
1473 vty_out(vty, "%8d ", json_object_get_int(json_tmp));
1474
1475 if (json_object_object_get_ex(
1476 val, "pimDesignatedRouterLocal",
1477 &json_tmp)) {
1478 vty_out(vty, "%15s ", "local");
1479 } else {
1480 json_object_object_get_ex(
1481 val, "pimDesignatedRouter", &json_tmp);
1482 vty_out(vty, "%15s ",
1483 json_object_get_string(json_tmp));
1484 }
1485
1486 json_object_object_get_ex(val, "firstHopRouter",
1487 &json_tmp);
1488 vty_out(vty, "%3d ", json_object_get_int(json_tmp));
1489
1490 json_object_object_get_ex(val, "pimIfChannels",
1491 &json_tmp);
1492 vty_out(vty, "%9d\n", json_object_get_int(json_tmp));
1493 }
1494 }
1495
1496 json_object_free(json);
1497 }
1498
1499 static void pim_show_interface_traffic(struct pim_instance *pim,
1500 struct vty *vty, bool uj)
1501 {
1502 struct interface *ifp = NULL;
1503 struct pim_interface *pim_ifp = NULL;
1504 json_object *json = NULL;
1505 json_object *json_row = NULL;
1506
1507 if (uj)
1508 json = json_object_new_object();
1509 else {
1510 vty_out(vty, "\n");
1511 vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
1512 "Interface", " HELLO", " JOIN",
1513 " PRUNE", " REGISTER", "REGISTER-STOP",
1514 " ASSERT", " BSM");
1515 vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
1516 " Rx/Tx", " Rx/Tx", " Rx/Tx",
1517 " Rx/Tx", " Rx/Tx", " Rx/Tx",
1518 " Rx/Tx");
1519 vty_out(vty,
1520 "---------------------------------------------------------------------------------------------------------------\n");
1521 }
1522
1523 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1524 pim_ifp = ifp->info;
1525
1526 if (!pim_ifp)
1527 continue;
1528
1529 if (pim_ifp->pim_sock_fd < 0)
1530 continue;
1531 if (uj) {
1532 json_row = json_object_new_object();
1533 json_object_pim_ifp_add(json_row, ifp);
1534 json_object_int_add(json_row, "helloRx",
1535 pim_ifp->pim_ifstat_hello_recv);
1536 json_object_int_add(json_row, "helloTx",
1537 pim_ifp->pim_ifstat_hello_sent);
1538 json_object_int_add(json_row, "joinRx",
1539 pim_ifp->pim_ifstat_join_recv);
1540 json_object_int_add(json_row, "joinTx",
1541 pim_ifp->pim_ifstat_join_send);
1542 json_object_int_add(json_row, "pruneTx",
1543 pim_ifp->pim_ifstat_prune_send);
1544 json_object_int_add(json_row, "pruneRx",
1545 pim_ifp->pim_ifstat_prune_recv);
1546 json_object_int_add(json_row, "registerRx",
1547 pim_ifp->pim_ifstat_reg_recv);
1548 json_object_int_add(json_row, "registerTx",
1549 pim_ifp->pim_ifstat_reg_recv);
1550 json_object_int_add(json_row, "registerStopRx",
1551 pim_ifp->pim_ifstat_reg_stop_recv);
1552 json_object_int_add(json_row, "registerStopTx",
1553 pim_ifp->pim_ifstat_reg_stop_send);
1554 json_object_int_add(json_row, "assertRx",
1555 pim_ifp->pim_ifstat_assert_recv);
1556 json_object_int_add(json_row, "assertTx",
1557 pim_ifp->pim_ifstat_assert_send);
1558 json_object_int_add(json_row, "bsmRx",
1559 pim_ifp->pim_ifstat_bsm_rx);
1560 json_object_int_add(json_row, "bsmTx",
1561 pim_ifp->pim_ifstat_bsm_tx);
1562 json_object_object_add(json, ifp->name, json_row);
1563 } else {
1564 vty_out(vty,
1565 "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64 "/%-7" PRIu64 "\n",
1566 ifp->name, pim_ifp->pim_ifstat_hello_recv,
1567 pim_ifp->pim_ifstat_hello_sent,
1568 pim_ifp->pim_ifstat_join_recv,
1569 pim_ifp->pim_ifstat_join_send,
1570 pim_ifp->pim_ifstat_prune_recv,
1571 pim_ifp->pim_ifstat_prune_send,
1572 pim_ifp->pim_ifstat_reg_recv,
1573 pim_ifp->pim_ifstat_reg_send,
1574 pim_ifp->pim_ifstat_reg_stop_recv,
1575 pim_ifp->pim_ifstat_reg_stop_send,
1576 pim_ifp->pim_ifstat_assert_recv,
1577 pim_ifp->pim_ifstat_assert_send,
1578 pim_ifp->pim_ifstat_bsm_rx,
1579 pim_ifp->pim_ifstat_bsm_tx);
1580 }
1581 }
1582 if (uj) {
1583 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1584 json, JSON_C_TO_STRING_PRETTY));
1585 json_object_free(json);
1586 }
1587 }
1588
1589 static void pim_show_interface_traffic_single(struct pim_instance *pim,
1590 struct vty *vty,
1591 const char *ifname, bool uj)
1592 {
1593 struct interface *ifp = NULL;
1594 struct pim_interface *pim_ifp = NULL;
1595 json_object *json = NULL;
1596 json_object *json_row = NULL;
1597 uint8_t found_ifname = 0;
1598
1599 if (uj)
1600 json = json_object_new_object();
1601 else {
1602 vty_out(vty, "\n");
1603 vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
1604 "Interface", " HELLO", " JOIN", " PRUNE",
1605 " REGISTER", " REGISTER-STOP", " ASSERT",
1606 " BSM");
1607 vty_out(vty, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
1608 " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
1609 " Rx/Tx", " Rx/Tx", " Rx/Tx");
1610 vty_out(vty,
1611 "-------------------------------------------------------------------------------------------------------------------------------\n");
1612 }
1613
1614 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1615 if (strcmp(ifname, ifp->name))
1616 continue;
1617
1618 pim_ifp = ifp->info;
1619
1620 if (!pim_ifp)
1621 continue;
1622
1623 if (pim_ifp->pim_sock_fd < 0)
1624 continue;
1625
1626 found_ifname = 1;
1627 if (uj) {
1628 json_row = json_object_new_object();
1629 json_object_pim_ifp_add(json_row, ifp);
1630 json_object_int_add(json_row, "helloRx",
1631 pim_ifp->pim_ifstat_hello_recv);
1632 json_object_int_add(json_row, "helloTx",
1633 pim_ifp->pim_ifstat_hello_sent);
1634 json_object_int_add(json_row, "joinRx",
1635 pim_ifp->pim_ifstat_join_recv);
1636 json_object_int_add(json_row, "joinTx",
1637 pim_ifp->pim_ifstat_join_send);
1638 json_object_int_add(json_row, "registerRx",
1639 pim_ifp->pim_ifstat_reg_recv);
1640 json_object_int_add(json_row, "registerTx",
1641 pim_ifp->pim_ifstat_reg_recv);
1642 json_object_int_add(json_row, "registerStopRx",
1643 pim_ifp->pim_ifstat_reg_stop_recv);
1644 json_object_int_add(json_row, "registerStopTx",
1645 pim_ifp->pim_ifstat_reg_stop_send);
1646 json_object_int_add(json_row, "assertRx",
1647 pim_ifp->pim_ifstat_assert_recv);
1648 json_object_int_add(json_row, "assertTx",
1649 pim_ifp->pim_ifstat_assert_send);
1650 json_object_int_add(json_row, "bsmRx",
1651 pim_ifp->pim_ifstat_bsm_rx);
1652 json_object_int_add(json_row, "bsmTx",
1653 pim_ifp->pim_ifstat_bsm_tx);
1654
1655 json_object_object_add(json, ifp->name, json_row);
1656 } else {
1657 vty_out(vty,
1658 "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64 "/%-7" PRIu64 "\n",
1659 ifp->name, pim_ifp->pim_ifstat_hello_recv,
1660 pim_ifp->pim_ifstat_hello_sent,
1661 pim_ifp->pim_ifstat_join_recv,
1662 pim_ifp->pim_ifstat_join_send,
1663 pim_ifp->pim_ifstat_prune_recv,
1664 pim_ifp->pim_ifstat_prune_send,
1665 pim_ifp->pim_ifstat_reg_recv,
1666 pim_ifp->pim_ifstat_reg_send,
1667 pim_ifp->pim_ifstat_reg_stop_recv,
1668 pim_ifp->pim_ifstat_reg_stop_send,
1669 pim_ifp->pim_ifstat_assert_recv,
1670 pim_ifp->pim_ifstat_assert_send,
1671 pim_ifp->pim_ifstat_bsm_rx,
1672 pim_ifp->pim_ifstat_bsm_tx);
1673 }
1674 }
1675 if (uj) {
1676 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1677 json, JSON_C_TO_STRING_PRETTY));
1678 json_object_free(json);
1679 } else {
1680 if (!found_ifname)
1681 vty_out(vty, "%% No such interface\n");
1682 }
1683 }
1684
1685 static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
1686 struct pim_ifchannel *ch, json_object *json,
1687 time_t now, bool uj)
1688 {
1689 char ch_src_str[INET_ADDRSTRLEN];
1690 char ch_grp_str[INET_ADDRSTRLEN];
1691 json_object *json_iface = NULL;
1692 json_object *json_row = NULL;
1693 json_object *json_grp = NULL;
1694 struct in_addr ifaddr;
1695 char uptime[10];
1696 char expire[10];
1697 char prune[10];
1698 char buf[PREFIX_STRLEN];
1699
1700 ifaddr = pim_ifp->primary_address;
1701
1702 pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str));
1703 pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str));
1704
1705 pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation);
1706 pim_time_timer_to_mmss(expire, sizeof(expire),
1707 ch->t_ifjoin_expiry_timer);
1708 pim_time_timer_to_mmss(prune, sizeof(prune),
1709 ch->t_ifjoin_prune_pending_timer);
1710
1711 if (uj) {
1712 json_object_object_get_ex(json, ch->interface->name,
1713 &json_iface);
1714
1715 if (!json_iface) {
1716 json_iface = json_object_new_object();
1717 json_object_pim_ifp_add(json_iface, ch->interface);
1718 json_object_object_add(json, ch->interface->name,
1719 json_iface);
1720 }
1721
1722 json_row = json_object_new_object();
1723 json_object_string_add(json_row, "source", ch_src_str);
1724 json_object_string_add(json_row, "group", ch_grp_str);
1725 json_object_string_add(json_row, "upTime", uptime);
1726 json_object_string_add(json_row, "expire", expire);
1727 json_object_string_add(json_row, "prune", prune);
1728 json_object_string_add(
1729 json_row, "channelJoinName",
1730 pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
1731 if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
1732 json_object_int_add(json_row, "SGRpt", 1);
1733 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
1734 json_object_int_add(json_row, "protocolPim", 1);
1735 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
1736 json_object_int_add(json_row, "protocolIgmp", 1);
1737 json_object_object_get_ex(json_iface, ch_grp_str, &json_grp);
1738 if (!json_grp) {
1739 json_grp = json_object_new_object();
1740 json_object_object_add(json_grp, ch_src_str, json_row);
1741 json_object_object_add(json_iface, ch_grp_str,
1742 json_grp);
1743 } else
1744 json_object_object_add(json_grp, ch_src_str, json_row);
1745 } else {
1746 vty_out(vty, "%-16s %-15s %-15s %-15s %-10s %8s %-6s %5s\n",
1747 ch->interface->name,
1748 inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)),
1749 ch_src_str, ch_grp_str,
1750 pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
1751 uptime, expire, prune);
1752 }
1753 }
1754
1755 static void pim_show_join(struct pim_instance *pim, struct vty *vty,
1756 struct prefix_sg *sg, bool uj)
1757 {
1758 struct pim_interface *pim_ifp;
1759 struct pim_ifchannel *ch;
1760 struct interface *ifp;
1761 time_t now;
1762 json_object *json = NULL;
1763
1764 now = pim_time_monotonic_sec();
1765
1766 if (uj)
1767 json = json_object_new_object();
1768 else
1769 vty_out(vty,
1770 "Interface Address Source Group State Uptime Expire Prune\n");
1771
1772 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1773 pim_ifp = ifp->info;
1774 if (!pim_ifp)
1775 continue;
1776
1777 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1778 if (sg->grp.s_addr != INADDR_ANY
1779 && sg->grp.s_addr != ch->sg.grp.s_addr)
1780 continue;
1781 if (sg->src.s_addr != INADDR_ANY
1782 && sg->src.s_addr != ch->sg.src.s_addr)
1783 continue;
1784 pim_show_join_helper(vty, pim_ifp, ch, json, now, uj);
1785 } /* scan interface channels */
1786 }
1787
1788 if (uj) {
1789 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1790 json, JSON_C_TO_STRING_PRETTY));
1791 json_object_free(json);
1792 }
1793 }
1794
1795 static void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
1796 const char *neighbor, bool uj)
1797 {
1798 struct listnode *neighnode;
1799 struct interface *ifp;
1800 struct pim_interface *pim_ifp;
1801 struct pim_neighbor *neigh;
1802 time_t now;
1803 int found_neighbor = 0;
1804 int option_address_list;
1805 int option_dr_priority;
1806 int option_generation_id;
1807 int option_holdtime;
1808 int option_lan_prune_delay;
1809 int option_t_bit;
1810 char uptime[10];
1811 char expire[10];
1812 char neigh_src_str[INET_ADDRSTRLEN];
1813
1814 json_object *json = NULL;
1815 json_object *json_ifp = NULL;
1816 json_object *json_row = NULL;
1817
1818 now = pim_time_monotonic_sec();
1819
1820 if (uj)
1821 json = json_object_new_object();
1822
1823 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1824 pim_ifp = ifp->info;
1825
1826 if (!pim_ifp)
1827 continue;
1828
1829 if (pim_ifp->pim_sock_fd < 0)
1830 continue;
1831
1832 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
1833 neigh)) {
1834 pim_inet4_dump("<src?>", neigh->source_addr,
1835 neigh_src_str, sizeof(neigh_src_str));
1836
1837 /*
1838 * The user can specify either the interface name or the
1839 * PIM neighbor IP.
1840 * If this pim_ifp matches neither then skip.
1841 */
1842 if (strcmp(neighbor, "detail")
1843 && strcmp(neighbor, ifp->name)
1844 && strcmp(neighbor, neigh_src_str))
1845 continue;
1846
1847 found_neighbor = 1;
1848 pim_time_uptime(uptime, sizeof(uptime),
1849 now - neigh->creation);
1850 pim_time_timer_to_hhmmss(expire, sizeof(expire),
1851 neigh->t_expire_timer);
1852
1853 option_address_list = 0;
1854 option_dr_priority = 0;
1855 option_generation_id = 0;
1856 option_holdtime = 0;
1857 option_lan_prune_delay = 0;
1858 option_t_bit = 0;
1859
1860 if (PIM_OPTION_IS_SET(neigh->hello_options,
1861 PIM_OPTION_MASK_ADDRESS_LIST))
1862 option_address_list = 1;
1863
1864 if (PIM_OPTION_IS_SET(neigh->hello_options,
1865 PIM_OPTION_MASK_DR_PRIORITY))
1866 option_dr_priority = 1;
1867
1868 if (PIM_OPTION_IS_SET(neigh->hello_options,
1869 PIM_OPTION_MASK_GENERATION_ID))
1870 option_generation_id = 1;
1871
1872 if (PIM_OPTION_IS_SET(neigh->hello_options,
1873 PIM_OPTION_MASK_HOLDTIME))
1874 option_holdtime = 1;
1875
1876 if (PIM_OPTION_IS_SET(neigh->hello_options,
1877 PIM_OPTION_MASK_LAN_PRUNE_DELAY))
1878 option_lan_prune_delay = 1;
1879
1880 if (PIM_OPTION_IS_SET(
1881 neigh->hello_options,
1882 PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION))
1883 option_t_bit = 1;
1884
1885 if (uj) {
1886
1887 /* Does this ifp live in json? If not create
1888 * it. */
1889 json_object_object_get_ex(json, ifp->name,
1890 &json_ifp);
1891
1892 if (!json_ifp) {
1893 json_ifp = json_object_new_object();
1894 json_object_pim_ifp_add(json_ifp, ifp);
1895 json_object_object_add(json, ifp->name,
1896 json_ifp);
1897 }
1898
1899 json_row = json_object_new_object();
1900 json_object_string_add(json_row, "interface",
1901 ifp->name);
1902 json_object_string_add(json_row, "address",
1903 neigh_src_str);
1904 json_object_string_add(json_row, "upTime",
1905 uptime);
1906 json_object_string_add(json_row, "holdtime",
1907 expire);
1908 json_object_int_add(json_row, "drPriority",
1909 neigh->dr_priority);
1910 json_object_int_add(json_row, "generationId",
1911 neigh->generation_id);
1912
1913 if (option_address_list)
1914 json_object_boolean_true_add(
1915 json_row,
1916 "helloOptionAddressList");
1917
1918 if (option_dr_priority)
1919 json_object_boolean_true_add(
1920 json_row,
1921 "helloOptionDrPriority");
1922
1923 if (option_generation_id)
1924 json_object_boolean_true_add(
1925 json_row,
1926 "helloOptionGenerationId");
1927
1928 if (option_holdtime)
1929 json_object_boolean_true_add(
1930 json_row,
1931 "helloOptionHoldtime");
1932
1933 if (option_lan_prune_delay)
1934 json_object_boolean_true_add(
1935 json_row,
1936 "helloOptionLanPruneDelay");
1937
1938 if (option_t_bit)
1939 json_object_boolean_true_add(
1940 json_row, "helloOptionTBit");
1941
1942 json_object_object_add(json_ifp, neigh_src_str,
1943 json_row);
1944
1945 } else {
1946 vty_out(vty, "Interface : %s\n", ifp->name);
1947 vty_out(vty, "Neighbor : %s\n", neigh_src_str);
1948 vty_out(vty,
1949 " Uptime : %s\n",
1950 uptime);
1951 vty_out(vty,
1952 " Holdtime : %s\n",
1953 expire);
1954 vty_out(vty,
1955 " DR Priority : %d\n",
1956 neigh->dr_priority);
1957 vty_out(vty,
1958 " Generation ID : %08x\n",
1959 neigh->generation_id);
1960 vty_out(vty,
1961 " Override Interval (msec) : %d\n",
1962 neigh->override_interval_msec);
1963 vty_out(vty,
1964 " Propagation Delay (msec) : %d\n",
1965 neigh->propagation_delay_msec);
1966 vty_out(vty,
1967 " Hello Option - Address List : %s\n",
1968 option_address_list ? "yes" : "no");
1969 vty_out(vty,
1970 " Hello Option - DR Priority : %s\n",
1971 option_dr_priority ? "yes" : "no");
1972 vty_out(vty,
1973 " Hello Option - Generation ID : %s\n",
1974 option_generation_id ? "yes" : "no");
1975 vty_out(vty,
1976 " Hello Option - Holdtime : %s\n",
1977 option_holdtime ? "yes" : "no");
1978 vty_out(vty,
1979 " Hello Option - LAN Prune Delay : %s\n",
1980 option_lan_prune_delay ? "yes" : "no");
1981 vty_out(vty,
1982 " Hello Option - T-bit : %s\n",
1983 option_t_bit ? "yes" : "no");
1984 bfd_sess_show(vty, json_ifp,
1985 neigh->bfd_session);
1986 vty_out(vty, "\n");
1987 }
1988 }
1989 }
1990
1991 if (uj) {
1992 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1993 json, JSON_C_TO_STRING_PRETTY));
1994 json_object_free(json);
1995 } else {
1996 {
1997 if (!found_neighbor)
1998 vty_out(vty,
1999 "%% No such interface or neighbor\n");
2000 }
2001 }
2002 }
2003
2004 static void pim_show_state(struct pim_instance *pim, struct vty *vty,
2005 const char *src_or_group, const char *group, bool uj)
2006 {
2007 struct channel_oil *c_oil;
2008 json_object *json = NULL;
2009 json_object *json_group = NULL;
2010 json_object *json_ifp_in = NULL;
2011 json_object *json_ifp_out = NULL;
2012 json_object *json_source = NULL;
2013 time_t now;
2014 int first_oif;
2015 now = pim_time_monotonic_sec();
2016
2017 if (uj) {
2018 json = json_object_new_object();
2019 } else {
2020 vty_out(vty,
2021 "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted");
2022 vty_out(vty,
2023 "\nActive Source Group RPT IIF OIL\n");
2024 }
2025
2026 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
2027 char grp_str[INET_ADDRSTRLEN];
2028 char src_str[INET_ADDRSTRLEN];
2029 char in_ifname[INTERFACE_NAMSIZ + 1];
2030 char out_ifname[INTERFACE_NAMSIZ + 1];
2031 int oif_vif_index;
2032 struct interface *ifp_in;
2033 bool isRpt;
2034 first_oif = 1;
2035
2036 if ((c_oil->up &&
2037 PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil->up->flags)) ||
2038 c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
2039 isRpt = true;
2040 else
2041 isRpt = false;
2042
2043 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str,
2044 sizeof(grp_str));
2045 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str,
2046 sizeof(src_str));
2047 ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent);
2048
2049 if (ifp_in)
2050 strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
2051 else
2052 strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
2053
2054 if (src_or_group) {
2055 if (strcmp(src_or_group, src_str)
2056 && strcmp(src_or_group, grp_str))
2057 continue;
2058
2059 if (group && strcmp(group, grp_str))
2060 continue;
2061 }
2062
2063 if (uj) {
2064
2065 /* Find the group, create it if it doesn't exist */
2066 json_object_object_get_ex(json, grp_str, &json_group);
2067
2068 if (!json_group) {
2069 json_group = json_object_new_object();
2070 json_object_object_add(json, grp_str,
2071 json_group);
2072 }
2073
2074 /* Find the source nested under the group, create it if
2075 * it doesn't exist */
2076 json_object_object_get_ex(json_group, src_str,
2077 &json_source);
2078
2079 if (!json_source) {
2080 json_source = json_object_new_object();
2081 json_object_object_add(json_group, src_str,
2082 json_source);
2083 }
2084
2085 /* Find the inbound interface nested under the source,
2086 * create it if it doesn't exist */
2087 json_object_object_get_ex(json_source, in_ifname,
2088 &json_ifp_in);
2089
2090 if (!json_ifp_in) {
2091 json_ifp_in = json_object_new_object();
2092 json_object_object_add(json_source, in_ifname,
2093 json_ifp_in);
2094 json_object_int_add(json_source, "Installed",
2095 c_oil->installed);
2096 if (isRpt)
2097 json_object_boolean_true_add(
2098 json_source, "isRpt");
2099 else
2100 json_object_boolean_false_add(
2101 json_source, "isRpt");
2102 json_object_int_add(json_source, "RefCount",
2103 c_oil->oil_ref_count);
2104 json_object_int_add(json_source, "OilListSize",
2105 c_oil->oil_size);
2106 json_object_int_add(
2107 json_source, "OilRescan",
2108 c_oil->oil_inherited_rescan);
2109 json_object_int_add(json_source, "LastUsed",
2110 c_oil->cc.lastused);
2111 json_object_int_add(json_source, "PacketCount",
2112 c_oil->cc.pktcnt);
2113 json_object_int_add(json_source, "ByteCount",
2114 c_oil->cc.bytecnt);
2115 json_object_int_add(json_source,
2116 "WrongInterface",
2117 c_oil->cc.wrong_if);
2118 }
2119 } else {
2120 vty_out(vty, "%-6d %-15s %-15s %-3s %-16s ",
2121 c_oil->installed, src_str, grp_str,
2122 isRpt ? "y" : "n", in_ifname);
2123 }
2124
2125 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
2126 ++oif_vif_index) {
2127 struct interface *ifp_out;
2128 char oif_uptime[10];
2129 int ttl;
2130
2131 ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
2132 if (ttl < 1)
2133 continue;
2134
2135 ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
2136 pim_time_uptime(
2137 oif_uptime, sizeof(oif_uptime),
2138 now - c_oil->oif_creation[oif_vif_index]);
2139
2140 if (ifp_out)
2141 strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname));
2142 else
2143 strlcpy(out_ifname, "<oif?>", sizeof(out_ifname));
2144
2145 if (uj) {
2146 json_ifp_out = json_object_new_object();
2147 json_object_string_add(json_ifp_out, "source",
2148 src_str);
2149 json_object_string_add(json_ifp_out, "group",
2150 grp_str);
2151 json_object_string_add(json_ifp_out,
2152 "inboundInterface",
2153 in_ifname);
2154 json_object_string_add(json_ifp_out,
2155 "outboundInterface",
2156 out_ifname);
2157 json_object_int_add(json_ifp_out, "installed",
2158 c_oil->installed);
2159
2160 json_object_object_add(json_ifp_in, out_ifname,
2161 json_ifp_out);
2162 } else {
2163 if (first_oif) {
2164 first_oif = 0;
2165 vty_out(vty, "%s(%c%c%c%c%c)",
2166 out_ifname,
2167 (c_oil->oif_flags[oif_vif_index]
2168 & PIM_OIF_FLAG_PROTO_IGMP)
2169 ? 'I'
2170 : ' ',
2171 (c_oil->oif_flags[oif_vif_index]
2172 & PIM_OIF_FLAG_PROTO_PIM)
2173 ? 'J'
2174 : ' ',
2175 (c_oil->oif_flags[oif_vif_index]
2176 & PIM_OIF_FLAG_PROTO_VXLAN)
2177 ? 'V'
2178 : ' ',
2179 (c_oil->oif_flags[oif_vif_index]
2180 & PIM_OIF_FLAG_PROTO_STAR)
2181 ? '*'
2182 : ' ',
2183 (c_oil->oif_flags[oif_vif_index]
2184 & PIM_OIF_FLAG_MUTE)
2185 ? 'M'
2186 : ' ');
2187 } else
2188 vty_out(vty, ", %s(%c%c%c%c%c)",
2189 out_ifname,
2190 (c_oil->oif_flags[oif_vif_index]
2191 & PIM_OIF_FLAG_PROTO_IGMP)
2192 ? 'I'
2193 : ' ',
2194 (c_oil->oif_flags[oif_vif_index]
2195 & PIM_OIF_FLAG_PROTO_PIM)
2196 ? 'J'
2197 : ' ',
2198 (c_oil->oif_flags[oif_vif_index]
2199 & PIM_OIF_FLAG_PROTO_VXLAN)
2200 ? 'V'
2201 : ' ',
2202 (c_oil->oif_flags[oif_vif_index]
2203 & PIM_OIF_FLAG_PROTO_STAR)
2204 ? '*'
2205 : ' ',
2206 (c_oil->oif_flags[oif_vif_index]
2207 & PIM_OIF_FLAG_MUTE)
2208 ? 'M'
2209 : ' ');
2210 }
2211 }
2212
2213 if (!uj)
2214 vty_out(vty, "\n");
2215 }
2216
2217
2218 if (uj) {
2219 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2220 json, JSON_C_TO_STRING_PRETTY));
2221 json_object_free(json);
2222 } else {
2223 vty_out(vty, "\n");
2224 }
2225 }
2226
2227 static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
2228 bool uj)
2229 {
2230 struct listnode *neighnode;
2231 struct interface *ifp;
2232 struct pim_interface *pim_ifp;
2233 struct pim_neighbor *neigh;
2234 time_t now;
2235 char uptime[10];
2236 char expire[10];
2237 char neigh_src_str[INET_ADDRSTRLEN];
2238 json_object *json = NULL;
2239 json_object *json_ifp_rows = NULL;
2240 json_object *json_row = NULL;
2241
2242 now = pim_time_monotonic_sec();
2243
2244 if (uj) {
2245 json = json_object_new_object();
2246 } else {
2247 vty_out(vty,
2248 "Interface Neighbor Uptime Holdtime DR Pri\n");
2249 }
2250
2251 FOR_ALL_INTERFACES (pim->vrf, ifp) {
2252 pim_ifp = ifp->info;
2253
2254 if (!pim_ifp)
2255 continue;
2256
2257 if (pim_ifp->pim_sock_fd < 0)
2258 continue;
2259
2260 if (uj)
2261 json_ifp_rows = json_object_new_object();
2262
2263 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
2264 neigh)) {
2265 pim_inet4_dump("<src?>", neigh->source_addr,
2266 neigh_src_str, sizeof(neigh_src_str));
2267 pim_time_uptime(uptime, sizeof(uptime),
2268 now - neigh->creation);
2269 pim_time_timer_to_hhmmss(expire, sizeof(expire),
2270 neigh->t_expire_timer);
2271
2272 if (uj) {
2273 json_row = json_object_new_object();
2274 json_object_string_add(json_row, "interface",
2275 ifp->name);
2276 json_object_string_add(json_row, "neighbor",
2277 neigh_src_str);
2278 json_object_string_add(json_row, "upTime",
2279 uptime);
2280 json_object_string_add(json_row, "holdTime",
2281 expire);
2282 json_object_int_add(json_row, "holdTimeMax",
2283 neigh->holdtime);
2284 json_object_int_add(json_row, "drPriority",
2285 neigh->dr_priority);
2286 json_object_object_add(json_ifp_rows,
2287 neigh_src_str, json_row);
2288
2289 } else {
2290 vty_out(vty, "%-16s %15s %8s %8s %6d\n",
2291 ifp->name, neigh_src_str, uptime,
2292 expire, neigh->dr_priority);
2293 }
2294 }
2295
2296 if (uj) {
2297 json_object_object_add(json, ifp->name, json_ifp_rows);
2298 json_ifp_rows = NULL;
2299 }
2300 }
2301
2302 if (uj) {
2303 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2304 json, JSON_C_TO_STRING_PRETTY));
2305 json_object_free(json);
2306 }
2307 }
2308
2309 static void pim_show_neighbors_secondary(struct pim_instance *pim,
2310 struct vty *vty)
2311 {
2312 struct interface *ifp;
2313
2314 vty_out(vty,
2315 "Interface Address Neighbor Secondary \n");
2316
2317 FOR_ALL_INTERFACES (pim->vrf, ifp) {
2318 struct pim_interface *pim_ifp;
2319 struct in_addr ifaddr;
2320 struct listnode *neighnode;
2321 struct pim_neighbor *neigh;
2322 char buf[PREFIX_STRLEN];
2323
2324 pim_ifp = ifp->info;
2325
2326 if (!pim_ifp)
2327 continue;
2328
2329 if (pim_ifp->pim_sock_fd < 0)
2330 continue;
2331
2332 ifaddr = pim_ifp->primary_address;
2333
2334 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
2335 neigh)) {
2336 char neigh_src_str[INET_ADDRSTRLEN];
2337 struct listnode *prefix_node;
2338 struct prefix *p;
2339
2340 if (!neigh->prefix_list)
2341 continue;
2342
2343 pim_inet4_dump("<src?>", neigh->source_addr,
2344 neigh_src_str, sizeof(neigh_src_str));
2345
2346 for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list,
2347 prefix_node, p))
2348 vty_out(vty, "%-16s %-15s %-15s %-15pFX\n",
2349 ifp->name,
2350 inet_ntop(AF_INET, &ifaddr,
2351 buf, sizeof(buf)),
2352 neigh_src_str, p);
2353 }
2354 }
2355 }
2356
2357 static void json_object_pim_upstream_add(json_object *json,
2358 struct pim_upstream *up)
2359 {
2360 if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
2361 json_object_boolean_true_add(json, "drJoinDesired");
2362
2363 if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
2364 json_object_boolean_true_add(json, "drJoinDesiredUpdated");
2365
2366 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
2367 json_object_boolean_true_add(json, "firstHopRouter");
2368
2369 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
2370 json_object_boolean_true_add(json, "sourceIgmp");
2371
2372 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
2373 json_object_boolean_true_add(json, "sourcePim");
2374
2375 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
2376 json_object_boolean_true_add(json, "sourceStream");
2377
2378 /* XXX: need to print ths flag in the plain text display as well */
2379 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
2380 json_object_boolean_true_add(json, "sourceMsdp");
2381
2382 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
2383 json_object_boolean_true_add(json, "sendSGRptPrune");
2384
2385 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
2386 json_object_boolean_true_add(json, "lastHopRouter");
2387
2388 if (up->flags & PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY)
2389 json_object_boolean_true_add(json, "disableKATExpiry");
2390
2391 if (up->flags & PIM_UPSTREAM_FLAG_MASK_STATIC_IIF)
2392 json_object_boolean_true_add(json, "staticIncomingInterface");
2393
2394 if (up->flags & PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL)
2395 json_object_boolean_true_add(json,
2396 "allowIncomingInterfaceinOil");
2397
2398 if (up->flags & PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA)
2399 json_object_boolean_true_add(json, "noPimRegistrationData");
2400
2401 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG)
2402 json_object_boolean_true_add(json, "forcePimRegistration");
2403
2404 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG)
2405 json_object_boolean_true_add(json, "sourceVxlanOrigination");
2406
2407 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM)
2408 json_object_boolean_true_add(json, "sourceVxlanTermination");
2409
2410 if (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN)
2411 json_object_boolean_true_add(json, "mlagVxlan");
2412
2413 if (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF)
2414 json_object_boolean_true_add(json,
2415 "mlagNonDesignatedForwarder");
2416 }
2417
2418 static const char *
2419 pim_upstream_state2brief_str(enum pim_upstream_state join_state,
2420 char *state_str, size_t state_str_len)
2421 {
2422 switch (join_state) {
2423 case PIM_UPSTREAM_NOTJOINED:
2424 strlcpy(state_str, "NotJ", state_str_len);
2425 break;
2426 case PIM_UPSTREAM_JOINED:
2427 strlcpy(state_str, "J", state_str_len);
2428 break;
2429 default:
2430 strlcpy(state_str, "Unk", state_str_len);
2431 }
2432 return state_str;
2433 }
2434
2435 static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state,
2436 char *state_str, size_t state_str_len)
2437 {
2438 switch (reg_state) {
2439 case PIM_REG_NOINFO:
2440 strlcpy(state_str, "RegNI", state_str_len);
2441 break;
2442 case PIM_REG_JOIN:
2443 strlcpy(state_str, "RegJ", state_str_len);
2444 break;
2445 case PIM_REG_JOIN_PENDING:
2446 case PIM_REG_PRUNE:
2447 strlcpy(state_str, "RegP", state_str_len);
2448 break;
2449 default:
2450 strlcpy(state_str, "Unk", state_str_len);
2451 }
2452 return state_str;
2453 }
2454
2455 static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
2456 struct prefix_sg *sg, bool uj)
2457 {
2458 struct pim_upstream *up;
2459 time_t now;
2460 json_object *json = NULL;
2461 json_object *json_group = NULL;
2462 json_object *json_row = NULL;
2463
2464 now = pim_time_monotonic_sec();
2465
2466 if (uj)
2467 json = json_object_new_object();
2468 else
2469 vty_out(vty,
2470 "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n");
2471
2472 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
2473 char src_str[INET_ADDRSTRLEN];
2474 char grp_str[INET_ADDRSTRLEN];
2475 char uptime[10];
2476 char join_timer[10];
2477 char rs_timer[10];
2478 char ka_timer[10];
2479 char msdp_reg_timer[10];
2480 char state_str[PIM_REG_STATE_STR_LEN];
2481
2482 if (sg->grp.s_addr != INADDR_ANY
2483 && sg->grp.s_addr != up->sg.grp.s_addr)
2484 continue;
2485 if (sg->src.s_addr != INADDR_ANY
2486 && sg->src.s_addr != up->sg.src.s_addr)
2487 continue;
2488
2489 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
2490 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
2491 pim_time_uptime(uptime, sizeof(uptime),
2492 now - up->state_transition);
2493 pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer),
2494 up->t_join_timer);
2495
2496 /*
2497 * If the upstream is not dummy and it has a J/P timer for the
2498 * neighbor display that
2499 */
2500 if (!up->t_join_timer && up->rpf.source_nexthop.interface) {
2501 struct pim_neighbor *nbr;
2502
2503 nbr = pim_neighbor_find(
2504 up->rpf.source_nexthop.interface,
2505 up->rpf.rpf_addr.u.prefix4);
2506 if (nbr)
2507 pim_time_timer_to_hhmmss(join_timer,
2508 sizeof(join_timer),
2509 nbr->jp_timer);
2510 }
2511
2512 pim_time_timer_to_hhmmss(rs_timer, sizeof(rs_timer),
2513 up->t_rs_timer);
2514 pim_time_timer_to_hhmmss(ka_timer, sizeof(ka_timer),
2515 up->t_ka_timer);
2516 pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer),
2517 up->t_msdp_reg_timer);
2518
2519 pim_upstream_state2brief_str(up->join_state, state_str, sizeof(state_str));
2520 if (up->reg_state != PIM_REG_NOINFO) {
2521 char tmp_str[PIM_REG_STATE_STR_LEN];
2522 char tmp[sizeof(state_str) + 1];
2523
2524 snprintf(tmp, sizeof(tmp), ",%s",
2525 pim_reg_state2brief_str(up->reg_state, tmp_str,
2526 sizeof(tmp_str)));
2527 strlcat(state_str, tmp, sizeof(state_str));
2528 }
2529
2530 if (uj) {
2531 json_object_object_get_ex(json, grp_str, &json_group);
2532
2533 if (!json_group) {
2534 json_group = json_object_new_object();
2535 json_object_object_add(json, grp_str,
2536 json_group);
2537 }
2538
2539 json_row = json_object_new_object();
2540 json_object_pim_upstream_add(json_row, up);
2541 json_object_string_add(
2542 json_row, "inboundInterface",
2543 up->rpf.source_nexthop.interface
2544 ? up->rpf.source_nexthop.interface->name
2545 : "Unknown");
2546
2547 /*
2548 * The RPF address we use is slightly different
2549 * based upon what we are looking up.
2550 * If we have a S, list that unless
2551 * we are the FHR, else we just put
2552 * the RP as the rpfAddress
2553 */
2554 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR
2555 || up->sg.src.s_addr == INADDR_ANY) {
2556 char rpf[PREFIX_STRLEN];
2557 struct pim_rpf *rpg;
2558
2559 rpg = RP(pim, up->sg.grp);
2560 pim_inet4_dump("<rpf?>",
2561 rpg->rpf_addr.u.prefix4, rpf,
2562 sizeof(rpf));
2563 json_object_string_add(json_row, "rpfAddress",
2564 rpf);
2565 } else {
2566 json_object_string_add(json_row, "rpfAddress",
2567 src_str);
2568 }
2569
2570 json_object_string_add(json_row, "source", src_str);
2571 json_object_string_add(json_row, "group", grp_str);
2572 json_object_string_add(json_row, "state", state_str);
2573 json_object_string_add(
2574 json_row, "joinState",
2575 pim_upstream_state2str(up->join_state));
2576 json_object_string_add(
2577 json_row, "regState",
2578 pim_reg_state2str(up->reg_state, state_str, sizeof(state_str)));
2579 json_object_string_add(json_row, "upTime", uptime);
2580 json_object_string_add(json_row, "joinTimer",
2581 join_timer);
2582 json_object_string_add(json_row, "resetTimer",
2583 rs_timer);
2584 json_object_string_add(json_row, "keepaliveTimer",
2585 ka_timer);
2586 json_object_string_add(json_row, "msdpRegTimer",
2587 msdp_reg_timer);
2588 json_object_int_add(json_row, "refCount",
2589 up->ref_count);
2590 json_object_int_add(json_row, "sptBit", up->sptbit);
2591 json_object_object_add(json_group, src_str, json_row);
2592 } else {
2593 vty_out(vty,
2594 "%-16s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n",
2595 up->rpf.source_nexthop.interface
2596 ? up->rpf.source_nexthop.interface->name
2597 : "Unknown",
2598 src_str, grp_str, state_str, uptime, join_timer,
2599 rs_timer, ka_timer, up->ref_count);
2600 }
2601 }
2602
2603 if (uj) {
2604 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2605 json, JSON_C_TO_STRING_PRETTY));
2606 json_object_free(json);
2607 }
2608 }
2609
2610 static void pim_show_channel_helper(struct pim_instance *pim,
2611 struct vty *vty,
2612 struct pim_interface *pim_ifp,
2613 struct pim_ifchannel *ch,
2614 json_object *json, bool uj)
2615 {
2616 struct pim_upstream *up = ch->upstream;
2617 json_object *json_group = NULL;
2618 char src_str[INET_ADDRSTRLEN];
2619 char grp_str[INET_ADDRSTRLEN];
2620 json_object *json_row = NULL;
2621
2622 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
2623 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
2624
2625 if (uj) {
2626 json_object_object_get_ex(json, grp_str, &json_group);
2627
2628 if (!json_group) {
2629 json_group = json_object_new_object();
2630 json_object_object_add(json, grp_str, json_group);
2631 }
2632
2633 json_row = json_object_new_object();
2634 json_object_pim_upstream_add(json_row, up);
2635 json_object_string_add(json_row, "interface",
2636 ch->interface->name);
2637 json_object_string_add(json_row, "source", src_str);
2638 json_object_string_add(json_row, "group", grp_str);
2639
2640 if (pim_macro_ch_lost_assert(ch))
2641 json_object_boolean_true_add(json_row, "lostAssert");
2642
2643 if (pim_macro_chisin_joins(ch))
2644 json_object_boolean_true_add(json_row, "joins");
2645
2646 if (pim_macro_chisin_pim_include(ch))
2647 json_object_boolean_true_add(json_row, "pimInclude");
2648
2649 if (pim_upstream_evaluate_join_desired(pim, up))
2650 json_object_boolean_true_add(json_row,
2651 "evaluateJoinDesired");
2652
2653 json_object_object_add(json_group, src_str, json_row);
2654
2655 } else {
2656 vty_out(vty, "%-16s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n",
2657 ch->interface->name, src_str, grp_str,
2658 pim_macro_ch_lost_assert(ch) ? "yes" : "no",
2659 pim_macro_chisin_joins(ch) ? "yes" : "no",
2660 pim_macro_chisin_pim_include(ch) ? "yes" : "no",
2661 PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags)
2662 ? "yes"
2663 : "no",
2664 pim_upstream_evaluate_join_desired(pim, up) ? "yes"
2665 : "no");
2666 }
2667 }
2668
2669 static void pim_show_channel(struct pim_instance *pim, struct vty *vty,
2670 bool uj)
2671 {
2672 struct pim_interface *pim_ifp;
2673 struct pim_ifchannel *ch;
2674 struct interface *ifp;
2675
2676 json_object *json = NULL;
2677
2678 if (uj)
2679 json = json_object_new_object();
2680 else
2681 vty_out(vty,
2682 "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n");
2683
2684 /* scan per-interface (S,G) state */
2685 FOR_ALL_INTERFACES (pim->vrf, ifp) {
2686 pim_ifp = ifp->info;
2687 if (!pim_ifp)
2688 continue;
2689
2690
2691 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
2692 /* scan all interfaces */
2693 pim_show_channel_helper(pim, vty, pim_ifp, ch,
2694 json, uj);
2695 }
2696 }
2697
2698 if (uj) {
2699 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2700 json, JSON_C_TO_STRING_PRETTY));
2701 json_object_free(json);
2702 }
2703 }
2704
2705 static void pim_show_join_desired_helper(struct pim_instance *pim,
2706 struct vty *vty,
2707 struct pim_upstream *up,
2708 json_object *json, bool uj)
2709 {
2710 json_object *json_group = NULL;
2711 char src_str[INET_ADDRSTRLEN];
2712 char grp_str[INET_ADDRSTRLEN];
2713 json_object *json_row = NULL;
2714
2715 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
2716 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
2717
2718 if (uj) {
2719 json_object_object_get_ex(json, grp_str, &json_group);
2720
2721 if (!json_group) {
2722 json_group = json_object_new_object();
2723 json_object_object_add(json, grp_str, json_group);
2724 }
2725
2726 json_row = json_object_new_object();
2727 json_object_pim_upstream_add(json_row, up);
2728 json_object_string_add(json_row, "source", src_str);
2729 json_object_string_add(json_row, "group", grp_str);
2730
2731 if (pim_upstream_evaluate_join_desired(pim, up))
2732 json_object_boolean_true_add(json_row,
2733 "evaluateJoinDesired");
2734
2735 json_object_object_add(json_group, src_str, json_row);
2736
2737 } else {
2738 vty_out(vty, "%-15s %-15s %-6s\n",
2739 src_str, grp_str,
2740 pim_upstream_evaluate_join_desired(pim, up) ? "yes"
2741 : "no");
2742 }
2743 }
2744
2745 static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty,
2746 bool uj)
2747 {
2748 struct pim_upstream *up;
2749
2750 json_object *json = NULL;
2751
2752 if (uj)
2753 json = json_object_new_object();
2754 else
2755 vty_out(vty,
2756 "Source Group EvalJD\n");
2757
2758 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
2759 /* scan all interfaces */
2760 pim_show_join_desired_helper(pim, vty, up,
2761 json, uj);
2762 }
2763
2764 if (uj) {
2765 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2766 json, JSON_C_TO_STRING_PRETTY));
2767 json_object_free(json);
2768 }
2769 }
2770
2771 static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty,
2772 bool uj)
2773 {
2774 struct pim_upstream *up;
2775 json_object *json = NULL;
2776 json_object *json_group = NULL;
2777 json_object *json_row = NULL;
2778
2779 if (uj)
2780 json = json_object_new_object();
2781 else
2782 vty_out(vty,
2783 "Source Group RpfIface RibNextHop RpfAddress \n");
2784
2785 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
2786 char src_str[INET_ADDRSTRLEN];
2787 char grp_str[INET_ADDRSTRLEN];
2788 char rpf_nexthop_str[PREFIX_STRLEN];
2789 char rpf_addr_str[PREFIX_STRLEN];
2790 struct pim_rpf *rpf;
2791 const char *rpf_ifname;
2792
2793 rpf = &up->rpf;
2794
2795 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
2796 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
2797 pim_addr_dump("<nexthop?>",
2798 &rpf->source_nexthop.mrib_nexthop_addr,
2799 rpf_nexthop_str, sizeof(rpf_nexthop_str));
2800 pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str,
2801 sizeof(rpf_addr_str));
2802
2803 rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
2804
2805 if (uj) {
2806 json_object_object_get_ex(json, grp_str, &json_group);
2807
2808 if (!json_group) {
2809 json_group = json_object_new_object();
2810 json_object_object_add(json, grp_str,
2811 json_group);
2812 }
2813
2814 json_row = json_object_new_object();
2815 json_object_pim_upstream_add(json_row, up);
2816 json_object_string_add(json_row, "source", src_str);
2817 json_object_string_add(json_row, "group", grp_str);
2818 json_object_string_add(json_row, "rpfInterface",
2819 rpf_ifname);
2820 json_object_string_add(json_row, "ribNexthop",
2821 rpf_nexthop_str);
2822 json_object_string_add(json_row, "rpfAddress",
2823 rpf_addr_str);
2824 json_object_object_add(json_group, src_str, json_row);
2825 } else {
2826 vty_out(vty, "%-15s %-15s %-16s %-15s %-15s\n", src_str,
2827 grp_str, rpf_ifname, rpf_nexthop_str,
2828 rpf_addr_str);
2829 }
2830 }
2831
2832 if (uj) {
2833 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2834 json, JSON_C_TO_STRING_PRETTY));
2835 json_object_free(json);
2836 }
2837 }
2838
2839 static void show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
2840 time_t now, json_object *json)
2841 {
2842 char refresh_uptime[10];
2843
2844 pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now,
2845 pim->rpf_cache_refresh_last);
2846
2847 if (json) {
2848 json_object_int_add(json, "rpfCacheRefreshDelayMsecs",
2849 router->rpf_cache_refresh_delay_msec);
2850 json_object_int_add(
2851 json, "rpfCacheRefreshTimer",
2852 pim_time_timer_remain_msec(pim->rpf_cache_refresher));
2853 json_object_int_add(json, "rpfCacheRefreshRequests",
2854 pim->rpf_cache_refresh_requests);
2855 json_object_int_add(json, "rpfCacheRefreshEvents",
2856 pim->rpf_cache_refresh_events);
2857 json_object_string_add(json, "rpfCacheRefreshLast",
2858 refresh_uptime);
2859 json_object_int_add(json, "nexthopLookups",
2860 pim->nexthop_lookups);
2861 json_object_int_add(json, "nexthopLookupsAvoided",
2862 pim->nexthop_lookups_avoided);
2863 } else {
2864 vty_out(vty,
2865 "RPF Cache Refresh Delay: %ld msecs\n"
2866 "RPF Cache Refresh Timer: %ld msecs\n"
2867 "RPF Cache Refresh Requests: %lld\n"
2868 "RPF Cache Refresh Events: %lld\n"
2869 "RPF Cache Refresh Last: %s\n"
2870 "Nexthop Lookups: %lld\n"
2871 "Nexthop Lookups Avoided: %lld\n",
2872 router->rpf_cache_refresh_delay_msec,
2873 pim_time_timer_remain_msec(pim->rpf_cache_refresher),
2874 (long long)pim->rpf_cache_refresh_requests,
2875 (long long)pim->rpf_cache_refresh_events,
2876 refresh_uptime, (long long)pim->nexthop_lookups,
2877 (long long)pim->nexthop_lookups_avoided);
2878 }
2879 }
2880
2881 static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
2882 time_t now)
2883 {
2884 char uptime_scan_oil[10];
2885 char uptime_mroute_add[10];
2886 char uptime_mroute_del[10];
2887
2888 pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now,
2889 pim->scan_oil_last);
2890 pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now,
2891 pim->mroute_add_last);
2892 pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now,
2893 pim->mroute_del_last);
2894
2895 vty_out(vty,
2896 "Scan OIL - Last: %s Events: %lld\n"
2897 "MFC Add - Last: %s Events: %lld\n"
2898 "MFC Del - Last: %s Events: %lld\n",
2899 uptime_scan_oil, (long long)pim->scan_oil_events,
2900 uptime_mroute_add, (long long)pim->mroute_add_events,
2901 uptime_mroute_del, (long long)pim->mroute_del_events);
2902 }
2903
2904 static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
2905 {
2906 struct pim_upstream *up;
2907 time_t now = pim_time_monotonic_sec();
2908 json_object *json = NULL;
2909 json_object *json_group = NULL;
2910 json_object *json_row = NULL;
2911
2912 if (uj) {
2913 json = json_object_new_object();
2914 show_rpf_refresh_stats(vty, pim, now, json);
2915 } else {
2916 show_rpf_refresh_stats(vty, pim, now, json);
2917 vty_out(vty, "\n");
2918 vty_out(vty,
2919 "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n");
2920 }
2921
2922 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
2923 char src_str[INET_ADDRSTRLEN];
2924 char grp_str[INET_ADDRSTRLEN];
2925 char rpf_addr_str[PREFIX_STRLEN];
2926 char rib_nexthop_str[PREFIX_STRLEN];
2927 const char *rpf_ifname;
2928 struct pim_rpf *rpf = &up->rpf;
2929
2930 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
2931 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
2932 pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str,
2933 sizeof(rpf_addr_str));
2934 pim_addr_dump("<nexthop?>",
2935 &rpf->source_nexthop.mrib_nexthop_addr,
2936 rib_nexthop_str, sizeof(rib_nexthop_str));
2937
2938 rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
2939
2940 if (uj) {
2941 json_object_object_get_ex(json, grp_str, &json_group);
2942
2943 if (!json_group) {
2944 json_group = json_object_new_object();
2945 json_object_object_add(json, grp_str,
2946 json_group);
2947 }
2948
2949 json_row = json_object_new_object();
2950 json_object_string_add(json_row, "source", src_str);
2951 json_object_string_add(json_row, "group", grp_str);
2952 json_object_string_add(json_row, "rpfInterface",
2953 rpf_ifname);
2954 json_object_string_add(json_row, "rpfAddress",
2955 rpf_addr_str);
2956 json_object_string_add(json_row, "ribNexthop",
2957 rib_nexthop_str);
2958 json_object_int_add(
2959 json_row, "routeMetric",
2960 rpf->source_nexthop.mrib_route_metric);
2961 json_object_int_add(
2962 json_row, "routePreference",
2963 rpf->source_nexthop.mrib_metric_preference);
2964 json_object_object_add(json_group, src_str, json_row);
2965
2966 } else {
2967 vty_out(vty, "%-15s %-15s %-16s %-15s %-15s %6d %4d\n",
2968 src_str, grp_str, rpf_ifname, rpf_addr_str,
2969 rib_nexthop_str,
2970 rpf->source_nexthop.mrib_route_metric,
2971 rpf->source_nexthop.mrib_metric_preference);
2972 }
2973 }
2974
2975 if (uj) {
2976 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2977 json, JSON_C_TO_STRING_PRETTY));
2978 json_object_free(json);
2979 }
2980 }
2981
2982 struct pnc_cache_walk_data {
2983 struct vty *vty;
2984 struct pim_instance *pim;
2985 };
2986
2987 static int pim_print_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
2988 {
2989 struct pim_nexthop_cache *pnc = bucket->data;
2990 struct pnc_cache_walk_data *cwd = arg;
2991 struct vty *vty = cwd->vty;
2992 struct pim_instance *pim = cwd->pim;
2993 struct nexthop *nh_node = NULL;
2994 ifindex_t first_ifindex;
2995 struct interface *ifp = NULL;
2996 char buf[PREFIX_STRLEN];
2997
2998 for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
2999 first_ifindex = nh_node->ifindex;
3000 ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
3001
3002 vty_out(vty, "%-15s ", inet_ntop(AF_INET,
3003 &pnc->rpf.rpf_addr.u.prefix4,
3004 buf, sizeof(buf)));
3005 vty_out(vty, "%-16s ", ifp ? ifp->name : "NULL");
3006 vty_out(vty, "%pI4 ", &nh_node->gate.ipv4);
3007 vty_out(vty, "\n");
3008 }
3009 return CMD_SUCCESS;
3010 }
3011
3012 static void pim_show_nexthop(struct pim_instance *pim, struct vty *vty)
3013 {
3014 struct pnc_cache_walk_data cwd;
3015
3016 cwd.vty = vty;
3017 cwd.pim = pim;
3018 vty_out(vty, "Number of registered addresses: %lu\n",
3019 pim->rpf_hash->count);
3020 vty_out(vty, "Address Interface Nexthop\n");
3021 vty_out(vty, "---------------------------------------------\n");
3022
3023 hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd);
3024 }
3025
3026 /* Display the bsm database details */
3027 static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj)
3028 {
3029 int count = 0;
3030 int fragment = 1;
3031 struct bsm_frag *bsfrag;
3032 json_object *json = NULL;
3033 json_object *json_group = NULL;
3034 json_object *json_row = NULL;
3035
3036 count = bsm_frags_count(pim->global_scope.bsm_frags);
3037
3038 if (uj) {
3039 json = json_object_new_object();
3040 json_object_int_add(json, "Number of the fragments", count);
3041 } else {
3042 vty_out(vty, "Scope Zone: Global\n");
3043 vty_out(vty, "Number of the fragments: %d\n", count);
3044 vty_out(vty, "\n");
3045 }
3046
3047 frr_each (bsm_frags, pim->global_scope.bsm_frags, bsfrag) {
3048 char grp_str[PREFIX_STRLEN];
3049 char rp_str[INET_ADDRSTRLEN];
3050 char bsr_str[INET_ADDRSTRLEN];
3051 struct bsmmsg_grpinfo *group;
3052 struct bsmmsg_rpinfo *rpaddr;
3053 struct prefix grp;
3054 struct bsm_hdr *hdr;
3055 uint32_t offset = 0;
3056 uint8_t *buf;
3057 uint32_t len = 0;
3058 uint32_t frag_rp_cnt = 0;
3059
3060 buf = bsfrag->data;
3061 len = bsfrag->size;
3062
3063 /* skip pim header */
3064 buf += PIM_MSG_HEADER_LEN;
3065 len -= PIM_MSG_HEADER_LEN;
3066
3067 hdr = (struct bsm_hdr *)buf;
3068
3069 /* BSM starts with bsr header */
3070 buf += sizeof(struct bsm_hdr);
3071 len -= sizeof(struct bsm_hdr);
3072
3073 pim_inet4_dump("<BSR Address?>", hdr->bsr_addr.addr, bsr_str,
3074 sizeof(bsr_str));
3075
3076
3077 if (uj) {
3078 json_object_string_add(json, "BSR address", bsr_str);
3079 json_object_int_add(json, "BSR priority",
3080 hdr->bsr_prio);
3081 json_object_int_add(json, "Hashmask Length",
3082 hdr->hm_len);
3083 json_object_int_add(json, "Fragment Tag",
3084 ntohs(hdr->frag_tag));
3085 } else {
3086 vty_out(vty, "BSM Fragment : %d\n", fragment);
3087 vty_out(vty, "------------------\n");
3088 vty_out(vty, "%-15s %-15s %-15s %-15s\n", "BSR-Address",
3089 "BSR-Priority", "Hashmask-len", "Fragment-Tag");
3090 vty_out(vty, "%-15s %-15d %-15d %-15d\n", bsr_str,
3091 hdr->bsr_prio, hdr->hm_len,
3092 ntohs(hdr->frag_tag));
3093 }
3094
3095 vty_out(vty, "\n");
3096
3097 while (offset < len) {
3098 group = (struct bsmmsg_grpinfo *)buf;
3099
3100 if (group->group.family == PIM_MSG_ADDRESS_FAMILY_IPV4)
3101 grp.family = AF_INET;
3102
3103 grp.prefixlen = group->group.mask;
3104 grp.u.prefix4.s_addr = group->group.addr.s_addr;
3105
3106 prefix2str(&grp, grp_str, sizeof(grp_str));
3107
3108 buf += sizeof(struct bsmmsg_grpinfo);
3109 offset += sizeof(struct bsmmsg_grpinfo);
3110
3111 if (uj) {
3112 json_object_object_get_ex(json, grp_str,
3113 &json_group);
3114 if (!json_group) {
3115 json_group = json_object_new_object();
3116 json_object_int_add(json_group,
3117 "Rp Count",
3118 group->rp_count);
3119 json_object_int_add(
3120 json_group, "Fragment Rp count",
3121 group->frag_rp_count);
3122 json_object_object_add(json, grp_str,
3123 json_group);
3124 }
3125 } else {
3126 vty_out(vty, "Group : %s\n", grp_str);
3127 vty_out(vty, "-------------------\n");
3128 vty_out(vty, "Rp Count:%d\n", group->rp_count);
3129 vty_out(vty, "Fragment Rp Count : %d\n",
3130 group->frag_rp_count);
3131 }
3132
3133 frag_rp_cnt = group->frag_rp_count;
3134
3135 if (!frag_rp_cnt)
3136 continue;
3137
3138 if (!uj)
3139 vty_out(vty,
3140 "RpAddress HoldTime Priority\n");
3141
3142 while (frag_rp_cnt--) {
3143 rpaddr = (struct bsmmsg_rpinfo *)buf;
3144
3145 buf += sizeof(struct bsmmsg_rpinfo);
3146 offset += sizeof(struct bsmmsg_rpinfo);
3147
3148 pim_inet4_dump("<Rp addr?>",
3149 rpaddr->rpaddr.addr, rp_str,
3150 sizeof(rp_str));
3151
3152 if (uj) {
3153 json_row = json_object_new_object();
3154 json_object_string_add(
3155 json_row, "Rp Address", rp_str);
3156 json_object_int_add(
3157 json_row, "Rp HoldTime",
3158 ntohs(rpaddr->rp_holdtime));
3159 json_object_int_add(json_row,
3160 "Rp Priority",
3161 rpaddr->rp_pri);
3162 json_object_object_add(
3163 json_group, rp_str, json_row);
3164 } else {
3165 vty_out(vty, "%-15s %-12d %d\n", rp_str,
3166 ntohs(rpaddr->rp_holdtime),
3167 rpaddr->rp_pri);
3168 }
3169 }
3170 vty_out(vty, "\n");
3171 }
3172
3173 fragment++;
3174 }
3175
3176 if (uj) {
3177 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3178 json, JSON_C_TO_STRING_PRETTY));
3179 json_object_free(json);
3180 }
3181 }
3182
3183 /*Display the group-rp mappings */
3184 static void pim_show_group_rp_mappings_info(struct pim_instance *pim,
3185 struct vty *vty, bool uj)
3186 {
3187 struct bsgrp_node *bsgrp;
3188 struct bsm_rpinfo *bsm_rp;
3189 struct route_node *rn;
3190 char bsr_str[INET_ADDRSTRLEN];
3191 json_object *json = NULL;
3192 json_object *json_group = NULL;
3193 json_object *json_row = NULL;
3194
3195 if (pim->global_scope.current_bsr.s_addr == INADDR_ANY)
3196 strlcpy(bsr_str, "0.0.0.0", sizeof(bsr_str));
3197
3198 else
3199 pim_inet4_dump("<bsr?>", pim->global_scope.current_bsr, bsr_str,
3200 sizeof(bsr_str));
3201
3202 if (uj) {
3203 json = json_object_new_object();
3204 json_object_string_add(json, "BSR Address", bsr_str);
3205 } else {
3206 vty_out(vty, "BSR Address %s\n", bsr_str);
3207 }
3208
3209 for (rn = route_top(pim->global_scope.bsrp_table); rn;
3210 rn = route_next(rn)) {
3211 bsgrp = (struct bsgrp_node *)rn->info;
3212
3213 if (!bsgrp)
3214 continue;
3215
3216 char grp_str[PREFIX_STRLEN];
3217
3218 prefix2str(&bsgrp->group, grp_str, sizeof(grp_str));
3219
3220 if (uj) {
3221 json_object_object_get_ex(json, grp_str, &json_group);
3222 if (!json_group) {
3223 json_group = json_object_new_object();
3224 json_object_object_add(json, grp_str,
3225 json_group);
3226 }
3227 } else {
3228 vty_out(vty, "Group Address %pFX\n", &bsgrp->group);
3229 vty_out(vty, "--------------------------\n");
3230 vty_out(vty, "%-15s %-15s %-15s %-15s\n", "Rp Address",
3231 "priority", "Holdtime", "Hash");
3232
3233 vty_out(vty, "(ACTIVE)\n");
3234 }
3235
3236 frr_each (bsm_rpinfos, bsgrp->bsrp_list, bsm_rp) {
3237 char rp_str[INET_ADDRSTRLEN];
3238
3239 pim_inet4_dump("<Rp Address?>", bsm_rp->rp_address,
3240 rp_str, sizeof(rp_str));
3241
3242 if (uj) {
3243 json_row = json_object_new_object();
3244 json_object_string_add(json_row, "Rp Address",
3245 rp_str);
3246 json_object_int_add(json_row, "Rp HoldTime",
3247 bsm_rp->rp_holdtime);
3248 json_object_int_add(json_row, "Rp Priority",
3249 bsm_rp->rp_prio);
3250 json_object_int_add(json_row, "Hash Val",
3251 bsm_rp->hash);
3252 json_object_object_add(json_group, rp_str,
3253 json_row);
3254
3255 } else {
3256 vty_out(vty, "%-15s %-15u %-15u %-15u\n",
3257 rp_str, bsm_rp->rp_prio,
3258 bsm_rp->rp_holdtime, bsm_rp->hash);
3259 }
3260 }
3261 if (!bsm_rpinfos_count(bsgrp->bsrp_list) && !uj)
3262 vty_out(vty, "Active List is empty.\n");
3263
3264 if (uj) {
3265 json_object_int_add(json_group, "Pending RP count",
3266 bsgrp->pend_rp_cnt);
3267 } else {
3268 vty_out(vty, "(PENDING)\n");
3269 vty_out(vty, "Pending RP count :%d\n",
3270 bsgrp->pend_rp_cnt);
3271 if (bsgrp->pend_rp_cnt)
3272 vty_out(vty, "%-15s %-15s %-15s %-15s\n",
3273 "Rp Address", "priority", "Holdtime",
3274 "Hash");
3275 }
3276
3277 frr_each (bsm_rpinfos, bsgrp->partial_bsrp_list, bsm_rp) {
3278 char rp_str[INET_ADDRSTRLEN];
3279
3280 pim_inet4_dump("<Rp Addr?>", bsm_rp->rp_address, rp_str,
3281 sizeof(rp_str));
3282
3283 if (uj) {
3284 json_row = json_object_new_object();
3285 json_object_string_add(json_row, "Rp Address",
3286 rp_str);
3287 json_object_int_add(json_row, "Rp HoldTime",
3288 bsm_rp->rp_holdtime);
3289 json_object_int_add(json_row, "Rp Priority",
3290 bsm_rp->rp_prio);
3291 json_object_int_add(json_row, "Hash Val",
3292 bsm_rp->hash);
3293 json_object_object_add(json_group, rp_str,
3294 json_row);
3295 } else {
3296 vty_out(vty, "%-15s %-15u %-15u %-15u\n",
3297 rp_str, bsm_rp->rp_prio,
3298 bsm_rp->rp_holdtime, bsm_rp->hash);
3299 }
3300 }
3301 if (!bsm_rpinfos_count(bsgrp->partial_bsrp_list) && !uj)
3302 vty_out(vty, "Partial List is empty\n");
3303
3304 if (!uj)
3305 vty_out(vty, "\n");
3306 }
3307
3308 if (uj) {
3309 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3310 json, JSON_C_TO_STRING_PRETTY));
3311 json_object_free(json);
3312 }
3313 }
3314
3315 /* pim statistics - just adding only bsm related now.
3316 * We can continue to add all pim related stats here.
3317 */
3318 static void pim_show_statistics(struct pim_instance *pim, struct vty *vty,
3319 const char *ifname, bool uj)
3320 {
3321 json_object *json = NULL;
3322 struct interface *ifp;
3323
3324 if (uj) {
3325 json = json_object_new_object();
3326 json_object_int_add(json, "bsmRx", pim->bsm_rcvd);
3327 json_object_int_add(json, "bsmTx", pim->bsm_sent);
3328 json_object_int_add(json, "bsmDropped", pim->bsm_dropped);
3329 } else {
3330 vty_out(vty, "BSM Statistics :\n");
3331 vty_out(vty, "----------------\n");
3332 vty_out(vty, "Number of Received BSMs : %" PRIu64 "\n",
3333 pim->bsm_rcvd);
3334 vty_out(vty, "Number of Forwared BSMs : %" PRIu64 "\n",
3335 pim->bsm_sent);
3336 vty_out(vty, "Number of Dropped BSMs : %" PRIu64 "\n",
3337 pim->bsm_dropped);
3338 }
3339
3340 vty_out(vty, "\n");
3341
3342 /* scan interfaces */
3343 FOR_ALL_INTERFACES (pim->vrf, ifp) {
3344 struct pim_interface *pim_ifp = ifp->info;
3345
3346 if (ifname && strcmp(ifname, ifp->name))
3347 continue;
3348
3349 if (!pim_ifp)
3350 continue;
3351
3352 if (!uj) {
3353 vty_out(vty, "Interface : %s\n", ifp->name);
3354 vty_out(vty, "-------------------\n");
3355 vty_out(vty,
3356 "Number of BSMs dropped due to config miss : %u\n",
3357 pim_ifp->pim_ifstat_bsm_cfg_miss);
3358 vty_out(vty, "Number of unicast BSMs dropped : %u\n",
3359 pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
3360 vty_out(vty,
3361 "Number of BSMs dropped due to invalid scope zone : %u\n",
3362 pim_ifp->pim_ifstat_bsm_invalid_sz);
3363 } else {
3364
3365 json_object *json_row = NULL;
3366
3367 json_row = json_object_new_object();
3368
3369 json_object_string_add(json_row, "If Name", ifp->name);
3370 json_object_int_add(json_row, "bsmDroppedConfig",
3371 pim_ifp->pim_ifstat_bsm_cfg_miss);
3372 json_object_int_add(
3373 json_row, "bsmDroppedUnicast",
3374 pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
3375 json_object_int_add(json_row,
3376 "bsmDroppedInvalidScopeZone",
3377 pim_ifp->pim_ifstat_bsm_invalid_sz);
3378 json_object_object_add(json, ifp->name, json_row);
3379 }
3380 vty_out(vty, "\n");
3381 }
3382
3383 if (uj) {
3384 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3385 json, JSON_C_TO_STRING_PRETTY));
3386 json_object_free(json);
3387 }
3388 }
3389
3390 static void clear_pim_statistics(struct pim_instance *pim)
3391 {
3392 struct interface *ifp;
3393
3394 pim->bsm_rcvd = 0;
3395 pim->bsm_sent = 0;
3396 pim->bsm_dropped = 0;
3397
3398 /* scan interfaces */
3399 FOR_ALL_INTERFACES (pim->vrf, ifp) {
3400 struct pim_interface *pim_ifp = ifp->info;
3401
3402 if (!pim_ifp)
3403 continue;
3404
3405 pim_ifp->pim_ifstat_bsm_cfg_miss = 0;
3406 pim_ifp->pim_ifstat_ucast_bsm_cfg_miss = 0;
3407 pim_ifp->pim_ifstat_bsm_invalid_sz = 0;
3408 }
3409 }
3410
3411 static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj)
3412 {
3413 struct interface *ifp;
3414 time_t now;
3415 json_object *json = NULL;
3416 json_object *json_iface = NULL;
3417 json_object *json_group = NULL;
3418 json_object *json_groups = NULL;
3419
3420 now = pim_time_monotonic_sec();
3421
3422 if (uj) {
3423 json = json_object_new_object();
3424 json_object_int_add(json, "totalGroups", pim->igmp_group_count);
3425 json_object_int_add(json, "watermarkLimit",
3426 pim->igmp_watermark_limit);
3427 } else {
3428 vty_out(vty, "Total IGMP groups: %u\n", pim->igmp_group_count);
3429 vty_out(vty, "Watermark warn limit(%s): %u\n",
3430 pim->igmp_watermark_limit ? "Set" : "Not Set",
3431 pim->igmp_watermark_limit);
3432 vty_out(vty,
3433 "Interface Group Mode Timer Srcs V Uptime \n");
3434 }
3435
3436 /* scan interfaces */
3437 FOR_ALL_INTERFACES (pim->vrf, ifp) {
3438 struct pim_interface *pim_ifp = ifp->info;
3439 struct listnode *grpnode;
3440 struct igmp_group *grp;
3441
3442 if (!pim_ifp)
3443 continue;
3444
3445 /* scan igmp groups */
3446 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_group_list, grpnode,
3447 grp)) {
3448 char group_str[INET_ADDRSTRLEN];
3449 char hhmmss[10];
3450 char uptime[10];
3451
3452 pim_inet4_dump("<group?>", grp->group_addr, group_str,
3453 sizeof(group_str));
3454 pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss),
3455 grp->t_group_timer);
3456 pim_time_uptime(uptime, sizeof(uptime),
3457 now - grp->group_creation);
3458
3459 if (uj) {
3460 json_object_object_get_ex(json, ifp->name,
3461 &json_iface);
3462
3463 if (!json_iface) {
3464 json_iface = json_object_new_object();
3465 json_object_pim_ifp_add(json_iface,
3466 ifp);
3467 json_object_object_add(json, ifp->name,
3468 json_iface);
3469 json_groups = json_object_new_array();
3470 json_object_object_add(json_iface,
3471 "groups",
3472 json_groups);
3473 }
3474
3475 json_group = json_object_new_object();
3476 json_object_string_add(json_group, "group",
3477 group_str);
3478
3479 if (grp->igmp_version == 3)
3480 json_object_string_add(
3481 json_group, "mode",
3482 grp->group_filtermode_isexcl
3483 ? "EXCLUDE"
3484 : "INCLUDE");
3485
3486 json_object_string_add(json_group, "timer",
3487 hhmmss);
3488 json_object_int_add(
3489 json_group, "sourcesCount",
3490 grp->group_source_list ? listcount(
3491 grp->group_source_list)
3492 : 0);
3493 json_object_int_add(json_group, "version",
3494 grp->igmp_version);
3495 json_object_string_add(json_group, "uptime",
3496 uptime);
3497 json_object_array_add(json_groups, json_group);
3498 } else {
3499 vty_out(vty, "%-16s %-15s %4s %8s %4d %d %8s\n",
3500 ifp->name, group_str,
3501 grp->igmp_version == 3
3502 ? (grp->group_filtermode_isexcl
3503 ? "EXCL"
3504 : "INCL")
3505 : "----",
3506 hhmmss,
3507 grp->group_source_list ? listcount(
3508 grp->group_source_list)
3509 : 0,
3510 grp->igmp_version, uptime);
3511 }
3512 } /* scan igmp groups */
3513 } /* scan interfaces */
3514
3515 if (uj) {
3516 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3517 json, JSON_C_TO_STRING_PRETTY));
3518 json_object_free(json);
3519 }
3520 }
3521
3522 static void igmp_show_group_retransmission(struct pim_instance *pim,
3523 struct vty *vty)
3524 {
3525 struct interface *ifp;
3526
3527 vty_out(vty,
3528 "Interface Group RetTimer Counter RetSrcs\n");
3529
3530 /* scan interfaces */
3531 FOR_ALL_INTERFACES (pim->vrf, ifp) {
3532 struct pim_interface *pim_ifp = ifp->info;
3533 struct listnode *grpnode;
3534 struct igmp_group *grp;
3535
3536 if (!pim_ifp)
3537 continue;
3538
3539 /* scan igmp groups */
3540 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_group_list, grpnode,
3541 grp)) {
3542 char group_str[INET_ADDRSTRLEN];
3543 char grp_retr_mmss[10];
3544 struct listnode *src_node;
3545 struct igmp_source *src;
3546 int grp_retr_sources = 0;
3547
3548 pim_inet4_dump("<group?>", grp->group_addr, group_str,
3549 sizeof(group_str));
3550 pim_time_timer_to_mmss(
3551 grp_retr_mmss, sizeof(grp_retr_mmss),
3552 grp->t_group_query_retransmit_timer);
3553
3554
3555 /* count group sources with retransmission state
3556 */
3557 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list,
3558 src_node, src)) {
3559 if (src->source_query_retransmit_count > 0) {
3560 ++grp_retr_sources;
3561 }
3562 }
3563
3564 vty_out(vty, "%-16s %-15s %-8s %7d %7d\n", ifp->name,
3565 group_str, grp_retr_mmss,
3566 grp->group_specific_query_retransmit_count,
3567 grp_retr_sources);
3568
3569 } /* scan igmp groups */
3570 } /* scan interfaces */
3571 }
3572
3573 static void igmp_show_sources(struct pim_instance *pim, struct vty *vty)
3574 {
3575 struct interface *ifp;
3576 time_t now;
3577
3578 now = pim_time_monotonic_sec();
3579
3580 vty_out(vty,
3581 "Interface Group Source Timer Fwd Uptime \n");
3582
3583 /* scan interfaces */
3584 FOR_ALL_INTERFACES (pim->vrf, ifp) {
3585 struct pim_interface *pim_ifp = ifp->info;
3586 struct listnode *grpnode;
3587 struct igmp_group *grp;
3588
3589 if (!pim_ifp)
3590 continue;
3591
3592 /* scan igmp groups */
3593 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_group_list, grpnode,
3594 grp)) {
3595 char group_str[INET_ADDRSTRLEN];
3596 struct listnode *srcnode;
3597 struct igmp_source *src;
3598
3599 pim_inet4_dump("<group?>", grp->group_addr, group_str,
3600 sizeof(group_str));
3601
3602 /* scan group sources */
3603 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list,
3604 srcnode, src)) {
3605 char source_str[INET_ADDRSTRLEN];
3606 char mmss[10];
3607 char uptime[10];
3608
3609 pim_inet4_dump("<source?>", src->source_addr,
3610 source_str, sizeof(source_str));
3611
3612 pim_time_timer_to_mmss(mmss, sizeof(mmss),
3613 src->t_source_timer);
3614
3615 pim_time_uptime(uptime, sizeof(uptime),
3616 now - src->source_creation);
3617
3618 vty_out(vty, "%-16s %-15s %-15s %5s %3s %8s\n",
3619 ifp->name, group_str, source_str, mmss,
3620 IGMP_SOURCE_TEST_FORWARDING(
3621 src->source_flags)
3622 ? "Y"
3623 : "N",
3624 uptime);
3625
3626 } /* scan group sources */
3627 } /* scan igmp groups */
3628 } /* scan interfaces */
3629 }
3630
3631 static void igmp_show_source_retransmission(struct pim_instance *pim,
3632 struct vty *vty)
3633 {
3634 struct interface *ifp;
3635
3636 vty_out(vty,
3637 "Interface Group Source Counter\n");
3638
3639 /* scan interfaces */
3640 FOR_ALL_INTERFACES (pim->vrf, ifp) {
3641 struct pim_interface *pim_ifp = ifp->info;
3642 struct listnode *grpnode;
3643 struct igmp_group *grp;
3644
3645 if (!pim_ifp)
3646 continue;
3647
3648 /* scan igmp groups */
3649 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_group_list, grpnode,
3650 grp)) {
3651 char group_str[INET_ADDRSTRLEN];
3652 struct listnode *srcnode;
3653 struct igmp_source *src;
3654
3655 pim_inet4_dump("<group?>", grp->group_addr, group_str,
3656 sizeof(group_str));
3657
3658 /* scan group sources */
3659 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list,
3660 srcnode, src)) {
3661 char source_str[INET_ADDRSTRLEN];
3662
3663 pim_inet4_dump("<source?>", src->source_addr,
3664 source_str, sizeof(source_str));
3665
3666 vty_out(vty, "%-16s %-15s %-15s %7d\n",
3667 ifp->name, group_str, source_str,
3668 src->source_query_retransmit_count);
3669
3670 } /* scan group sources */
3671 } /* scan igmp groups */
3672 } /* scan interfaces */
3673 }
3674
3675 static void pim_show_bsr(struct pim_instance *pim,
3676 struct vty *vty,
3677 bool uj)
3678 {
3679 char uptime[10];
3680 char last_bsm_seen[10];
3681 time_t now;
3682 char bsr_state[20];
3683 char bsr_str[PREFIX_STRLEN];
3684 json_object *json = NULL;
3685
3686 if (pim->global_scope.current_bsr.s_addr == INADDR_ANY) {
3687 strlcpy(bsr_str, "0.0.0.0", sizeof(bsr_str));
3688 pim_time_uptime(uptime, sizeof(uptime),
3689 pim->global_scope.current_bsr_first_ts);
3690 pim_time_uptime(last_bsm_seen, sizeof(last_bsm_seen),
3691 pim->global_scope.current_bsr_last_ts);
3692 }
3693
3694 else {
3695 pim_inet4_dump("<bsr?>", pim->global_scope.current_bsr,
3696 bsr_str, sizeof(bsr_str));
3697 now = pim_time_monotonic_sec();
3698 pim_time_uptime(uptime, sizeof(uptime),
3699 (now - pim->global_scope.current_bsr_first_ts));
3700 pim_time_uptime(last_bsm_seen, sizeof(last_bsm_seen),
3701 now - pim->global_scope.current_bsr_last_ts);
3702 }
3703
3704 switch (pim->global_scope.state) {
3705 case NO_INFO:
3706 strlcpy(bsr_state, "NO_INFO", sizeof(bsr_state));
3707 break;
3708 case ACCEPT_ANY:
3709 strlcpy(bsr_state, "ACCEPT_ANY", sizeof(bsr_state));
3710 break;
3711 case ACCEPT_PREFERRED:
3712 strlcpy(bsr_state, "ACCEPT_PREFERRED", sizeof(bsr_state));
3713 break;
3714 default:
3715 strlcpy(bsr_state, "", sizeof(bsr_state));
3716 }
3717
3718 if (uj) {
3719 json = json_object_new_object();
3720 json_object_string_add(json, "bsr", bsr_str);
3721 json_object_int_add(json, "priority",
3722 pim->global_scope.current_bsr_prio);
3723 json_object_int_add(json, "fragmentTag",
3724 pim->global_scope.bsm_frag_tag);
3725 json_object_string_add(json, "state", bsr_state);
3726 json_object_string_add(json, "upTime", uptime);
3727 json_object_string_add(json, "lastBsmSeen", last_bsm_seen);
3728 }
3729
3730 else {
3731 vty_out(vty, "PIMv2 Bootstrap information\n");
3732 vty_out(vty, "Current preferred BSR address: %s\n", bsr_str);
3733 vty_out(vty,
3734 "Priority Fragment-Tag State UpTime\n");
3735 vty_out(vty, " %-12d %-12d %-13s %7s\n",
3736 pim->global_scope.current_bsr_prio,
3737 pim->global_scope.bsm_frag_tag,
3738 bsr_state,
3739 uptime);
3740 vty_out(vty, "Last BSM seen: %s\n", last_bsm_seen);
3741 }
3742
3743 if (uj) {
3744 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3745 json, JSON_C_TO_STRING_PRETTY));
3746 json_object_free(json);
3747 }
3748 }
3749
3750 static void clear_igmp_interfaces(struct pim_instance *pim)
3751 {
3752 struct interface *ifp;
3753
3754 FOR_ALL_INTERFACES (pim->vrf, ifp)
3755 pim_if_addr_del_all_igmp(ifp);
3756
3757 FOR_ALL_INTERFACES (pim->vrf, ifp)
3758 pim_if_addr_add_all(ifp);
3759 }
3760
3761 static void clear_pim_interfaces(struct pim_instance *pim)
3762 {
3763 struct interface *ifp;
3764
3765 FOR_ALL_INTERFACES (pim->vrf, ifp) {
3766 if (ifp->info) {
3767 pim_neighbor_delete_all(ifp, "interface cleared");
3768 }
3769 }
3770 }
3771
3772 static void clear_interfaces(struct pim_instance *pim)
3773 {
3774 clear_igmp_interfaces(pim);
3775 clear_pim_interfaces(pim);
3776 }
3777
3778 #define PIM_GET_PIM_INTERFACE(pim_ifp, ifp) \
3779 pim_ifp = ifp->info; \
3780 if (!pim_ifp) { \
3781 vty_out(vty, \
3782 "%% Enable PIM and/or IGMP on this interface first\n"); \
3783 return CMD_WARNING_CONFIG_FAILED; \
3784 }
3785
3786 /**
3787 * Get current node VRF name.
3788 *
3789 * NOTE:
3790 * In case of failure it will print error message to user.
3791 *
3792 * \returns name or NULL if failed to get VRF.
3793 */
3794 static const char *pim_cli_get_vrf_name(struct vty *vty)
3795 {
3796 const struct lyd_node *vrf_node;
3797
3798 /* Not inside any VRF context. */
3799 if (vty->xpath_index == 0)
3800 return VRF_DEFAULT_NAME;
3801
3802 vrf_node = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
3803 if (vrf_node == NULL) {
3804 vty_out(vty, "%% Failed to get vrf dnode in configuration\n");
3805 return NULL;
3806 }
3807
3808 return yang_dnode_get_string(vrf_node, "./name");
3809 }
3810
3811 /**
3812 * Compatibility function to keep the legacy mesh group CLI behavior:
3813 * Delete group when there are no more configurations in it.
3814 *
3815 * NOTE:
3816 * Don't forget to call `nb_cli_apply_changes` after this.
3817 */
3818 static void pim_cli_legacy_mesh_group_behavior(struct vty *vty,
3819 const char *gname)
3820 {
3821 const char *vrfname;
3822 char xpath_value[XPATH_MAXLEN];
3823 char xpath_member_value[XPATH_MAXLEN];
3824 const struct lyd_node *member_dnode;
3825
3826 vrfname = pim_cli_get_vrf_name(vty);
3827 if (vrfname == NULL)
3828 return;
3829
3830 /* Get mesh group base XPath. */
3831 snprintf(xpath_value, sizeof(xpath_value),
3832 FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']",
3833 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname);
3834 /* Group must exists, otherwise just quit. */
3835 if (!yang_dnode_exists(vty->candidate_config->dnode, xpath_value))
3836 return;
3837
3838 /* Group members check: */
3839 strlcpy(xpath_member_value, xpath_value, sizeof(xpath_member_value));
3840 strlcat(xpath_member_value, "/members", sizeof(xpath_member_value));
3841 if (yang_dnode_exists(vty->candidate_config->dnode,
3842 xpath_member_value)) {
3843 member_dnode = yang_dnode_get(vty->candidate_config->dnode,
3844 xpath_member_value);
3845 if (!member_dnode || !yang_is_last_list_dnode(member_dnode))
3846 return;
3847 }
3848
3849 /* Source address check: */
3850 strlcpy(xpath_member_value, xpath_value, sizeof(xpath_member_value));
3851 strlcat(xpath_member_value, "/source", sizeof(xpath_member_value));
3852 if (yang_dnode_exists(vty->candidate_config->dnode, xpath_member_value))
3853 return;
3854
3855 /* No configurations found: delete it. */
3856 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL);
3857 }
3858
3859 DEFUN (clear_ip_interfaces,
3860 clear_ip_interfaces_cmd,
3861 "clear ip interfaces [vrf NAME]",
3862 CLEAR_STR
3863 IP_STR
3864 "Reset interfaces\n"
3865 VRF_CMD_HELP_STR)
3866 {
3867 int idx = 2;
3868 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3869
3870 if (!vrf)
3871 return CMD_WARNING;
3872
3873 clear_interfaces(vrf->info);
3874
3875 return CMD_SUCCESS;
3876 }
3877
3878 DEFUN (clear_ip_igmp_interfaces,
3879 clear_ip_igmp_interfaces_cmd,
3880 "clear ip igmp [vrf NAME] interfaces",
3881 CLEAR_STR
3882 IP_STR
3883 CLEAR_IP_IGMP_STR
3884 VRF_CMD_HELP_STR
3885 "Reset IGMP interfaces\n")
3886 {
3887 int idx = 2;
3888 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3889
3890 if (!vrf)
3891 return CMD_WARNING;
3892
3893 clear_igmp_interfaces(vrf->info);
3894
3895 return CMD_SUCCESS;
3896 }
3897
3898 DEFUN (clear_ip_pim_statistics,
3899 clear_ip_pim_statistics_cmd,
3900 "clear ip pim statistics [vrf NAME]",
3901 CLEAR_STR
3902 IP_STR
3903 CLEAR_IP_PIM_STR
3904 VRF_CMD_HELP_STR
3905 "Reset PIM statistics\n")
3906 {
3907 int idx = 2;
3908 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3909
3910 if (!vrf)
3911 return CMD_WARNING;
3912
3913 clear_pim_statistics(vrf->info);
3914 return CMD_SUCCESS;
3915 }
3916
3917 static void clear_mroute(struct pim_instance *pim)
3918 {
3919 struct pim_upstream *up;
3920 struct interface *ifp;
3921
3922 /* scan interfaces */
3923 FOR_ALL_INTERFACES (pim->vrf, ifp) {
3924 struct pim_interface *pim_ifp = ifp->info;
3925 struct igmp_group *grp;
3926 struct pim_ifchannel *ch;
3927
3928 if (!pim_ifp)
3929 continue;
3930
3931 /* deleting all ifchannels */
3932 while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
3933 ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
3934
3935 pim_ifchannel_delete(ch);
3936 }
3937
3938 /* clean up all igmp groups */
3939
3940 if (pim_ifp->igmp_group_list) {
3941 while (pim_ifp->igmp_group_list->count) {
3942 grp = listnode_head(pim_ifp->igmp_group_list);
3943 igmp_group_delete(grp);
3944 }
3945 }
3946 }
3947
3948 /* clean up all upstreams*/
3949 while ((up = rb_pim_upstream_first(&pim->upstream_head)))
3950 pim_upstream_del(pim, up, __func__);
3951
3952 }
3953
3954 DEFUN (clear_ip_mroute,
3955 clear_ip_mroute_cmd,
3956 "clear ip mroute [vrf NAME]",
3957 CLEAR_STR
3958 IP_STR
3959 "Reset multicast routes\n"
3960 VRF_CMD_HELP_STR)
3961 {
3962 int idx = 2;
3963 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3964
3965 if (!vrf)
3966 return CMD_WARNING;
3967
3968 clear_mroute(vrf->info);
3969
3970 return CMD_SUCCESS;
3971 }
3972
3973 DEFUN (clear_ip_pim_interfaces,
3974 clear_ip_pim_interfaces_cmd,
3975 "clear ip pim [vrf NAME] interfaces",
3976 CLEAR_STR
3977 IP_STR
3978 CLEAR_IP_PIM_STR
3979 VRF_CMD_HELP_STR
3980 "Reset PIM interfaces\n")
3981 {
3982 int idx = 2;
3983 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3984
3985 if (!vrf)
3986 return CMD_WARNING;
3987
3988 clear_pim_interfaces(vrf->info);
3989
3990 return CMD_SUCCESS;
3991 }
3992
3993 DEFUN (clear_ip_pim_interface_traffic,
3994 clear_ip_pim_interface_traffic_cmd,
3995 "clear ip pim [vrf NAME] interface traffic",
3996 "Reset functions\n"
3997 "IP information\n"
3998 "PIM clear commands\n"
3999 VRF_CMD_HELP_STR
4000 "Reset PIM interfaces\n"
4001 "Reset Protocol Packet counters\n")
4002 {
4003 int idx = 2;
4004 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4005 struct interface *ifp = NULL;
4006 struct pim_interface *pim_ifp = NULL;
4007
4008 if (!vrf)
4009 return CMD_WARNING;
4010
4011 FOR_ALL_INTERFACES (vrf, ifp) {
4012 pim_ifp = ifp->info;
4013
4014 if (!pim_ifp)
4015 continue;
4016
4017 pim_ifp->pim_ifstat_hello_recv = 0;
4018 pim_ifp->pim_ifstat_hello_sent = 0;
4019 pim_ifp->pim_ifstat_join_recv = 0;
4020 pim_ifp->pim_ifstat_join_send = 0;
4021 pim_ifp->pim_ifstat_prune_recv = 0;
4022 pim_ifp->pim_ifstat_prune_send = 0;
4023 pim_ifp->pim_ifstat_reg_recv = 0;
4024 pim_ifp->pim_ifstat_reg_send = 0;
4025 pim_ifp->pim_ifstat_reg_stop_recv = 0;
4026 pim_ifp->pim_ifstat_reg_stop_send = 0;
4027 pim_ifp->pim_ifstat_assert_recv = 0;
4028 pim_ifp->pim_ifstat_assert_send = 0;
4029 pim_ifp->pim_ifstat_bsm_rx = 0;
4030 pim_ifp->pim_ifstat_bsm_tx = 0;
4031 }
4032
4033 return CMD_SUCCESS;
4034 }
4035
4036 DEFUN (clear_ip_pim_oil,
4037 clear_ip_pim_oil_cmd,
4038 "clear ip pim [vrf NAME] oil",
4039 CLEAR_STR
4040 IP_STR
4041 CLEAR_IP_PIM_STR
4042 VRF_CMD_HELP_STR
4043 "Rescan PIM OIL (output interface list)\n")
4044 {
4045 int idx = 2;
4046 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4047
4048 if (!vrf)
4049 return CMD_WARNING;
4050
4051 pim_scan_oil(vrf->info);
4052
4053 return CMD_SUCCESS;
4054 }
4055
4056 static void clear_pim_bsr_db(struct pim_instance *pim)
4057 {
4058 struct route_node *rn;
4059 struct route_node *rpnode;
4060 struct bsgrp_node *bsgrp;
4061 struct prefix nht_p;
4062 struct prefix g_all;
4063 struct rp_info *rp_all;
4064 struct pim_upstream *up;
4065 struct rp_info *rp_info;
4066 bool is_bsr_tracking = true;
4067
4068 /* Remove next hop tracking for the bsr */
4069 nht_p.family = AF_INET;
4070 nht_p.prefixlen = IPV4_MAX_BITLEN;
4071 nht_p.u.prefix4 = pim->global_scope.current_bsr;
4072 if (PIM_DEBUG_BSM) {
4073 zlog_debug("%s: Deregister BSR addr %pFX with Zebra NHT",
4074 __func__, &nht_p);
4075 }
4076 pim_delete_tracked_nexthop(pim, &nht_p, NULL, NULL, is_bsr_tracking);
4077
4078 /* Reset scope zone data */
4079 pim->global_scope.accept_nofwd_bsm = false;
4080 pim->global_scope.state = ACCEPT_ANY;
4081 pim->global_scope.current_bsr.s_addr = INADDR_ANY;
4082 pim->global_scope.current_bsr_prio = 0;
4083 pim->global_scope.current_bsr_first_ts = 0;
4084 pim->global_scope.current_bsr_last_ts = 0;
4085 pim->global_scope.bsm_frag_tag = 0;
4086 pim_bsm_frags_free(&pim->global_scope);
4087
4088 pim_bs_timer_stop(&pim->global_scope);
4089
4090 for (rn = route_top(pim->global_scope.bsrp_table); rn;
4091 rn = route_next(rn)) {
4092 bsgrp = rn->info;
4093 if (!bsgrp)
4094 continue;
4095
4096 rpnode = route_node_lookup(pim->rp_table, &bsgrp->group);
4097
4098 if (!rpnode) {
4099 pim_free_bsgrp_node(bsgrp->scope->bsrp_table,
4100 &bsgrp->group);
4101 pim_free_bsgrp_data(bsgrp);
4102 continue;
4103 }
4104
4105 rp_info = (struct rp_info *)rpnode->info;
4106
4107 if ((!rp_info) || (rp_info->rp_src != RP_SRC_BSR)) {
4108 pim_free_bsgrp_node(bsgrp->scope->bsrp_table,
4109 &bsgrp->group);
4110 pim_free_bsgrp_data(bsgrp);
4111 continue;
4112 }
4113
4114 /* Deregister addr with Zebra NHT */
4115 nht_p.family = AF_INET;
4116 nht_p.prefixlen = IPV4_MAX_BITLEN;
4117 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
4118
4119 if (PIM_DEBUG_PIM_NHT_RP) {
4120 zlog_debug("%s: Deregister RP addr %pFX with Zebra ",
4121 __func__, &nht_p);
4122 }
4123
4124 pim_delete_tracked_nexthop(pim, &nht_p, NULL, rp_info, false);
4125
4126 if (!str2prefix("224.0.0.0/4", &g_all))
4127 return;
4128
4129 rp_all = pim_rp_find_match_group(pim, &g_all);
4130
4131 if (rp_all == rp_info) {
4132 rp_all->rp.rpf_addr.family = AF_INET;
4133 rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE;
4134 rp_all->i_am_rp = 0;
4135 } else {
4136 /* Delete the rp_info from rp-list */
4137 listnode_delete(pim->rp_list, rp_info);
4138
4139 /* Delete the rp node from rp_table */
4140 rpnode->info = NULL;
4141 route_unlock_node(rpnode);
4142 route_unlock_node(rpnode);
4143 XFREE(MTYPE_PIM_RP, rp_info);
4144 }
4145
4146 pim_free_bsgrp_node(bsgrp->scope->bsrp_table, &bsgrp->group);
4147 pim_free_bsgrp_data(bsgrp);
4148 }
4149 pim_rp_refresh_group_to_rp_mapping(pim);
4150
4151
4152 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
4153 /* Find the upstream (*, G) whose upstream address is same as
4154 * the RP
4155 */
4156 if (up->sg.src.s_addr != INADDR_ANY)
4157 continue;
4158
4159 struct prefix grp;
4160 struct rp_info *trp_info;
4161
4162 grp.family = AF_INET;
4163 grp.prefixlen = IPV4_MAX_BITLEN;
4164 grp.u.prefix4 = up->sg.grp;
4165
4166 trp_info = pim_rp_find_match_group(pim, &grp);
4167
4168 /* RP not found for the group grp */
4169 if (pim_rpf_addr_is_inaddr_none(&trp_info->rp)) {
4170 pim_upstream_rpf_clear(pim, up);
4171 pim_rp_set_upstream_addr(pim, &up->upstream_addr,
4172 up->sg.src, up->sg.grp);
4173 } else {
4174 /* RP found for the group grp */
4175 pim_upstream_update(pim, up);
4176 }
4177 }
4178 }
4179
4180
4181 DEFUN (clear_ip_pim_bsr_db,
4182 clear_ip_pim_bsr_db_cmd,
4183 "clear ip pim [vrf NAME] bsr-data",
4184 CLEAR_STR
4185 IP_STR
4186 CLEAR_IP_PIM_STR
4187 VRF_CMD_HELP_STR
4188 "Reset pim bsr data\n")
4189 {
4190 int idx = 2;
4191 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4192
4193 if (!vrf)
4194 return CMD_WARNING;
4195
4196 clear_pim_bsr_db(vrf->info);
4197
4198 return CMD_SUCCESS;
4199 }
4200
4201 DEFUN (show_ip_igmp_interface,
4202 show_ip_igmp_interface_cmd,
4203 "show ip igmp [vrf NAME] interface [detail|WORD] [json]",
4204 SHOW_STR
4205 IP_STR
4206 IGMP_STR
4207 VRF_CMD_HELP_STR
4208 "IGMP interface information\n"
4209 "Detailed output\n"
4210 "interface name\n"
4211 JSON_STR)
4212 {
4213 int idx = 2;
4214 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4215 bool uj = use_json(argc, argv);
4216
4217 if (!vrf)
4218 return CMD_WARNING;
4219
4220 if (argv_find(argv, argc, "detail", &idx)
4221 || argv_find(argv, argc, "WORD", &idx))
4222 igmp_show_interfaces_single(vrf->info, vty, argv[idx]->arg, uj);
4223 else
4224 igmp_show_interfaces(vrf->info, vty, uj);
4225
4226 return CMD_SUCCESS;
4227 }
4228
4229 DEFUN (show_ip_igmp_interface_vrf_all,
4230 show_ip_igmp_interface_vrf_all_cmd,
4231 "show ip igmp vrf all interface [detail|WORD] [json]",
4232 SHOW_STR
4233 IP_STR
4234 IGMP_STR
4235 VRF_CMD_HELP_STR
4236 "IGMP interface information\n"
4237 "Detailed output\n"
4238 "interface name\n"
4239 JSON_STR)
4240 {
4241 int idx = 2;
4242 bool uj = use_json(argc, argv);
4243 struct vrf *vrf;
4244 bool first = true;
4245
4246 if (uj)
4247 vty_out(vty, "{ ");
4248 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4249 if (uj) {
4250 if (!first)
4251 vty_out(vty, ", ");
4252 vty_out(vty, " \"%s\": ", vrf->name);
4253 first = false;
4254 } else
4255 vty_out(vty, "VRF: %s\n", vrf->name);
4256 if (argv_find(argv, argc, "detail", &idx)
4257 || argv_find(argv, argc, "WORD", &idx))
4258 igmp_show_interfaces_single(vrf->info, vty,
4259 argv[idx]->arg, uj);
4260 else
4261 igmp_show_interfaces(vrf->info, vty, uj);
4262 }
4263 if (uj)
4264 vty_out(vty, "}\n");
4265
4266 return CMD_SUCCESS;
4267 }
4268
4269 DEFUN (show_ip_igmp_join,
4270 show_ip_igmp_join_cmd,
4271 "show ip igmp [vrf NAME] join [json]",
4272 SHOW_STR
4273 IP_STR
4274 IGMP_STR
4275 VRF_CMD_HELP_STR
4276 "IGMP static join information\n"
4277 JSON_STR)
4278 {
4279 int idx = 2;
4280 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4281 bool uj = use_json(argc, argv);
4282
4283 if (!vrf)
4284 return CMD_WARNING;
4285
4286 igmp_show_interface_join(vrf->info, vty, uj);
4287
4288 return CMD_SUCCESS;
4289 }
4290
4291 DEFUN (show_ip_igmp_join_vrf_all,
4292 show_ip_igmp_join_vrf_all_cmd,
4293 "show ip igmp vrf all join [json]",
4294 SHOW_STR
4295 IP_STR
4296 IGMP_STR
4297 VRF_CMD_HELP_STR
4298 "IGMP static join information\n"
4299 JSON_STR)
4300 {
4301 bool uj = use_json(argc, argv);
4302 struct vrf *vrf;
4303 bool first = true;
4304
4305 if (uj)
4306 vty_out(vty, "{ ");
4307 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4308 if (uj) {
4309 if (!first)
4310 vty_out(vty, ", ");
4311 vty_out(vty, " \"%s\": ", vrf->name);
4312 first = false;
4313 } else
4314 vty_out(vty, "VRF: %s\n", vrf->name);
4315 igmp_show_interface_join(vrf->info, vty, uj);
4316 }
4317 if (uj)
4318 vty_out(vty, "}\n");
4319
4320 return CMD_SUCCESS;
4321 }
4322
4323 DEFUN (show_ip_igmp_groups,
4324 show_ip_igmp_groups_cmd,
4325 "show ip igmp [vrf NAME] groups [json]",
4326 SHOW_STR
4327 IP_STR
4328 IGMP_STR
4329 VRF_CMD_HELP_STR
4330 IGMP_GROUP_STR
4331 JSON_STR)
4332 {
4333 int idx = 2;
4334 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4335 bool uj = use_json(argc, argv);
4336
4337 if (!vrf)
4338 return CMD_WARNING;
4339
4340 igmp_show_groups(vrf->info, vty, uj);
4341
4342 return CMD_SUCCESS;
4343 }
4344
4345 DEFUN (show_ip_igmp_groups_vrf_all,
4346 show_ip_igmp_groups_vrf_all_cmd,
4347 "show ip igmp vrf all groups [json]",
4348 SHOW_STR
4349 IP_STR
4350 IGMP_STR
4351 VRF_CMD_HELP_STR
4352 IGMP_GROUP_STR
4353 JSON_STR)
4354 {
4355 bool uj = use_json(argc, argv);
4356 struct vrf *vrf;
4357 bool first = true;
4358
4359 if (uj)
4360 vty_out(vty, "{ ");
4361 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4362 if (uj) {
4363 if (!first)
4364 vty_out(vty, ", ");
4365 vty_out(vty, " \"%s\": ", vrf->name);
4366 first = false;
4367 } else
4368 vty_out(vty, "VRF: %s\n", vrf->name);
4369 igmp_show_groups(vrf->info, vty, uj);
4370 }
4371 if (uj)
4372 vty_out(vty, "}\n");
4373
4374 return CMD_SUCCESS;
4375 }
4376
4377 DEFUN (show_ip_igmp_groups_retransmissions,
4378 show_ip_igmp_groups_retransmissions_cmd,
4379 "show ip igmp [vrf NAME] groups retransmissions",
4380 SHOW_STR
4381 IP_STR
4382 IGMP_STR
4383 VRF_CMD_HELP_STR
4384 IGMP_GROUP_STR
4385 "IGMP group retransmissions\n")
4386 {
4387 int idx = 2;
4388 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4389
4390 if (!vrf)
4391 return CMD_WARNING;
4392
4393 igmp_show_group_retransmission(vrf->info, vty);
4394
4395 return CMD_SUCCESS;
4396 }
4397
4398 DEFUN (show_ip_igmp_sources,
4399 show_ip_igmp_sources_cmd,
4400 "show ip igmp [vrf NAME] sources",
4401 SHOW_STR
4402 IP_STR
4403 IGMP_STR
4404 VRF_CMD_HELP_STR
4405 IGMP_SOURCE_STR)
4406 {
4407 int idx = 2;
4408 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4409
4410 if (!vrf)
4411 return CMD_WARNING;
4412
4413 igmp_show_sources(vrf->info, vty);
4414
4415 return CMD_SUCCESS;
4416 }
4417
4418 DEFUN (show_ip_igmp_sources_retransmissions,
4419 show_ip_igmp_sources_retransmissions_cmd,
4420 "show ip igmp [vrf NAME] sources retransmissions",
4421 SHOW_STR
4422 IP_STR
4423 IGMP_STR
4424 VRF_CMD_HELP_STR
4425 IGMP_SOURCE_STR
4426 "IGMP source retransmissions\n")
4427 {
4428 int idx = 2;
4429 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4430
4431 if (!vrf)
4432 return CMD_WARNING;
4433
4434 igmp_show_source_retransmission(vrf->info, vty);
4435
4436 return CMD_SUCCESS;
4437 }
4438
4439 DEFUN (show_ip_igmp_statistics,
4440 show_ip_igmp_statistics_cmd,
4441 "show ip igmp [vrf NAME] statistics [interface WORD] [json]",
4442 SHOW_STR
4443 IP_STR
4444 IGMP_STR
4445 VRF_CMD_HELP_STR
4446 "IGMP statistics\n"
4447 "interface\n"
4448 "IGMP interface\n"
4449 JSON_STR)
4450 {
4451 int idx = 2;
4452 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4453 bool uj = use_json(argc, argv);
4454
4455 if (!vrf)
4456 return CMD_WARNING;
4457
4458 if (argv_find(argv, argc, "WORD", &idx))
4459 igmp_show_statistics(vrf->info, vty, argv[idx]->arg, uj);
4460 else
4461 igmp_show_statistics(vrf->info, vty, NULL, uj);
4462
4463 return CMD_SUCCESS;
4464 }
4465
4466 DEFUN (show_ip_pim_mlag_summary,
4467 show_ip_pim_mlag_summary_cmd,
4468 "show ip pim mlag summary [json]",
4469 SHOW_STR
4470 IP_STR
4471 PIM_STR
4472 "MLAG\n"
4473 "status and stats\n"
4474 JSON_STR)
4475 {
4476 bool uj = use_json(argc, argv);
4477 char role_buf[MLAG_ROLE_STRSIZE];
4478 char addr_buf[INET_ADDRSTRLEN];
4479
4480 if (uj) {
4481 json_object *json = NULL;
4482 json_object *json_stat = NULL;
4483
4484 json = json_object_new_object();
4485 if (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
4486 json_object_boolean_true_add(json, "mlagConnUp");
4487 if (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
4488 json_object_boolean_true_add(json, "mlagPeerConnUp");
4489 if (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
4490 json_object_boolean_true_add(json, "mlagPeerZebraUp");
4491 json_object_string_add(json, "mlagRole",
4492 mlag_role2str(router->mlag_role,
4493 role_buf, sizeof(role_buf)));
4494 inet_ntop(AF_INET, &router->local_vtep_ip,
4495 addr_buf, INET_ADDRSTRLEN);
4496 json_object_string_add(json, "localVtepIp", addr_buf);
4497 inet_ntop(AF_INET, &router->anycast_vtep_ip,
4498 addr_buf, INET_ADDRSTRLEN);
4499 json_object_string_add(json, "anycastVtepIp", addr_buf);
4500 json_object_string_add(json, "peerlinkRif",
4501 router->peerlink_rif);
4502
4503 json_stat = json_object_new_object();
4504 json_object_int_add(json_stat, "mlagConnFlaps",
4505 router->mlag_stats.mlagd_session_downs);
4506 json_object_int_add(json_stat, "mlagPeerConnFlaps",
4507 router->mlag_stats.peer_session_downs);
4508 json_object_int_add(json_stat, "mlagPeerZebraFlaps",
4509 router->mlag_stats.peer_zebra_downs);
4510 json_object_int_add(json_stat, "mrouteAddRx",
4511 router->mlag_stats.msg.mroute_add_rx);
4512 json_object_int_add(json_stat, "mrouteAddTx",
4513 router->mlag_stats.msg.mroute_add_tx);
4514 json_object_int_add(json_stat, "mrouteDelRx",
4515 router->mlag_stats.msg.mroute_del_rx);
4516 json_object_int_add(json_stat, "mrouteDelTx",
4517 router->mlag_stats.msg.mroute_del_tx);
4518 json_object_int_add(json_stat, "mlagStatusUpdates",
4519 router->mlag_stats.msg.mlag_status_updates);
4520 json_object_int_add(json_stat, "peerZebraStatusUpdates",
4521 router->mlag_stats.msg.peer_zebra_status_updates);
4522 json_object_int_add(json_stat, "pimStatusUpdates",
4523 router->mlag_stats.msg.pim_status_updates);
4524 json_object_int_add(json_stat, "vxlanUpdates",
4525 router->mlag_stats.msg.vxlan_updates);
4526 json_object_object_add(json, "connStats", json_stat);
4527
4528 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4529 json, JSON_C_TO_STRING_PRETTY));
4530 json_object_free(json);
4531 return CMD_SUCCESS;
4532 }
4533
4534 vty_out(vty, "MLAG daemon connection: %s\n",
4535 (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
4536 ? "up" : "down");
4537 vty_out(vty, "MLAG peer state: %s\n",
4538 (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
4539 ? "up" : "down");
4540 vty_out(vty, "Zebra peer state: %s\n",
4541 (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
4542 ? "up" : "down");
4543 vty_out(vty, "MLAG role: %s\n",
4544 mlag_role2str(router->mlag_role, role_buf, sizeof(role_buf)));
4545 inet_ntop(AF_INET, &router->local_vtep_ip,
4546 addr_buf, INET_ADDRSTRLEN);
4547 vty_out(vty, "Local VTEP IP: %s\n", addr_buf);
4548 inet_ntop(AF_INET, &router->anycast_vtep_ip,
4549 addr_buf, INET_ADDRSTRLEN);
4550 vty_out(vty, "Anycast VTEP IP: %s\n", addr_buf);
4551 vty_out(vty, "Peerlink: %s\n", router->peerlink_rif);
4552 vty_out(vty, "Session flaps: mlagd: %d mlag-peer: %d zebra-peer: %d\n",
4553 router->mlag_stats.mlagd_session_downs,
4554 router->mlag_stats.peer_session_downs,
4555 router->mlag_stats.peer_zebra_downs);
4556 vty_out(vty, "Message Statistics:\n");
4557 vty_out(vty, " mroute adds: rx: %d, tx: %d\n",
4558 router->mlag_stats.msg.mroute_add_rx,
4559 router->mlag_stats.msg.mroute_add_tx);
4560 vty_out(vty, " mroute dels: rx: %d, tx: %d\n",
4561 router->mlag_stats.msg.mroute_del_rx,
4562 router->mlag_stats.msg.mroute_del_tx);
4563 vty_out(vty, " peer zebra status updates: %d\n",
4564 router->mlag_stats.msg.peer_zebra_status_updates);
4565 vty_out(vty, " PIM status updates: %d\n",
4566 router->mlag_stats.msg.pim_status_updates);
4567 vty_out(vty, " VxLAN updates: %d\n",
4568 router->mlag_stats.msg.vxlan_updates);
4569
4570 return CMD_SUCCESS;
4571 }
4572
4573 DEFUN (show_ip_pim_assert,
4574 show_ip_pim_assert_cmd,
4575 "show ip pim [vrf NAME] assert",
4576 SHOW_STR
4577 IP_STR
4578 PIM_STR
4579 VRF_CMD_HELP_STR
4580 "PIM interface assert\n")
4581 {
4582 int idx = 2;
4583 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4584
4585 if (!vrf)
4586 return CMD_WARNING;
4587
4588 pim_show_assert(vrf->info, vty);
4589
4590 return CMD_SUCCESS;
4591 }
4592
4593 DEFUN (show_ip_pim_assert_internal,
4594 show_ip_pim_assert_internal_cmd,
4595 "show ip pim [vrf NAME] assert-internal",
4596 SHOW_STR
4597 IP_STR
4598 PIM_STR
4599 VRF_CMD_HELP_STR
4600 "PIM interface internal assert state\n")
4601 {
4602 int idx = 2;
4603 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4604
4605 if (!vrf)
4606 return CMD_WARNING;
4607
4608 pim_show_assert_internal(vrf->info, vty);
4609
4610 return CMD_SUCCESS;
4611 }
4612
4613 DEFUN (show_ip_pim_assert_metric,
4614 show_ip_pim_assert_metric_cmd,
4615 "show ip pim [vrf NAME] assert-metric",
4616 SHOW_STR
4617 IP_STR
4618 PIM_STR
4619 VRF_CMD_HELP_STR
4620 "PIM interface assert metric\n")
4621 {
4622 int idx = 2;
4623 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4624
4625 if (!vrf)
4626 return CMD_WARNING;
4627
4628 pim_show_assert_metric(vrf->info, vty);
4629
4630 return CMD_SUCCESS;
4631 }
4632
4633 DEFUN (show_ip_pim_assert_winner_metric,
4634 show_ip_pim_assert_winner_metric_cmd,
4635 "show ip pim [vrf NAME] assert-winner-metric",
4636 SHOW_STR
4637 IP_STR
4638 PIM_STR
4639 VRF_CMD_HELP_STR
4640 "PIM interface assert winner metric\n")
4641 {
4642 int idx = 2;
4643 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4644
4645 if (!vrf)
4646 return CMD_WARNING;
4647
4648 pim_show_assert_winner_metric(vrf->info, vty);
4649
4650 return CMD_SUCCESS;
4651 }
4652
4653 DEFUN (show_ip_pim_interface,
4654 show_ip_pim_interface_cmd,
4655 "show ip pim [mlag] [vrf NAME] interface [detail|WORD] [json]",
4656 SHOW_STR
4657 IP_STR
4658 PIM_STR
4659 "MLAG\n"
4660 VRF_CMD_HELP_STR
4661 "PIM interface information\n"
4662 "Detailed output\n"
4663 "interface name\n"
4664 JSON_STR)
4665 {
4666 int idx = 2;
4667 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4668 bool uj = use_json(argc, argv);
4669 bool mlag = false;
4670
4671 if (!vrf)
4672 return CMD_WARNING;
4673
4674 if (argv_find(argv, argc, "mlag", &idx))
4675 mlag = true;
4676
4677 if (argv_find(argv, argc, "WORD", &idx)
4678 || argv_find(argv, argc, "detail", &idx))
4679 pim_show_interfaces_single(vrf->info, vty, argv[idx]->arg, mlag,
4680 uj);
4681 else
4682 pim_show_interfaces(vrf->info, vty, mlag, uj);
4683
4684 return CMD_SUCCESS;
4685 }
4686
4687 DEFUN (show_ip_pim_interface_vrf_all,
4688 show_ip_pim_interface_vrf_all_cmd,
4689 "show ip pim [mlag] vrf all interface [detail|WORD] [json]",
4690 SHOW_STR
4691 IP_STR
4692 PIM_STR
4693 "MLAG\n"
4694 VRF_CMD_HELP_STR
4695 "PIM interface information\n"
4696 "Detailed output\n"
4697 "interface name\n"
4698 JSON_STR)
4699 {
4700 int idx = 2;
4701 bool uj = use_json(argc, argv);
4702 struct vrf *vrf;
4703 bool first = true;
4704 bool mlag = false;
4705
4706 if (argv_find(argv, argc, "mlag", &idx))
4707 mlag = true;
4708
4709 idx = 6;
4710 if (uj)
4711 vty_out(vty, "{ ");
4712 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4713 if (uj) {
4714 if (!first)
4715 vty_out(vty, ", ");
4716 vty_out(vty, " \"%s\": ", vrf->name);
4717 first = false;
4718 } else
4719 vty_out(vty, "VRF: %s\n", vrf->name);
4720 if (argv_find(argv, argc, "WORD", &idx)
4721 || argv_find(argv, argc, "detail", &idx))
4722 pim_show_interfaces_single(vrf->info, vty,
4723 argv[idx]->arg, mlag, uj);
4724 else
4725 pim_show_interfaces(vrf->info, vty, mlag, uj);
4726 }
4727 if (uj)
4728 vty_out(vty, "}\n");
4729
4730 return CMD_SUCCESS;
4731 }
4732
4733 DEFPY (show_ip_pim_join,
4734 show_ip_pim_join_cmd,
4735 "show ip pim [vrf NAME] join [A.B.C.D$s_or_g [A.B.C.D$g]] [json$json]",
4736 SHOW_STR
4737 IP_STR
4738 PIM_STR
4739 VRF_CMD_HELP_STR
4740 "PIM interface join information\n"
4741 "The Source or Group\n"
4742 "The Group\n"
4743 JSON_STR)
4744 {
4745 struct prefix_sg sg = {0};
4746 struct vrf *v;
4747 bool uj = !!json;
4748 struct pim_instance *pim;
4749
4750 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4751
4752 if (!v) {
4753 vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
4754 return CMD_WARNING;
4755 }
4756 pim = pim_get_pim_instance(v->vrf_id);
4757
4758 if (!pim) {
4759 vty_out(vty, "%% Unable to find pim instance\n");
4760 return CMD_WARNING;
4761 }
4762
4763 if (s_or_g.s_addr != INADDR_ANY) {
4764 if (g.s_addr != INADDR_ANY) {
4765 sg.src = s_or_g;
4766 sg.grp = g;
4767 } else
4768 sg.grp = s_or_g;
4769 }
4770
4771 pim_show_join(pim, vty, &sg, uj);
4772
4773 return CMD_SUCCESS;
4774 }
4775
4776 DEFUN (show_ip_pim_join_vrf_all,
4777 show_ip_pim_join_vrf_all_cmd,
4778 "show ip pim vrf all join [json]",
4779 SHOW_STR
4780 IP_STR
4781 PIM_STR
4782 VRF_CMD_HELP_STR
4783 "PIM interface join information\n"
4784 JSON_STR)
4785 {
4786 struct prefix_sg sg = {0};
4787 bool uj = use_json(argc, argv);
4788 struct vrf *vrf;
4789 bool first = true;
4790
4791 if (uj)
4792 vty_out(vty, "{ ");
4793 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4794 if (uj) {
4795 if (!first)
4796 vty_out(vty, ", ");
4797 vty_out(vty, " \"%s\": ", vrf->name);
4798 first = false;
4799 } else
4800 vty_out(vty, "VRF: %s\n", vrf->name);
4801 pim_show_join(vrf->info, vty, &sg, uj);
4802 }
4803 if (uj)
4804 vty_out(vty, "}\n");
4805
4806 return CMD_WARNING;
4807 }
4808
4809 static void pim_show_jp_agg_helper(struct vty *vty,
4810 struct interface *ifp,
4811 struct pim_neighbor *neigh,
4812 struct pim_upstream *up,
4813 int is_join)
4814 {
4815 char src_str[INET_ADDRSTRLEN];
4816 char grp_str[INET_ADDRSTRLEN];
4817 char rpf_str[INET_ADDRSTRLEN];
4818
4819 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
4820 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
4821 /* pius->address.s_addr */
4822 pim_inet4_dump("<rpf?>", neigh->source_addr, rpf_str, sizeof(rpf_str));
4823
4824 vty_out(vty, "%-16s %-15s %-15s %-15s %5s\n",
4825 ifp->name, rpf_str, src_str,
4826 grp_str, is_join?"J":"P");
4827 }
4828
4829 static void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty)
4830 {
4831 struct interface *ifp;
4832 struct pim_interface *pim_ifp;
4833 struct listnode *n_node;
4834 struct pim_neighbor *neigh;
4835 struct listnode *jag_node;
4836 struct pim_jp_agg_group *jag;
4837 struct listnode *js_node;
4838 struct pim_jp_sources *js;
4839
4840 vty_out(vty,
4841 "Interface RPF Nbr Source Group State\n");
4842
4843 FOR_ALL_INTERFACES (pim->vrf, ifp) {
4844 pim_ifp = ifp->info;
4845 if (!pim_ifp)
4846 continue;
4847
4848 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
4849 n_node, neigh)) {
4850 for (ALL_LIST_ELEMENTS_RO(neigh->upstream_jp_agg,
4851 jag_node, jag)) {
4852 for (ALL_LIST_ELEMENTS_RO(jag->sources,
4853 js_node, js)) {
4854 pim_show_jp_agg_helper(vty,
4855 ifp, neigh, js->up,
4856 js->is_join);
4857 }
4858 }
4859 }
4860 }
4861 }
4862
4863 DEFPY (show_ip_pim_jp_agg,
4864 show_ip_pim_jp_agg_cmd,
4865 "show ip pim [vrf NAME] jp-agg",
4866 SHOW_STR
4867 IP_STR
4868 PIM_STR
4869 VRF_CMD_HELP_STR
4870 "join prune aggregation list\n")
4871 {
4872 struct vrf *v;
4873 struct pim_instance *pim;
4874
4875 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4876
4877 if (!v) {
4878 vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
4879 return CMD_WARNING;
4880 }
4881 pim = pim_get_pim_instance(v->vrf_id);
4882
4883 if (!pim) {
4884 vty_out(vty, "%% Unable to find pim instance\n");
4885 return CMD_WARNING;
4886 }
4887
4888 pim_show_jp_agg_list(pim, vty);
4889
4890 return CMD_SUCCESS;
4891 }
4892
4893 DEFUN (show_ip_pim_local_membership,
4894 show_ip_pim_local_membership_cmd,
4895 "show ip pim [vrf NAME] local-membership [json]",
4896 SHOW_STR
4897 IP_STR
4898 PIM_STR
4899 VRF_CMD_HELP_STR
4900 "PIM interface local-membership\n"
4901 JSON_STR)
4902 {
4903 int idx = 2;
4904 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4905 bool uj = use_json(argc, argv);
4906
4907 if (!vrf)
4908 return CMD_WARNING;
4909
4910 pim_show_membership(vrf->info, vty, uj);
4911
4912 return CMD_SUCCESS;
4913 }
4914
4915 static void pim_show_mlag_up_entry_detail(struct vrf *vrf,
4916 struct vty *vty,
4917 struct pim_upstream *up,
4918 char *src_str, char *grp_str,
4919 json_object *json)
4920 {
4921 if (json) {
4922 json_object *json_row = NULL;
4923 json_object *own_list = NULL;
4924 json_object *json_group = NULL;
4925
4926
4927 json_object_object_get_ex(json, grp_str, &json_group);
4928 if (!json_group) {
4929 json_group = json_object_new_object();
4930 json_object_object_add(json, grp_str,
4931 json_group);
4932 }
4933
4934 json_row = json_object_new_object();
4935 json_object_string_add(json_row, "source", src_str);
4936 json_object_string_add(json_row, "group", grp_str);
4937
4938 own_list = json_object_new_array();
4939 if (pim_up_mlag_is_local(up))
4940 json_object_array_add(own_list,
4941 json_object_new_string("local"));
4942 if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_PEER))
4943 json_object_array_add(own_list,
4944 json_object_new_string("peer"));
4945 if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE))
4946 json_object_array_add(
4947 own_list, json_object_new_string("Interface"));
4948 json_object_object_add(json_row, "owners", own_list);
4949
4950 json_object_int_add(json_row, "localCost",
4951 pim_up_mlag_local_cost(up));
4952 json_object_int_add(json_row, "peerCost",
4953 pim_up_mlag_peer_cost(up));
4954 if (PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags))
4955 json_object_boolean_false_add(json_row, "df");
4956 else
4957 json_object_boolean_true_add(json_row, "df");
4958 json_object_object_add(json_group, src_str, json_row);
4959 } else {
4960 char own_str[6];
4961
4962 own_str[0] = '\0';
4963 if (pim_up_mlag_is_local(up))
4964 strlcat(own_str, "L", sizeof(own_str));
4965 if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_PEER))
4966 strlcat(own_str, "P", sizeof(own_str));
4967 if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE))
4968 strlcat(own_str, "I", sizeof(own_str));
4969 /* XXX - fixup, print paragraph output */
4970 vty_out(vty,
4971 "%-15s %-15s %-6s %-11u %-10d %2s\n",
4972 src_str, grp_str, own_str,
4973 pim_up_mlag_local_cost(up),
4974 pim_up_mlag_peer_cost(up),
4975 PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags)
4976 ? "n" : "y");
4977 }
4978 }
4979
4980 static void pim_show_mlag_up_detail(struct vrf *vrf,
4981 struct vty *vty, const char *src_or_group,
4982 const char *group, bool uj)
4983 {
4984 char src_str[INET_ADDRSTRLEN];
4985 char grp_str[INET_ADDRSTRLEN];
4986 struct pim_upstream *up;
4987 struct pim_instance *pim = vrf->info;
4988 json_object *json = NULL;
4989
4990 if (uj)
4991 json = json_object_new_object();
4992 else
4993 vty_out(vty,
4994 "Source Group Owner Local-cost Peer-cost DF\n");
4995
4996 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
4997 if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_PEER)
4998 && !(up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE)
4999 && !pim_up_mlag_is_local(up))
5000 continue;
5001
5002 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
5003 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
5004 /* XXX: strcmps are clearly inefficient. we should do uint comps
5005 * here instead.
5006 */
5007 if (group) {
5008 if (strcmp(src_str, src_or_group) ||
5009 strcmp(grp_str, group))
5010 continue;
5011 } else {
5012 if (strcmp(src_str, src_or_group) &&
5013 strcmp(grp_str, src_or_group))
5014 continue;
5015 }
5016 pim_show_mlag_up_entry_detail(vrf, vty, up,
5017 src_str, grp_str, json);
5018 }
5019
5020 if (uj) {
5021 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5022 json, JSON_C_TO_STRING_PRETTY));
5023 json_object_free(json);
5024 }
5025 }
5026
5027 static void pim_show_mlag_up_vrf(struct vrf *vrf, struct vty *vty, bool uj)
5028 {
5029 json_object *json = NULL;
5030 json_object *json_row;
5031 struct pim_upstream *up;
5032 char src_str[INET_ADDRSTRLEN];
5033 char grp_str[INET_ADDRSTRLEN];
5034 struct pim_instance *pim = vrf->info;
5035 json_object *json_group = NULL;
5036
5037 if (uj) {
5038 json = json_object_new_object();
5039 } else {
5040 vty_out(vty,
5041 "Source Group Owner Local-cost Peer-cost DF\n");
5042 }
5043
5044 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
5045 if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_PEER)
5046 && !(up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE)
5047 && !pim_up_mlag_is_local(up))
5048 continue;
5049 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
5050 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
5051 if (uj) {
5052 json_object *own_list = NULL;
5053
5054 json_object_object_get_ex(json, grp_str, &json_group);
5055 if (!json_group) {
5056 json_group = json_object_new_object();
5057 json_object_object_add(json, grp_str,
5058 json_group);
5059 }
5060
5061 json_row = json_object_new_object();
5062 json_object_string_add(json_row, "vrf", vrf->name);
5063 json_object_string_add(json_row, "source", src_str);
5064 json_object_string_add(json_row, "group", grp_str);
5065
5066 own_list = json_object_new_array();
5067 if (pim_up_mlag_is_local(up)) {
5068
5069 json_object_array_add(own_list,
5070 json_object_new_string(
5071 "local"));
5072 }
5073 if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_PEER)) {
5074 json_object_array_add(own_list,
5075 json_object_new_string(
5076 "peer"));
5077 }
5078 json_object_object_add(json_row, "owners", own_list);
5079
5080 json_object_int_add(json_row, "localCost",
5081 pim_up_mlag_local_cost(up));
5082 json_object_int_add(json_row, "peerCost",
5083 pim_up_mlag_peer_cost(up));
5084 if (PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags))
5085 json_object_boolean_false_add(json_row, "df");
5086 else
5087 json_object_boolean_true_add(json_row, "df");
5088 json_object_object_add(json_group, src_str, json_row);
5089 } else {
5090 char own_str[6];
5091
5092 own_str[0] = '\0';
5093 if (pim_up_mlag_is_local(up))
5094 strlcat(own_str, "L", sizeof(own_str));
5095 if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_PEER))
5096 strlcat(own_str, "P", sizeof(own_str));
5097 if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE))
5098 strlcat(own_str, "I", sizeof(own_str));
5099 vty_out(vty,
5100 "%-15s %-15s %-6s %-11u %-10u %2s\n",
5101 src_str, grp_str, own_str,
5102 pim_up_mlag_local_cost(up),
5103 pim_up_mlag_peer_cost(up),
5104 PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags)
5105 ? "n" : "y");
5106 }
5107 }
5108 if (uj) {
5109 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5110 json, JSON_C_TO_STRING_PRETTY));
5111 json_object_free(json);
5112 }
5113 }
5114
5115 static void pim_show_mlag_help_string(struct vty *vty, bool uj)
5116 {
5117 if (!uj) {
5118 vty_out(vty, "Owner codes:\n");
5119 vty_out(vty,
5120 "L: EVPN-MLAG Entry, I:PIM-MLAG Entry, P: Peer Entry\n");
5121 }
5122 }
5123
5124
5125 DEFUN(show_ip_pim_mlag_up, show_ip_pim_mlag_up_cmd,
5126 "show ip pim [vrf NAME] mlag upstream [A.B.C.D [A.B.C.D]] [json]",
5127 SHOW_STR
5128 IP_STR
5129 PIM_STR
5130 VRF_CMD_HELP_STR
5131 "MLAG\n"
5132 "upstream\n"
5133 "Unicast or Multicast address\n"
5134 "Multicast address\n" JSON_STR)
5135 {
5136 const char *src_or_group = NULL;
5137 const char *group = NULL;
5138 int idx = 2;
5139 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5140 bool uj = use_json(argc, argv);
5141
5142 if (!vrf || !vrf->info) {
5143 vty_out(vty, "%s: VRF or Info missing\n", __func__);
5144 return CMD_WARNING;
5145 }
5146
5147 if (uj)
5148 argc--;
5149
5150 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
5151 src_or_group = argv[idx]->arg;
5152 if (idx + 1 < argc)
5153 group = argv[idx + 1]->arg;
5154 }
5155
5156 pim_show_mlag_help_string(vty, uj);
5157
5158 if (src_or_group)
5159 pim_show_mlag_up_detail(vrf, vty, src_or_group, group, uj);
5160 else
5161 pim_show_mlag_up_vrf(vrf, vty, uj);
5162
5163 return CMD_SUCCESS;
5164 }
5165
5166
5167 DEFUN(show_ip_pim_mlag_up_vrf_all, show_ip_pim_mlag_up_vrf_all_cmd,
5168 "show ip pim vrf all mlag upstream [json]",
5169 SHOW_STR IP_STR PIM_STR VRF_CMD_HELP_STR
5170 "MLAG\n"
5171 "upstream\n" JSON_STR)
5172 {
5173 struct vrf *vrf;
5174 bool uj = use_json(argc, argv);
5175
5176 pim_show_mlag_help_string(vty, uj);
5177 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5178 pim_show_mlag_up_vrf(vrf, vty, uj);
5179 }
5180
5181 return CMD_SUCCESS;
5182 }
5183
5184 DEFUN (show_ip_pim_neighbor,
5185 show_ip_pim_neighbor_cmd,
5186 "show ip pim [vrf NAME] neighbor [detail|WORD] [json]",
5187 SHOW_STR
5188 IP_STR
5189 PIM_STR
5190 VRF_CMD_HELP_STR
5191 "PIM neighbor information\n"
5192 "Detailed output\n"
5193 "Name of interface or neighbor\n"
5194 JSON_STR)
5195 {
5196 int idx = 2;
5197 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5198 bool uj = use_json(argc, argv);
5199
5200 if (!vrf)
5201 return CMD_WARNING;
5202
5203 if (argv_find(argv, argc, "detail", &idx)
5204 || argv_find(argv, argc, "WORD", &idx))
5205 pim_show_neighbors_single(vrf->info, vty, argv[idx]->arg, uj);
5206 else
5207 pim_show_neighbors(vrf->info, vty, uj);
5208
5209 return CMD_SUCCESS;
5210 }
5211
5212 DEFUN (show_ip_pim_neighbor_vrf_all,
5213 show_ip_pim_neighbor_vrf_all_cmd,
5214 "show ip pim vrf all neighbor [detail|WORD] [json]",
5215 SHOW_STR
5216 IP_STR
5217 PIM_STR
5218 VRF_CMD_HELP_STR
5219 "PIM neighbor information\n"
5220 "Detailed output\n"
5221 "Name of interface or neighbor\n"
5222 JSON_STR)
5223 {
5224 int idx = 2;
5225 bool uj = use_json(argc, argv);
5226 struct vrf *vrf;
5227 bool first = true;
5228
5229 if (uj)
5230 vty_out(vty, "{ ");
5231 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5232 if (uj) {
5233 if (!first)
5234 vty_out(vty, ", ");
5235 vty_out(vty, " \"%s\": ", vrf->name);
5236 first = false;
5237 } else
5238 vty_out(vty, "VRF: %s\n", vrf->name);
5239 if (argv_find(argv, argc, "detail", &idx)
5240 || argv_find(argv, argc, "WORD", &idx))
5241 pim_show_neighbors_single(vrf->info, vty,
5242 argv[idx]->arg, uj);
5243 else
5244 pim_show_neighbors(vrf->info, vty, uj);
5245 }
5246 if (uj)
5247 vty_out(vty, "}\n");
5248
5249 return CMD_SUCCESS;
5250 }
5251
5252 DEFUN (show_ip_pim_secondary,
5253 show_ip_pim_secondary_cmd,
5254 "show ip pim [vrf NAME] secondary",
5255 SHOW_STR
5256 IP_STR
5257 PIM_STR
5258 VRF_CMD_HELP_STR
5259 "PIM neighbor addresses\n")
5260 {
5261 int idx = 2;
5262 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5263
5264 if (!vrf)
5265 return CMD_WARNING;
5266
5267 pim_show_neighbors_secondary(vrf->info, vty);
5268
5269 return CMD_SUCCESS;
5270 }
5271
5272 DEFUN (show_ip_pim_state,
5273 show_ip_pim_state_cmd,
5274 "show ip pim [vrf NAME] state [A.B.C.D [A.B.C.D]] [json]",
5275 SHOW_STR
5276 IP_STR
5277 PIM_STR
5278 VRF_CMD_HELP_STR
5279 "PIM state information\n"
5280 "Unicast or Multicast address\n"
5281 "Multicast address\n"
5282 JSON_STR)
5283 {
5284 const char *src_or_group = NULL;
5285 const char *group = NULL;
5286 int idx = 2;
5287 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5288 bool uj = use_json(argc, argv);
5289
5290 if (!vrf)
5291 return CMD_WARNING;
5292
5293 if (uj)
5294 argc--;
5295
5296 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
5297 src_or_group = argv[idx]->arg;
5298 if (idx + 1 < argc)
5299 group = argv[idx + 1]->arg;
5300 }
5301
5302 pim_show_state(vrf->info, vty, src_or_group, group, uj);
5303
5304 return CMD_SUCCESS;
5305 }
5306
5307 DEFUN (show_ip_pim_state_vrf_all,
5308 show_ip_pim_state_vrf_all_cmd,
5309 "show ip pim vrf all state [A.B.C.D [A.B.C.D]] [json]",
5310 SHOW_STR
5311 IP_STR
5312 PIM_STR
5313 VRF_CMD_HELP_STR
5314 "PIM state information\n"
5315 "Unicast or Multicast address\n"
5316 "Multicast address\n"
5317 JSON_STR)
5318 {
5319 const char *src_or_group = NULL;
5320 const char *group = NULL;
5321 int idx = 2;
5322 bool uj = use_json(argc, argv);
5323 struct vrf *vrf;
5324 bool first = true;
5325
5326 if (uj) {
5327 vty_out(vty, "{ ");
5328 argc--;
5329 }
5330
5331 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
5332 src_or_group = argv[idx]->arg;
5333 if (idx + 1 < argc)
5334 group = argv[idx + 1]->arg;
5335 }
5336
5337 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5338 if (uj) {
5339 if (!first)
5340 vty_out(vty, ", ");
5341 vty_out(vty, " \"%s\": ", vrf->name);
5342 first = false;
5343 } else
5344 vty_out(vty, "VRF: %s\n", vrf->name);
5345 pim_show_state(vrf->info, vty, src_or_group, group, uj);
5346 }
5347 if (uj)
5348 vty_out(vty, "}\n");
5349
5350 return CMD_SUCCESS;
5351 }
5352
5353 DEFPY (show_ip_pim_upstream,
5354 show_ip_pim_upstream_cmd,
5355 "show ip pim [vrf NAME] upstream [A.B.C.D$s_or_g [A.B.C.D$g]] [json$json]",
5356 SHOW_STR
5357 IP_STR
5358 PIM_STR
5359 VRF_CMD_HELP_STR
5360 "PIM upstream information\n"
5361 "The Source or Group\n"
5362 "The Group\n"
5363 JSON_STR)
5364 {
5365 struct prefix_sg sg = {0};
5366 struct vrf *v;
5367 bool uj = !!json;
5368 struct pim_instance *pim;
5369
5370 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
5371
5372 if (!v) {
5373 vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
5374 return CMD_WARNING;
5375 }
5376 pim = pim_get_pim_instance(v->vrf_id);
5377
5378 if (!pim) {
5379 vty_out(vty, "%% Unable to find pim instance\n");
5380 return CMD_WARNING;
5381 }
5382
5383 if (s_or_g.s_addr != INADDR_ANY) {
5384 if (g.s_addr != INADDR_ANY) {
5385 sg.src = s_or_g;
5386 sg.grp = g;
5387 } else
5388 sg.grp = s_or_g;
5389 }
5390 pim_show_upstream(pim, vty, &sg, uj);
5391
5392 return CMD_SUCCESS;
5393 }
5394
5395 DEFUN (show_ip_pim_upstream_vrf_all,
5396 show_ip_pim_upstream_vrf_all_cmd,
5397 "show ip pim vrf all upstream [json]",
5398 SHOW_STR
5399 IP_STR
5400 PIM_STR
5401 VRF_CMD_HELP_STR
5402 "PIM upstream information\n"
5403 JSON_STR)
5404 {
5405 struct prefix_sg sg = {0};
5406 bool uj = use_json(argc, argv);
5407 struct vrf *vrf;
5408 bool first = true;
5409
5410 if (uj)
5411 vty_out(vty, "{ ");
5412 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5413 if (uj) {
5414 if (!first)
5415 vty_out(vty, ", ");
5416 vty_out(vty, " \"%s\": ", vrf->name);
5417 first = false;
5418 } else
5419 vty_out(vty, "VRF: %s\n", vrf->name);
5420 pim_show_upstream(vrf->info, vty, &sg, uj);
5421 }
5422
5423 return CMD_SUCCESS;
5424 }
5425
5426 DEFUN (show_ip_pim_channel,
5427 show_ip_pim_channel_cmd,
5428 "show ip pim [vrf NAME] channel [json]",
5429 SHOW_STR
5430 IP_STR
5431 PIM_STR
5432 VRF_CMD_HELP_STR
5433 "PIM downstream channel info\n"
5434 JSON_STR)
5435 {
5436 int idx = 2;
5437 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5438 bool uj = use_json(argc, argv);
5439
5440 if (!vrf)
5441 return CMD_WARNING;
5442
5443 pim_show_channel(vrf->info, vty, uj);
5444
5445 return CMD_SUCCESS;
5446 }
5447
5448 DEFUN (show_ip_pim_upstream_join_desired,
5449 show_ip_pim_upstream_join_desired_cmd,
5450 "show ip pim [vrf NAME] upstream-join-desired [json]",
5451 SHOW_STR
5452 IP_STR
5453 PIM_STR
5454 VRF_CMD_HELP_STR
5455 "PIM upstream join-desired\n"
5456 JSON_STR)
5457 {
5458 int idx = 2;
5459 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5460 bool uj = use_json(argc, argv);
5461
5462 if (!vrf)
5463 return CMD_WARNING;
5464
5465 pim_show_join_desired(vrf->info, vty, uj);
5466
5467 return CMD_SUCCESS;
5468 }
5469
5470 DEFUN (show_ip_pim_upstream_rpf,
5471 show_ip_pim_upstream_rpf_cmd,
5472 "show ip pim [vrf NAME] upstream-rpf [json]",
5473 SHOW_STR
5474 IP_STR
5475 PIM_STR
5476 VRF_CMD_HELP_STR
5477 "PIM upstream source rpf\n"
5478 JSON_STR)
5479 {
5480 int idx = 2;
5481 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5482 bool uj = use_json(argc, argv);
5483
5484 if (!vrf)
5485 return CMD_WARNING;
5486
5487 pim_show_upstream_rpf(vrf->info, vty, uj);
5488
5489 return CMD_SUCCESS;
5490 }
5491
5492 DEFUN (show_ip_pim_rp,
5493 show_ip_pim_rp_cmd,
5494 "show ip pim [vrf NAME] rp-info [json]",
5495 SHOW_STR
5496 IP_STR
5497 PIM_STR
5498 VRF_CMD_HELP_STR
5499 "PIM RP information\n"
5500 JSON_STR)
5501 {
5502 int idx = 2;
5503 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5504 bool uj = use_json(argc, argv);
5505
5506 if (!vrf)
5507 return CMD_WARNING;
5508
5509 pim_rp_show_information(vrf->info, vty, uj);
5510
5511 return CMD_SUCCESS;
5512 }
5513
5514 DEFUN (show_ip_pim_rp_vrf_all,
5515 show_ip_pim_rp_vrf_all_cmd,
5516 "show ip pim vrf all rp-info [json]",
5517 SHOW_STR
5518 IP_STR
5519 PIM_STR
5520 VRF_CMD_HELP_STR
5521 "PIM RP information\n"
5522 JSON_STR)
5523 {
5524 bool uj = use_json(argc, argv);
5525 struct vrf *vrf;
5526 bool first = true;
5527
5528 if (uj)
5529 vty_out(vty, "{ ");
5530 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5531 if (uj) {
5532 if (!first)
5533 vty_out(vty, ", ");
5534 vty_out(vty, " \"%s\": ", vrf->name);
5535 first = false;
5536 } else
5537 vty_out(vty, "VRF: %s\n", vrf->name);
5538 pim_rp_show_information(vrf->info, vty, uj);
5539 }
5540 if (uj)
5541 vty_out(vty, "}\n");
5542
5543 return CMD_SUCCESS;
5544 }
5545
5546 DEFUN (show_ip_pim_rpf,
5547 show_ip_pim_rpf_cmd,
5548 "show ip pim [vrf NAME] rpf [json]",
5549 SHOW_STR
5550 IP_STR
5551 PIM_STR
5552 VRF_CMD_HELP_STR
5553 "PIM cached source rpf information\n"
5554 JSON_STR)
5555 {
5556 int idx = 2;
5557 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5558 bool uj = use_json(argc, argv);
5559
5560 if (!vrf)
5561 return CMD_WARNING;
5562
5563 pim_show_rpf(vrf->info, vty, uj);
5564
5565 return CMD_SUCCESS;
5566 }
5567
5568 DEFUN (show_ip_pim_rpf_vrf_all,
5569 show_ip_pim_rpf_vrf_all_cmd,
5570 "show ip pim vrf all rpf [json]",
5571 SHOW_STR
5572 IP_STR
5573 PIM_STR
5574 VRF_CMD_HELP_STR
5575 "PIM cached source rpf information\n"
5576 JSON_STR)
5577 {
5578 bool uj = use_json(argc, argv);
5579 struct vrf *vrf;
5580 bool first = true;
5581
5582 if (uj)
5583 vty_out(vty, "{ ");
5584 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5585 if (uj) {
5586 if (!first)
5587 vty_out(vty, ", ");
5588 vty_out(vty, " \"%s\": ", vrf->name);
5589 first = false;
5590 } else
5591 vty_out(vty, "VRF: %s\n", vrf->name);
5592 pim_show_rpf(vrf->info, vty, uj);
5593 }
5594 if (uj)
5595 vty_out(vty, "}\n");
5596
5597 return CMD_SUCCESS;
5598 }
5599
5600 DEFUN (show_ip_pim_nexthop,
5601 show_ip_pim_nexthop_cmd,
5602 "show ip pim [vrf NAME] nexthop",
5603 SHOW_STR
5604 IP_STR
5605 PIM_STR
5606 VRF_CMD_HELP_STR
5607 "PIM cached nexthop rpf information\n")
5608 {
5609 int idx = 2;
5610 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5611
5612 if (!vrf)
5613 return CMD_WARNING;
5614
5615 pim_show_nexthop(vrf->info, vty);
5616
5617 return CMD_SUCCESS;
5618 }
5619
5620 DEFUN (show_ip_pim_nexthop_lookup,
5621 show_ip_pim_nexthop_lookup_cmd,
5622 "show ip pim [vrf NAME] nexthop-lookup A.B.C.D A.B.C.D",
5623 SHOW_STR
5624 IP_STR
5625 PIM_STR
5626 VRF_CMD_HELP_STR
5627 "PIM cached nexthop rpf lookup\n"
5628 "Source/RP address\n"
5629 "Multicast Group address\n")
5630 {
5631 struct prefix nht_p;
5632 int result = 0;
5633 struct in_addr src_addr, grp_addr;
5634 struct in_addr vif_source;
5635 const char *addr_str, *addr_str1;
5636 struct prefix grp;
5637 struct pim_nexthop nexthop;
5638 char nexthop_addr_str[PREFIX_STRLEN];
5639 char grp_str[PREFIX_STRLEN];
5640 int idx = 2;
5641 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5642
5643 if (!vrf)
5644 return CMD_WARNING;
5645
5646 argv_find(argv, argc, "A.B.C.D", &idx);
5647 addr_str = argv[idx]->arg;
5648 result = inet_pton(AF_INET, addr_str, &src_addr);
5649 if (result <= 0) {
5650 vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str,
5651 errno, safe_strerror(errno));
5652 return CMD_WARNING;
5653 }
5654
5655 if (pim_is_group_224_4(src_addr)) {
5656 vty_out(vty,
5657 "Invalid argument. Expected Valid Source Address.\n");
5658 return CMD_WARNING;
5659 }
5660
5661 addr_str1 = argv[idx + 1]->arg;
5662 result = inet_pton(AF_INET, addr_str1, &grp_addr);
5663 if (result <= 0) {
5664 vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str,
5665 errno, safe_strerror(errno));
5666 return CMD_WARNING;
5667 }
5668
5669 if (!pim_is_group_224_4(grp_addr)) {
5670 vty_out(vty,
5671 "Invalid argument. Expected Valid Multicast Group Address.\n");
5672 return CMD_WARNING;
5673 }
5674
5675 if (!pim_rp_set_upstream_addr(vrf->info, &vif_source, src_addr,
5676 grp_addr))
5677 return CMD_SUCCESS;
5678
5679 nht_p.family = AF_INET;
5680 nht_p.prefixlen = IPV4_MAX_BITLEN;
5681 nht_p.u.prefix4 = vif_source;
5682 grp.family = AF_INET;
5683 grp.prefixlen = IPV4_MAX_BITLEN;
5684 grp.u.prefix4 = grp_addr;
5685 memset(&nexthop, 0, sizeof(nexthop));
5686
5687 result = pim_ecmp_nexthop_lookup(vrf->info, &nexthop, &nht_p, &grp, 0);
5688
5689 if (!result) {
5690 vty_out(vty,
5691 "Nexthop Lookup failed, no usable routes returned.\n");
5692 return CMD_SUCCESS;
5693 }
5694
5695 pim_addr_dump("<grp?>", &grp, grp_str, sizeof(grp_str));
5696 pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr,
5697 nexthop_addr_str, sizeof(nexthop_addr_str));
5698 vty_out(vty, "Group %s --- Nexthop %s Interface %s \n", grp_str,
5699 nexthop_addr_str, nexthop.interface->name);
5700
5701 return CMD_SUCCESS;
5702 }
5703
5704 DEFUN (show_ip_pim_interface_traffic,
5705 show_ip_pim_interface_traffic_cmd,
5706 "show ip pim [vrf NAME] interface traffic [WORD] [json]",
5707 SHOW_STR
5708 IP_STR
5709 PIM_STR
5710 VRF_CMD_HELP_STR
5711 "PIM interface information\n"
5712 "Protocol Packet counters\n"
5713 "Interface name\n"
5714 JSON_STR)
5715 {
5716 int idx = 2;
5717 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5718 bool uj = use_json(argc, argv);
5719
5720 if (!vrf)
5721 return CMD_WARNING;
5722
5723 if (argv_find(argv, argc, "WORD", &idx))
5724 pim_show_interface_traffic_single(vrf->info, vty,
5725 argv[idx]->arg, uj);
5726 else
5727 pim_show_interface_traffic(vrf->info, vty, uj);
5728
5729 return CMD_SUCCESS;
5730 }
5731
5732 DEFUN (show_ip_pim_bsm_db,
5733 show_ip_pim_bsm_db_cmd,
5734 "show ip pim bsm-database [vrf NAME] [json]",
5735 SHOW_STR
5736 IP_STR
5737 PIM_STR
5738 "PIM cached bsm packets information\n"
5739 VRF_CMD_HELP_STR
5740 JSON_STR)
5741 {
5742 int idx = 2;
5743 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5744 bool uj = use_json(argc, argv);
5745
5746 if (!vrf)
5747 return CMD_WARNING;
5748
5749 pim_show_bsm_db(vrf->info, vty, uj);
5750 return CMD_SUCCESS;
5751 }
5752
5753 DEFUN (show_ip_pim_bsrp,
5754 show_ip_pim_bsrp_cmd,
5755 "show ip pim bsrp-info [vrf NAME] [json]",
5756 SHOW_STR
5757 IP_STR
5758 PIM_STR
5759 "PIM cached group-rp mappings information\n"
5760 VRF_CMD_HELP_STR
5761 JSON_STR)
5762 {
5763 int idx = 2;
5764 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5765 bool uj = use_json(argc, argv);
5766
5767 if (!vrf)
5768 return CMD_WARNING;
5769
5770 pim_show_group_rp_mappings_info(vrf->info, vty, uj);
5771
5772 return CMD_SUCCESS;
5773 }
5774
5775 DEFUN (show_ip_pim_statistics,
5776 show_ip_pim_statistics_cmd,
5777 "show ip pim [vrf NAME] statistics [interface WORD] [json]",
5778 SHOW_STR
5779 IP_STR
5780 PIM_STR
5781 VRF_CMD_HELP_STR
5782 "PIM statistics\n"
5783 INTERFACE_STR
5784 "PIM interface\n"
5785 JSON_STR)
5786 {
5787 int idx = 2;
5788 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5789 bool uj = use_json(argc, argv);
5790
5791 if (!vrf)
5792 return CMD_WARNING;
5793
5794 if (argv_find(argv, argc, "WORD", &idx))
5795 pim_show_statistics(vrf->info, vty, argv[idx]->arg, uj);
5796 else
5797 pim_show_statistics(vrf->info, vty, NULL, uj);
5798
5799 return CMD_SUCCESS;
5800 }
5801
5802 static void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty,
5803 bool uj)
5804 {
5805 struct interface *ifp;
5806 char buf[PREFIX_STRLEN];
5807 json_object *json = NULL;
5808 json_object *json_row = NULL;
5809
5810 vty_out(vty, "\n");
5811
5812 if (uj)
5813 json = json_object_new_object();
5814 else
5815 vty_out(vty,
5816 "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut\n");
5817
5818 FOR_ALL_INTERFACES (pim->vrf, ifp) {
5819 struct pim_interface *pim_ifp;
5820 struct in_addr ifaddr;
5821 struct sioc_vif_req vreq;
5822
5823 pim_ifp = ifp->info;
5824
5825 if (!pim_ifp)
5826 continue;
5827
5828 memset(&vreq, 0, sizeof(vreq));
5829 vreq.vifi = pim_ifp->mroute_vif_index;
5830
5831 if (ioctl(pim->mroute_socket, SIOCGETVIFCNT, &vreq)) {
5832 zlog_warn(
5833 "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
5834 (unsigned long)SIOCGETVIFCNT, ifp->name,
5835 pim_ifp->mroute_vif_index, errno,
5836 safe_strerror(errno));
5837 }
5838
5839 ifaddr = pim_ifp->primary_address;
5840 if (uj) {
5841 json_row = json_object_new_object();
5842 json_object_string_add(json_row, "name", ifp->name);
5843 json_object_string_add(json_row, "state",
5844 if_is_up(ifp) ? "up" : "down");
5845 json_object_string_add(
5846 json_row, "address",
5847 inet_ntop(AF_INET, &pim_ifp->primary_address,
5848 buf, sizeof(buf)));
5849 json_object_int_add(json_row, "ifIndex", ifp->ifindex);
5850 json_object_int_add(json_row, "vif",
5851 pim_ifp->mroute_vif_index);
5852 json_object_int_add(json_row, "pktsIn",
5853 (unsigned long)vreq.icount);
5854 json_object_int_add(json_row, "pktsOut",
5855 (unsigned long)vreq.ocount);
5856 json_object_int_add(json_row, "bytesIn",
5857 (unsigned long)vreq.ibytes);
5858 json_object_int_add(json_row, "bytesOut",
5859 (unsigned long)vreq.obytes);
5860 json_object_object_add(json, ifp->name, json_row);
5861 } else {
5862 vty_out(vty,
5863 "%-16s %-15s %3d %3d %7lu %7lu %10lu %10lu\n",
5864 ifp->name,
5865 inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)),
5866 ifp->ifindex, pim_ifp->mroute_vif_index,
5867 (unsigned long)vreq.icount,
5868 (unsigned long)vreq.ocount,
5869 (unsigned long)vreq.ibytes,
5870 (unsigned long)vreq.obytes);
5871 }
5872 }
5873
5874 if (uj) {
5875 vty_out(vty, "%s\n",
5876 json_object_to_json_string_ext(
5877 json, JSON_C_TO_STRING_PRETTY));
5878 json_object_free(json);
5879 }
5880 }
5881
5882 static void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim,
5883 struct vty *vty)
5884 {
5885 struct vrf *vrf = pim->vrf;
5886 time_t now = pim_time_monotonic_sec();
5887 char uptime[10];
5888 char mlag_role[80];
5889
5890 pim = vrf->info;
5891
5892 vty_out(vty, "Router MLAG Role: %s\n",
5893 mlag_role2str(router->mlag_role, mlag_role, sizeof(mlag_role)));
5894 vty_out(vty, "Mroute socket descriptor:");
5895
5896 vty_out(vty, " %d(%s)\n", pim->mroute_socket, vrf->name);
5897
5898 pim_time_uptime(uptime, sizeof(uptime),
5899 now - pim->mroute_socket_creation);
5900 vty_out(vty, "Mroute socket uptime: %s\n", uptime);
5901
5902 vty_out(vty, "\n");
5903
5904 pim_zebra_zclient_update(vty);
5905 pim_zlookup_show_ip_multicast(vty);
5906
5907 vty_out(vty, "\n");
5908 vty_out(vty, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS);
5909
5910 vty_out(vty, "\n");
5911 vty_out(vty, "Upstream Join Timer: %d secs\n", router->t_periodic);
5912 vty_out(vty, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME);
5913 vty_out(vty, "PIM ECMP: %s\n", pim->ecmp_enable ? "Enable" : "Disable");
5914 vty_out(vty, "PIM ECMP Rebalance: %s\n",
5915 pim->ecmp_rebalance_enable ? "Enable" : "Disable");
5916
5917 vty_out(vty, "\n");
5918
5919 show_rpf_refresh_stats(vty, pim, now, NULL);
5920
5921 vty_out(vty, "\n");
5922
5923 show_scan_oil_stats(pim, vty, now);
5924
5925 show_multicast_interfaces(pim, vty, false);
5926 }
5927
5928 DEFUN (show_ip_multicast,
5929 show_ip_multicast_cmd,
5930 "show ip multicast [vrf NAME]",
5931 SHOW_STR
5932 IP_STR
5933 VRF_CMD_HELP_STR
5934 "Multicast global information\n")
5935 {
5936 int idx = 2;
5937 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5938
5939 if (!vrf)
5940 return CMD_WARNING;
5941
5942 pim_cmd_show_ip_multicast_helper(vrf->info, vty);
5943
5944 return CMD_SUCCESS;
5945 }
5946
5947 DEFUN (show_ip_multicast_vrf_all,
5948 show_ip_multicast_vrf_all_cmd,
5949 "show ip multicast vrf all",
5950 SHOW_STR
5951 IP_STR
5952 VRF_CMD_HELP_STR
5953 "Multicast global information\n")
5954 {
5955 bool uj = use_json(argc, argv);
5956 struct vrf *vrf;
5957 bool first = true;
5958
5959 if (uj)
5960 vty_out(vty, "{ ");
5961 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5962 if (uj) {
5963 if (!first)
5964 vty_out(vty, ", ");
5965 vty_out(vty, " \"%s\": ", vrf->name);
5966 first = false;
5967 } else
5968 vty_out(vty, "VRF: %s\n", vrf->name);
5969 pim_cmd_show_ip_multicast_helper(vrf->info, vty);
5970 }
5971 if (uj)
5972 vty_out(vty, "}\n");
5973
5974 return CMD_SUCCESS;
5975 }
5976
5977 DEFUN(show_ip_multicast_count,
5978 show_ip_multicast_count_cmd,
5979 "show ip multicast count [vrf NAME] [json]",
5980 SHOW_STR IP_STR
5981 "Multicast global information\n"
5982 "Data packet count\n"
5983 VRF_CMD_HELP_STR JSON_STR)
5984 {
5985 int idx = 3;
5986 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5987 bool uj = use_json(argc, argv);
5988
5989 if (!vrf)
5990 return CMD_WARNING;
5991
5992 show_multicast_interfaces(vrf->info, vty, uj);
5993
5994 return CMD_SUCCESS;
5995 }
5996
5997 DEFUN(show_ip_multicast_count_vrf_all,
5998 show_ip_multicast_count_vrf_all_cmd,
5999 "show ip multicast count vrf all [json]",
6000 SHOW_STR IP_STR
6001 "Multicast global information\n"
6002 "Data packet count\n"
6003 VRF_CMD_HELP_STR JSON_STR)
6004 {
6005 bool uj = use_json(argc, argv);
6006 struct vrf *vrf;
6007 bool first = true;
6008
6009 if (uj)
6010 vty_out(vty, "{ ");
6011
6012 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
6013 if (uj) {
6014 if (!first)
6015 vty_out(vty, ", ");
6016
6017 vty_out(vty, " \"%s\": ", vrf->name);
6018 first = false;
6019 } else
6020 vty_out(vty, "VRF: %s\n", vrf->name);
6021
6022 show_multicast_interfaces(vrf->info, vty, uj);
6023 }
6024
6025 if (uj)
6026 vty_out(vty, "}\n");
6027
6028 return CMD_SUCCESS;
6029 }
6030
6031 static void show_mroute(struct pim_instance *pim, struct vty *vty,
6032 struct prefix_sg *sg, bool fill, bool uj)
6033 {
6034 struct listnode *node;
6035 struct channel_oil *c_oil;
6036 struct static_route *s_route;
6037 time_t now;
6038 json_object *json = NULL;
6039 json_object *json_group = NULL;
6040 json_object *json_source = NULL;
6041 json_object *json_oil = NULL;
6042 json_object *json_ifp_out = NULL;
6043 int found_oif;
6044 int first;
6045 char grp_str[INET_ADDRSTRLEN];
6046 char src_str[INET_ADDRSTRLEN];
6047 char in_ifname[INTERFACE_NAMSIZ + 1];
6048 char out_ifname[INTERFACE_NAMSIZ + 1];
6049 int oif_vif_index;
6050 struct interface *ifp_in;
6051 char proto[100];
6052 char state_str[PIM_REG_STATE_STR_LEN];
6053 char mroute_uptime[10];
6054
6055 if (uj) {
6056 json = json_object_new_object();
6057 } else {
6058 vty_out(vty, "IP Multicast Routing Table\n");
6059 vty_out(vty, "Flags: S - Sparse, C - Connected, P - Pruned\n");
6060 vty_out(vty,
6061 " R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n");
6062 vty_out(vty,
6063 "\nSource Group Flags Proto Input Output TTL Uptime\n");
6064 }
6065
6066 now = pim_time_monotonic_sec();
6067
6068 /* print list of PIM and IGMP routes */
6069 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
6070 found_oif = 0;
6071 first = 1;
6072 if (!c_oil->installed)
6073 continue;
6074
6075 if (sg->grp.s_addr != INADDR_ANY
6076 && sg->grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr)
6077 continue;
6078 if (sg->src.s_addr != INADDR_ANY
6079 && sg->src.s_addr != c_oil->oil.mfcc_origin.s_addr)
6080 continue;
6081
6082 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str,
6083 sizeof(grp_str));
6084 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str,
6085 sizeof(src_str));
6086
6087 strlcpy(state_str, "S", sizeof(state_str));
6088 /* When a non DR receives a igmp join, it creates a (*,G)
6089 * channel_oil without any upstream creation */
6090 if (c_oil->up) {
6091 if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil->up->flags))
6092 strlcat(state_str, "C", sizeof(state_str));
6093 if (pim_upstream_is_sg_rpt(c_oil->up))
6094 strlcat(state_str, "R", sizeof(state_str));
6095 if (PIM_UPSTREAM_FLAG_TEST_FHR(c_oil->up->flags))
6096 strlcat(state_str, "F", sizeof(state_str));
6097 if (c_oil->up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
6098 strlcat(state_str, "T", sizeof(state_str));
6099 }
6100 if (pim_channel_oil_empty(c_oil))
6101 strlcat(state_str, "P", sizeof(state_str));
6102
6103 ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent);
6104
6105 if (ifp_in)
6106 strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
6107 else
6108 strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
6109
6110
6111 pim_time_uptime(mroute_uptime, sizeof(mroute_uptime),
6112 now - c_oil->mroute_creation);
6113
6114 if (uj) {
6115
6116 /* Find the group, create it if it doesn't exist */
6117 json_object_object_get_ex(json, grp_str, &json_group);
6118
6119 if (!json_group) {
6120 json_group = json_object_new_object();
6121 json_object_object_add(json, grp_str,
6122 json_group);
6123 }
6124
6125 /* Find the source nested under the group, create it if
6126 * it doesn't exist
6127 */
6128 json_object_object_get_ex(json_group, src_str,
6129 &json_source);
6130
6131 if (!json_source) {
6132 json_source = json_object_new_object();
6133 json_object_object_add(json_group, src_str,
6134 json_source);
6135 }
6136
6137 /* Find the inbound interface nested under the source,
6138 * create it if it doesn't exist */
6139 json_object_int_add(json_source, "installed",
6140 c_oil->installed);
6141 json_object_int_add(json_source, "refCount",
6142 c_oil->oil_ref_count);
6143 json_object_int_add(json_source, "oilSize",
6144 c_oil->oil_size);
6145 json_object_int_add(json_source, "OilInheritedRescan",
6146 c_oil->oil_inherited_rescan);
6147 json_object_string_add(json_source, "iif", in_ifname);
6148 json_object_string_add(json_source, "upTime",
6149 mroute_uptime);
6150 json_oil = NULL;
6151 }
6152
6153 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
6154 ++oif_vif_index) {
6155 struct interface *ifp_out;
6156 int ttl;
6157
6158 ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
6159 if (ttl < 1)
6160 continue;
6161
6162 /* do not display muted OIFs */
6163 if (c_oil->oif_flags[oif_vif_index]
6164 & PIM_OIF_FLAG_MUTE)
6165 continue;
6166
6167 if (c_oil->oil.mfcc_parent == oif_vif_index &&
6168 !pim_mroute_allow_iif_in_oil(c_oil,
6169 oif_vif_index))
6170 continue;
6171
6172 ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
6173 found_oif = 1;
6174
6175 if (ifp_out)
6176 strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname));
6177 else
6178 strlcpy(out_ifname, "<oif?>", sizeof(out_ifname));
6179
6180 if (uj) {
6181 json_ifp_out = json_object_new_object();
6182 json_object_string_add(json_ifp_out, "source",
6183 src_str);
6184 json_object_string_add(json_ifp_out, "group",
6185 grp_str);
6186
6187 if (c_oil->oif_flags[oif_vif_index]
6188 & PIM_OIF_FLAG_PROTO_PIM)
6189 json_object_boolean_true_add(
6190 json_ifp_out, "protocolPim");
6191
6192 if (c_oil->oif_flags[oif_vif_index]
6193 & PIM_OIF_FLAG_PROTO_IGMP)
6194 json_object_boolean_true_add(
6195 json_ifp_out, "protocolIgmp");
6196
6197 if (c_oil->oif_flags[oif_vif_index]
6198 & PIM_OIF_FLAG_PROTO_VXLAN)
6199 json_object_boolean_true_add(
6200 json_ifp_out, "protocolVxlan");
6201
6202 if (c_oil->oif_flags[oif_vif_index]
6203 & PIM_OIF_FLAG_PROTO_STAR)
6204 json_object_boolean_true_add(
6205 json_ifp_out,
6206 "protocolInherited");
6207
6208 json_object_string_add(json_ifp_out,
6209 "inboundInterface",
6210 in_ifname);
6211 json_object_int_add(json_ifp_out, "iVifI",
6212 c_oil->oil.mfcc_parent);
6213 json_object_string_add(json_ifp_out,
6214 "outboundInterface",
6215 out_ifname);
6216 json_object_int_add(json_ifp_out, "oVifI",
6217 oif_vif_index);
6218 json_object_int_add(json_ifp_out, "ttl", ttl);
6219 json_object_string_add(json_ifp_out, "upTime",
6220 mroute_uptime);
6221 json_object_string_add(json_source, "flags",
6222 state_str);
6223 if (!json_oil) {
6224 json_oil = json_object_new_object();
6225 json_object_object_add(json_source,
6226 "oil", json_oil);
6227 }
6228 json_object_object_add(json_oil, out_ifname,
6229 json_ifp_out);
6230 } else {
6231 proto[0] = '\0';
6232 if (c_oil->oif_flags[oif_vif_index]
6233 & PIM_OIF_FLAG_PROTO_PIM) {
6234 strlcpy(proto, "PIM", sizeof(proto));
6235 }
6236
6237 if (c_oil->oif_flags[oif_vif_index]
6238 & PIM_OIF_FLAG_PROTO_IGMP) {
6239 strlcpy(proto, "IGMP", sizeof(proto));
6240 }
6241
6242 if (c_oil->oif_flags[oif_vif_index]
6243 & PIM_OIF_FLAG_PROTO_VXLAN) {
6244 strlcpy(proto, "VxLAN", sizeof(proto));
6245 }
6246
6247 if (c_oil->oif_flags[oif_vif_index]
6248 & PIM_OIF_FLAG_PROTO_STAR) {
6249 strlcpy(proto, "STAR", sizeof(proto));
6250 }
6251
6252 vty_out(vty,
6253 "%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
6254 src_str, grp_str, state_str, proto,
6255 in_ifname, out_ifname, ttl,
6256 mroute_uptime);
6257
6258 if (first) {
6259 src_str[0] = '\0';
6260 grp_str[0] = '\0';
6261 in_ifname[0] = '\0';
6262 state_str[0] = '\0';
6263 mroute_uptime[0] = '\0';
6264 first = 0;
6265 }
6266 }
6267 }
6268
6269 if (!uj && !found_oif) {
6270 vty_out(vty,
6271 "%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
6272 src_str, grp_str, state_str, "none", in_ifname,
6273 "none", 0, "--:--:--");
6274 }
6275 }
6276
6277 /* Print list of static routes */
6278 for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
6279 first = 1;
6280
6281 if (!s_route->c_oil.installed)
6282 continue;
6283
6284 pim_inet4_dump("<group?>", s_route->group, grp_str,
6285 sizeof(grp_str));
6286 pim_inet4_dump("<source?>", s_route->source, src_str,
6287 sizeof(src_str));
6288 ifp_in = pim_if_find_by_vif_index(pim, s_route->iif);
6289 found_oif = 0;
6290
6291 if (ifp_in)
6292 strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
6293 else
6294 strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
6295
6296 if (uj) {
6297
6298 /* Find the group, create it if it doesn't exist */
6299 json_object_object_get_ex(json, grp_str, &json_group);
6300
6301 if (!json_group) {
6302 json_group = json_object_new_object();
6303 json_object_object_add(json, grp_str,
6304 json_group);
6305 }
6306
6307 /* Find the source nested under the group, create it if
6308 * it doesn't exist */
6309 json_object_object_get_ex(json_group, src_str,
6310 &json_source);
6311
6312 if (!json_source) {
6313 json_source = json_object_new_object();
6314 json_object_object_add(json_group, src_str,
6315 json_source);
6316 }
6317
6318 json_object_string_add(json_source, "iif", in_ifname);
6319 json_oil = NULL;
6320 } else {
6321 strlcpy(proto, "STATIC", sizeof(proto));
6322 }
6323
6324 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
6325 ++oif_vif_index) {
6326 struct interface *ifp_out;
6327 char oif_uptime[10];
6328 int ttl;
6329
6330 ttl = s_route->oif_ttls[oif_vif_index];
6331 if (ttl < 1)
6332 continue;
6333
6334 ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
6335 pim_time_uptime(
6336 oif_uptime, sizeof(oif_uptime),
6337 now
6338 - s_route->c_oil
6339 .oif_creation[oif_vif_index]);
6340 found_oif = 1;
6341
6342 if (ifp_out)
6343 strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname));
6344 else
6345 strlcpy(out_ifname, "<oif?>", sizeof(out_ifname));
6346
6347 if (uj) {
6348 json_ifp_out = json_object_new_object();
6349 json_object_string_add(json_ifp_out, "source",
6350 src_str);
6351 json_object_string_add(json_ifp_out, "group",
6352 grp_str);
6353 json_object_boolean_true_add(json_ifp_out,
6354 "protocolStatic");
6355 json_object_string_add(json_ifp_out,
6356 "inboundInterface",
6357 in_ifname);
6358 json_object_int_add(
6359 json_ifp_out, "iVifI",
6360 s_route->c_oil.oil.mfcc_parent);
6361 json_object_string_add(json_ifp_out,
6362 "outboundInterface",
6363 out_ifname);
6364 json_object_int_add(json_ifp_out, "oVifI",
6365 oif_vif_index);
6366 json_object_int_add(json_ifp_out, "ttl", ttl);
6367 json_object_string_add(json_ifp_out, "upTime",
6368 oif_uptime);
6369 if (!json_oil) {
6370 json_oil = json_object_new_object();
6371 json_object_object_add(json_source,
6372 "oil", json_oil);
6373 }
6374 json_object_object_add(json_oil, out_ifname,
6375 json_ifp_out);
6376 } else {
6377 vty_out(vty,
6378 "%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
6379 src_str, grp_str, "-", proto, in_ifname,
6380 out_ifname, ttl, oif_uptime);
6381 if (first && !fill) {
6382 src_str[0] = '\0';
6383 grp_str[0] = '\0';
6384 in_ifname[0] = '\0';
6385 first = 0;
6386 }
6387 }
6388 }
6389
6390 if (!uj && !found_oif) {
6391 vty_out(vty,
6392 "%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
6393 src_str, grp_str, "-", proto, in_ifname, "none",
6394 0, "--:--:--");
6395 }
6396 }
6397
6398 if (uj) {
6399 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6400 json, JSON_C_TO_STRING_PRETTY));
6401 json_object_free(json);
6402 }
6403 }
6404
6405 DEFPY (show_ip_mroute,
6406 show_ip_mroute_cmd,
6407 "show ip mroute [vrf NAME] [A.B.C.D$s_or_g [A.B.C.D$g]] [fill$fill] [json$json]",
6408 SHOW_STR
6409 IP_STR
6410 MROUTE_STR
6411 VRF_CMD_HELP_STR
6412 "The Source or Group\n"
6413 "The Group\n"
6414 "Fill in Assumed data\n"
6415 JSON_STR)
6416 {
6417 struct prefix_sg sg = {0};
6418 struct pim_instance *pim;
6419 struct vrf *v;
6420
6421 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
6422
6423 if (!v) {
6424 vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
6425 return CMD_WARNING;
6426 }
6427 pim = pim_get_pim_instance(v->vrf_id);
6428
6429 if (!pim) {
6430 vty_out(vty, "%% Unable to find pim instance\n");
6431 return CMD_WARNING;
6432 }
6433
6434 if (s_or_g.s_addr != INADDR_ANY) {
6435 if (g.s_addr != INADDR_ANY) {
6436 sg.src = s_or_g;
6437 sg.grp = g;
6438 } else
6439 sg.grp = s_or_g;
6440 }
6441 show_mroute(pim, vty, &sg, !!fill, !!json);
6442 return CMD_SUCCESS;
6443 }
6444
6445 DEFUN (show_ip_mroute_vrf_all,
6446 show_ip_mroute_vrf_all_cmd,
6447 "show ip mroute vrf all [fill] [json]",
6448 SHOW_STR
6449 IP_STR
6450 MROUTE_STR
6451 VRF_CMD_HELP_STR
6452 "Fill in Assumed data\n"
6453 JSON_STR)
6454 {
6455 struct prefix_sg sg = {0};
6456 bool uj = use_json(argc, argv);
6457 int idx = 4;
6458 struct vrf *vrf;
6459 bool first = true;
6460 bool fill = false;
6461
6462 if (argv_find(argv, argc, "fill", &idx))
6463 fill = true;
6464
6465 if (uj)
6466 vty_out(vty, "{ ");
6467 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
6468 if (uj) {
6469 if (!first)
6470 vty_out(vty, ", ");
6471 vty_out(vty, " \"%s\": ", vrf->name);
6472 first = false;
6473 } else
6474 vty_out(vty, "VRF: %s\n", vrf->name);
6475 show_mroute(vrf->info, vty, &sg, fill, uj);
6476 }
6477 if (uj)
6478 vty_out(vty, "}\n");
6479
6480 return CMD_SUCCESS;
6481 }
6482
6483 DEFUN (clear_ip_mroute_count,
6484 clear_ip_mroute_count_cmd,
6485 "clear ip mroute [vrf NAME] count",
6486 CLEAR_STR
6487 IP_STR
6488 MROUTE_STR
6489 VRF_CMD_HELP_STR
6490 "Route and packet count data\n")
6491 {
6492 int idx = 2;
6493 struct listnode *node;
6494 struct channel_oil *c_oil;
6495 struct static_route *sr;
6496 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
6497 struct pim_instance *pim;
6498
6499 if (!vrf)
6500 return CMD_WARNING;
6501
6502 pim = vrf->info;
6503 frr_each(rb_pim_oil, &pim->channel_oil_head, c_oil) {
6504 if (!c_oil->installed)
6505 continue;
6506
6507 pim_mroute_update_counters(c_oil);
6508 c_oil->cc.origpktcnt = c_oil->cc.pktcnt;
6509 c_oil->cc.origbytecnt = c_oil->cc.bytecnt;
6510 c_oil->cc.origwrong_if = c_oil->cc.wrong_if;
6511 }
6512
6513 for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr)) {
6514 if (!sr->c_oil.installed)
6515 continue;
6516
6517 pim_mroute_update_counters(&sr->c_oil);
6518
6519 sr->c_oil.cc.origpktcnt = sr->c_oil.cc.pktcnt;
6520 sr->c_oil.cc.origbytecnt = sr->c_oil.cc.bytecnt;
6521 sr->c_oil.cc.origwrong_if = sr->c_oil.cc.wrong_if;
6522 }
6523 return CMD_SUCCESS;
6524 }
6525
6526 static void show_mroute_count_per_channel_oil(struct channel_oil *c_oil,
6527 json_object *json,
6528 struct vty *vty)
6529 {
6530 char group_str[INET_ADDRSTRLEN];
6531 char source_str[INET_ADDRSTRLEN];
6532 json_object *json_group = NULL;
6533 json_object *json_source = NULL;
6534
6535 if (!c_oil->installed)
6536 return;
6537
6538 pim_mroute_update_counters(c_oil);
6539
6540 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str,
6541 sizeof(group_str));
6542 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str,
6543 sizeof(source_str));
6544
6545 if (json) {
6546 json_object_object_get_ex(json, group_str, &json_group);
6547
6548 if (!json_group) {
6549 json_group = json_object_new_object();
6550 json_object_object_add(json, group_str, json_group);
6551 }
6552
6553 json_source = json_object_new_object();
6554 json_object_object_add(json_group, source_str, json_source);
6555 json_object_int_add(json_source, "lastUsed",
6556 c_oil->cc.lastused / 100);
6557 json_object_int_add(json_source, "packets", c_oil->cc.pktcnt);
6558 json_object_int_add(json_source, "bytes", c_oil->cc.bytecnt);
6559 json_object_int_add(json_source, "wrongIf", c_oil->cc.wrong_if);
6560
6561 } else {
6562 vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n",
6563 source_str, group_str, c_oil->cc.lastused / 100,
6564 c_oil->cc.pktcnt - c_oil->cc.origpktcnt,
6565 c_oil->cc.bytecnt - c_oil->cc.origbytecnt,
6566 c_oil->cc.wrong_if - c_oil->cc.origwrong_if);
6567 }
6568 }
6569
6570 static void show_mroute_count(struct pim_instance *pim, struct vty *vty,
6571 bool uj)
6572 {
6573 struct listnode *node;
6574 struct channel_oil *c_oil;
6575 struct static_route *sr;
6576 json_object *json = NULL;
6577
6578 if (uj)
6579 json = json_object_new_object();
6580 else {
6581 vty_out(vty, "\n");
6582
6583 vty_out(vty,
6584 "Source Group LastUsed Packets Bytes WrongIf \n");
6585 }
6586
6587 /* Print PIM and IGMP route counts */
6588 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
6589 show_mroute_count_per_channel_oil(c_oil, json, vty);
6590
6591 for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr))
6592 show_mroute_count_per_channel_oil(&sr->c_oil, json, vty);
6593
6594 if (uj) {
6595 vty_out(vty, "%s\n",
6596 json_object_to_json_string_ext(
6597 json, JSON_C_TO_STRING_PRETTY));
6598 json_object_free(json);
6599 }
6600 }
6601
6602 DEFUN (show_ip_mroute_count,
6603 show_ip_mroute_count_cmd,
6604 "show ip mroute [vrf NAME] count [json]",
6605 SHOW_STR
6606 IP_STR
6607 MROUTE_STR
6608 VRF_CMD_HELP_STR
6609 "Route and packet count data\n"
6610 JSON_STR)
6611 {
6612 int idx = 2;
6613 bool uj = use_json(argc, argv);
6614 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
6615
6616 if (!vrf)
6617 return CMD_WARNING;
6618
6619 show_mroute_count(vrf->info, vty, uj);
6620 return CMD_SUCCESS;
6621 }
6622
6623 DEFUN (show_ip_mroute_count_vrf_all,
6624 show_ip_mroute_count_vrf_all_cmd,
6625 "show ip mroute vrf all count [json]",
6626 SHOW_STR
6627 IP_STR
6628 MROUTE_STR
6629 VRF_CMD_HELP_STR
6630 "Route and packet count data\n"
6631 JSON_STR)
6632 {
6633 bool uj = use_json(argc, argv);
6634 struct vrf *vrf;
6635 bool first = true;
6636
6637 if (uj)
6638 vty_out(vty, "{ ");
6639 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
6640 if (uj) {
6641 if (!first)
6642 vty_out(vty, ", ");
6643 vty_out(vty, " \"%s\": ", vrf->name);
6644 first = false;
6645 } else
6646 vty_out(vty, "VRF: %s\n", vrf->name);
6647 show_mroute_count(vrf->info, vty, uj);
6648 }
6649 if (uj)
6650 vty_out(vty, "}\n");
6651
6652 return CMD_SUCCESS;
6653 }
6654
6655 static void show_mroute_summary(struct pim_instance *pim, struct vty *vty,
6656 json_object *json)
6657 {
6658 struct listnode *node;
6659 struct channel_oil *c_oil;
6660 struct static_route *s_route;
6661 uint32_t starg_sw_mroute_cnt = 0;
6662 uint32_t sg_sw_mroute_cnt = 0;
6663 uint32_t starg_hw_mroute_cnt = 0;
6664 uint32_t sg_hw_mroute_cnt = 0;
6665 json_object *json_starg = NULL;
6666 json_object *json_sg = NULL;
6667
6668 if (!json)
6669 vty_out(vty, "Mroute Type Installed/Total\n");
6670
6671 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
6672 if (!c_oil->installed) {
6673 if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
6674 starg_sw_mroute_cnt++;
6675 else
6676 sg_sw_mroute_cnt++;
6677 } else {
6678 if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
6679 starg_hw_mroute_cnt++;
6680 else
6681 sg_hw_mroute_cnt++;
6682 }
6683 }
6684
6685 for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
6686 if (!s_route->c_oil.installed) {
6687 if (s_route->c_oil.oil.mfcc_origin.s_addr == INADDR_ANY)
6688 starg_sw_mroute_cnt++;
6689 else
6690 sg_sw_mroute_cnt++;
6691 } else {
6692 if (s_route->c_oil.oil.mfcc_origin.s_addr == INADDR_ANY)
6693 starg_hw_mroute_cnt++;
6694 else
6695 sg_hw_mroute_cnt++;
6696 }
6697 }
6698
6699 if (!json) {
6700 vty_out(vty, "%-20s %u/%u\n", "(*, G)", starg_hw_mroute_cnt,
6701 starg_sw_mroute_cnt + starg_hw_mroute_cnt);
6702 vty_out(vty, "%-20s %u/%u\n", "(S, G)", sg_hw_mroute_cnt,
6703 sg_sw_mroute_cnt + sg_hw_mroute_cnt);
6704 vty_out(vty, "------\n");
6705 vty_out(vty, "%-20s %u/%u\n", "Total",
6706 (starg_hw_mroute_cnt + sg_hw_mroute_cnt),
6707 (starg_sw_mroute_cnt + starg_hw_mroute_cnt
6708 + sg_sw_mroute_cnt + sg_hw_mroute_cnt));
6709 } else {
6710 /* (*,G) route details */
6711 json_starg = json_object_new_object();
6712 json_object_object_add(json, "wildcardGroup", json_starg);
6713
6714 json_object_int_add(json_starg, "installed",
6715 starg_hw_mroute_cnt);
6716 json_object_int_add(json_starg, "total",
6717 starg_sw_mroute_cnt + starg_hw_mroute_cnt);
6718
6719 /* (S, G) route details */
6720 json_sg = json_object_new_object();
6721 json_object_object_add(json, "sourceGroup", json_sg);
6722
6723 json_object_int_add(json_sg, "installed", sg_hw_mroute_cnt);
6724 json_object_int_add(json_sg, "total",
6725 sg_sw_mroute_cnt + sg_hw_mroute_cnt);
6726
6727 json_object_int_add(json, "totalNumOfInstalledMroutes",
6728 starg_hw_mroute_cnt + sg_hw_mroute_cnt);
6729 json_object_int_add(json, "totalNumOfMroutes",
6730 starg_sw_mroute_cnt + starg_hw_mroute_cnt
6731 + sg_sw_mroute_cnt
6732 + sg_hw_mroute_cnt);
6733 }
6734 }
6735
6736 DEFUN (show_ip_mroute_summary,
6737 show_ip_mroute_summary_cmd,
6738 "show ip mroute [vrf NAME] summary [json]",
6739 SHOW_STR
6740 IP_STR
6741 MROUTE_STR
6742 VRF_CMD_HELP_STR
6743 "Summary of all mroutes\n"
6744 JSON_STR)
6745 {
6746 int idx = 2;
6747 bool uj = use_json(argc, argv);
6748 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
6749 json_object *json = NULL;
6750
6751 if (uj)
6752 json = json_object_new_object();
6753
6754 if (!vrf)
6755 return CMD_WARNING;
6756
6757 show_mroute_summary(vrf->info, vty, json);
6758
6759 if (uj) {
6760 vty_out(vty, "%s\n",
6761 json_object_to_json_string_ext(
6762 json, JSON_C_TO_STRING_PRETTY));
6763 json_object_free(json);
6764 }
6765 return CMD_SUCCESS;
6766 }
6767
6768 DEFUN (show_ip_mroute_summary_vrf_all,
6769 show_ip_mroute_summary_vrf_all_cmd,
6770 "show ip mroute vrf all summary [json]",
6771 SHOW_STR
6772 IP_STR
6773 MROUTE_STR
6774 VRF_CMD_HELP_STR
6775 "Summary of all mroutes\n"
6776 JSON_STR)
6777 {
6778 struct vrf *vrf;
6779 bool uj = use_json(argc, argv);
6780 json_object *json = NULL;
6781 json_object *json_vrf = NULL;
6782
6783 if (uj)
6784 json = json_object_new_object();
6785
6786 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
6787 if (uj)
6788 json_vrf = json_object_new_object();
6789 else
6790 vty_out(vty, "VRF: %s\n", vrf->name);
6791
6792 show_mroute_summary(vrf->info, vty, json_vrf);
6793
6794 if (uj)
6795 json_object_object_add(json, vrf->name, json_vrf);
6796 }
6797
6798 if (uj) {
6799 vty_out(vty, "%s\n",
6800 json_object_to_json_string_ext(
6801 json, JSON_C_TO_STRING_PRETTY));
6802 json_object_free(json);
6803 }
6804
6805 return CMD_SUCCESS;
6806 }
6807
6808 DEFUN (show_ip_rib,
6809 show_ip_rib_cmd,
6810 "show ip rib [vrf NAME] A.B.C.D",
6811 SHOW_STR
6812 IP_STR
6813 RIB_STR
6814 VRF_CMD_HELP_STR
6815 "Unicast address\n")
6816 {
6817 int idx = 2;
6818 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
6819 struct in_addr addr;
6820 const char *addr_str;
6821 struct pim_nexthop nexthop;
6822 char nexthop_addr_str[PREFIX_STRLEN];
6823 int result;
6824
6825 if (!vrf)
6826 return CMD_WARNING;
6827
6828 memset(&nexthop, 0, sizeof(nexthop));
6829 argv_find(argv, argc, "A.B.C.D", &idx);
6830 addr_str = argv[idx]->arg;
6831 result = inet_pton(AF_INET, addr_str, &addr);
6832 if (result <= 0) {
6833 vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str,
6834 errno, safe_strerror(errno));
6835 return CMD_WARNING;
6836 }
6837
6838 if (!pim_nexthop_lookup(vrf->info, &nexthop, addr, 0)) {
6839 vty_out(vty,
6840 "Failure querying RIB nexthop for unicast address %s\n",
6841 addr_str);
6842 return CMD_WARNING;
6843 }
6844
6845 vty_out(vty,
6846 "Address NextHop Interface Metric Preference\n");
6847
6848 pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr,
6849 nexthop_addr_str, sizeof(nexthop_addr_str));
6850
6851 vty_out(vty, "%-15s %-15s %-9s %6d %10d\n", addr_str, nexthop_addr_str,
6852 nexthop.interface ? nexthop.interface->name : "<ifname?>",
6853 nexthop.mrib_route_metric, nexthop.mrib_metric_preference);
6854
6855 return CMD_SUCCESS;
6856 }
6857
6858 static void show_ssmpingd(struct pim_instance *pim, struct vty *vty)
6859 {
6860 struct listnode *node;
6861 struct ssmpingd_sock *ss;
6862 time_t now;
6863
6864 vty_out(vty,
6865 "Source Socket Address Port Uptime Requests\n");
6866
6867 if (!pim->ssmpingd_list)
6868 return;
6869
6870 now = pim_time_monotonic_sec();
6871
6872 for (ALL_LIST_ELEMENTS_RO(pim->ssmpingd_list, node, ss)) {
6873 char source_str[INET_ADDRSTRLEN];
6874 char ss_uptime[10];
6875 struct sockaddr_in bind_addr;
6876 socklen_t len = sizeof(bind_addr);
6877 char bind_addr_str[INET_ADDRSTRLEN];
6878
6879 pim_inet4_dump("<src?>", ss->source_addr, source_str,
6880 sizeof(source_str));
6881
6882 if (pim_socket_getsockname(
6883 ss->sock_fd, (struct sockaddr *)&bind_addr, &len)) {
6884 vty_out(vty,
6885 "%% Failure reading socket name for ssmpingd source %s on fd=%d\n",
6886 source_str, ss->sock_fd);
6887 }
6888
6889 pim_inet4_dump("<addr?>", bind_addr.sin_addr, bind_addr_str,
6890 sizeof(bind_addr_str));
6891 pim_time_uptime(ss_uptime, sizeof(ss_uptime),
6892 now - ss->creation);
6893
6894 vty_out(vty, "%-15s %6d %-15s %5d %8s %8lld\n", source_str,
6895 ss->sock_fd, bind_addr_str, ntohs(bind_addr.sin_port),
6896 ss_uptime, (long long)ss->requests);
6897 }
6898 }
6899
6900 DEFUN (show_ip_ssmpingd,
6901 show_ip_ssmpingd_cmd,
6902 "show ip ssmpingd [vrf NAME]",
6903 SHOW_STR
6904 IP_STR
6905 SHOW_SSMPINGD_STR
6906 VRF_CMD_HELP_STR)
6907 {
6908 int idx = 2;
6909 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
6910
6911 if (!vrf)
6912 return CMD_WARNING;
6913
6914 show_ssmpingd(vrf->info, vty);
6915 return CMD_SUCCESS;
6916 }
6917
6918 DEFUN (ip_pim_spt_switchover_infinity,
6919 ip_pim_spt_switchover_infinity_cmd,
6920 "ip pim spt-switchover infinity-and-beyond",
6921 IP_STR
6922 PIM_STR
6923 "SPT-Switchover\n"
6924 "Never switch to SPT Tree\n")
6925 {
6926 const char *vrfname;
6927 char spt_plist_xpath[XPATH_MAXLEN];
6928 char spt_action_xpath[XPATH_MAXLEN];
6929
6930 vrfname = pim_cli_get_vrf_name(vty);
6931 if (vrfname == NULL)
6932 return CMD_WARNING_CONFIG_FAILED;
6933
6934 snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
6935 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
6936 "frr-routing:ipv4");
6937 strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
6938 sizeof(spt_plist_xpath));
6939
6940 snprintf(spt_action_xpath, sizeof(spt_action_xpath),
6941 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
6942 "frr-routing:ipv4");
6943 strlcat(spt_action_xpath, "/spt-switchover/spt-action",
6944 sizeof(spt_action_xpath));
6945
6946 if (yang_dnode_exists(vty->candidate_config->dnode, spt_plist_xpath))
6947 nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY,
6948 NULL);
6949 nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
6950 "PIM_SPT_INFINITY");
6951
6952 return nb_cli_apply_changes(vty, NULL);
6953 }
6954
6955 DEFUN (ip_pim_spt_switchover_infinity_plist,
6956 ip_pim_spt_switchover_infinity_plist_cmd,
6957 "ip pim spt-switchover infinity-and-beyond prefix-list WORD",
6958 IP_STR
6959 PIM_STR
6960 "SPT-Switchover\n"
6961 "Never switch to SPT Tree\n"
6962 "Prefix-List to control which groups to switch\n"
6963 "Prefix-List name\n")
6964 {
6965 const char *vrfname;
6966 char spt_plist_xpath[XPATH_MAXLEN];
6967 char spt_action_xpath[XPATH_MAXLEN];
6968
6969 vrfname = pim_cli_get_vrf_name(vty);
6970 if (vrfname == NULL)
6971 return CMD_WARNING_CONFIG_FAILED;
6972
6973 snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
6974 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
6975 "frr-routing:ipv4");
6976 strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
6977 sizeof(spt_plist_xpath));
6978
6979 snprintf(spt_action_xpath, sizeof(spt_action_xpath),
6980 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
6981 "frr-routing:ipv4");
6982 strlcat(spt_action_xpath, "/spt-switchover/spt-action",
6983 sizeof(spt_action_xpath));
6984
6985 nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
6986 "PIM_SPT_INFINITY");
6987 nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_MODIFY,
6988 argv[5]->arg);
6989
6990 return nb_cli_apply_changes(vty, NULL);
6991 }
6992
6993 DEFUN (no_ip_pim_spt_switchover_infinity,
6994 no_ip_pim_spt_switchover_infinity_cmd,
6995 "no ip pim spt-switchover infinity-and-beyond",
6996 NO_STR
6997 IP_STR
6998 PIM_STR
6999 "SPT_Switchover\n"
7000 "Never switch to SPT Tree\n")
7001 {
7002 const char *vrfname;
7003 char spt_plist_xpath[XPATH_MAXLEN];
7004 char spt_action_xpath[XPATH_MAXLEN];
7005
7006 vrfname = pim_cli_get_vrf_name(vty);
7007 if (vrfname == NULL)
7008 return CMD_WARNING_CONFIG_FAILED;
7009
7010 snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
7011 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
7012 "frr-routing:ipv4");
7013 strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
7014 sizeof(spt_plist_xpath));
7015
7016 snprintf(spt_action_xpath, sizeof(spt_action_xpath),
7017 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
7018 "frr-routing:ipv4");
7019 strlcat(spt_action_xpath, "/spt-switchover/spt-action",
7020 sizeof(spt_action_xpath));
7021
7022 nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY, NULL);
7023 nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
7024 "PIM_SPT_IMMEDIATE");
7025
7026 return nb_cli_apply_changes(vty, NULL);
7027 }
7028
7029 DEFUN (no_ip_pim_spt_switchover_infinity_plist,
7030 no_ip_pim_spt_switchover_infinity_plist_cmd,
7031 "no ip pim spt-switchover infinity-and-beyond prefix-list WORD",
7032 NO_STR
7033 IP_STR
7034 PIM_STR
7035 "SPT_Switchover\n"
7036 "Never switch to SPT Tree\n"
7037 "Prefix-List to control which groups to switch\n"
7038 "Prefix-List name\n")
7039 {
7040 const char *vrfname;
7041 char spt_plist_xpath[XPATH_MAXLEN];
7042 char spt_action_xpath[XPATH_MAXLEN];
7043
7044 vrfname = pim_cli_get_vrf_name(vty);
7045 if (vrfname == NULL)
7046 return CMD_WARNING_CONFIG_FAILED;
7047
7048 snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
7049 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
7050 "frr-routing:ipv4");
7051 strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
7052 sizeof(spt_plist_xpath));
7053
7054 snprintf(spt_action_xpath, sizeof(spt_action_xpath),
7055 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
7056 "frr-routing:ipv4");
7057 strlcat(spt_action_xpath, "/spt-switchover/spt-action",
7058 sizeof(spt_action_xpath));
7059
7060 nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY, NULL);
7061 nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
7062 "PIM_SPT_IMMEDIATE");
7063
7064 return nb_cli_apply_changes(vty, NULL);
7065 }
7066
7067 DEFPY (pim_register_accept_list,
7068 pim_register_accept_list_cmd,
7069 "[no] ip pim register-accept-list WORD$word",
7070 NO_STR
7071 IP_STR
7072 PIM_STR
7073 "Only accept registers from a specific source prefix list\n"
7074 "Prefix-List name\n")
7075 {
7076 const char *vrfname;
7077 char reg_alist_xpath[XPATH_MAXLEN];
7078
7079 vrfname = pim_cli_get_vrf_name(vty);
7080 if (vrfname == NULL)
7081 return CMD_WARNING_CONFIG_FAILED;
7082
7083 snprintf(reg_alist_xpath, sizeof(reg_alist_xpath),
7084 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
7085 "frr-routing:ipv4");
7086 strlcat(reg_alist_xpath, "/register-accept-list",
7087 sizeof(reg_alist_xpath));
7088
7089 if (no)
7090 nb_cli_enqueue_change(vty, reg_alist_xpath,
7091 NB_OP_DESTROY, NULL);
7092 else
7093 nb_cli_enqueue_change(vty, reg_alist_xpath,
7094 NB_OP_MODIFY, word);
7095
7096 return nb_cli_apply_changes(vty, NULL);
7097 }
7098
7099 DEFUN (ip_pim_joinprune_time,
7100 ip_pim_joinprune_time_cmd,
7101 "ip pim join-prune-interval (1-65535)",
7102 IP_STR
7103 "pim multicast routing\n"
7104 "Join Prune Send Interval\n"
7105 "Seconds\n")
7106 {
7107 nb_cli_enqueue_change(vty, "/frr-pim:pim/join-prune-interval",
7108 NB_OP_MODIFY, argv[3]->arg);
7109
7110 return nb_cli_apply_changes(vty, NULL);
7111 }
7112
7113 DEFUN (no_ip_pim_joinprune_time,
7114 no_ip_pim_joinprune_time_cmd,
7115 "no ip pim join-prune-interval [(1-65535)]",
7116 NO_STR
7117 IP_STR
7118 "pim multicast routing\n"
7119 "Join Prune Send Interval\n"
7120 IGNORED_IN_NO_STR)
7121 {
7122 nb_cli_enqueue_change(vty, "/frr-pim:pim/join-prune-interval",
7123 NB_OP_DESTROY, NULL);
7124
7125 return nb_cli_apply_changes(vty, NULL);
7126 }
7127
7128 DEFUN (ip_pim_register_suppress,
7129 ip_pim_register_suppress_cmd,
7130 "ip pim register-suppress-time (1-65535)",
7131 IP_STR
7132 "pim multicast routing\n"
7133 "Register Suppress Timer\n"
7134 "Seconds\n")
7135 {
7136 nb_cli_enqueue_change(vty, "/frr-pim:pim/register-suppress-time",
7137 NB_OP_MODIFY, argv[3]->arg);
7138
7139 return nb_cli_apply_changes(vty, NULL);
7140 }
7141
7142 DEFUN (no_ip_pim_register_suppress,
7143 no_ip_pim_register_suppress_cmd,
7144 "no ip pim register-suppress-time [(1-65535)]",
7145 NO_STR
7146 IP_STR
7147 "pim multicast routing\n"
7148 "Register Suppress Timer\n"
7149 IGNORED_IN_NO_STR)
7150 {
7151 nb_cli_enqueue_change(vty, "/frr-pim:pim/register-suppress-time",
7152 NB_OP_DESTROY, NULL);
7153
7154 return nb_cli_apply_changes(vty, NULL);
7155 }
7156
7157 DEFUN (ip_pim_rp_keep_alive,
7158 ip_pim_rp_keep_alive_cmd,
7159 "ip pim rp keep-alive-timer (1-65535)",
7160 IP_STR
7161 "pim multicast routing\n"
7162 "Rendevous Point\n"
7163 "Keep alive Timer\n"
7164 "Seconds\n")
7165 {
7166 const char *vrfname;
7167 char rp_ka_timer_xpath[XPATH_MAXLEN];
7168
7169 vrfname = pim_cli_get_vrf_name(vty);
7170 if (vrfname == NULL)
7171 return CMD_WARNING_CONFIG_FAILED;
7172
7173 snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
7174 FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname);
7175 strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
7176 sizeof(rp_ka_timer_xpath));
7177
7178 nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
7179 argv[4]->arg);
7180
7181 return nb_cli_apply_changes(vty, NULL);
7182 }
7183
7184 DEFUN (no_ip_pim_rp_keep_alive,
7185 no_ip_pim_rp_keep_alive_cmd,
7186 "no ip pim rp keep-alive-timer [(1-65535)]",
7187 NO_STR
7188 IP_STR
7189 "pim multicast routing\n"
7190 "Rendevous Point\n"
7191 "Keep alive Timer\n"
7192 IGNORED_IN_NO_STR)
7193 {
7194 const char *vrfname;
7195 char rp_ka_timer[6];
7196 char rp_ka_timer_xpath[XPATH_MAXLEN];
7197 uint v;
7198
7199 /* RFC4601 */
7200 v = yang_dnode_get_uint16(vty->candidate_config->dnode,
7201 "/frr-pim:pim/register-suppress-time");
7202 v = 3 * v + PIM_REGISTER_PROBE_TIME_DEFAULT;
7203 if (v > UINT16_MAX)
7204 v = UINT16_MAX;
7205 snprintf(rp_ka_timer, sizeof(rp_ka_timer), "%u", v);
7206
7207 vrfname = pim_cli_get_vrf_name(vty);
7208 if (vrfname == NULL)
7209 return CMD_WARNING_CONFIG_FAILED;
7210
7211 snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
7212 FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname);
7213 strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
7214 sizeof(rp_ka_timer_xpath));
7215
7216 nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
7217 rp_ka_timer);
7218
7219 return nb_cli_apply_changes(vty, NULL);
7220 }
7221
7222 DEFUN (ip_pim_keep_alive,
7223 ip_pim_keep_alive_cmd,
7224 "ip pim keep-alive-timer (1-65535)",
7225 IP_STR
7226 "pim multicast routing\n"
7227 "Keep alive Timer\n"
7228 "Seconds\n")
7229 {
7230 const char *vrfname;
7231 char ka_timer_xpath[XPATH_MAXLEN];
7232
7233 vrfname = pim_cli_get_vrf_name(vty);
7234 if (vrfname == NULL)
7235 return CMD_WARNING_CONFIG_FAILED;
7236
7237 snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_XPATH,
7238 "frr-pim:pimd", "pim", vrfname);
7239 strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
7240
7241 nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_MODIFY,
7242 argv[3]->arg);
7243
7244 return nb_cli_apply_changes(vty, NULL);
7245 }
7246
7247 DEFUN (no_ip_pim_keep_alive,
7248 no_ip_pim_keep_alive_cmd,
7249 "no ip pim keep-alive-timer [(1-65535)]",
7250 NO_STR
7251 IP_STR
7252 "pim multicast routing\n"
7253 "Keep alive Timer\n"
7254 IGNORED_IN_NO_STR)
7255 {
7256 const char *vrfname;
7257 char ka_timer_xpath[XPATH_MAXLEN];
7258
7259 vrfname = pim_cli_get_vrf_name(vty);
7260 if (vrfname == NULL)
7261 return CMD_WARNING_CONFIG_FAILED;
7262
7263 snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_XPATH,
7264 "frr-pim:pimd", "pim", vrfname);
7265 strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
7266
7267 nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_DESTROY, NULL);
7268
7269 return nb_cli_apply_changes(vty, NULL);
7270 }
7271
7272 DEFUN (ip_pim_packets,
7273 ip_pim_packets_cmd,
7274 "ip pim packets (1-255)",
7275 IP_STR
7276 "pim multicast routing\n"
7277 "packets to process at one time per fd\n"
7278 "Number of packets\n")
7279 {
7280 nb_cli_enqueue_change(vty, "/frr-pim:pim/packets", NB_OP_MODIFY,
7281 argv[3]->arg);
7282
7283 return nb_cli_apply_changes(vty, NULL);
7284 }
7285
7286 DEFUN (no_ip_pim_packets,
7287 no_ip_pim_packets_cmd,
7288 "no ip pim packets [(1-255)]",
7289 NO_STR
7290 IP_STR
7291 "pim multicast routing\n"
7292 "packets to process at one time per fd\n"
7293 IGNORED_IN_NO_STR)
7294 {
7295 nb_cli_enqueue_change(vty, "/frr-pim:pim/packets", NB_OP_DESTROY, NULL);
7296
7297 return nb_cli_apply_changes(vty, NULL);
7298 }
7299
7300 DEFPY (igmp_group_watermark,
7301 igmp_group_watermark_cmd,
7302 "ip igmp watermark-warn (1-65535)$limit",
7303 IP_STR
7304 IGMP_STR
7305 "Configure group limit for watermark warning\n"
7306 "Group count to generate watermark warning\n")
7307 {
7308 PIM_DECLVAR_CONTEXT(vrf, pim);
7309 pim->igmp_watermark_limit = limit;
7310
7311 return CMD_SUCCESS;
7312 }
7313
7314 DEFPY (no_igmp_group_watermark,
7315 no_igmp_group_watermark_cmd,
7316 "no ip igmp watermark-warn [(1-65535)$limit]",
7317 NO_STR
7318 IP_STR
7319 IGMP_STR
7320 "Unconfigure group limit for watermark warning\n"
7321 IGNORED_IN_NO_STR)
7322 {
7323 PIM_DECLVAR_CONTEXT(vrf, pim);
7324 pim->igmp_watermark_limit = 0;
7325
7326 return CMD_SUCCESS;
7327 }
7328
7329 DEFUN (ip_pim_v6_secondary,
7330 ip_pim_v6_secondary_cmd,
7331 "ip pim send-v6-secondary",
7332 IP_STR
7333 "pim multicast routing\n"
7334 "Send v6 secondary addresses\n")
7335 {
7336 const char *vrfname;
7337 char send_v6_secondary_xpath[XPATH_MAXLEN];
7338
7339 vrfname = pim_cli_get_vrf_name(vty);
7340 if (vrfname == NULL)
7341 return CMD_WARNING_CONFIG_FAILED;
7342
7343 snprintf(send_v6_secondary_xpath, sizeof(send_v6_secondary_xpath),
7344 FRR_PIM_AF_XPATH,
7345 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
7346 strlcat(send_v6_secondary_xpath, "/send-v6-secondary",
7347 sizeof(send_v6_secondary_xpath));
7348
7349 nb_cli_enqueue_change(vty, send_v6_secondary_xpath, NB_OP_MODIFY,
7350 "true");
7351
7352 return nb_cli_apply_changes(vty, NULL);
7353 }
7354
7355 DEFUN (no_ip_pim_v6_secondary,
7356 no_ip_pim_v6_secondary_cmd,
7357 "no ip pim send-v6-secondary",
7358 NO_STR
7359 IP_STR
7360 "pim multicast routing\n"
7361 "Send v6 secondary addresses\n")
7362 {
7363 const char *vrfname;
7364 char send_v6_secondary_xpath[XPATH_MAXLEN];
7365
7366 vrfname = pim_cli_get_vrf_name(vty);
7367 if (vrfname == NULL)
7368 return CMD_WARNING_CONFIG_FAILED;
7369
7370 snprintf(send_v6_secondary_xpath, sizeof(send_v6_secondary_xpath),
7371 FRR_PIM_AF_XPATH,
7372 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
7373 strlcat(send_v6_secondary_xpath, "/send-v6-secondary",
7374 sizeof(send_v6_secondary_xpath));
7375
7376 nb_cli_enqueue_change(vty, send_v6_secondary_xpath, NB_OP_MODIFY,
7377 "false");
7378
7379 return nb_cli_apply_changes(vty, NULL);
7380 }
7381
7382 DEFUN (ip_pim_rp,
7383 ip_pim_rp_cmd,
7384 "ip pim rp A.B.C.D [A.B.C.D/M]",
7385 IP_STR
7386 "pim multicast routing\n"
7387 "Rendevous Point\n"
7388 "ip address of RP\n"
7389 "Group Address range to cover\n")
7390 {
7391 const char *vrfname;
7392 int idx_rp = 3, idx_group = 4;
7393 char rp_group_xpath[XPATH_MAXLEN];
7394 int result = 0;
7395 struct prefix group;
7396 struct in_addr rp_addr;
7397 const char *group_str =
7398 (argc == 5) ? argv[idx_group]->arg : "224.0.0.0/4";
7399
7400 result = str2prefix(group_str, &group);
7401 if (result) {
7402 struct prefix temp;
7403
7404 prefix_copy(&temp, &group);
7405 apply_mask(&temp);
7406 if (!prefix_same(&group, &temp)) {
7407 vty_out(vty, "%% Inconsistent address and mask: %s\n",
7408 group_str);
7409 return CMD_WARNING_CONFIG_FAILED;
7410 }
7411 }
7412
7413 if (!result) {
7414 vty_out(vty, "%% Bad group address specified: %s\n",
7415 group_str);
7416 return CMD_WARNING_CONFIG_FAILED;
7417 }
7418
7419 result = inet_pton(AF_INET, argv[idx_rp]->arg, &rp_addr);
7420 if (result <= 0) {
7421 vty_out(vty, "%% Bad RP address specified: %s\n",
7422 argv[idx_rp]->arg);
7423 return CMD_WARNING_CONFIG_FAILED;
7424 }
7425
7426 vrfname = pim_cli_get_vrf_name(vty);
7427 if (vrfname == NULL)
7428 return CMD_WARNING_CONFIG_FAILED;
7429
7430 snprintf(rp_group_xpath, sizeof(rp_group_xpath),
7431 FRR_PIM_STATIC_RP_XPATH,
7432 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
7433 argv[idx_rp]->arg);
7434 strlcat(rp_group_xpath, "/group-list", sizeof(rp_group_xpath));
7435
7436 nb_cli_enqueue_change(vty, rp_group_xpath, NB_OP_CREATE, group_str);
7437
7438 return nb_cli_apply_changes(vty, NULL);
7439 }
7440
7441 DEFUN (ip_pim_rp_prefix_list,
7442 ip_pim_rp_prefix_list_cmd,
7443 "ip pim rp A.B.C.D prefix-list WORD",
7444 IP_STR
7445 "pim multicast routing\n"
7446 "Rendevous Point\n"
7447 "ip address of RP\n"
7448 "group prefix-list filter\n"
7449 "Name of a prefix-list\n")
7450 {
7451 int idx_rp = 3, idx_plist = 5;
7452 const char *vrfname;
7453 char rp_plist_xpath[XPATH_MAXLEN];
7454
7455 vrfname = pim_cli_get_vrf_name(vty);
7456 if (vrfname == NULL)
7457 return CMD_WARNING_CONFIG_FAILED;
7458
7459 snprintf(rp_plist_xpath, sizeof(rp_plist_xpath),
7460 FRR_PIM_STATIC_RP_XPATH,
7461 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
7462 argv[idx_rp]->arg);
7463 strlcat(rp_plist_xpath, "/prefix-list", sizeof(rp_plist_xpath));
7464
7465 nb_cli_enqueue_change(vty, rp_plist_xpath, NB_OP_MODIFY,
7466 argv[idx_plist]->arg);
7467
7468 return nb_cli_apply_changes(vty, NULL);
7469 }
7470
7471 DEFUN (no_ip_pim_rp,
7472 no_ip_pim_rp_cmd,
7473 "no ip pim rp A.B.C.D [A.B.C.D/M]",
7474 NO_STR
7475 IP_STR
7476 "pim multicast routing\n"
7477 "Rendevous Point\n"
7478 "ip address of RP\n"
7479 "Group Address range to cover\n")
7480 {
7481 int idx_rp = 4, idx_group = 5;
7482 const char *group_str =
7483 (argc == 6) ? argv[idx_group]->arg : "224.0.0.0/4";
7484 char group_list_xpath[XPATH_MAXLEN + 32];
7485 char group_xpath[XPATH_MAXLEN + 64];
7486 char rp_xpath[XPATH_MAXLEN];
7487 const char *vrfname;
7488 const struct lyd_node *group_dnode;
7489
7490 vrfname = pim_cli_get_vrf_name(vty);
7491 if (vrfname == NULL)
7492 return CMD_WARNING_CONFIG_FAILED;
7493
7494 snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
7495 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
7496 argv[idx_rp]->arg);
7497
7498 snprintf(group_list_xpath, sizeof(group_list_xpath), "%s/group-list",
7499 rp_xpath);
7500
7501 snprintf(group_xpath, sizeof(group_xpath), "%s[.='%s']",
7502 group_list_xpath, group_str);
7503
7504 if (!yang_dnode_exists(vty->candidate_config->dnode, group_xpath)) {
7505 vty_out(vty, "%% Unable to find specified RP\n");
7506 return NB_OK;
7507 }
7508
7509 group_dnode = yang_dnode_get(vty->candidate_config->dnode, group_xpath);
7510
7511 if (yang_is_last_list_dnode(group_dnode))
7512 nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
7513 else
7514 nb_cli_enqueue_change(vty, group_list_xpath, NB_OP_DESTROY,
7515 group_str);
7516
7517 return nb_cli_apply_changes(vty, NULL);
7518 }
7519
7520 DEFUN (no_ip_pim_rp_prefix_list,
7521 no_ip_pim_rp_prefix_list_cmd,
7522 "no ip pim rp A.B.C.D prefix-list WORD",
7523 NO_STR
7524 IP_STR
7525 "pim multicast routing\n"
7526 "Rendevous Point\n"
7527 "ip address of RP\n"
7528 "group prefix-list filter\n"
7529 "Name of a prefix-list\n")
7530 {
7531 int idx_rp = 4;
7532 int idx_plist = 6;
7533 char rp_xpath[XPATH_MAXLEN];
7534 char plist_xpath[XPATH_MAXLEN];
7535 const char *vrfname;
7536 const struct lyd_node *plist_dnode;
7537 const char *plist;
7538
7539 vrfname = pim_cli_get_vrf_name(vty);
7540 if (vrfname == NULL)
7541 return CMD_WARNING_CONFIG_FAILED;
7542
7543 snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
7544 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
7545 argv[idx_rp]->arg);
7546
7547 snprintf(plist_xpath, sizeof(plist_xpath), FRR_PIM_STATIC_RP_XPATH,
7548 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
7549 argv[idx_rp]->arg);
7550 strlcat(plist_xpath, "/prefix-list", sizeof(plist_xpath));
7551
7552 plist_dnode = yang_dnode_get(vty->candidate_config->dnode, plist_xpath);
7553 if (!plist_dnode) {
7554 vty_out(vty, "%% Unable to find specified RP\n");
7555 return NB_OK;
7556 }
7557
7558 plist = yang_dnode_get_string(plist_dnode, plist_xpath);
7559 if (strcmp(argv[idx_plist]->arg, plist)) {
7560 vty_out(vty, "%% Unable to find specified RP\n");
7561 return NB_OK;
7562 }
7563
7564 nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
7565
7566 return nb_cli_apply_changes(vty, NULL);
7567 }
7568
7569 DEFUN (ip_pim_ssm_prefix_list,
7570 ip_pim_ssm_prefix_list_cmd,
7571 "ip pim ssm prefix-list WORD",
7572 IP_STR
7573 "pim multicast routing\n"
7574 "Source Specific Multicast\n"
7575 "group range prefix-list filter\n"
7576 "Name of a prefix-list\n")
7577 {
7578 const char *vrfname;
7579 char ssm_plist_xpath[XPATH_MAXLEN];
7580
7581 vrfname = pim_cli_get_vrf_name(vty);
7582 if (vrfname == NULL)
7583 return CMD_WARNING_CONFIG_FAILED;
7584
7585 snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath), FRR_PIM_AF_XPATH,
7586 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
7587 strlcat(ssm_plist_xpath, "/ssm-prefix-list", sizeof(ssm_plist_xpath));
7588
7589 nb_cli_enqueue_change(vty, ssm_plist_xpath, NB_OP_MODIFY, argv[4]->arg);
7590
7591 return nb_cli_apply_changes(vty, NULL);
7592 }
7593
7594 DEFUN (no_ip_pim_ssm_prefix_list,
7595 no_ip_pim_ssm_prefix_list_cmd,
7596 "no ip pim ssm prefix-list",
7597 NO_STR
7598 IP_STR
7599 "pim multicast routing\n"
7600 "Source Specific Multicast\n"
7601 "group range prefix-list filter\n")
7602 {
7603 const char *vrfname;
7604 char ssm_plist_xpath[XPATH_MAXLEN];
7605
7606 vrfname = pim_cli_get_vrf_name(vty);
7607 if (vrfname == NULL)
7608 return CMD_WARNING_CONFIG_FAILED;
7609
7610 snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath),
7611 FRR_PIM_AF_XPATH,
7612 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
7613 strlcat(ssm_plist_xpath, "/ssm-prefix-list", sizeof(ssm_plist_xpath));
7614
7615 nb_cli_enqueue_change(vty, ssm_plist_xpath, NB_OP_DESTROY, NULL);
7616
7617 return nb_cli_apply_changes(vty, NULL);
7618 }
7619
7620 DEFUN (no_ip_pim_ssm_prefix_list_name,
7621 no_ip_pim_ssm_prefix_list_name_cmd,
7622 "no ip pim ssm prefix-list WORD",
7623 NO_STR
7624 IP_STR
7625 "pim multicast routing\n"
7626 "Source Specific Multicast\n"
7627 "group range prefix-list filter\n"
7628 "Name of a prefix-list\n")
7629 {
7630 const char *vrfname;
7631 const struct lyd_node *ssm_plist_dnode;
7632 char ssm_plist_xpath[XPATH_MAXLEN];
7633 const char *ssm_plist_name;
7634
7635 vrfname = pim_cli_get_vrf_name(vty);
7636 if (vrfname == NULL)
7637 return CMD_WARNING_CONFIG_FAILED;
7638
7639 snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath),
7640 FRR_PIM_AF_XPATH,
7641 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
7642 strlcat(ssm_plist_xpath, "/ssm-prefix-list", sizeof(ssm_plist_xpath));
7643 ssm_plist_dnode = yang_dnode_get(vty->candidate_config->dnode,
7644 ssm_plist_xpath);
7645
7646 if (!ssm_plist_dnode) {
7647 vty_out(vty,
7648 "%% pim ssm prefix-list %s doesn't exist\n",
7649 argv[5]->arg);
7650 return CMD_WARNING_CONFIG_FAILED;
7651 }
7652
7653 ssm_plist_name = yang_dnode_get_string(ssm_plist_dnode, ".");
7654
7655 if (ssm_plist_name && !strcmp(ssm_plist_name, argv[5]->arg)) {
7656 nb_cli_enqueue_change(vty, ssm_plist_xpath, NB_OP_DESTROY,
7657 NULL);
7658
7659 return nb_cli_apply_changes(vty, NULL);
7660 }
7661
7662 vty_out(vty, "%% pim ssm prefix-list %s doesn't exist\n", argv[5]->arg);
7663
7664 return CMD_WARNING_CONFIG_FAILED;
7665 }
7666
7667 static void ip_pim_ssm_show_group_range(struct pim_instance *pim,
7668 struct vty *vty, bool uj)
7669 {
7670 struct pim_ssm *ssm = pim->ssm_info;
7671 const char *range_str =
7672 ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
7673
7674 if (uj) {
7675 json_object *json;
7676 json = json_object_new_object();
7677 json_object_string_add(json, "ssmGroups", range_str);
7678 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7679 json, JSON_C_TO_STRING_PRETTY));
7680 json_object_free(json);
7681 } else
7682 vty_out(vty, "SSM group range : %s\n", range_str);
7683 }
7684
7685 DEFUN (show_ip_pim_ssm_range,
7686 show_ip_pim_ssm_range_cmd,
7687 "show ip pim [vrf NAME] group-type [json]",
7688 SHOW_STR
7689 IP_STR
7690 PIM_STR
7691 VRF_CMD_HELP_STR
7692 "PIM group type\n"
7693 JSON_STR)
7694 {
7695 int idx = 2;
7696 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
7697 bool uj = use_json(argc, argv);
7698
7699 if (!vrf)
7700 return CMD_WARNING;
7701
7702 ip_pim_ssm_show_group_range(vrf->info, vty, uj);
7703
7704 return CMD_SUCCESS;
7705 }
7706
7707 static void ip_pim_ssm_show_group_type(struct pim_instance *pim,
7708 struct vty *vty, bool uj,
7709 const char *group)
7710 {
7711 struct in_addr group_addr;
7712 const char *type_str;
7713 int result;
7714
7715 result = inet_pton(AF_INET, group, &group_addr);
7716 if (result <= 0)
7717 type_str = "invalid";
7718 else {
7719 if (pim_is_group_224_4(group_addr))
7720 type_str =
7721 pim_is_grp_ssm(pim, group_addr) ? "SSM" : "ASM";
7722 else
7723 type_str = "not-multicast";
7724 }
7725
7726 if (uj) {
7727 json_object *json;
7728 json = json_object_new_object();
7729 json_object_string_add(json, "groupType", type_str);
7730 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7731 json, JSON_C_TO_STRING_PRETTY));
7732 json_object_free(json);
7733 } else
7734 vty_out(vty, "Group type : %s\n", type_str);
7735 }
7736
7737 DEFUN (show_ip_pim_group_type,
7738 show_ip_pim_group_type_cmd,
7739 "show ip pim [vrf NAME] group-type A.B.C.D [json]",
7740 SHOW_STR
7741 IP_STR
7742 PIM_STR
7743 VRF_CMD_HELP_STR
7744 "multicast group type\n"
7745 "group address\n"
7746 JSON_STR)
7747 {
7748 int idx = 2;
7749 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
7750 bool uj = use_json(argc, argv);
7751
7752 if (!vrf)
7753 return CMD_WARNING;
7754
7755 argv_find(argv, argc, "A.B.C.D", &idx);
7756 ip_pim_ssm_show_group_type(vrf->info, vty, uj, argv[idx]->arg);
7757
7758 return CMD_SUCCESS;
7759 }
7760
7761 DEFUN (show_ip_pim_bsr,
7762 show_ip_pim_bsr_cmd,
7763 "show ip pim bsr [json]",
7764 SHOW_STR
7765 IP_STR
7766 PIM_STR
7767 "boot-strap router information\n"
7768 JSON_STR)
7769 {
7770 int idx = 2;
7771 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
7772 bool uj = use_json(argc, argv);
7773
7774 if (!vrf)
7775 return CMD_WARNING;
7776
7777 pim_show_bsr(vrf->info, vty, uj);
7778
7779 return CMD_SUCCESS;
7780 }
7781
7782 DEFUN (ip_ssmpingd,
7783 ip_ssmpingd_cmd,
7784 "ip ssmpingd [A.B.C.D]",
7785 IP_STR
7786 CONF_SSMPINGD_STR
7787 "Source address\n")
7788 {
7789 int idx_ipv4 = 2;
7790 const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0";
7791 const char *vrfname;
7792 char ssmpingd_ip_xpath[XPATH_MAXLEN];
7793
7794 vrfname = pim_cli_get_vrf_name(vty);
7795 if (vrfname == NULL)
7796 return CMD_WARNING_CONFIG_FAILED;
7797
7798 snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
7799 FRR_PIM_AF_XPATH,
7800 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
7801 strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
7802 sizeof(ssmpingd_ip_xpath));
7803
7804 nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, NB_OP_CREATE,
7805 source_str);
7806
7807 return nb_cli_apply_changes(vty, NULL);
7808 }
7809
7810 DEFUN (no_ip_ssmpingd,
7811 no_ip_ssmpingd_cmd,
7812 "no ip ssmpingd [A.B.C.D]",
7813 NO_STR
7814 IP_STR
7815 CONF_SSMPINGD_STR
7816 "Source address\n")
7817 {
7818 const char *vrfname;
7819 int idx_ipv4 = 3;
7820 const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0";
7821 char ssmpingd_ip_xpath[XPATH_MAXLEN];
7822
7823 vrfname = pim_cli_get_vrf_name(vty);
7824 if (vrfname == NULL)
7825 return CMD_WARNING_CONFIG_FAILED;
7826
7827 snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
7828 FRR_PIM_AF_XPATH,
7829 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
7830 strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
7831 sizeof(ssmpingd_ip_xpath));
7832
7833 nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, NB_OP_DESTROY,
7834 source_str);
7835
7836 return nb_cli_apply_changes(vty, NULL);
7837 }
7838
7839 DEFUN (ip_pim_ecmp,
7840 ip_pim_ecmp_cmd,
7841 "ip pim ecmp",
7842 IP_STR
7843 "pim multicast routing\n"
7844 "Enable PIM ECMP \n")
7845 {
7846 const char *vrfname;
7847 char ecmp_xpath[XPATH_MAXLEN];
7848
7849 vrfname = pim_cli_get_vrf_name(vty);
7850 if (vrfname == NULL)
7851 return CMD_WARNING_CONFIG_FAILED;
7852
7853 snprintf(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH,
7854 "frr-pim:pimd", "pim", vrfname);
7855 strlcat(ecmp_xpath, "/ecmp", sizeof(ecmp_xpath));
7856
7857 nb_cli_enqueue_change(vty, ecmp_xpath, NB_OP_MODIFY, "true");
7858 return nb_cli_apply_changes(vty, NULL);
7859 }
7860
7861 DEFUN (no_ip_pim_ecmp,
7862 no_ip_pim_ecmp_cmd,
7863 "no ip pim ecmp",
7864 NO_STR
7865 IP_STR
7866 "pim multicast routing\n"
7867 "Disable PIM ECMP \n")
7868 {
7869 const char *vrfname;
7870 char ecmp_xpath[XPATH_MAXLEN];
7871
7872 vrfname = pim_cli_get_vrf_name(vty);
7873 if (vrfname == NULL)
7874 return CMD_WARNING_CONFIG_FAILED;
7875
7876 snprintf(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH,
7877 "frr-pim:pimd", "pim", vrfname);
7878 strlcat(ecmp_xpath, "/ecmp", sizeof(ecmp_xpath));
7879
7880 nb_cli_enqueue_change(vty, ecmp_xpath, NB_OP_MODIFY, "false");
7881
7882 return nb_cli_apply_changes(vty, NULL);
7883 }
7884
7885 DEFUN (ip_pim_ecmp_rebalance,
7886 ip_pim_ecmp_rebalance_cmd,
7887 "ip pim ecmp rebalance",
7888 IP_STR
7889 "pim multicast routing\n"
7890 "Enable PIM ECMP \n"
7891 "Enable PIM ECMP Rebalance\n")
7892 {
7893 const char *vrfname;
7894 char ecmp_xpath[XPATH_MAXLEN];
7895 char ecmp_rebalance_xpath[XPATH_MAXLEN];
7896
7897 vrfname = pim_cli_get_vrf_name(vty);
7898 if (vrfname == NULL)
7899 return CMD_WARNING_CONFIG_FAILED;
7900
7901 snprintf(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH,
7902 "frr-pim:pimd", "pim", vrfname);
7903 strlcat(ecmp_xpath, "/ecmp", sizeof(ecmp_xpath));
7904 snprintf(ecmp_rebalance_xpath, sizeof(ecmp_rebalance_xpath),
7905 FRR_PIM_XPATH,
7906 "frr-pim:pimd", "pim", vrfname);
7907 strlcat(ecmp_rebalance_xpath, "/ecmp-rebalance",
7908 sizeof(ecmp_rebalance_xpath));
7909
7910 nb_cli_enqueue_change(vty, ecmp_xpath, NB_OP_MODIFY, "true");
7911 nb_cli_enqueue_change(vty, ecmp_rebalance_xpath, NB_OP_MODIFY, "true");
7912
7913 return nb_cli_apply_changes(vty, NULL);
7914 }
7915
7916 DEFUN (no_ip_pim_ecmp_rebalance,
7917 no_ip_pim_ecmp_rebalance_cmd,
7918 "no ip pim ecmp rebalance",
7919 NO_STR
7920 IP_STR
7921 "pim multicast routing\n"
7922 "Disable PIM ECMP \n"
7923 "Disable PIM ECMP Rebalance\n")
7924 {
7925 const char *vrfname;
7926 char ecmp_rebalance_xpath[XPATH_MAXLEN];
7927
7928 vrfname = pim_cli_get_vrf_name(vty);
7929 if (vrfname == NULL)
7930 return CMD_WARNING_CONFIG_FAILED;
7931
7932 snprintf(ecmp_rebalance_xpath, sizeof(ecmp_rebalance_xpath),
7933 FRR_PIM_XPATH,
7934 "frr-pim:pimd", "pim", vrfname);
7935 strlcat(ecmp_rebalance_xpath, "/ecmp-rebalance",
7936 sizeof(ecmp_rebalance_xpath));
7937
7938 nb_cli_enqueue_change(vty, ecmp_rebalance_xpath, NB_OP_MODIFY, "false");
7939
7940 return nb_cli_apply_changes(vty, NULL);
7941 }
7942
7943 DEFUN (interface_ip_igmp,
7944 interface_ip_igmp_cmd,
7945 "ip igmp",
7946 IP_STR
7947 IFACE_IGMP_STR)
7948 {
7949 nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY, "true");
7950
7951 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
7952 }
7953
7954 DEFUN (interface_no_ip_igmp,
7955 interface_no_ip_igmp_cmd,
7956 "no ip igmp",
7957 NO_STR
7958 IP_STR
7959 IFACE_IGMP_STR)
7960 {
7961 const struct lyd_node *pim_enable_dnode;
7962 char pim_if_xpath[XPATH_MAXLEN + 20];
7963
7964 snprintf(pim_if_xpath, sizeof(pim_if_xpath),
7965 "%s/frr-pim:pim", VTY_CURR_XPATH);
7966
7967 pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
7968 "%s/pim-enable", pim_if_xpath);
7969 if (!pim_enable_dnode) {
7970 nb_cli_enqueue_change(vty, pim_if_xpath, NB_OP_DESTROY, NULL);
7971 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7972 } else {
7973 if (!yang_dnode_get_bool(pim_enable_dnode, ".")) {
7974 nb_cli_enqueue_change(vty, pim_if_xpath, NB_OP_DESTROY,
7975 NULL);
7976 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7977 } else
7978 nb_cli_enqueue_change(vty, "./igmp-enable",
7979 NB_OP_MODIFY, "false");
7980 }
7981
7982 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
7983 }
7984
7985 DEFUN (interface_ip_igmp_join,
7986 interface_ip_igmp_join_cmd,
7987 "ip igmp join A.B.C.D [A.B.C.D]",
7988 IP_STR
7989 IFACE_IGMP_STR
7990 "IGMP join multicast group\n"
7991 "Multicast group address\n"
7992 "Source address\n")
7993 {
7994 int idx_group = 3;
7995 int idx_source = 4;
7996 const char *source_str;
7997 char xpath[XPATH_MAXLEN];
7998
7999 if (argc == 5) {
8000 source_str = argv[idx_source]->arg;
8001
8002 if (strcmp(source_str, "0.0.0.0") == 0) {
8003 vty_out(vty, "Bad source address %s\n",
8004 argv[idx_source]->arg);
8005 return CMD_WARNING_CONFIG_FAILED;
8006 }
8007 } else
8008 source_str = "0.0.0.0";
8009
8010 snprintf(xpath, sizeof(xpath), FRR_IGMP_JOIN_XPATH,
8011 "frr-routing:ipv4", argv[idx_group]->arg, source_str);
8012
8013 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
8014
8015 return nb_cli_apply_changes(vty, NULL);
8016 }
8017
8018 DEFUN (interface_no_ip_igmp_join,
8019 interface_no_ip_igmp_join_cmd,
8020 "no ip igmp join A.B.C.D [A.B.C.D]",
8021 NO_STR
8022 IP_STR
8023 IFACE_IGMP_STR
8024 "IGMP join multicast group\n"
8025 "Multicast group address\n"
8026 "Source address\n")
8027 {
8028 int idx_group = 4;
8029 int idx_source = 5;
8030 const char *source_str;
8031 char xpath[XPATH_MAXLEN];
8032
8033 if (argc == 6) {
8034 source_str = argv[idx_source]->arg;
8035
8036 if (strcmp(source_str, "0.0.0.0") == 0) {
8037 vty_out(vty, "Bad source address %s\n",
8038 argv[idx_source]->arg);
8039 return CMD_WARNING_CONFIG_FAILED;
8040 }
8041 } else
8042 source_str = "0.0.0.0";
8043
8044 snprintf(xpath, sizeof(xpath), FRR_IGMP_JOIN_XPATH,
8045 "frr-routing:ipv4", argv[idx_group]->arg, source_str);
8046
8047 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
8048
8049 return nb_cli_apply_changes(vty, NULL);
8050 }
8051
8052 DEFUN (interface_ip_igmp_query_interval,
8053 interface_ip_igmp_query_interval_cmd,
8054 "ip igmp query-interval (1-65535)",
8055 IP_STR
8056 IFACE_IGMP_STR
8057 IFACE_IGMP_QUERY_INTERVAL_STR
8058 "Query interval in seconds\n")
8059 {
8060 const struct lyd_node *pim_enable_dnode;
8061
8062 pim_enable_dnode =
8063 yang_dnode_getf(vty->candidate_config->dnode,
8064 "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH);
8065 if (!pim_enable_dnode) {
8066 nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
8067 "true");
8068 } else {
8069 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
8070 nb_cli_enqueue_change(vty, "./igmp-enable",
8071 NB_OP_MODIFY, "true");
8072 }
8073
8074 nb_cli_enqueue_change(vty, "./query-interval", NB_OP_MODIFY,
8075 argv[3]->arg);
8076
8077 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8078 }
8079
8080 DEFUN (interface_no_ip_igmp_query_interval,
8081 interface_no_ip_igmp_query_interval_cmd,
8082 "no ip igmp query-interval [(1-65535)]",
8083 NO_STR
8084 IP_STR
8085 IFACE_IGMP_STR
8086 IFACE_IGMP_QUERY_INTERVAL_STR
8087 IGNORED_IN_NO_STR)
8088 {
8089 nb_cli_enqueue_change(vty, "./query-interval", NB_OP_DESTROY, NULL);
8090
8091 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8092 }
8093
8094 DEFUN (interface_ip_igmp_version,
8095 interface_ip_igmp_version_cmd,
8096 "ip igmp version (2-3)",
8097 IP_STR
8098 IFACE_IGMP_STR
8099 "IGMP version\n"
8100 "IGMP version number\n")
8101 {
8102 nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
8103 "true");
8104 nb_cli_enqueue_change(vty, "./version", NB_OP_MODIFY, argv[3]->arg);
8105
8106 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8107 }
8108
8109 DEFUN (interface_no_ip_igmp_version,
8110 interface_no_ip_igmp_version_cmd,
8111 "no ip igmp version (2-3)",
8112 NO_STR
8113 IP_STR
8114 IFACE_IGMP_STR
8115 "IGMP version\n"
8116 "IGMP version number\n")
8117 {
8118 nb_cli_enqueue_change(vty, "./version", NB_OP_DESTROY, NULL);
8119
8120 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8121 }
8122
8123 DEFUN (interface_ip_igmp_query_max_response_time,
8124 interface_ip_igmp_query_max_response_time_cmd,
8125 "ip igmp query-max-response-time (1-65535)",
8126 IP_STR
8127 IFACE_IGMP_STR
8128 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
8129 "Query response value in deci-seconds\n")
8130 {
8131 const struct lyd_node *pim_enable_dnode;
8132
8133 pim_enable_dnode =
8134 yang_dnode_getf(vty->candidate_config->dnode,
8135 "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH);
8136
8137 if (!pim_enable_dnode) {
8138 nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
8139 "true");
8140 } else {
8141 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
8142 nb_cli_enqueue_change(vty, "./igmp-enable",
8143 NB_OP_MODIFY, "true");
8144 }
8145
8146 nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
8147 argv[3]->arg);
8148
8149 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8150 }
8151
8152 DEFUN (interface_no_ip_igmp_query_max_response_time,
8153 interface_no_ip_igmp_query_max_response_time_cmd,
8154 "no ip igmp query-max-response-time [(1-65535)]",
8155 NO_STR
8156 IP_STR
8157 IFACE_IGMP_STR
8158 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
8159 IGNORED_IN_NO_STR)
8160 {
8161 nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_DESTROY,
8162 NULL);
8163 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8164 }
8165
8166 DEFUN_HIDDEN (interface_ip_igmp_query_max_response_time_dsec,
8167 interface_ip_igmp_query_max_response_time_dsec_cmd,
8168 "ip igmp query-max-response-time-dsec (1-65535)",
8169 IP_STR
8170 IFACE_IGMP_STR
8171 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR
8172 "Query response value in deciseconds\n")
8173 {
8174 const struct lyd_node *pim_enable_dnode;
8175
8176 pim_enable_dnode =
8177 yang_dnode_getf(vty->candidate_config->dnode,
8178 "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH);
8179 if (!pim_enable_dnode) {
8180 nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
8181 "true");
8182 } else {
8183 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
8184 nb_cli_enqueue_change(vty, "./igmp-enable",
8185 NB_OP_MODIFY, "true");
8186 }
8187
8188 nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
8189 argv[3]->arg);
8190
8191 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8192 }
8193
8194 DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec,
8195 interface_no_ip_igmp_query_max_response_time_dsec_cmd,
8196 "no ip igmp query-max-response-time-dsec [(1-65535)]",
8197 NO_STR
8198 IP_STR
8199 IFACE_IGMP_STR
8200 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR
8201 IGNORED_IN_NO_STR)
8202 {
8203 nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_DESTROY,
8204 NULL);
8205
8206 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8207 }
8208
8209 DEFUN (interface_ip_igmp_last_member_query_count,
8210 interface_ip_igmp_last_member_query_count_cmd,
8211 "ip igmp last-member-query-count (1-255)",
8212 IP_STR
8213 IFACE_IGMP_STR
8214 IFACE_IGMP_LAST_MEMBER_QUERY_COUNT_STR
8215 "Last member query count\n")
8216 {
8217 const struct lyd_node *pim_enable_dnode;
8218
8219 pim_enable_dnode =
8220 yang_dnode_getf(vty->candidate_config->dnode,
8221 "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH);
8222 if (!pim_enable_dnode) {
8223 nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
8224 "true");
8225 } else {
8226 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
8227 nb_cli_enqueue_change(vty, "./igmp-enable",
8228 NB_OP_MODIFY, "true");
8229 }
8230
8231 nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_MODIFY,
8232 argv[3]->arg);
8233
8234 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8235 }
8236
8237 DEFUN (interface_no_ip_igmp_last_member_query_count,
8238 interface_no_ip_igmp_last_member_query_count_cmd,
8239 "no ip igmp last-member-query-count [(1-255)]",
8240 NO_STR
8241 IP_STR
8242 IFACE_IGMP_STR
8243 IFACE_IGMP_LAST_MEMBER_QUERY_COUNT_STR
8244 IGNORED_IN_NO_STR)
8245 {
8246 nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_DESTROY,
8247 NULL);
8248
8249 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8250 }
8251
8252 DEFUN (interface_ip_igmp_last_member_query_interval,
8253 interface_ip_igmp_last_member_query_interval_cmd,
8254 "ip igmp last-member-query-interval (1-65535)",
8255 IP_STR
8256 IFACE_IGMP_STR
8257 IFACE_IGMP_LAST_MEMBER_QUERY_INTERVAL_STR
8258 "Last member query interval in deciseconds\n")
8259 {
8260 const struct lyd_node *pim_enable_dnode;
8261
8262 pim_enable_dnode =
8263 yang_dnode_getf(vty->candidate_config->dnode,
8264 "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH);
8265 if (!pim_enable_dnode) {
8266 nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
8267 "true");
8268 } else {
8269 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
8270 nb_cli_enqueue_change(vty, "./igmp-enable",
8271 NB_OP_MODIFY, "true");
8272 }
8273
8274 nb_cli_enqueue_change(vty, "./last-member-query-interval", NB_OP_MODIFY,
8275 argv[3]->arg);
8276
8277 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8278 }
8279
8280 DEFUN (interface_no_ip_igmp_last_member_query_interval,
8281 interface_no_ip_igmp_last_member_query_interval_cmd,
8282 "no ip igmp last-member-query-interval [(1-65535)]",
8283 NO_STR
8284 IP_STR
8285 IFACE_IGMP_STR
8286 IFACE_IGMP_LAST_MEMBER_QUERY_INTERVAL_STR
8287 IGNORED_IN_NO_STR)
8288 {
8289 nb_cli_enqueue_change(vty, "./last-member-query-interval",
8290 NB_OP_DESTROY, NULL);
8291
8292 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8293 }
8294
8295 DEFUN (interface_ip_pim_drprio,
8296 interface_ip_pim_drprio_cmd,
8297 "ip pim drpriority (1-4294967295)",
8298 IP_STR
8299 PIM_STR
8300 "Set the Designated Router Election Priority\n"
8301 "Value of the new DR Priority\n")
8302 {
8303 int idx_number = 3;
8304
8305 nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_MODIFY,
8306 argv[idx_number]->arg);
8307
8308 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8309 }
8310
8311 DEFUN (interface_no_ip_pim_drprio,
8312 interface_no_ip_pim_drprio_cmd,
8313 "no ip pim drpriority [(1-4294967295)]",
8314 NO_STR
8315 IP_STR
8316 PIM_STR
8317 "Revert the Designated Router Priority to default\n"
8318 "Old Value of the Priority\n")
8319 {
8320 nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_DESTROY, NULL);
8321
8322 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8323 }
8324
8325 DEFPY_HIDDEN (interface_ip_igmp_query_generate,
8326 interface_ip_igmp_query_generate_cmd,
8327 "ip igmp generate-query-once [version (2-3)]",
8328 IP_STR
8329 IFACE_IGMP_STR
8330 "Generate igmp general query once\n"
8331 "IGMP version\n"
8332 "IGMP version number\n")
8333 {
8334 VTY_DECLVAR_CONTEXT(interface, ifp);
8335 int igmp_version = 2;
8336
8337 if (!ifp->info) {
8338 vty_out(vty, "IGMP/PIM is not enabled on the interface %s\n",
8339 ifp->name);
8340 return CMD_WARNING_CONFIG_FAILED;
8341 }
8342
8343 if (argc > 3)
8344 igmp_version = atoi(argv[4]->arg);
8345
8346 igmp_send_query_on_intf(ifp, igmp_version);
8347
8348 return CMD_SUCCESS;
8349 }
8350
8351 DEFPY_HIDDEN (pim_test_sg_keepalive,
8352 pim_test_sg_keepalive_cmd,
8353 "test pim [vrf NAME$name] keepalive-reset A.B.C.D$source A.B.C.D$group",
8354 "Test code\n"
8355 PIM_STR
8356 VRF_CMD_HELP_STR
8357 "Reset the Keepalive Timer\n"
8358 "The Source we are resetting\n"
8359 "The Group we are resetting\n")
8360 {
8361 struct pim_upstream *up;
8362 struct pim_instance *pim;
8363 struct prefix_sg sg;
8364
8365 sg.src = source;
8366 sg.grp = group;
8367
8368 if (!name)
8369 pim = pim_get_pim_instance(VRF_DEFAULT);
8370 else {
8371 struct vrf *vrf = vrf_lookup_by_name(name);
8372
8373 if (!vrf) {
8374 vty_out(vty, "%% Vrf specified: %s does not exist\n",
8375 name);
8376 return CMD_WARNING;
8377 }
8378
8379 pim = pim_get_pim_instance(vrf->vrf_id);
8380 }
8381
8382 if (!pim) {
8383 vty_out(vty, "%% Unable to find pim instance\n");
8384 return CMD_WARNING;
8385 }
8386
8387 up = pim_upstream_find(pim, &sg);
8388 if (!up) {
8389 vty_out(vty, "%% Unable to find %s specified\n",
8390 pim_str_sg_dump(&sg));
8391 return CMD_WARNING;
8392 }
8393
8394 vty_out(vty, "Setting %s to current keep alive time: %d\n",
8395 pim_str_sg_dump(&sg), pim->keep_alive_time);
8396 pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
8397
8398 return CMD_SUCCESS;
8399 }
8400
8401 DEFPY (interface_ip_pim_activeactive,
8402 interface_ip_pim_activeactive_cmd,
8403 "[no$no] ip pim active-active",
8404 NO_STR
8405 IP_STR
8406 PIM_STR
8407 "Mark interface as Active-Active for MLAG operations, Hidden because not finished yet\n")
8408 {
8409 if (no)
8410 nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
8411 "false");
8412 else {
8413 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
8414 "true");
8415
8416 nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
8417 "true");
8418 }
8419
8420 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8421 }
8422
8423 DEFUN_HIDDEN (interface_ip_pim_ssm,
8424 interface_ip_pim_ssm_cmd,
8425 "ip pim ssm",
8426 IP_STR
8427 PIM_STR
8428 IFACE_PIM_STR)
8429 {
8430 int ret;
8431
8432 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
8433
8434 ret = nb_cli_apply_changes(vty, "./frr-pim:pim");
8435
8436 if (ret != NB_OK)
8437 return ret;
8438
8439 vty_out(vty,
8440 "WARN: Enabled PIM SM on interface; configure PIM SSM range if needed\n");
8441
8442 return NB_OK;
8443 }
8444
8445 DEFUN_HIDDEN (interface_ip_pim_sm,
8446 interface_ip_pim_sm_cmd,
8447 "ip pim sm",
8448 IP_STR
8449 PIM_STR
8450 IFACE_PIM_SM_STR)
8451 {
8452 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
8453
8454 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8455 }
8456
8457 DEFUN (interface_ip_pim,
8458 interface_ip_pim_cmd,
8459 "ip pim",
8460 IP_STR
8461 PIM_STR)
8462 {
8463 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
8464
8465 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8466 }
8467
8468 DEFUN_HIDDEN (interface_no_ip_pim_ssm,
8469 interface_no_ip_pim_ssm_cmd,
8470 "no ip pim ssm",
8471 NO_STR
8472 IP_STR
8473 PIM_STR
8474 IFACE_PIM_STR)
8475 {
8476 const struct lyd_node *igmp_enable_dnode;
8477 char igmp_if_xpath[XPATH_MAXLEN + 20];
8478
8479 snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
8480 "%s/frr-igmp:igmp", VTY_CURR_XPATH);
8481 igmp_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
8482 "%s/igmp-enable", igmp_if_xpath);
8483
8484 if (!igmp_enable_dnode) {
8485 nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY, NULL);
8486 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8487 } else {
8488 if (!yang_dnode_get_bool(igmp_enable_dnode, ".")) {
8489 nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY,
8490 NULL);
8491 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8492 } else
8493 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
8494 "false");
8495 }
8496
8497 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8498 }
8499
8500 DEFUN_HIDDEN (interface_no_ip_pim_sm,
8501 interface_no_ip_pim_sm_cmd,
8502 "no ip pim sm",
8503 NO_STR
8504 IP_STR
8505 PIM_STR
8506 IFACE_PIM_SM_STR)
8507 {
8508 const struct lyd_node *igmp_enable_dnode;
8509 char igmp_if_xpath[XPATH_MAXLEN + 20];
8510
8511 snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
8512 "%s/frr-igmp:igmp", VTY_CURR_XPATH);
8513 igmp_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
8514 "%s/igmp-enable", igmp_if_xpath);
8515
8516 if (!igmp_enable_dnode) {
8517 nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY, NULL);
8518 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8519 } else {
8520 if (!yang_dnode_get_bool(igmp_enable_dnode, ".")) {
8521 nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY,
8522 NULL);
8523 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8524 } else
8525 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
8526 "false");
8527 }
8528
8529 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8530 }
8531
8532 DEFUN (interface_no_ip_pim,
8533 interface_no_ip_pim_cmd,
8534 "no ip pim",
8535 NO_STR
8536 IP_STR
8537 PIM_STR)
8538 {
8539 const struct lyd_node *igmp_enable_dnode;
8540 char igmp_if_xpath[XPATH_MAXLEN + 20];
8541
8542 snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
8543 "%s/frr-igmp:igmp", VTY_CURR_XPATH);
8544 igmp_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
8545 "%s/igmp-enable", igmp_if_xpath);
8546
8547 if (!igmp_enable_dnode) {
8548 nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY, NULL);
8549 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8550 } else {
8551 if (!yang_dnode_get_bool(igmp_enable_dnode, ".")) {
8552 nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY,
8553 NULL);
8554 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8555 } else
8556 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
8557 "false");
8558 }
8559
8560 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8561 }
8562
8563 /* boundaries */
8564 DEFUN(interface_ip_pim_boundary_oil,
8565 interface_ip_pim_boundary_oil_cmd,
8566 "ip multicast boundary oil WORD",
8567 IP_STR
8568 "Generic multicast configuration options\n"
8569 "Define multicast boundary\n"
8570 "Filter OIL by group using prefix list\n"
8571 "Prefix list to filter OIL with\n")
8572 {
8573 nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_MODIFY,
8574 argv[4]->arg);
8575
8576 return nb_cli_apply_changes(vty,
8577 "./frr-pim:pim/address-family[address-family='%s']",
8578 "frr-routing:ipv4");
8579
8580 }
8581
8582 DEFUN(interface_no_ip_pim_boundary_oil,
8583 interface_no_ip_pim_boundary_oil_cmd,
8584 "no ip multicast boundary oil [WORD]",
8585 NO_STR
8586 IP_STR
8587 "Generic multicast configuration options\n"
8588 "Define multicast boundary\n"
8589 "Filter OIL by group using prefix list\n"
8590 "Prefix list to filter OIL with\n")
8591 {
8592 nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_DESTROY,
8593 NULL);
8594
8595 return nb_cli_apply_changes(vty,
8596 "./frr-pim:pim/address-family[address-family='%s']",
8597 "frr-routing:ipv4");
8598 }
8599
8600 DEFUN (interface_ip_mroute,
8601 interface_ip_mroute_cmd,
8602 "ip mroute INTERFACE A.B.C.D [A.B.C.D]",
8603 IP_STR
8604 "Add multicast route\n"
8605 "Outgoing interface name\n"
8606 "Group address\n"
8607 "Source address\n")
8608 {
8609 int idx_interface = 2;
8610 int idx_ipv4 = 3;
8611 const char *source_str;
8612
8613 if (argc == (idx_ipv4 + 1))
8614 source_str = "0.0.0.0";
8615 else
8616 source_str = argv[idx_ipv4 + 1]->arg;
8617
8618 nb_cli_enqueue_change(vty, "./oif", NB_OP_MODIFY,
8619 argv[idx_interface]->arg);
8620
8621 return nb_cli_apply_changes(vty,
8622 "./frr-pim:pim/address-family[address-family='%s']/mroute[source-addr='%s'][group-addr='%s']",
8623 "frr-routing:ipv4", source_str,
8624 argv[idx_ipv4]->arg);
8625 }
8626
8627 DEFUN (interface_no_ip_mroute,
8628 interface_no_ip_mroute_cmd,
8629 "no ip mroute INTERFACE A.B.C.D [A.B.C.D]",
8630 NO_STR
8631 IP_STR
8632 "Add multicast route\n"
8633 "Outgoing interface name\n"
8634 "Group Address\n"
8635 "Source Address\n")
8636 {
8637 int idx_ipv4 = 4;
8638 const char *source_str;
8639
8640 if (argc == (idx_ipv4 + 1))
8641 source_str = "0.0.0.0";
8642 else
8643 source_str = argv[idx_ipv4 + 1]->arg;
8644
8645 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8646
8647 return nb_cli_apply_changes(vty,
8648 "./frr-pim:pim/address-family[address-family='%s']/mroute[source-addr='%s'][group-addr='%s']",
8649 "frr-routing:ipv4", source_str,
8650 argv[idx_ipv4]->arg);
8651 }
8652
8653 DEFUN (interface_ip_pim_hello,
8654 interface_ip_pim_hello_cmd,
8655 "ip pim hello (1-65535) [(1-65535)]",
8656 IP_STR
8657 PIM_STR
8658 IFACE_PIM_HELLO_STR
8659 IFACE_PIM_HELLO_TIME_STR
8660 IFACE_PIM_HELLO_HOLD_STR)
8661 {
8662 int idx_time = 3;
8663 int idx_hold = 4;
8664 const struct lyd_node *igmp_enable_dnode;
8665
8666 igmp_enable_dnode =
8667 yang_dnode_getf(vty->candidate_config->dnode,
8668 "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH);
8669 if (!igmp_enable_dnode) {
8670 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
8671 "true");
8672 } else {
8673 if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
8674 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
8675 "true");
8676 }
8677
8678 nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_MODIFY,
8679 argv[idx_time]->arg);
8680
8681 if (argc == idx_hold + 1)
8682 nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_MODIFY,
8683 argv[idx_hold]->arg);
8684
8685 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8686 }
8687
8688 DEFUN (interface_no_ip_pim_hello,
8689 interface_no_ip_pim_hello_cmd,
8690 "no ip pim hello [(1-65535) [(1-65535)]]",
8691 NO_STR
8692 IP_STR
8693 PIM_STR
8694 IFACE_PIM_HELLO_STR
8695 IGNORED_IN_NO_STR
8696 IGNORED_IN_NO_STR)
8697 {
8698 nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_DESTROY, NULL);
8699 nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_DESTROY, NULL);
8700
8701 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8702 }
8703
8704 DEFUN (debug_igmp,
8705 debug_igmp_cmd,
8706 "debug igmp",
8707 DEBUG_STR
8708 DEBUG_IGMP_STR)
8709 {
8710 PIM_DO_DEBUG_IGMP_EVENTS;
8711 PIM_DO_DEBUG_IGMP_PACKETS;
8712 PIM_DO_DEBUG_IGMP_TRACE;
8713 return CMD_SUCCESS;
8714 }
8715
8716 DEFUN (no_debug_igmp,
8717 no_debug_igmp_cmd,
8718 "no debug igmp",
8719 NO_STR
8720 DEBUG_STR
8721 DEBUG_IGMP_STR)
8722 {
8723 PIM_DONT_DEBUG_IGMP_EVENTS;
8724 PIM_DONT_DEBUG_IGMP_PACKETS;
8725 PIM_DONT_DEBUG_IGMP_TRACE;
8726 return CMD_SUCCESS;
8727 }
8728
8729
8730 DEFUN (debug_igmp_events,
8731 debug_igmp_events_cmd,
8732 "debug igmp events",
8733 DEBUG_STR
8734 DEBUG_IGMP_STR
8735 DEBUG_IGMP_EVENTS_STR)
8736 {
8737 PIM_DO_DEBUG_IGMP_EVENTS;
8738 return CMD_SUCCESS;
8739 }
8740
8741 DEFUN (no_debug_igmp_events,
8742 no_debug_igmp_events_cmd,
8743 "no debug igmp events",
8744 NO_STR
8745 DEBUG_STR
8746 DEBUG_IGMP_STR
8747 DEBUG_IGMP_EVENTS_STR)
8748 {
8749 PIM_DONT_DEBUG_IGMP_EVENTS;
8750 return CMD_SUCCESS;
8751 }
8752
8753
8754 DEFUN (debug_igmp_packets,
8755 debug_igmp_packets_cmd,
8756 "debug igmp packets",
8757 DEBUG_STR
8758 DEBUG_IGMP_STR
8759 DEBUG_IGMP_PACKETS_STR)
8760 {
8761 PIM_DO_DEBUG_IGMP_PACKETS;
8762 return CMD_SUCCESS;
8763 }
8764
8765 DEFUN (no_debug_igmp_packets,
8766 no_debug_igmp_packets_cmd,
8767 "no debug igmp packets",
8768 NO_STR
8769 DEBUG_STR
8770 DEBUG_IGMP_STR
8771 DEBUG_IGMP_PACKETS_STR)
8772 {
8773 PIM_DONT_DEBUG_IGMP_PACKETS;
8774 return CMD_SUCCESS;
8775 }
8776
8777
8778 DEFUN (debug_igmp_trace,
8779 debug_igmp_trace_cmd,
8780 "debug igmp trace",
8781 DEBUG_STR
8782 DEBUG_IGMP_STR
8783 DEBUG_IGMP_TRACE_STR)
8784 {
8785 PIM_DO_DEBUG_IGMP_TRACE;
8786 return CMD_SUCCESS;
8787 }
8788
8789 DEFUN (no_debug_igmp_trace,
8790 no_debug_igmp_trace_cmd,
8791 "no debug igmp trace",
8792 NO_STR
8793 DEBUG_STR
8794 DEBUG_IGMP_STR
8795 DEBUG_IGMP_TRACE_STR)
8796 {
8797 PIM_DONT_DEBUG_IGMP_TRACE;
8798 return CMD_SUCCESS;
8799 }
8800
8801
8802 DEFUN (debug_mroute,
8803 debug_mroute_cmd,
8804 "debug mroute",
8805 DEBUG_STR
8806 DEBUG_MROUTE_STR)
8807 {
8808 PIM_DO_DEBUG_MROUTE;
8809 return CMD_SUCCESS;
8810 }
8811
8812 DEFUN (debug_mroute_detail,
8813 debug_mroute_detail_cmd,
8814 "debug mroute detail",
8815 DEBUG_STR
8816 DEBUG_MROUTE_STR
8817 "detailed\n")
8818 {
8819 PIM_DO_DEBUG_MROUTE_DETAIL;
8820 return CMD_SUCCESS;
8821 }
8822
8823 DEFUN (no_debug_mroute,
8824 no_debug_mroute_cmd,
8825 "no debug mroute",
8826 NO_STR
8827 DEBUG_STR
8828 DEBUG_MROUTE_STR)
8829 {
8830 PIM_DONT_DEBUG_MROUTE;
8831 return CMD_SUCCESS;
8832 }
8833
8834 DEFUN (no_debug_mroute_detail,
8835 no_debug_mroute_detail_cmd,
8836 "no debug mroute detail",
8837 NO_STR
8838 DEBUG_STR
8839 DEBUG_MROUTE_STR
8840 "detailed\n")
8841 {
8842 PIM_DONT_DEBUG_MROUTE_DETAIL;
8843 return CMD_SUCCESS;
8844 }
8845
8846 DEFUN (debug_pim_static,
8847 debug_pim_static_cmd,
8848 "debug pim static",
8849 DEBUG_STR
8850 DEBUG_PIM_STR
8851 DEBUG_STATIC_STR)
8852 {
8853 PIM_DO_DEBUG_STATIC;
8854 return CMD_SUCCESS;
8855 }
8856
8857 DEFUN (no_debug_pim_static,
8858 no_debug_pim_static_cmd,
8859 "no debug pim static",
8860 NO_STR
8861 DEBUG_STR
8862 DEBUG_PIM_STR
8863 DEBUG_STATIC_STR)
8864 {
8865 PIM_DONT_DEBUG_STATIC;
8866 return CMD_SUCCESS;
8867 }
8868
8869
8870 DEFUN (debug_pim,
8871 debug_pim_cmd,
8872 "debug pim",
8873 DEBUG_STR
8874 DEBUG_PIM_STR)
8875 {
8876 PIM_DO_DEBUG_PIM_EVENTS;
8877 PIM_DO_DEBUG_PIM_PACKETS;
8878 PIM_DO_DEBUG_PIM_TRACE;
8879 PIM_DO_DEBUG_MSDP_EVENTS;
8880 PIM_DO_DEBUG_MSDP_PACKETS;
8881 PIM_DO_DEBUG_BSM;
8882 return CMD_SUCCESS;
8883 }
8884
8885 DEFUN (no_debug_pim,
8886 no_debug_pim_cmd,
8887 "no debug pim",
8888 NO_STR
8889 DEBUG_STR
8890 DEBUG_PIM_STR)
8891 {
8892 PIM_DONT_DEBUG_PIM_EVENTS;
8893 PIM_DONT_DEBUG_PIM_PACKETS;
8894 PIM_DONT_DEBUG_PIM_TRACE;
8895 PIM_DONT_DEBUG_MSDP_EVENTS;
8896 PIM_DONT_DEBUG_MSDP_PACKETS;
8897
8898 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
8899 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
8900 PIM_DONT_DEBUG_BSM;
8901
8902 return CMD_SUCCESS;
8903 }
8904
8905 DEFUN (debug_pim_nht,
8906 debug_pim_nht_cmd,
8907 "debug pim nht",
8908 DEBUG_STR
8909 DEBUG_PIM_STR
8910 "Nexthop Tracking\n")
8911 {
8912 PIM_DO_DEBUG_PIM_NHT;
8913 return CMD_SUCCESS;
8914 }
8915
8916 DEFUN (no_debug_pim_nht,
8917 no_debug_pim_nht_cmd,
8918 "no debug pim nht",
8919 NO_STR
8920 DEBUG_STR
8921 DEBUG_PIM_STR
8922 "Nexthop Tracking\n")
8923 {
8924 PIM_DONT_DEBUG_PIM_NHT;
8925 return CMD_SUCCESS;
8926 }
8927
8928 DEFUN (debug_pim_nht_rp,
8929 debug_pim_nht_rp_cmd,
8930 "debug pim nht rp",
8931 DEBUG_STR
8932 DEBUG_PIM_STR
8933 "Nexthop Tracking\n"
8934 "RP Nexthop Tracking\n")
8935 {
8936 PIM_DO_DEBUG_PIM_NHT_RP;
8937 return CMD_SUCCESS;
8938 }
8939
8940 DEFUN (no_debug_pim_nht_rp,
8941 no_debug_pim_nht_rp_cmd,
8942 "no debug pim nht rp",
8943 NO_STR
8944 DEBUG_STR
8945 DEBUG_PIM_STR
8946 "Nexthop Tracking\n"
8947 "RP Nexthop Tracking\n")
8948 {
8949 PIM_DONT_DEBUG_PIM_NHT_RP;
8950 return CMD_SUCCESS;
8951 }
8952
8953 DEFUN (debug_pim_events,
8954 debug_pim_events_cmd,
8955 "debug pim events",
8956 DEBUG_STR
8957 DEBUG_PIM_STR
8958 DEBUG_PIM_EVENTS_STR)
8959 {
8960 PIM_DO_DEBUG_PIM_EVENTS;
8961 return CMD_SUCCESS;
8962 }
8963
8964 DEFUN (no_debug_pim_events,
8965 no_debug_pim_events_cmd,
8966 "no debug pim events",
8967 NO_STR
8968 DEBUG_STR
8969 DEBUG_PIM_STR
8970 DEBUG_PIM_EVENTS_STR)
8971 {
8972 PIM_DONT_DEBUG_PIM_EVENTS;
8973 return CMD_SUCCESS;
8974 }
8975
8976 DEFUN (debug_pim_packets,
8977 debug_pim_packets_cmd,
8978 "debug pim packets [<hello|joins|register>]",
8979 DEBUG_STR
8980 DEBUG_PIM_STR
8981 DEBUG_PIM_PACKETS_STR
8982 DEBUG_PIM_HELLO_PACKETS_STR
8983 DEBUG_PIM_J_P_PACKETS_STR
8984 DEBUG_PIM_PIM_REG_PACKETS_STR)
8985 {
8986 int idx = 0;
8987 if (argv_find(argv, argc, "hello", &idx)) {
8988 PIM_DO_DEBUG_PIM_HELLO;
8989 vty_out(vty, "PIM Hello debugging is on\n");
8990 } else if (argv_find(argv, argc, "joins", &idx)) {
8991 PIM_DO_DEBUG_PIM_J_P;
8992 vty_out(vty, "PIM Join/Prune debugging is on\n");
8993 } else if (argv_find(argv, argc, "register", &idx)) {
8994 PIM_DO_DEBUG_PIM_REG;
8995 vty_out(vty, "PIM Register debugging is on\n");
8996 } else {
8997 PIM_DO_DEBUG_PIM_PACKETS;
8998 vty_out(vty, "PIM Packet debugging is on \n");
8999 }
9000 return CMD_SUCCESS;
9001 }
9002
9003 DEFUN (no_debug_pim_packets,
9004 no_debug_pim_packets_cmd,
9005 "no debug pim packets [<hello|joins|register>]",
9006 NO_STR
9007 DEBUG_STR
9008 DEBUG_PIM_STR
9009 DEBUG_PIM_PACKETS_STR
9010 DEBUG_PIM_HELLO_PACKETS_STR
9011 DEBUG_PIM_J_P_PACKETS_STR
9012 DEBUG_PIM_PIM_REG_PACKETS_STR)
9013 {
9014 int idx = 0;
9015 if (argv_find(argv, argc, "hello", &idx)) {
9016 PIM_DONT_DEBUG_PIM_HELLO;
9017 vty_out(vty, "PIM Hello debugging is off \n");
9018 } else if (argv_find(argv, argc, "joins", &idx)) {
9019 PIM_DONT_DEBUG_PIM_J_P;
9020 vty_out(vty, "PIM Join/Prune debugging is off \n");
9021 } else if (argv_find(argv, argc, "register", &idx)) {
9022 PIM_DONT_DEBUG_PIM_REG;
9023 vty_out(vty, "PIM Register debugging is off\n");
9024 } else
9025 PIM_DONT_DEBUG_PIM_PACKETS;
9026
9027 return CMD_SUCCESS;
9028 }
9029
9030
9031 DEFUN (debug_pim_packetdump_send,
9032 debug_pim_packetdump_send_cmd,
9033 "debug pim packet-dump send",
9034 DEBUG_STR
9035 DEBUG_PIM_STR
9036 DEBUG_PIM_PACKETDUMP_STR
9037 DEBUG_PIM_PACKETDUMP_SEND_STR)
9038 {
9039 PIM_DO_DEBUG_PIM_PACKETDUMP_SEND;
9040 return CMD_SUCCESS;
9041 }
9042
9043 DEFUN (no_debug_pim_packetdump_send,
9044 no_debug_pim_packetdump_send_cmd,
9045 "no debug pim packet-dump send",
9046 NO_STR
9047 DEBUG_STR
9048 DEBUG_PIM_STR
9049 DEBUG_PIM_PACKETDUMP_STR
9050 DEBUG_PIM_PACKETDUMP_SEND_STR)
9051 {
9052 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
9053 return CMD_SUCCESS;
9054 }
9055
9056 DEFUN (debug_pim_packetdump_recv,
9057 debug_pim_packetdump_recv_cmd,
9058 "debug pim packet-dump receive",
9059 DEBUG_STR
9060 DEBUG_PIM_STR
9061 DEBUG_PIM_PACKETDUMP_STR
9062 DEBUG_PIM_PACKETDUMP_RECV_STR)
9063 {
9064 PIM_DO_DEBUG_PIM_PACKETDUMP_RECV;
9065 return CMD_SUCCESS;
9066 }
9067
9068 DEFUN (no_debug_pim_packetdump_recv,
9069 no_debug_pim_packetdump_recv_cmd,
9070 "no debug pim packet-dump receive",
9071 NO_STR
9072 DEBUG_STR
9073 DEBUG_PIM_STR
9074 DEBUG_PIM_PACKETDUMP_STR
9075 DEBUG_PIM_PACKETDUMP_RECV_STR)
9076 {
9077 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
9078 return CMD_SUCCESS;
9079 }
9080
9081 DEFUN (debug_pim_trace,
9082 debug_pim_trace_cmd,
9083 "debug pim trace",
9084 DEBUG_STR
9085 DEBUG_PIM_STR
9086 DEBUG_PIM_TRACE_STR)
9087 {
9088 PIM_DO_DEBUG_PIM_TRACE;
9089 return CMD_SUCCESS;
9090 }
9091
9092 DEFUN (debug_pim_trace_detail,
9093 debug_pim_trace_detail_cmd,
9094 "debug pim trace detail",
9095 DEBUG_STR
9096 DEBUG_PIM_STR
9097 DEBUG_PIM_TRACE_STR
9098 "Detailed Information\n")
9099 {
9100 PIM_DO_DEBUG_PIM_TRACE_DETAIL;
9101 return CMD_SUCCESS;
9102 }
9103
9104 DEFUN (no_debug_pim_trace,
9105 no_debug_pim_trace_cmd,
9106 "no debug pim trace",
9107 NO_STR
9108 DEBUG_STR
9109 DEBUG_PIM_STR
9110 DEBUG_PIM_TRACE_STR)
9111 {
9112 PIM_DONT_DEBUG_PIM_TRACE;
9113 return CMD_SUCCESS;
9114 }
9115
9116 DEFUN (no_debug_pim_trace_detail,
9117 no_debug_pim_trace_detail_cmd,
9118 "no debug pim trace detail",
9119 NO_STR
9120 DEBUG_STR
9121 DEBUG_PIM_STR
9122 DEBUG_PIM_TRACE_STR
9123 "Detailed Information\n")
9124 {
9125 PIM_DONT_DEBUG_PIM_TRACE_DETAIL;
9126 return CMD_SUCCESS;
9127 }
9128
9129 DEFUN (debug_ssmpingd,
9130 debug_ssmpingd_cmd,
9131 "debug ssmpingd",
9132 DEBUG_STR
9133 DEBUG_SSMPINGD_STR)
9134 {
9135 PIM_DO_DEBUG_SSMPINGD;
9136 return CMD_SUCCESS;
9137 }
9138
9139 DEFUN (no_debug_ssmpingd,
9140 no_debug_ssmpingd_cmd,
9141 "no debug ssmpingd",
9142 NO_STR
9143 DEBUG_STR
9144 DEBUG_SSMPINGD_STR)
9145 {
9146 PIM_DONT_DEBUG_SSMPINGD;
9147 return CMD_SUCCESS;
9148 }
9149
9150 DEFUN (debug_pim_zebra,
9151 debug_pim_zebra_cmd,
9152 "debug pim zebra",
9153 DEBUG_STR
9154 DEBUG_PIM_STR
9155 DEBUG_PIM_ZEBRA_STR)
9156 {
9157 PIM_DO_DEBUG_ZEBRA;
9158 return CMD_SUCCESS;
9159 }
9160
9161 DEFUN (no_debug_pim_zebra,
9162 no_debug_pim_zebra_cmd,
9163 "no debug pim zebra",
9164 NO_STR
9165 DEBUG_STR
9166 DEBUG_PIM_STR
9167 DEBUG_PIM_ZEBRA_STR)
9168 {
9169 PIM_DONT_DEBUG_ZEBRA;
9170 return CMD_SUCCESS;
9171 }
9172
9173 DEFUN(debug_pim_mlag, debug_pim_mlag_cmd, "debug pim mlag",
9174 DEBUG_STR DEBUG_PIM_STR DEBUG_PIM_MLAG_STR)
9175 {
9176 PIM_DO_DEBUG_MLAG;
9177 return CMD_SUCCESS;
9178 }
9179
9180 DEFUN(no_debug_pim_mlag, no_debug_pim_mlag_cmd, "no debug pim mlag",
9181 NO_STR DEBUG_STR DEBUG_PIM_STR DEBUG_PIM_MLAG_STR)
9182 {
9183 PIM_DONT_DEBUG_MLAG;
9184 return CMD_SUCCESS;
9185 }
9186
9187 DEFUN (debug_pim_vxlan,
9188 debug_pim_vxlan_cmd,
9189 "debug pim vxlan",
9190 DEBUG_STR
9191 DEBUG_PIM_STR
9192 DEBUG_PIM_VXLAN_STR)
9193 {
9194 PIM_DO_DEBUG_VXLAN;
9195 return CMD_SUCCESS;
9196 }
9197
9198 DEFUN (no_debug_pim_vxlan,
9199 no_debug_pim_vxlan_cmd,
9200 "no debug pim vxlan",
9201 NO_STR
9202 DEBUG_STR
9203 DEBUG_PIM_STR
9204 DEBUG_PIM_VXLAN_STR)
9205 {
9206 PIM_DONT_DEBUG_VXLAN;
9207 return CMD_SUCCESS;
9208 }
9209
9210 DEFUN (debug_msdp,
9211 debug_msdp_cmd,
9212 "debug msdp",
9213 DEBUG_STR
9214 DEBUG_MSDP_STR)
9215 {
9216 PIM_DO_DEBUG_MSDP_EVENTS;
9217 PIM_DO_DEBUG_MSDP_PACKETS;
9218 return CMD_SUCCESS;
9219 }
9220
9221 DEFUN (no_debug_msdp,
9222 no_debug_msdp_cmd,
9223 "no debug msdp",
9224 NO_STR
9225 DEBUG_STR
9226 DEBUG_MSDP_STR)
9227 {
9228 PIM_DONT_DEBUG_MSDP_EVENTS;
9229 PIM_DONT_DEBUG_MSDP_PACKETS;
9230 return CMD_SUCCESS;
9231 }
9232
9233 DEFUN (debug_msdp_events,
9234 debug_msdp_events_cmd,
9235 "debug msdp events",
9236 DEBUG_STR
9237 DEBUG_MSDP_STR
9238 DEBUG_MSDP_EVENTS_STR)
9239 {
9240 PIM_DO_DEBUG_MSDP_EVENTS;
9241 return CMD_SUCCESS;
9242 }
9243
9244 DEFUN (no_debug_msdp_events,
9245 no_debug_msdp_events_cmd,
9246 "no debug msdp events",
9247 NO_STR
9248 DEBUG_STR
9249 DEBUG_MSDP_STR
9250 DEBUG_MSDP_EVENTS_STR)
9251 {
9252 PIM_DONT_DEBUG_MSDP_EVENTS;
9253 return CMD_SUCCESS;
9254 }
9255
9256 DEFUN (debug_msdp_packets,
9257 debug_msdp_packets_cmd,
9258 "debug msdp packets",
9259 DEBUG_STR
9260 DEBUG_MSDP_STR
9261 DEBUG_MSDP_PACKETS_STR)
9262 {
9263 PIM_DO_DEBUG_MSDP_PACKETS;
9264 return CMD_SUCCESS;
9265 }
9266
9267 DEFUN (no_debug_msdp_packets,
9268 no_debug_msdp_packets_cmd,
9269 "no debug msdp packets",
9270 NO_STR
9271 DEBUG_STR
9272 DEBUG_MSDP_STR
9273 DEBUG_MSDP_PACKETS_STR)
9274 {
9275 PIM_DONT_DEBUG_MSDP_PACKETS;
9276 return CMD_SUCCESS;
9277 }
9278
9279 DEFUN (debug_mtrace,
9280 debug_mtrace_cmd,
9281 "debug mtrace",
9282 DEBUG_STR
9283 DEBUG_MTRACE_STR)
9284 {
9285 PIM_DO_DEBUG_MTRACE;
9286 return CMD_SUCCESS;
9287 }
9288
9289 DEFUN (no_debug_mtrace,
9290 no_debug_mtrace_cmd,
9291 "no debug mtrace",
9292 NO_STR
9293 DEBUG_STR
9294 DEBUG_MTRACE_STR)
9295 {
9296 PIM_DONT_DEBUG_MTRACE;
9297 return CMD_SUCCESS;
9298 }
9299
9300 DEFUN (debug_bsm,
9301 debug_bsm_cmd,
9302 "debug pim bsm",
9303 DEBUG_STR
9304 DEBUG_PIM_STR
9305 DEBUG_PIM_BSM_STR)
9306 {
9307 PIM_DO_DEBUG_BSM;
9308 return CMD_SUCCESS;
9309 }
9310
9311 DEFUN (no_debug_bsm,
9312 no_debug_bsm_cmd,
9313 "no debug pim bsm",
9314 NO_STR
9315 DEBUG_STR
9316 DEBUG_PIM_STR
9317 DEBUG_PIM_BSM_STR)
9318 {
9319 PIM_DONT_DEBUG_BSM;
9320 return CMD_SUCCESS;
9321 }
9322
9323
9324 DEFUN_NOSH (show_debugging_pim,
9325 show_debugging_pim_cmd,
9326 "show debugging [pim]",
9327 SHOW_STR
9328 DEBUG_STR
9329 PIM_STR)
9330 {
9331 vty_out(vty, "PIM debugging status\n");
9332
9333 pim_debug_config_write(vty);
9334
9335 return CMD_SUCCESS;
9336 }
9337
9338 DEFUN (interface_pim_use_source,
9339 interface_pim_use_source_cmd,
9340 "ip pim use-source A.B.C.D",
9341 IP_STR
9342 PIM_STR
9343 "Configure primary IP address\n"
9344 "source ip address\n")
9345 {
9346 nb_cli_enqueue_change(vty, "./use-source", NB_OP_MODIFY, argv[3]->arg);
9347
9348 return nb_cli_apply_changes(vty,
9349 "./frr-pim:pim/address-family[address-family='%s']",
9350 "frr-routing:ipv4");
9351 }
9352
9353 DEFUN (interface_no_pim_use_source,
9354 interface_no_pim_use_source_cmd,
9355 "no ip pim use-source [A.B.C.D]",
9356 NO_STR
9357 IP_STR
9358 PIM_STR
9359 "Delete source IP address\n"
9360 "source ip address\n")
9361 {
9362 nb_cli_enqueue_change(vty, "./use-source", NB_OP_MODIFY, "0.0.0.0");
9363
9364 return nb_cli_apply_changes(vty,
9365 "./frr-pim:pim/address-family[address-family='%s']",
9366 "frr-routing:ipv4");
9367 }
9368
9369 DEFPY (ip_pim_bfd,
9370 ip_pim_bfd_cmd,
9371 "ip pim bfd [profile BFDPROF$prof]",
9372 IP_STR
9373 PIM_STR
9374 "Enables BFD support\n"
9375 "Use BFD profile\n"
9376 "Use BFD profile name\n")
9377 {
9378 const struct lyd_node *igmp_enable_dnode;
9379
9380 igmp_enable_dnode =
9381 yang_dnode_getf(vty->candidate_config->dnode,
9382 "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH);
9383 if (!igmp_enable_dnode)
9384 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9385 "true");
9386 else {
9387 if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
9388 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9389 "true");
9390 }
9391
9392 nb_cli_enqueue_change(vty, "./bfd", NB_OP_CREATE, NULL);
9393 if (prof)
9394 nb_cli_enqueue_change(vty, "./bfd/profile", NB_OP_MODIFY, prof);
9395
9396 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9397 }
9398
9399 DEFPY(no_ip_pim_bfd_profile, no_ip_pim_bfd_profile_cmd,
9400 "no ip pim bfd profile [BFDPROF]",
9401 NO_STR
9402 IP_STR
9403 PIM_STR
9404 "Enables BFD support\n"
9405 "Disable BFD profile\n"
9406 "BFD Profile name\n")
9407 {
9408 nb_cli_enqueue_change(vty, "./bfd/profile", NB_OP_DESTROY, NULL);
9409
9410 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9411 }
9412
9413 DEFUN (no_ip_pim_bfd,
9414 no_ip_pim_bfd_cmd,
9415 "no ip pim bfd",
9416 NO_STR
9417 IP_STR
9418 PIM_STR
9419 "Disables BFD support\n")
9420 {
9421 nb_cli_enqueue_change(vty, "./bfd", NB_OP_DESTROY, NULL);
9422
9423 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9424 }
9425
9426 DEFUN (ip_pim_bsm,
9427 ip_pim_bsm_cmd,
9428 "ip pim bsm",
9429 IP_STR
9430 PIM_STR
9431 "Enables BSM support on the interface\n")
9432 {
9433 const struct lyd_node *igmp_enable_dnode;
9434
9435 igmp_enable_dnode =
9436 yang_dnode_getf(vty->candidate_config->dnode,
9437 "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH);
9438 if (!igmp_enable_dnode)
9439 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9440 "true");
9441 else {
9442 if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
9443 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9444 "true");
9445 }
9446
9447 nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "true");
9448
9449 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9450 }
9451
9452 DEFUN (no_ip_pim_bsm,
9453 no_ip_pim_bsm_cmd,
9454 "no ip pim bsm",
9455 NO_STR
9456 IP_STR
9457 PIM_STR
9458 "Disables BSM support\n")
9459 {
9460 nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "false");
9461
9462 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9463 }
9464
9465 DEFUN (ip_pim_ucast_bsm,
9466 ip_pim_ucast_bsm_cmd,
9467 "ip pim unicast-bsm",
9468 IP_STR
9469 PIM_STR
9470 "Accept/Send unicast BSM on the interface\n")
9471 {
9472 const struct lyd_node *igmp_enable_dnode;
9473
9474 igmp_enable_dnode =
9475 yang_dnode_getf(vty->candidate_config->dnode,
9476 "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH);
9477 if (!igmp_enable_dnode)
9478 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9479 "true");
9480 else {
9481 if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
9482 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9483 "true");
9484 }
9485
9486 nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "true");
9487
9488 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9489 }
9490
9491 DEFUN (no_ip_pim_ucast_bsm,
9492 no_ip_pim_ucast_bsm_cmd,
9493 "no ip pim unicast-bsm",
9494 NO_STR
9495 IP_STR
9496 PIM_STR
9497 "Block send/receive unicast BSM on this interface\n")
9498 {
9499 nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "false");
9500
9501 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9502 }
9503
9504 #if HAVE_BFDD > 0
9505 DEFUN_HIDDEN (
9506 ip_pim_bfd_param,
9507 ip_pim_bfd_param_cmd,
9508 "ip pim bfd (2-255) (1-65535) (1-65535)",
9509 IP_STR
9510 PIM_STR
9511 "Enables BFD support\n"
9512 "Detect Multiplier\n"
9513 "Required min receive interval\n"
9514 "Desired min transmit interval\n")
9515 #else
9516 DEFUN(
9517 ip_pim_bfd_param,
9518 ip_pim_bfd_param_cmd,
9519 "ip pim bfd (2-255) (1-65535) (1-65535)",
9520 IP_STR
9521 PIM_STR
9522 "Enables BFD support\n"
9523 "Detect Multiplier\n"
9524 "Required min receive interval\n"
9525 "Desired min transmit interval\n")
9526 #endif /* HAVE_BFDD */
9527 {
9528 int idx_number = 3;
9529 int idx_number_2 = 4;
9530 int idx_number_3 = 5;
9531 const struct lyd_node *igmp_enable_dnode;
9532
9533 igmp_enable_dnode =
9534 yang_dnode_getf(vty->candidate_config->dnode,
9535 "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH);
9536 if (!igmp_enable_dnode)
9537 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9538 "true");
9539 else {
9540 if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
9541 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9542 "true");
9543 }
9544
9545 nb_cli_enqueue_change(vty, "./bfd", NB_OP_CREATE, NULL);
9546 nb_cli_enqueue_change(vty, "./bfd/min-rx-interval", NB_OP_MODIFY,
9547 argv[idx_number_2]->arg);
9548 nb_cli_enqueue_change(vty, "./bfd/min-tx-interval", NB_OP_MODIFY,
9549 argv[idx_number_3]->arg);
9550 nb_cli_enqueue_change(vty, "./bfd/detect_mult", NB_OP_MODIFY,
9551 argv[idx_number]->arg);
9552
9553 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9554 }
9555
9556 #if HAVE_BFDD == 0
9557 ALIAS(no_ip_pim_bfd, no_ip_pim_bfd_param_cmd,
9558 "no ip pim bfd (2-255) (1-65535) (1-65535)",
9559 NO_STR
9560 IP_STR
9561 PIM_STR
9562 "Enables BFD support\n"
9563 "Detect Multiplier\n"
9564 "Required min receive interval\n"
9565 "Desired min transmit interval\n")
9566 #endif /* !HAVE_BFDD */
9567
9568 DEFPY(ip_msdp_peer, ip_msdp_peer_cmd,
9569 "ip msdp peer A.B.C.D$peer source A.B.C.D$source",
9570 IP_STR
9571 CFG_MSDP_STR
9572 "Configure MSDP peer\n"
9573 "Peer IP address\n"
9574 "Source address for TCP connection\n"
9575 "Local IP address\n")
9576 {
9577 const char *vrfname;
9578 char temp_xpath[XPATH_MAXLEN];
9579 char msdp_peer_source_xpath[XPATH_MAXLEN];
9580
9581 vrfname = pim_cli_get_vrf_name(vty);
9582 if (vrfname == NULL)
9583 return CMD_WARNING_CONFIG_FAILED;
9584
9585 snprintf(msdp_peer_source_xpath, sizeof(msdp_peer_source_xpath),
9586 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
9587 "frr-routing:ipv4");
9588 snprintf(temp_xpath, sizeof(temp_xpath),
9589 "/msdp-peer[peer-ip='%s']/source-ip", peer_str);
9590 strlcat(msdp_peer_source_xpath, temp_xpath,
9591 sizeof(msdp_peer_source_xpath));
9592
9593 nb_cli_enqueue_change(vty, msdp_peer_source_xpath, NB_OP_MODIFY,
9594 source_str);
9595
9596 return nb_cli_apply_changes(vty, NULL);
9597 }
9598
9599 DEFPY(ip_msdp_timers, ip_msdp_timers_cmd,
9600 "ip msdp timers (1-65535)$keepalive (1-65535)$holdtime [(1-65535)$connretry]",
9601 IP_STR
9602 CFG_MSDP_STR
9603 "MSDP timers configuration\n"
9604 "Keep alive period (in seconds)\n"
9605 "Hold time period (in seconds)\n"
9606 "Connection retry period (in seconds)\n")
9607 {
9608 const char *vrfname;
9609 char xpath[XPATH_MAXLEN];
9610
9611 vrfname = pim_cli_get_vrf_name(vty);
9612 if (vrfname == NULL)
9613 return CMD_WARNING_CONFIG_FAILED;
9614
9615 snprintf(xpath, sizeof(xpath), FRR_PIM_MSDP_XPATH, "frr-pim:pimd",
9616 "pim", vrfname, "frr-routing:ipv4");
9617 nb_cli_enqueue_change(vty, "./hold-time", NB_OP_MODIFY, holdtime_str);
9618 nb_cli_enqueue_change(vty, "./keep-alive", NB_OP_MODIFY, keepalive_str);
9619 if (connretry_str)
9620 nb_cli_enqueue_change(vty, "./connection-retry", NB_OP_MODIFY,
9621 connretry_str);
9622 else
9623 nb_cli_enqueue_change(vty, "./connection-retry", NB_OP_DESTROY,
9624 NULL);
9625
9626 nb_cli_apply_changes(vty, xpath);
9627
9628 return CMD_SUCCESS;
9629 }
9630
9631 DEFPY(no_ip_msdp_timers, no_ip_msdp_timers_cmd,
9632 "no ip msdp timers [(1-65535) (1-65535) [(1-65535)]]",
9633 NO_STR
9634 IP_STR
9635 CFG_MSDP_STR
9636 "MSDP timers configuration\n"
9637 IGNORED_IN_NO_STR
9638 IGNORED_IN_NO_STR
9639 IGNORED_IN_NO_STR)
9640 {
9641 const char *vrfname;
9642 char xpath[XPATH_MAXLEN];
9643
9644 vrfname = pim_cli_get_vrf_name(vty);
9645 if (vrfname == NULL)
9646 return CMD_WARNING_CONFIG_FAILED;
9647
9648 snprintf(xpath, sizeof(xpath), FRR_PIM_MSDP_XPATH, "frr-pim:pimd",
9649 "pim", vrfname, "frr-routing:ipv4");
9650
9651 nb_cli_enqueue_change(vty, "./hold-time", NB_OP_DESTROY, NULL);
9652 nb_cli_enqueue_change(vty, "./keep-alive", NB_OP_DESTROY, NULL);
9653 nb_cli_enqueue_change(vty, "./connection-retry", NB_OP_DESTROY, NULL);
9654
9655 nb_cli_apply_changes(vty, xpath);
9656
9657 return CMD_SUCCESS;
9658 }
9659
9660 DEFUN (no_ip_msdp_peer,
9661 no_ip_msdp_peer_cmd,
9662 "no ip msdp peer A.B.C.D",
9663 NO_STR
9664 IP_STR
9665 CFG_MSDP_STR
9666 "Delete MSDP peer\n"
9667 "peer ip address\n")
9668 {
9669 const char *vrfname;
9670 char msdp_peer_xpath[XPATH_MAXLEN];
9671 char temp_xpath[XPATH_MAXLEN];
9672
9673 vrfname = pim_cli_get_vrf_name(vty);
9674 if (vrfname == NULL)
9675 return CMD_WARNING_CONFIG_FAILED;
9676
9677 snprintf(msdp_peer_xpath, sizeof(msdp_peer_xpath),
9678 FRR_PIM_AF_XPATH,
9679 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
9680 snprintf(temp_xpath, sizeof(temp_xpath),
9681 "/msdp-peer[peer-ip='%s']",
9682 argv[4]->arg);
9683
9684 strlcat(msdp_peer_xpath, temp_xpath, sizeof(msdp_peer_xpath));
9685
9686 nb_cli_enqueue_change(vty, msdp_peer_xpath, NB_OP_DESTROY, NULL);
9687
9688 return nb_cli_apply_changes(vty, NULL);
9689 }
9690
9691 DEFPY(ip_msdp_mesh_group_member,
9692 ip_msdp_mesh_group_member_cmd,
9693 "ip msdp mesh-group WORD$gname member A.B.C.D$maddr",
9694 IP_STR
9695 CFG_MSDP_STR
9696 "Configure MSDP mesh-group\n"
9697 "Mesh group name\n"
9698 "Mesh group member\n"
9699 "Peer IP address\n")
9700 {
9701 const char *vrfname;
9702 char xpath_value[XPATH_MAXLEN];
9703
9704 vrfname = pim_cli_get_vrf_name(vty);
9705 if (vrfname == NULL)
9706 return CMD_WARNING_CONFIG_FAILED;
9707
9708 /* Create mesh group. */
9709 snprintf(xpath_value, sizeof(xpath_value),
9710 FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']",
9711 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname);
9712 nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL);
9713
9714 /* Create mesh group member. */
9715 strlcat(xpath_value, "/members[address='", sizeof(xpath_value));
9716 strlcat(xpath_value, maddr_str, sizeof(xpath_value));
9717 strlcat(xpath_value, "']", sizeof(xpath_value));
9718 nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL);
9719
9720 return nb_cli_apply_changes(vty, NULL);
9721 }
9722
9723 DEFPY(no_ip_msdp_mesh_group_member,
9724 no_ip_msdp_mesh_group_member_cmd,
9725 "no ip msdp mesh-group WORD$gname member A.B.C.D$maddr",
9726 NO_STR
9727 IP_STR
9728 CFG_MSDP_STR
9729 "Delete MSDP mesh-group member\n"
9730 "Mesh group name\n"
9731 "Mesh group member\n"
9732 "Peer IP address\n")
9733 {
9734 const char *vrfname;
9735 char xpath_value[XPATH_MAXLEN];
9736 char xpath_member_value[XPATH_MAXLEN];
9737
9738 vrfname = pim_cli_get_vrf_name(vty);
9739 if (vrfname == NULL)
9740 return CMD_WARNING_CONFIG_FAILED;
9741
9742 /* Get mesh group base XPath. */
9743 snprintf(xpath_value, sizeof(xpath_value),
9744 FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']",
9745 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname);
9746
9747 if (!yang_dnode_exists(vty->candidate_config->dnode, xpath_value)) {
9748 vty_out(vty, "%% mesh-group does not exist\n");
9749 return CMD_WARNING_CONFIG_FAILED;
9750 }
9751
9752 /* Remove mesh group member. */
9753 strlcpy(xpath_member_value, xpath_value, sizeof(xpath_member_value));
9754 strlcat(xpath_member_value, "/members[address='",
9755 sizeof(xpath_member_value));
9756 strlcat(xpath_member_value, maddr_str, sizeof(xpath_member_value));
9757 strlcat(xpath_member_value, "']", sizeof(xpath_member_value));
9758 if (!yang_dnode_exists(vty->candidate_config->dnode,
9759 xpath_member_value)) {
9760 vty_out(vty, "%% mesh-group member does not exist\n");
9761 return CMD_WARNING_CONFIG_FAILED;
9762 }
9763
9764 nb_cli_enqueue_change(vty, xpath_member_value, NB_OP_DESTROY, NULL);
9765
9766 /*
9767 * If this is the last member, then we must remove the group altogether
9768 * to not break legacy CLI behaviour.
9769 */
9770 pim_cli_legacy_mesh_group_behavior(vty, gname);
9771
9772 return nb_cli_apply_changes(vty, NULL);
9773 }
9774
9775 DEFPY(ip_msdp_mesh_group_source,
9776 ip_msdp_mesh_group_source_cmd,
9777 "ip msdp mesh-group WORD$gname source A.B.C.D$saddr",
9778 IP_STR
9779 CFG_MSDP_STR
9780 "Configure MSDP mesh-group\n"
9781 "Mesh group name\n"
9782 "Mesh group local address\n"
9783 "Source IP address for the TCP connection\n")
9784 {
9785 const char *vrfname;
9786 char xpath_value[XPATH_MAXLEN];
9787
9788 vrfname = pim_cli_get_vrf_name(vty);
9789 if (vrfname == NULL)
9790 return CMD_WARNING_CONFIG_FAILED;
9791
9792 /* Create mesh group. */
9793 snprintf(xpath_value, sizeof(xpath_value),
9794 FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']",
9795 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname);
9796 nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL);
9797
9798 /* Create mesh group source. */
9799 strlcat(xpath_value, "/source", sizeof(xpath_value));
9800 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, saddr_str);
9801
9802 return nb_cli_apply_changes(vty, NULL);
9803 }
9804
9805 DEFPY(no_ip_msdp_mesh_group_source,
9806 no_ip_msdp_mesh_group_source_cmd,
9807 "no ip msdp mesh-group WORD$gname source [A.B.C.D]",
9808 NO_STR
9809 IP_STR
9810 CFG_MSDP_STR
9811 "Delete MSDP mesh-group source\n"
9812 "Mesh group name\n"
9813 "Mesh group source\n"
9814 "Mesh group local address\n")
9815 {
9816 const char *vrfname;
9817 char xpath_value[XPATH_MAXLEN];
9818
9819 vrfname = pim_cli_get_vrf_name(vty);
9820 if (vrfname == NULL)
9821 return CMD_WARNING_CONFIG_FAILED;
9822
9823 /* Get mesh group base XPath. */
9824 snprintf(xpath_value, sizeof(xpath_value),
9825 FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']",
9826 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname);
9827 nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL);
9828
9829 /* Create mesh group source. */
9830 strlcat(xpath_value, "/source", sizeof(xpath_value));
9831 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL);
9832
9833 /*
9834 * If this is the last member, then we must remove the group altogether
9835 * to not break legacy CLI behaviour.
9836 */
9837 pim_cli_legacy_mesh_group_behavior(vty, gname);
9838
9839 return nb_cli_apply_changes(vty, NULL);
9840 }
9841
9842 DEFPY(no_ip_msdp_mesh_group,
9843 no_ip_msdp_mesh_group_cmd,
9844 "no ip msdp mesh-group WORD$gname",
9845 NO_STR
9846 IP_STR
9847 CFG_MSDP_STR
9848 "Delete MSDP mesh-group\n"
9849 "Mesh group name")
9850 {
9851 const char *vrfname;
9852 char xpath_value[XPATH_MAXLEN];
9853
9854 vrfname = pim_cli_get_vrf_name(vty);
9855 if (vrfname == NULL)
9856 return CMD_WARNING_CONFIG_FAILED;
9857
9858 /* Get mesh group base XPath. */
9859 snprintf(xpath_value, sizeof(xpath_value),
9860 FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']",
9861 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname);
9862 if (!yang_dnode_exists(vty->candidate_config->dnode, xpath_value))
9863 return CMD_SUCCESS;
9864
9865 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL);
9866 return nb_cli_apply_changes(vty, NULL);
9867 }
9868
9869 static void ip_msdp_show_mesh_group(struct vty *vty, struct pim_msdp_mg *mg,
9870 struct json_object *json)
9871 {
9872 struct listnode *mbrnode;
9873 struct pim_msdp_mg_mbr *mbr;
9874 char mbr_str[INET_ADDRSTRLEN];
9875 char src_str[INET_ADDRSTRLEN];
9876 char state_str[PIM_MSDP_STATE_STRLEN];
9877 enum pim_msdp_peer_state state;
9878 json_object *json_mg_row = NULL;
9879 json_object *json_members = NULL;
9880 json_object *json_row = NULL;
9881
9882 pim_inet4_dump("<source?>", mg->src_ip, src_str, sizeof(src_str));
9883 if (json) {
9884 /* currently there is only one mesh group but we should still
9885 * make
9886 * it a dict with mg-name as key */
9887 json_mg_row = json_object_new_object();
9888 json_object_string_add(json_mg_row, "name",
9889 mg->mesh_group_name);
9890 json_object_string_add(json_mg_row, "source", src_str);
9891 } else {
9892 vty_out(vty, "Mesh group : %s\n", mg->mesh_group_name);
9893 vty_out(vty, " Source : %s\n", src_str);
9894 vty_out(vty, " Member State\n");
9895 }
9896
9897 for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) {
9898 pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str));
9899 if (mbr->mp) {
9900 state = mbr->mp->state;
9901 } else {
9902 state = PIM_MSDP_DISABLED;
9903 }
9904 pim_msdp_state_dump(state, state_str, sizeof(state_str));
9905 if (json) {
9906 json_row = json_object_new_object();
9907 json_object_string_add(json_row, "member", mbr_str);
9908 json_object_string_add(json_row, "state", state_str);
9909 if (!json_members) {
9910 json_members = json_object_new_object();
9911 json_object_object_add(json_mg_row, "members",
9912 json_members);
9913 }
9914 json_object_object_add(json_members, mbr_str, json_row);
9915 } else {
9916 vty_out(vty, " %-15s %11s\n", mbr_str, state_str);
9917 }
9918 }
9919
9920 if (json)
9921 json_object_object_add(json, mg->mesh_group_name, json_mg_row);
9922 }
9923
9924 DEFUN (show_ip_msdp_mesh_group,
9925 show_ip_msdp_mesh_group_cmd,
9926 "show ip msdp [vrf NAME] mesh-group [json]",
9927 SHOW_STR
9928 IP_STR
9929 MSDP_STR
9930 VRF_CMD_HELP_STR
9931 "MSDP mesh-group information\n"
9932 JSON_STR)
9933 {
9934 bool uj = use_json(argc, argv);
9935 int idx = 2;
9936 struct pim_msdp_mg *mg;
9937 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
9938 struct pim_instance *pim = vrf->info;
9939 struct json_object *json = NULL;
9940
9941 if (!vrf)
9942 return CMD_WARNING;
9943
9944 /* Quick case: list is empty. */
9945 if (SLIST_EMPTY(&pim->msdp.mglist)) {
9946 if (uj)
9947 vty_out(vty, "{}\n");
9948
9949 return CMD_SUCCESS;
9950 }
9951
9952 if (uj)
9953 json = json_object_new_object();
9954
9955 SLIST_FOREACH (mg, &pim->msdp.mglist, mg_entry)
9956 ip_msdp_show_mesh_group(vty, mg, json);
9957
9958 if (uj) {
9959 vty_out(vty, "%s\n",
9960 json_object_to_json_string_ext(
9961 json, JSON_C_TO_STRING_PRETTY));
9962 json_object_free(json);
9963 }
9964
9965 return CMD_SUCCESS;
9966 }
9967
9968 DEFUN (show_ip_msdp_mesh_group_vrf_all,
9969 show_ip_msdp_mesh_group_vrf_all_cmd,
9970 "show ip msdp vrf all mesh-group [json]",
9971 SHOW_STR
9972 IP_STR
9973 MSDP_STR
9974 VRF_CMD_HELP_STR
9975 "MSDP mesh-group information\n"
9976 JSON_STR)
9977 {
9978 bool uj = use_json(argc, argv);
9979 struct json_object *json = NULL, *vrf_json = NULL;
9980 struct pim_instance *pim;
9981 struct pim_msdp_mg *mg;
9982 struct vrf *vrf;
9983
9984 if (uj)
9985 json = json_object_new_object();
9986
9987 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
9988 if (uj) {
9989 vrf_json = json_object_new_object();
9990 json_object_object_add(json, vrf->name, vrf_json);
9991 } else
9992 vty_out(vty, "VRF: %s\n", vrf->name);
9993
9994 pim = vrf->info;
9995 SLIST_FOREACH (mg, &pim->msdp.mglist, mg_entry)
9996 ip_msdp_show_mesh_group(vty, mg, vrf_json);
9997 }
9998
9999 if (uj) {
10000 vty_out(vty, "%s\n",
10001 json_object_to_json_string_ext(
10002 json, JSON_C_TO_STRING_PRETTY));
10003 json_object_free(json);
10004 }
10005
10006 return CMD_SUCCESS;
10007 }
10008
10009 static void ip_msdp_show_peers(struct pim_instance *pim, struct vty *vty,
10010 bool uj)
10011 {
10012 struct listnode *mpnode;
10013 struct pim_msdp_peer *mp;
10014 char peer_str[INET_ADDRSTRLEN];
10015 char local_str[INET_ADDRSTRLEN];
10016 char state_str[PIM_MSDP_STATE_STRLEN];
10017 char timebuf[PIM_MSDP_UPTIME_STRLEN];
10018 int64_t now;
10019 json_object *json = NULL;
10020 json_object *json_row = NULL;
10021
10022
10023 if (uj) {
10024 json = json_object_new_object();
10025 } else {
10026 vty_out(vty,
10027 "Peer Local State Uptime SaCnt\n");
10028 }
10029
10030 for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, mpnode, mp)) {
10031 if (mp->state == PIM_MSDP_ESTABLISHED) {
10032 now = pim_time_monotonic_sec();
10033 pim_time_uptime(timebuf, sizeof(timebuf),
10034 now - mp->uptime);
10035 } else {
10036 strlcpy(timebuf, "-", sizeof(timebuf));
10037 }
10038 pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
10039 pim_inet4_dump("<local?>", mp->local, local_str,
10040 sizeof(local_str));
10041 pim_msdp_state_dump(mp->state, state_str, sizeof(state_str));
10042 if (uj) {
10043 json_row = json_object_new_object();
10044 json_object_string_add(json_row, "peer", peer_str);
10045 json_object_string_add(json_row, "local", local_str);
10046 json_object_string_add(json_row, "state", state_str);
10047 json_object_string_add(json_row, "upTime", timebuf);
10048 json_object_int_add(json_row, "saCount", mp->sa_cnt);
10049 json_object_object_add(json, peer_str, json_row);
10050 } else {
10051 vty_out(vty, "%-15s %15s %11s %8s %6d\n", peer_str,
10052 local_str, state_str, timebuf, mp->sa_cnt);
10053 }
10054 }
10055
10056 if (uj) {
10057 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10058 json, JSON_C_TO_STRING_PRETTY));
10059 json_object_free(json);
10060 }
10061 }
10062
10063 static void ip_msdp_show_peers_detail(struct pim_instance *pim, struct vty *vty,
10064 const char *peer, bool uj)
10065 {
10066 struct listnode *mpnode;
10067 struct pim_msdp_peer *mp;
10068 char peer_str[INET_ADDRSTRLEN];
10069 char local_str[INET_ADDRSTRLEN];
10070 char state_str[PIM_MSDP_STATE_STRLEN];
10071 char timebuf[PIM_MSDP_UPTIME_STRLEN];
10072 char katimer[PIM_MSDP_TIMER_STRLEN];
10073 char crtimer[PIM_MSDP_TIMER_STRLEN];
10074 char holdtimer[PIM_MSDP_TIMER_STRLEN];
10075 int64_t now;
10076 json_object *json = NULL;
10077 json_object *json_row = NULL;
10078
10079 if (uj) {
10080 json = json_object_new_object();
10081 }
10082
10083 for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, mpnode, mp)) {
10084 pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
10085 if (strcmp(peer, "detail") && strcmp(peer, peer_str))
10086 continue;
10087
10088 if (mp->state == PIM_MSDP_ESTABLISHED) {
10089 now = pim_time_monotonic_sec();
10090 pim_time_uptime(timebuf, sizeof(timebuf),
10091 now - mp->uptime);
10092 } else {
10093 strlcpy(timebuf, "-", sizeof(timebuf));
10094 }
10095 pim_inet4_dump("<local?>", mp->local, local_str,
10096 sizeof(local_str));
10097 pim_msdp_state_dump(mp->state, state_str, sizeof(state_str));
10098 pim_time_timer_to_hhmmss(katimer, sizeof(katimer),
10099 mp->ka_timer);
10100 pim_time_timer_to_hhmmss(crtimer, sizeof(crtimer),
10101 mp->cr_timer);
10102 pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer),
10103 mp->hold_timer);
10104
10105 if (uj) {
10106 json_row = json_object_new_object();
10107 json_object_string_add(json_row, "peer", peer_str);
10108 json_object_string_add(json_row, "local", local_str);
10109 if (mp->flags & PIM_MSDP_PEERF_IN_GROUP)
10110 json_object_string_add(json_row,
10111 "meshGroupName",
10112 mp->mesh_group_name);
10113 json_object_string_add(json_row, "state", state_str);
10114 json_object_string_add(json_row, "upTime", timebuf);
10115 json_object_string_add(json_row, "keepAliveTimer",
10116 katimer);
10117 json_object_string_add(json_row, "connRetryTimer",
10118 crtimer);
10119 json_object_string_add(json_row, "holdTimer",
10120 holdtimer);
10121 json_object_string_add(json_row, "lastReset",
10122 mp->last_reset);
10123 json_object_int_add(json_row, "connAttempts",
10124 mp->conn_attempts);
10125 json_object_int_add(json_row, "establishedChanges",
10126 mp->est_flaps);
10127 json_object_int_add(json_row, "saCount", mp->sa_cnt);
10128 json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt);
10129 json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt);
10130 json_object_int_add(json_row, "saSent", mp->sa_tx_cnt);
10131 json_object_int_add(json_row, "saRcvd", mp->sa_rx_cnt);
10132 json_object_object_add(json, peer_str, json_row);
10133 } else {
10134 vty_out(vty, "Peer : %s\n", peer_str);
10135 vty_out(vty, " Local : %s\n", local_str);
10136 if (mp->flags & PIM_MSDP_PEERF_IN_GROUP)
10137 vty_out(vty, " Mesh Group : %s\n",
10138 mp->mesh_group_name);
10139 vty_out(vty, " State : %s\n", state_str);
10140 vty_out(vty, " Uptime : %s\n", timebuf);
10141
10142 vty_out(vty, " Keepalive Timer : %s\n", katimer);
10143 vty_out(vty, " Conn Retry Timer : %s\n", crtimer);
10144 vty_out(vty, " Hold Timer : %s\n", holdtimer);
10145 vty_out(vty, " Last Reset : %s\n",
10146 mp->last_reset);
10147 vty_out(vty, " Conn Attempts : %d\n",
10148 mp->conn_attempts);
10149 vty_out(vty, " Established Changes : %d\n",
10150 mp->est_flaps);
10151 vty_out(vty, " SA Count : %d\n",
10152 mp->sa_cnt);
10153 vty_out(vty, " Statistics :\n");
10154 vty_out(vty,
10155 " Sent Rcvd\n");
10156 vty_out(vty, " Keepalives : %10d %10d\n",
10157 mp->ka_tx_cnt, mp->ka_rx_cnt);
10158 vty_out(vty, " SAs : %10d %10d\n",
10159 mp->sa_tx_cnt, mp->sa_rx_cnt);
10160 vty_out(vty, "\n");
10161 }
10162 }
10163
10164 if (uj) {
10165 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10166 json, JSON_C_TO_STRING_PRETTY));
10167 json_object_free(json);
10168 }
10169 }
10170
10171 DEFUN (show_ip_msdp_peer_detail,
10172 show_ip_msdp_peer_detail_cmd,
10173 "show ip msdp [vrf NAME] peer [detail|A.B.C.D] [json]",
10174 SHOW_STR
10175 IP_STR
10176 MSDP_STR
10177 VRF_CMD_HELP_STR
10178 "MSDP peer information\n"
10179 "Detailed output\n"
10180 "peer ip address\n"
10181 JSON_STR)
10182 {
10183 bool uj = use_json(argc, argv);
10184 int idx = 2;
10185 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10186
10187 if (!vrf)
10188 return CMD_WARNING;
10189
10190 char *arg = NULL;
10191
10192 if (argv_find(argv, argc, "detail", &idx))
10193 arg = argv[idx]->text;
10194 else if (argv_find(argv, argc, "A.B.C.D", &idx))
10195 arg = argv[idx]->arg;
10196
10197 if (arg)
10198 ip_msdp_show_peers_detail(vrf->info, vty, argv[idx]->arg, uj);
10199 else
10200 ip_msdp_show_peers(vrf->info, vty, uj);
10201
10202 return CMD_SUCCESS;
10203 }
10204
10205 DEFUN (show_ip_msdp_peer_detail_vrf_all,
10206 show_ip_msdp_peer_detail_vrf_all_cmd,
10207 "show ip msdp vrf all peer [detail|A.B.C.D] [json]",
10208 SHOW_STR
10209 IP_STR
10210 MSDP_STR
10211 VRF_CMD_HELP_STR
10212 "MSDP peer information\n"
10213 "Detailed output\n"
10214 "peer ip address\n"
10215 JSON_STR)
10216 {
10217 int idx = 2;
10218 bool uj = use_json(argc, argv);
10219 struct vrf *vrf;
10220 bool first = true;
10221
10222 if (uj)
10223 vty_out(vty, "{ ");
10224 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
10225 if (uj) {
10226 if (!first)
10227 vty_out(vty, ", ");
10228 vty_out(vty, " \"%s\": ", vrf->name);
10229 first = false;
10230 } else
10231 vty_out(vty, "VRF: %s\n", vrf->name);
10232 if (argv_find(argv, argc, "detail", &idx)
10233 || argv_find(argv, argc, "A.B.C.D", &idx))
10234 ip_msdp_show_peers_detail(vrf->info, vty,
10235 argv[idx]->arg, uj);
10236 else
10237 ip_msdp_show_peers(vrf->info, vty, uj);
10238 }
10239 if (uj)
10240 vty_out(vty, "}\n");
10241
10242 return CMD_SUCCESS;
10243 }
10244
10245 static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty, bool uj)
10246 {
10247 struct listnode *sanode;
10248 struct pim_msdp_sa *sa;
10249 char src_str[INET_ADDRSTRLEN];
10250 char grp_str[INET_ADDRSTRLEN];
10251 char rp_str[INET_ADDRSTRLEN];
10252 char timebuf[PIM_MSDP_UPTIME_STRLEN];
10253 char spt_str[8];
10254 char local_str[8];
10255 int64_t now;
10256 json_object *json = NULL;
10257 json_object *json_group = NULL;
10258 json_object *json_row = NULL;
10259
10260 if (uj) {
10261 json = json_object_new_object();
10262 } else {
10263 vty_out(vty,
10264 "Source Group RP Local SPT Uptime\n");
10265 }
10266
10267 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
10268 now = pim_time_monotonic_sec();
10269 pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime);
10270 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
10271 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
10272 if (sa->flags & PIM_MSDP_SAF_PEER) {
10273 pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
10274 if (sa->up) {
10275 strlcpy(spt_str, "yes", sizeof(spt_str));
10276 } else {
10277 strlcpy(spt_str, "no", sizeof(spt_str));
10278 }
10279 } else {
10280 strlcpy(rp_str, "-", sizeof(rp_str));
10281 strlcpy(spt_str, "-", sizeof(spt_str));
10282 }
10283 if (sa->flags & PIM_MSDP_SAF_LOCAL) {
10284 strlcpy(local_str, "yes", sizeof(local_str));
10285 } else {
10286 strlcpy(local_str, "no", sizeof(local_str));
10287 }
10288 if (uj) {
10289 json_object_object_get_ex(json, grp_str, &json_group);
10290
10291 if (!json_group) {
10292 json_group = json_object_new_object();
10293 json_object_object_add(json, grp_str,
10294 json_group);
10295 }
10296
10297 json_row = json_object_new_object();
10298 json_object_string_add(json_row, "source", src_str);
10299 json_object_string_add(json_row, "group", grp_str);
10300 json_object_string_add(json_row, "rp", rp_str);
10301 json_object_string_add(json_row, "local", local_str);
10302 json_object_string_add(json_row, "sptSetup", spt_str);
10303 json_object_string_add(json_row, "upTime", timebuf);
10304 json_object_object_add(json_group, src_str, json_row);
10305 } else {
10306 vty_out(vty, "%-15s %15s %15s %5c %3c %8s\n",
10307 src_str, grp_str, rp_str, local_str[0],
10308 spt_str[0], timebuf);
10309 }
10310 }
10311
10312 if (uj) {
10313 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10314 json, JSON_C_TO_STRING_PRETTY));
10315 json_object_free(json);
10316 }
10317 }
10318
10319 static void ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa,
10320 const char *src_str,
10321 const char *grp_str, struct vty *vty,
10322 bool uj, json_object *json)
10323 {
10324 char rp_str[INET_ADDRSTRLEN];
10325 char peer_str[INET_ADDRSTRLEN];
10326 char timebuf[PIM_MSDP_UPTIME_STRLEN];
10327 char spt_str[8];
10328 char local_str[8];
10329 char statetimer[PIM_MSDP_TIMER_STRLEN];
10330 int64_t now;
10331 json_object *json_group = NULL;
10332 json_object *json_row = NULL;
10333
10334 now = pim_time_monotonic_sec();
10335 pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime);
10336 if (sa->flags & PIM_MSDP_SAF_PEER) {
10337 pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
10338 pim_inet4_dump("<peer?>", sa->peer, peer_str, sizeof(peer_str));
10339 if (sa->up) {
10340 strlcpy(spt_str, "yes", sizeof(spt_str));
10341 } else {
10342 strlcpy(spt_str, "no", sizeof(spt_str));
10343 }
10344 } else {
10345 strlcpy(rp_str, "-", sizeof(rp_str));
10346 strlcpy(peer_str, "-", sizeof(peer_str));
10347 strlcpy(spt_str, "-", sizeof(spt_str));
10348 }
10349 if (sa->flags & PIM_MSDP_SAF_LOCAL) {
10350 strlcpy(local_str, "yes", sizeof(local_str));
10351 } else {
10352 strlcpy(local_str, "no", sizeof(local_str));
10353 }
10354 pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer),
10355 sa->sa_state_timer);
10356 if (uj) {
10357 json_object_object_get_ex(json, grp_str, &json_group);
10358
10359 if (!json_group) {
10360 json_group = json_object_new_object();
10361 json_object_object_add(json, grp_str, json_group);
10362 }
10363
10364 json_row = json_object_new_object();
10365 json_object_string_add(json_row, "source", src_str);
10366 json_object_string_add(json_row, "group", grp_str);
10367 json_object_string_add(json_row, "rp", rp_str);
10368 json_object_string_add(json_row, "local", local_str);
10369 json_object_string_add(json_row, "sptSetup", spt_str);
10370 json_object_string_add(json_row, "upTime", timebuf);
10371 json_object_string_add(json_row, "stateTimer", statetimer);
10372 json_object_object_add(json_group, src_str, json_row);
10373 } else {
10374 vty_out(vty, "SA : %s\n", sa->sg_str);
10375 vty_out(vty, " RP : %s\n", rp_str);
10376 vty_out(vty, " Peer : %s\n", peer_str);
10377 vty_out(vty, " Local : %s\n", local_str);
10378 vty_out(vty, " SPT Setup : %s\n", spt_str);
10379 vty_out(vty, " Uptime : %s\n", timebuf);
10380 vty_out(vty, " State Timer : %s\n", statetimer);
10381 vty_out(vty, "\n");
10382 }
10383 }
10384
10385 static void ip_msdp_show_sa_detail(struct pim_instance *pim, struct vty *vty,
10386 bool uj)
10387 {
10388 struct listnode *sanode;
10389 struct pim_msdp_sa *sa;
10390 char src_str[INET_ADDRSTRLEN];
10391 char grp_str[INET_ADDRSTRLEN];
10392 json_object *json = NULL;
10393
10394 if (uj) {
10395 json = json_object_new_object();
10396 }
10397
10398 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
10399 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
10400 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
10401 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj,
10402 json);
10403 }
10404
10405 if (uj) {
10406 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10407 json, JSON_C_TO_STRING_PRETTY));
10408 json_object_free(json);
10409 }
10410 }
10411
10412 DEFUN (show_ip_msdp_sa_detail,
10413 show_ip_msdp_sa_detail_cmd,
10414 "show ip msdp [vrf NAME] sa detail [json]",
10415 SHOW_STR
10416 IP_STR
10417 MSDP_STR
10418 VRF_CMD_HELP_STR
10419 "MSDP active-source information\n"
10420 "Detailed output\n"
10421 JSON_STR)
10422 {
10423 bool uj = use_json(argc, argv);
10424 int idx = 2;
10425 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10426
10427 if (!vrf)
10428 return CMD_WARNING;
10429
10430 ip_msdp_show_sa_detail(vrf->info, vty, uj);
10431
10432 return CMD_SUCCESS;
10433 }
10434
10435 DEFUN (show_ip_msdp_sa_detail_vrf_all,
10436 show_ip_msdp_sa_detail_vrf_all_cmd,
10437 "show ip msdp vrf all sa detail [json]",
10438 SHOW_STR
10439 IP_STR
10440 MSDP_STR
10441 VRF_CMD_HELP_STR
10442 "MSDP active-source information\n"
10443 "Detailed output\n"
10444 JSON_STR)
10445 {
10446 bool uj = use_json(argc, argv);
10447 struct vrf *vrf;
10448 bool first = true;
10449
10450 if (uj)
10451 vty_out(vty, "{ ");
10452 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
10453 if (uj) {
10454 if (!first)
10455 vty_out(vty, ", ");
10456 vty_out(vty, " \"%s\": ", vrf->name);
10457 first = false;
10458 } else
10459 vty_out(vty, "VRF: %s\n", vrf->name);
10460 ip_msdp_show_sa_detail(vrf->info, vty, uj);
10461 }
10462 if (uj)
10463 vty_out(vty, "}\n");
10464
10465 return CMD_SUCCESS;
10466 }
10467
10468 static void ip_msdp_show_sa_addr(struct pim_instance *pim, struct vty *vty,
10469 const char *addr, bool uj)
10470 {
10471 struct listnode *sanode;
10472 struct pim_msdp_sa *sa;
10473 char src_str[INET_ADDRSTRLEN];
10474 char grp_str[INET_ADDRSTRLEN];
10475 json_object *json = NULL;
10476
10477 if (uj) {
10478 json = json_object_new_object();
10479 }
10480
10481 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
10482 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
10483 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
10484 if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) {
10485 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty,
10486 uj, json);
10487 }
10488 }
10489
10490 if (uj) {
10491 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10492 json, JSON_C_TO_STRING_PRETTY));
10493 json_object_free(json);
10494 }
10495 }
10496
10497 static void ip_msdp_show_sa_sg(struct pim_instance *pim, struct vty *vty,
10498 const char *src, const char *grp, bool uj)
10499 {
10500 struct listnode *sanode;
10501 struct pim_msdp_sa *sa;
10502 char src_str[INET_ADDRSTRLEN];
10503 char grp_str[INET_ADDRSTRLEN];
10504 json_object *json = NULL;
10505
10506 if (uj) {
10507 json = json_object_new_object();
10508 }
10509
10510 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
10511 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
10512 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
10513 if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) {
10514 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty,
10515 uj, json);
10516 }
10517 }
10518
10519 if (uj) {
10520 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10521 json, JSON_C_TO_STRING_PRETTY));
10522 json_object_free(json);
10523 }
10524 }
10525
10526 DEFUN (show_ip_msdp_sa_sg,
10527 show_ip_msdp_sa_sg_cmd,
10528 "show ip msdp [vrf NAME] sa [A.B.C.D [A.B.C.D]] [json]",
10529 SHOW_STR
10530 IP_STR
10531 MSDP_STR
10532 VRF_CMD_HELP_STR
10533 "MSDP active-source information\n"
10534 "source or group ip\n"
10535 "group ip\n"
10536 JSON_STR)
10537 {
10538 bool uj = use_json(argc, argv);
10539 struct vrf *vrf;
10540 int idx = 2;
10541
10542 vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10543
10544 if (!vrf)
10545 return CMD_WARNING;
10546
10547 char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg
10548 : NULL;
10549 char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx)
10550 ? argv[idx]->arg
10551 : NULL;
10552
10553 if (src_ip && grp_ip)
10554 ip_msdp_show_sa_sg(vrf->info, vty, src_ip, grp_ip, uj);
10555 else if (src_ip)
10556 ip_msdp_show_sa_addr(vrf->info, vty, src_ip, uj);
10557 else
10558 ip_msdp_show_sa(vrf->info, vty, uj);
10559
10560 return CMD_SUCCESS;
10561 }
10562
10563 DEFUN (show_ip_msdp_sa_sg_vrf_all,
10564 show_ip_msdp_sa_sg_vrf_all_cmd,
10565 "show ip msdp vrf all sa [A.B.C.D [A.B.C.D]] [json]",
10566 SHOW_STR
10567 IP_STR
10568 MSDP_STR
10569 VRF_CMD_HELP_STR
10570 "MSDP active-source information\n"
10571 "source or group ip\n"
10572 "group ip\n"
10573 JSON_STR)
10574 {
10575 bool uj = use_json(argc, argv);
10576 struct vrf *vrf;
10577 bool first = true;
10578 int idx = 2;
10579
10580 char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg
10581 : NULL;
10582 char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx)
10583 ? argv[idx]->arg
10584 : NULL;
10585
10586 if (uj)
10587 vty_out(vty, "{ ");
10588 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
10589 if (uj) {
10590 if (!first)
10591 vty_out(vty, ", ");
10592 vty_out(vty, " \"%s\": ", vrf->name);
10593 first = false;
10594 } else
10595 vty_out(vty, "VRF: %s\n", vrf->name);
10596
10597 if (src_ip && grp_ip)
10598 ip_msdp_show_sa_sg(vrf->info, vty, src_ip, grp_ip, uj);
10599 else if (src_ip)
10600 ip_msdp_show_sa_addr(vrf->info, vty, src_ip, uj);
10601 else
10602 ip_msdp_show_sa(vrf->info, vty, uj);
10603 }
10604 if (uj)
10605 vty_out(vty, "}\n");
10606
10607 return CMD_SUCCESS;
10608 }
10609
10610 struct pim_sg_cache_walk_data {
10611 struct vty *vty;
10612 json_object *json;
10613 json_object *json_group;
10614 struct in_addr addr;
10615 bool addr_match;
10616 };
10617
10618 static void pim_show_vxlan_sg_entry(struct pim_vxlan_sg *vxlan_sg,
10619 struct pim_sg_cache_walk_data *cwd)
10620 {
10621 struct vty *vty = cwd->vty;
10622 json_object *json = cwd->json;
10623 char src_str[INET_ADDRSTRLEN];
10624 char grp_str[INET_ADDRSTRLEN];
10625 json_object *json_row;
10626 bool installed = (vxlan_sg->up) ? true : false;
10627 const char *iif_name = vxlan_sg->iif?vxlan_sg->iif->name:"-";
10628 const char *oif_name;
10629
10630 if (pim_vxlan_is_orig_mroute(vxlan_sg))
10631 oif_name = vxlan_sg->orig_oif?vxlan_sg->orig_oif->name:"";
10632 else
10633 oif_name = vxlan_sg->term_oif?vxlan_sg->term_oif->name:"";
10634
10635 if (cwd->addr_match && (vxlan_sg->sg.src.s_addr != cwd->addr.s_addr) &&
10636 (vxlan_sg->sg.grp.s_addr != cwd->addr.s_addr)) {
10637 return;
10638 }
10639 pim_inet4_dump("<src?>", vxlan_sg->sg.src, src_str, sizeof(src_str));
10640 pim_inet4_dump("<grp?>", vxlan_sg->sg.grp, grp_str, sizeof(grp_str));
10641 if (json) {
10642 json_object_object_get_ex(json, grp_str, &cwd->json_group);
10643
10644 if (!cwd->json_group) {
10645 cwd->json_group = json_object_new_object();
10646 json_object_object_add(json, grp_str,
10647 cwd->json_group);
10648 }
10649
10650 json_row = json_object_new_object();
10651 json_object_string_add(json_row, "source", src_str);
10652 json_object_string_add(json_row, "group", grp_str);
10653 json_object_string_add(json_row, "input", iif_name);
10654 json_object_string_add(json_row, "output", oif_name);
10655 if (installed)
10656 json_object_boolean_true_add(json_row, "installed");
10657 else
10658 json_object_boolean_false_add(json_row, "installed");
10659 json_object_object_add(cwd->json_group, src_str, json_row);
10660 } else {
10661 vty_out(vty, "%-15s %-15s %-15s %-15s %-5s\n",
10662 src_str, grp_str, iif_name, oif_name,
10663 installed?"I":"");
10664 }
10665 }
10666
10667 static void pim_show_vxlan_sg_hash_entry(struct hash_bucket *bucket, void *arg)
10668 {
10669 pim_show_vxlan_sg_entry((struct pim_vxlan_sg *)bucket->data,
10670 (struct pim_sg_cache_walk_data *)arg);
10671 }
10672
10673 static void pim_show_vxlan_sg(struct pim_instance *pim,
10674 struct vty *vty, bool uj)
10675 {
10676 json_object *json = NULL;
10677 struct pim_sg_cache_walk_data cwd;
10678
10679 if (uj) {
10680 json = json_object_new_object();
10681 } else {
10682 vty_out(vty, "Codes: I -> installed\n");
10683 vty_out(vty,
10684 "Source Group Input Output Flags\n");
10685 }
10686
10687 memset(&cwd, 0, sizeof(cwd));
10688 cwd.vty = vty;
10689 cwd.json = json;
10690 hash_iterate(pim->vxlan.sg_hash, pim_show_vxlan_sg_hash_entry, &cwd);
10691
10692 if (uj) {
10693 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10694 json, JSON_C_TO_STRING_PRETTY));
10695 json_object_free(json);
10696 }
10697 }
10698
10699 static void pim_show_vxlan_sg_match_addr(struct pim_instance *pim,
10700 struct vty *vty, char *addr_str,
10701 bool uj)
10702 {
10703 json_object *json = NULL;
10704 struct pim_sg_cache_walk_data cwd;
10705 int result = 0;
10706
10707 memset(&cwd, 0, sizeof(cwd));
10708 result = inet_pton(AF_INET, addr_str, &cwd.addr);
10709 if (result <= 0) {
10710 vty_out(vty, "Bad address %s: errno=%d: %s\n", addr_str,
10711 errno, safe_strerror(errno));
10712 return;
10713 }
10714
10715 if (uj) {
10716 json = json_object_new_object();
10717 } else {
10718 vty_out(vty, "Codes: I -> installed\n");
10719 vty_out(vty,
10720 "Source Group Input Output Flags\n");
10721 }
10722
10723 cwd.vty = vty;
10724 cwd.json = json;
10725 cwd.addr_match = true;
10726 hash_iterate(pim->vxlan.sg_hash, pim_show_vxlan_sg_hash_entry, &cwd);
10727
10728 if (uj) {
10729 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10730 json, JSON_C_TO_STRING_PRETTY));
10731 json_object_free(json);
10732 }
10733 }
10734
10735 static void pim_show_vxlan_sg_one(struct pim_instance *pim,
10736 struct vty *vty, char *src_str, char *grp_str,
10737 bool uj)
10738 {
10739 json_object *json = NULL;
10740 struct prefix_sg sg;
10741 int result = 0;
10742 struct pim_vxlan_sg *vxlan_sg;
10743 const char *iif_name;
10744 bool installed;
10745 const char *oif_name;
10746
10747 result = inet_pton(AF_INET, src_str, &sg.src);
10748 if (result <= 0) {
10749 vty_out(vty, "Bad src address %s: errno=%d: %s\n", src_str,
10750 errno, safe_strerror(errno));
10751 return;
10752 }
10753 result = inet_pton(AF_INET, grp_str, &sg.grp);
10754 if (result <= 0) {
10755 vty_out(vty, "Bad grp address %s: errno=%d: %s\n", grp_str,
10756 errno, safe_strerror(errno));
10757 return;
10758 }
10759
10760 sg.family = AF_INET;
10761 sg.prefixlen = IPV4_MAX_BITLEN;
10762 if (uj)
10763 json = json_object_new_object();
10764
10765 vxlan_sg = pim_vxlan_sg_find(pim, &sg);
10766 if (vxlan_sg) {
10767 installed = (vxlan_sg->up) ? true : false;
10768 iif_name = vxlan_sg->iif?vxlan_sg->iif->name:"-";
10769
10770 if (pim_vxlan_is_orig_mroute(vxlan_sg))
10771 oif_name =
10772 vxlan_sg->orig_oif?vxlan_sg->orig_oif->name:"";
10773 else
10774 oif_name =
10775 vxlan_sg->term_oif?vxlan_sg->term_oif->name:"";
10776
10777 if (uj) {
10778 json_object_string_add(json, "source", src_str);
10779 json_object_string_add(json, "group", grp_str);
10780 json_object_string_add(json, "input", iif_name);
10781 json_object_string_add(json, "output", oif_name);
10782 if (installed)
10783 json_object_boolean_true_add(json, "installed");
10784 else
10785 json_object_boolean_false_add(json,
10786 "installed");
10787 } else {
10788 vty_out(vty, "SG : %s\n", vxlan_sg->sg_str);
10789 vty_out(vty, " Input : %s\n", iif_name);
10790 vty_out(vty, " Output : %s\n", oif_name);
10791 vty_out(vty, " installed : %s\n",
10792 installed?"yes":"no");
10793 }
10794 }
10795
10796 if (uj) {
10797 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10798 json, JSON_C_TO_STRING_PRETTY));
10799 json_object_free(json);
10800 }
10801 }
10802
10803 DEFUN (show_ip_pim_vxlan_sg,
10804 show_ip_pim_vxlan_sg_cmd,
10805 "show ip pim [vrf NAME] vxlan-groups [A.B.C.D [A.B.C.D]] [json]",
10806 SHOW_STR
10807 IP_STR
10808 PIM_STR
10809 VRF_CMD_HELP_STR
10810 "VxLAN BUM groups\n"
10811 "source or group ip\n"
10812 "group ip\n"
10813 JSON_STR)
10814 {
10815 bool uj = use_json(argc, argv);
10816 struct vrf *vrf;
10817 int idx = 2;
10818
10819 vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10820
10821 if (!vrf)
10822 return CMD_WARNING;
10823
10824 char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ?
10825 argv[idx++]->arg:NULL;
10826 char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx) ?
10827 argv[idx]->arg:NULL;
10828
10829 if (src_ip && grp_ip)
10830 pim_show_vxlan_sg_one(vrf->info, vty, src_ip, grp_ip, uj);
10831 else if (src_ip)
10832 pim_show_vxlan_sg_match_addr(vrf->info, vty, src_ip, uj);
10833 else
10834 pim_show_vxlan_sg(vrf->info, vty, uj);
10835
10836 return CMD_SUCCESS;
10837 }
10838
10839 static void pim_show_vxlan_sg_work(struct pim_instance *pim,
10840 struct vty *vty, bool uj)
10841 {
10842 json_object *json = NULL;
10843 struct pim_sg_cache_walk_data cwd;
10844 struct listnode *node;
10845 struct pim_vxlan_sg *vxlan_sg;
10846
10847 if (uj) {
10848 json = json_object_new_object();
10849 } else {
10850 vty_out(vty, "Codes: I -> installed\n");
10851 vty_out(vty,
10852 "Source Group Input Flags\n");
10853 }
10854
10855 memset(&cwd, 0, sizeof(cwd));
10856 cwd.vty = vty;
10857 cwd.json = json;
10858 for (ALL_LIST_ELEMENTS_RO(pim_vxlan_p->work_list, node, vxlan_sg))
10859 pim_show_vxlan_sg_entry(vxlan_sg, &cwd);
10860
10861 if (uj) {
10862 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10863 json, JSON_C_TO_STRING_PRETTY));
10864 json_object_free(json);
10865 }
10866 }
10867
10868 DEFUN_HIDDEN (show_ip_pim_vxlan_sg_work,
10869 show_ip_pim_vxlan_sg_work_cmd,
10870 "show ip pim [vrf NAME] vxlan-work [json]",
10871 SHOW_STR
10872 IP_STR
10873 PIM_STR
10874 VRF_CMD_HELP_STR
10875 "VxLAN work list\n"
10876 JSON_STR)
10877 {
10878 bool uj = use_json(argc, argv);
10879 struct vrf *vrf;
10880 int idx = 2;
10881
10882 vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10883
10884 if (!vrf)
10885 return CMD_WARNING;
10886
10887 pim_show_vxlan_sg_work(vrf->info, vty, uj);
10888
10889 return CMD_SUCCESS;
10890 }
10891
10892 DEFUN_HIDDEN (no_ip_pim_mlag,
10893 no_ip_pim_mlag_cmd,
10894 "no ip pim mlag",
10895 NO_STR
10896 IP_STR
10897 PIM_STR
10898 "MLAG\n")
10899 {
10900 char mlag_xpath[XPATH_MAXLEN];
10901
10902 snprintf(mlag_xpath, sizeof(mlag_xpath), FRR_PIM_AF_XPATH,
10903 "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
10904 strlcat(mlag_xpath, "/mlag", sizeof(mlag_xpath));
10905
10906 nb_cli_enqueue_change(vty, mlag_xpath, NB_OP_DESTROY, NULL);
10907
10908
10909 return nb_cli_apply_changes(vty, NULL);
10910 }
10911
10912 DEFUN_HIDDEN (ip_pim_mlag,
10913 ip_pim_mlag_cmd,
10914 "ip pim mlag INTERFACE role [primary|secondary] state [up|down] addr A.B.C.D",
10915 IP_STR
10916 PIM_STR
10917 "MLAG\n"
10918 "peerlink sub interface\n"
10919 "MLAG role\n"
10920 "MLAG role primary\n"
10921 "MLAG role secondary\n"
10922 "peer session state\n"
10923 "peer session state up\n"
10924 "peer session state down\n"
10925 "configure PIP\n"
10926 "unique ip address\n")
10927 {
10928 int idx;
10929 char mlag_peerlink_rif_xpath[XPATH_MAXLEN];
10930 char mlag_my_role_xpath[XPATH_MAXLEN];
10931 char mlag_peer_state_xpath[XPATH_MAXLEN];
10932 char mlag_reg_address_xpath[XPATH_MAXLEN];
10933
10934 snprintf(mlag_peerlink_rif_xpath, sizeof(mlag_peerlink_rif_xpath),
10935 FRR_PIM_AF_XPATH,
10936 "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
10937 strlcat(mlag_peerlink_rif_xpath, "/mlag/peerlink-rif",
10938 sizeof(mlag_peerlink_rif_xpath));
10939
10940 idx = 3;
10941 nb_cli_enqueue_change(vty, mlag_peerlink_rif_xpath, NB_OP_MODIFY,
10942 argv[idx]->arg);
10943
10944 snprintf(mlag_my_role_xpath, sizeof(mlag_my_role_xpath),
10945 FRR_PIM_AF_XPATH,
10946 "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
10947 strlcat(mlag_my_role_xpath, "/mlag/my-role",
10948 sizeof(mlag_my_role_xpath));
10949
10950 idx += 2;
10951 if (!strcmp(argv[idx]->arg, "primary")) {
10952 nb_cli_enqueue_change(vty, mlag_my_role_xpath, NB_OP_MODIFY,
10953 "MLAG_ROLE_PRIMARY");
10954
10955 } else if (!strcmp(argv[idx]->arg, "secondary")) {
10956 nb_cli_enqueue_change(vty, mlag_my_role_xpath, NB_OP_MODIFY,
10957 "MLAG_ROLE_SECONDARY");
10958
10959 } else {
10960 vty_out(vty, "unknown MLAG role %s\n", argv[idx]->arg);
10961 return CMD_WARNING;
10962 }
10963
10964 snprintf(mlag_peer_state_xpath, sizeof(mlag_peer_state_xpath),
10965 FRR_PIM_AF_XPATH,
10966 "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
10967 strlcat(mlag_peer_state_xpath, "/mlag/peer-state",
10968 sizeof(mlag_peer_state_xpath));
10969
10970 idx += 2;
10971 if (!strcmp(argv[idx]->arg, "up")) {
10972 nb_cli_enqueue_change(vty, mlag_peer_state_xpath, NB_OP_MODIFY,
10973 "true");
10974
10975 } else if (strcmp(argv[idx]->arg, "down")) {
10976 nb_cli_enqueue_change(vty, mlag_peer_state_xpath, NB_OP_MODIFY,
10977 "false");
10978
10979 } else {
10980 vty_out(vty, "unknown MLAG state %s\n", argv[idx]->arg);
10981 return CMD_WARNING;
10982 }
10983
10984 snprintf(mlag_reg_address_xpath, sizeof(mlag_reg_address_xpath),
10985 FRR_PIM_AF_XPATH,
10986 "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
10987 strlcat(mlag_reg_address_xpath, "/mlag/reg-address",
10988 sizeof(mlag_reg_address_xpath));
10989
10990 idx += 2;
10991 nb_cli_enqueue_change(vty, mlag_reg_address_xpath, NB_OP_MODIFY,
10992 argv[idx]->arg);
10993
10994 return nb_cli_apply_changes(vty, NULL);
10995 }
10996
10997 void pim_cmd_init(void)
10998 {
10999 if_cmd_init(pim_interface_config_write);
11000
11001 install_node(&debug_node);
11002
11003 install_element(ENABLE_NODE, &pim_test_sg_keepalive_cmd);
11004
11005 install_element(CONFIG_NODE, &ip_pim_rp_cmd);
11006 install_element(VRF_NODE, &ip_pim_rp_cmd);
11007 install_element(CONFIG_NODE, &no_ip_pim_rp_cmd);
11008 install_element(VRF_NODE, &no_ip_pim_rp_cmd);
11009 install_element(CONFIG_NODE, &ip_pim_rp_prefix_list_cmd);
11010 install_element(VRF_NODE, &ip_pim_rp_prefix_list_cmd);
11011 install_element(CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd);
11012 install_element(VRF_NODE, &no_ip_pim_rp_prefix_list_cmd);
11013 install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd);
11014 install_element(VRF_NODE, &no_ip_pim_ssm_prefix_list_cmd);
11015 install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
11016 install_element(VRF_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
11017 install_element(CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd);
11018 install_element(VRF_NODE, &ip_pim_ssm_prefix_list_cmd);
11019 install_element(CONFIG_NODE, &ip_pim_register_suppress_cmd);
11020 install_element(CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
11021 install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd);
11022 install_element(VRF_NODE, &ip_pim_spt_switchover_infinity_cmd);
11023 install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
11024 install_element(VRF_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
11025 install_element(CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
11026 install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
11027 install_element(CONFIG_NODE,
11028 &no_ip_pim_spt_switchover_infinity_plist_cmd);
11029 install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd);
11030 install_element(CONFIG_NODE, &pim_register_accept_list_cmd);
11031 install_element(VRF_NODE, &pim_register_accept_list_cmd);
11032 install_element(CONFIG_NODE, &ip_pim_joinprune_time_cmd);
11033 install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
11034 install_element(CONFIG_NODE, &ip_pim_keep_alive_cmd);
11035 install_element(VRF_NODE, &ip_pim_keep_alive_cmd);
11036 install_element(CONFIG_NODE, &ip_pim_rp_keep_alive_cmd);
11037 install_element(VRF_NODE, &ip_pim_rp_keep_alive_cmd);
11038 install_element(CONFIG_NODE, &no_ip_pim_keep_alive_cmd);
11039 install_element(VRF_NODE, &no_ip_pim_keep_alive_cmd);
11040 install_element(CONFIG_NODE, &no_ip_pim_rp_keep_alive_cmd);
11041 install_element(VRF_NODE, &no_ip_pim_rp_keep_alive_cmd);
11042 install_element(CONFIG_NODE, &ip_pim_packets_cmd);
11043 install_element(CONFIG_NODE, &no_ip_pim_packets_cmd);
11044 install_element(CONFIG_NODE, &ip_pim_v6_secondary_cmd);
11045 install_element(VRF_NODE, &ip_pim_v6_secondary_cmd);
11046 install_element(CONFIG_NODE, &no_ip_pim_v6_secondary_cmd);
11047 install_element(VRF_NODE, &no_ip_pim_v6_secondary_cmd);
11048 install_element(CONFIG_NODE, &ip_ssmpingd_cmd);
11049 install_element(VRF_NODE, &ip_ssmpingd_cmd);
11050 install_element(CONFIG_NODE, &no_ip_ssmpingd_cmd);
11051 install_element(VRF_NODE, &no_ip_ssmpingd_cmd);
11052 install_element(CONFIG_NODE, &ip_msdp_peer_cmd);
11053 install_element(VRF_NODE, &ip_msdp_peer_cmd);
11054 install_element(CONFIG_NODE, &no_ip_msdp_peer_cmd);
11055 install_element(VRF_NODE, &no_ip_msdp_peer_cmd);
11056 install_element(CONFIG_NODE, &ip_pim_ecmp_cmd);
11057 install_element(VRF_NODE, &ip_pim_ecmp_cmd);
11058 install_element(CONFIG_NODE, &no_ip_pim_ecmp_cmd);
11059 install_element(VRF_NODE, &no_ip_pim_ecmp_cmd);
11060 install_element(CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd);
11061 install_element(VRF_NODE, &ip_pim_ecmp_rebalance_cmd);
11062 install_element(CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd);
11063 install_element(VRF_NODE, &no_ip_pim_ecmp_rebalance_cmd);
11064 install_element(CONFIG_NODE, &ip_pim_mlag_cmd);
11065 install_element(CONFIG_NODE, &no_ip_pim_mlag_cmd);
11066 install_element(CONFIG_NODE, &igmp_group_watermark_cmd);
11067 install_element(VRF_NODE, &igmp_group_watermark_cmd);
11068 install_element(CONFIG_NODE, &no_igmp_group_watermark_cmd);
11069 install_element(VRF_NODE, &no_igmp_group_watermark_cmd);
11070
11071 install_element(INTERFACE_NODE, &interface_ip_igmp_cmd);
11072 install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd);
11073 install_element(INTERFACE_NODE, &interface_ip_igmp_join_cmd);
11074 install_element(INTERFACE_NODE, &interface_no_ip_igmp_join_cmd);
11075 install_element(INTERFACE_NODE, &interface_ip_igmp_version_cmd);
11076 install_element(INTERFACE_NODE, &interface_no_ip_igmp_version_cmd);
11077 install_element(INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd);
11078 install_element(INTERFACE_NODE,
11079 &interface_no_ip_igmp_query_interval_cmd);
11080 install_element(INTERFACE_NODE,
11081 &interface_ip_igmp_query_max_response_time_cmd);
11082 install_element(INTERFACE_NODE,
11083 &interface_no_ip_igmp_query_max_response_time_cmd);
11084 install_element(INTERFACE_NODE,
11085 &interface_ip_igmp_query_max_response_time_dsec_cmd);
11086 install_element(INTERFACE_NODE,
11087 &interface_no_ip_igmp_query_max_response_time_dsec_cmd);
11088 install_element(INTERFACE_NODE,
11089 &interface_ip_igmp_last_member_query_count_cmd);
11090 install_element(INTERFACE_NODE,
11091 &interface_no_ip_igmp_last_member_query_count_cmd);
11092 install_element(INTERFACE_NODE,
11093 &interface_ip_igmp_last_member_query_interval_cmd);
11094 install_element(INTERFACE_NODE,
11095 &interface_no_ip_igmp_last_member_query_interval_cmd);
11096 install_element(INTERFACE_NODE, &interface_ip_pim_activeactive_cmd);
11097 install_element(INTERFACE_NODE, &interface_ip_pim_ssm_cmd);
11098 install_element(INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd);
11099 install_element(INTERFACE_NODE, &interface_ip_pim_sm_cmd);
11100 install_element(INTERFACE_NODE, &interface_no_ip_pim_sm_cmd);
11101 install_element(INTERFACE_NODE, &interface_ip_pim_cmd);
11102 install_element(INTERFACE_NODE, &interface_no_ip_pim_cmd);
11103 install_element(INTERFACE_NODE, &interface_ip_pim_drprio_cmd);
11104 install_element(INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd);
11105 install_element(INTERFACE_NODE, &interface_ip_pim_hello_cmd);
11106 install_element(INTERFACE_NODE, &interface_no_ip_pim_hello_cmd);
11107 install_element(INTERFACE_NODE, &interface_ip_pim_boundary_oil_cmd);
11108 install_element(INTERFACE_NODE, &interface_no_ip_pim_boundary_oil_cmd);
11109 install_element(INTERFACE_NODE, &interface_ip_igmp_query_generate_cmd);
11110
11111 // Static mroutes NEB
11112 install_element(INTERFACE_NODE, &interface_ip_mroute_cmd);
11113 install_element(INTERFACE_NODE, &interface_no_ip_mroute_cmd);
11114
11115 install_element(VIEW_NODE, &show_ip_igmp_interface_cmd);
11116 install_element(VIEW_NODE, &show_ip_igmp_interface_vrf_all_cmd);
11117 install_element(VIEW_NODE, &show_ip_igmp_join_cmd);
11118 install_element(VIEW_NODE, &show_ip_igmp_join_vrf_all_cmd);
11119 install_element(VIEW_NODE, &show_ip_igmp_groups_cmd);
11120 install_element(VIEW_NODE, &show_ip_igmp_groups_vrf_all_cmd);
11121 install_element(VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd);
11122 install_element(VIEW_NODE, &show_ip_igmp_sources_cmd);
11123 install_element(VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd);
11124 install_element(VIEW_NODE, &show_ip_igmp_statistics_cmd);
11125 install_element(VIEW_NODE, &show_ip_pim_assert_cmd);
11126 install_element(VIEW_NODE, &show_ip_pim_assert_internal_cmd);
11127 install_element(VIEW_NODE, &show_ip_pim_assert_metric_cmd);
11128 install_element(VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd);
11129 install_element(VIEW_NODE, &show_ip_pim_interface_traffic_cmd);
11130 install_element(VIEW_NODE, &show_ip_pim_interface_cmd);
11131 install_element(VIEW_NODE, &show_ip_pim_interface_vrf_all_cmd);
11132 install_element(VIEW_NODE, &show_ip_pim_join_cmd);
11133 install_element(VIEW_NODE, &show_ip_pim_join_vrf_all_cmd);
11134 install_element(VIEW_NODE, &show_ip_pim_jp_agg_cmd);
11135 install_element(VIEW_NODE, &show_ip_pim_local_membership_cmd);
11136 install_element(VIEW_NODE, &show_ip_pim_mlag_summary_cmd);
11137 install_element(VIEW_NODE, &show_ip_pim_mlag_up_cmd);
11138 install_element(VIEW_NODE, &show_ip_pim_mlag_up_vrf_all_cmd);
11139 install_element(VIEW_NODE, &show_ip_pim_neighbor_cmd);
11140 install_element(VIEW_NODE, &show_ip_pim_neighbor_vrf_all_cmd);
11141 install_element(VIEW_NODE, &show_ip_pim_rpf_cmd);
11142 install_element(VIEW_NODE, &show_ip_pim_rpf_vrf_all_cmd);
11143 install_element(VIEW_NODE, &show_ip_pim_secondary_cmd);
11144 install_element(VIEW_NODE, &show_ip_pim_state_cmd);
11145 install_element(VIEW_NODE, &show_ip_pim_state_vrf_all_cmd);
11146 install_element(VIEW_NODE, &show_ip_pim_upstream_cmd);
11147 install_element(VIEW_NODE, &show_ip_pim_upstream_vrf_all_cmd);
11148 install_element(VIEW_NODE, &show_ip_pim_channel_cmd);
11149 install_element(VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd);
11150 install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd);
11151 install_element(VIEW_NODE, &show_ip_pim_rp_cmd);
11152 install_element(VIEW_NODE, &show_ip_pim_rp_vrf_all_cmd);
11153 install_element(VIEW_NODE, &show_ip_pim_bsr_cmd);
11154 install_element(VIEW_NODE, &show_ip_multicast_cmd);
11155 install_element(VIEW_NODE, &show_ip_multicast_vrf_all_cmd);
11156 install_element(VIEW_NODE, &show_ip_multicast_count_cmd);
11157 install_element(VIEW_NODE, &show_ip_multicast_count_vrf_all_cmd);
11158 install_element(VIEW_NODE, &show_ip_mroute_cmd);
11159 install_element(VIEW_NODE, &show_ip_mroute_vrf_all_cmd);
11160 install_element(VIEW_NODE, &show_ip_mroute_count_cmd);
11161 install_element(VIEW_NODE, &show_ip_mroute_count_vrf_all_cmd);
11162 install_element(VIEW_NODE, &show_ip_mroute_summary_cmd);
11163 install_element(VIEW_NODE, &show_ip_mroute_summary_vrf_all_cmd);
11164 install_element(VIEW_NODE, &show_ip_rib_cmd);
11165 install_element(VIEW_NODE, &show_ip_ssmpingd_cmd);
11166 install_element(VIEW_NODE, &show_ip_pim_nexthop_cmd);
11167 install_element(VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd);
11168 install_element(VIEW_NODE, &show_ip_pim_bsrp_cmd);
11169 install_element(VIEW_NODE, &show_ip_pim_bsm_db_cmd);
11170 install_element(VIEW_NODE, &show_ip_pim_statistics_cmd);
11171
11172 install_element(ENABLE_NODE, &clear_ip_mroute_count_cmd);
11173 install_element(ENABLE_NODE, &clear_ip_interfaces_cmd);
11174 install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd);
11175 install_element(ENABLE_NODE, &clear_ip_mroute_cmd);
11176 install_element(ENABLE_NODE, &clear_ip_pim_interfaces_cmd);
11177 install_element(ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd);
11178 install_element(ENABLE_NODE, &clear_ip_pim_oil_cmd);
11179 install_element(ENABLE_NODE, &clear_ip_pim_statistics_cmd);
11180 install_element(ENABLE_NODE, &clear_ip_pim_bsr_db_cmd);
11181
11182 install_element(ENABLE_NODE, &show_debugging_pim_cmd);
11183
11184 install_element(ENABLE_NODE, &debug_igmp_cmd);
11185 install_element(ENABLE_NODE, &no_debug_igmp_cmd);
11186 install_element(ENABLE_NODE, &debug_igmp_events_cmd);
11187 install_element(ENABLE_NODE, &no_debug_igmp_events_cmd);
11188 install_element(ENABLE_NODE, &debug_igmp_packets_cmd);
11189 install_element(ENABLE_NODE, &no_debug_igmp_packets_cmd);
11190 install_element(ENABLE_NODE, &debug_igmp_trace_cmd);
11191 install_element(ENABLE_NODE, &no_debug_igmp_trace_cmd);
11192 install_element(ENABLE_NODE, &debug_mroute_cmd);
11193 install_element(ENABLE_NODE, &debug_mroute_detail_cmd);
11194 install_element(ENABLE_NODE, &no_debug_mroute_cmd);
11195 install_element(ENABLE_NODE, &no_debug_mroute_detail_cmd);
11196 install_element(ENABLE_NODE, &debug_pim_static_cmd);
11197 install_element(ENABLE_NODE, &no_debug_pim_static_cmd);
11198 install_element(ENABLE_NODE, &debug_pim_cmd);
11199 install_element(ENABLE_NODE, &no_debug_pim_cmd);
11200 install_element(ENABLE_NODE, &debug_pim_nht_cmd);
11201 install_element(ENABLE_NODE, &no_debug_pim_nht_cmd);
11202 install_element(ENABLE_NODE, &debug_pim_nht_rp_cmd);
11203 install_element(ENABLE_NODE, &no_debug_pim_nht_rp_cmd);
11204 install_element(ENABLE_NODE, &debug_pim_events_cmd);
11205 install_element(ENABLE_NODE, &no_debug_pim_events_cmd);
11206 install_element(ENABLE_NODE, &debug_pim_packets_cmd);
11207 install_element(ENABLE_NODE, &no_debug_pim_packets_cmd);
11208 install_element(ENABLE_NODE, &debug_pim_packetdump_send_cmd);
11209 install_element(ENABLE_NODE, &no_debug_pim_packetdump_send_cmd);
11210 install_element(ENABLE_NODE, &debug_pim_packetdump_recv_cmd);
11211 install_element(ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd);
11212 install_element(ENABLE_NODE, &debug_pim_trace_cmd);
11213 install_element(ENABLE_NODE, &no_debug_pim_trace_cmd);
11214 install_element(ENABLE_NODE, &debug_pim_trace_detail_cmd);
11215 install_element(ENABLE_NODE, &no_debug_pim_trace_detail_cmd);
11216 install_element(ENABLE_NODE, &debug_ssmpingd_cmd);
11217 install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd);
11218 install_element(ENABLE_NODE, &debug_pim_zebra_cmd);
11219 install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd);
11220 install_element(ENABLE_NODE, &debug_pim_mlag_cmd);
11221 install_element(ENABLE_NODE, &no_debug_pim_mlag_cmd);
11222 install_element(ENABLE_NODE, &debug_pim_vxlan_cmd);
11223 install_element(ENABLE_NODE, &no_debug_pim_vxlan_cmd);
11224 install_element(ENABLE_NODE, &debug_msdp_cmd);
11225 install_element(ENABLE_NODE, &no_debug_msdp_cmd);
11226 install_element(ENABLE_NODE, &debug_msdp_events_cmd);
11227 install_element(ENABLE_NODE, &no_debug_msdp_events_cmd);
11228 install_element(ENABLE_NODE, &debug_msdp_packets_cmd);
11229 install_element(ENABLE_NODE, &no_debug_msdp_packets_cmd);
11230 install_element(ENABLE_NODE, &debug_mtrace_cmd);
11231 install_element(ENABLE_NODE, &no_debug_mtrace_cmd);
11232 install_element(ENABLE_NODE, &debug_bsm_cmd);
11233 install_element(ENABLE_NODE, &no_debug_bsm_cmd);
11234
11235 install_element(CONFIG_NODE, &debug_igmp_cmd);
11236 install_element(CONFIG_NODE, &no_debug_igmp_cmd);
11237 install_element(CONFIG_NODE, &debug_igmp_events_cmd);
11238 install_element(CONFIG_NODE, &no_debug_igmp_events_cmd);
11239 install_element(CONFIG_NODE, &debug_igmp_packets_cmd);
11240 install_element(CONFIG_NODE, &no_debug_igmp_packets_cmd);
11241 install_element(CONFIG_NODE, &debug_igmp_trace_cmd);
11242 install_element(CONFIG_NODE, &no_debug_igmp_trace_cmd);
11243 install_element(CONFIG_NODE, &debug_mroute_cmd);
11244 install_element(CONFIG_NODE, &debug_mroute_detail_cmd);
11245 install_element(CONFIG_NODE, &no_debug_mroute_cmd);
11246 install_element(CONFIG_NODE, &no_debug_mroute_detail_cmd);
11247 install_element(CONFIG_NODE, &debug_pim_static_cmd);
11248 install_element(CONFIG_NODE, &no_debug_pim_static_cmd);
11249 install_element(CONFIG_NODE, &debug_pim_cmd);
11250 install_element(CONFIG_NODE, &no_debug_pim_cmd);
11251 install_element(CONFIG_NODE, &debug_pim_nht_cmd);
11252 install_element(CONFIG_NODE, &no_debug_pim_nht_cmd);
11253 install_element(CONFIG_NODE, &debug_pim_nht_rp_cmd);
11254 install_element(CONFIG_NODE, &no_debug_pim_nht_rp_cmd);
11255 install_element(CONFIG_NODE, &debug_pim_events_cmd);
11256 install_element(CONFIG_NODE, &no_debug_pim_events_cmd);
11257 install_element(CONFIG_NODE, &debug_pim_packets_cmd);
11258 install_element(CONFIG_NODE, &no_debug_pim_packets_cmd);
11259 install_element(CONFIG_NODE, &debug_pim_trace_cmd);
11260 install_element(CONFIG_NODE, &no_debug_pim_trace_cmd);
11261 install_element(CONFIG_NODE, &debug_pim_trace_detail_cmd);
11262 install_element(CONFIG_NODE, &no_debug_pim_trace_detail_cmd);
11263 install_element(CONFIG_NODE, &debug_ssmpingd_cmd);
11264 install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd);
11265 install_element(CONFIG_NODE, &debug_pim_zebra_cmd);
11266 install_element(CONFIG_NODE, &no_debug_pim_zebra_cmd);
11267 install_element(CONFIG_NODE, &debug_pim_mlag_cmd);
11268 install_element(CONFIG_NODE, &no_debug_pim_mlag_cmd);
11269 install_element(CONFIG_NODE, &debug_pim_vxlan_cmd);
11270 install_element(CONFIG_NODE, &no_debug_pim_vxlan_cmd);
11271 install_element(CONFIG_NODE, &debug_msdp_cmd);
11272 install_element(CONFIG_NODE, &no_debug_msdp_cmd);
11273 install_element(CONFIG_NODE, &debug_msdp_events_cmd);
11274 install_element(CONFIG_NODE, &no_debug_msdp_events_cmd);
11275 install_element(CONFIG_NODE, &debug_msdp_packets_cmd);
11276 install_element(CONFIG_NODE, &no_debug_msdp_packets_cmd);
11277 install_element(CONFIG_NODE, &debug_mtrace_cmd);
11278 install_element(CONFIG_NODE, &no_debug_mtrace_cmd);
11279 install_element(CONFIG_NODE, &debug_bsm_cmd);
11280 install_element(CONFIG_NODE, &no_debug_bsm_cmd);
11281
11282 install_element(CONFIG_NODE, &ip_msdp_timers_cmd);
11283 install_element(VRF_NODE, &ip_msdp_timers_cmd);
11284 install_element(CONFIG_NODE, &no_ip_msdp_timers_cmd);
11285 install_element(VRF_NODE, &no_ip_msdp_timers_cmd);
11286 install_element(CONFIG_NODE, &ip_msdp_mesh_group_member_cmd);
11287 install_element(VRF_NODE, &ip_msdp_mesh_group_member_cmd);
11288 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd);
11289 install_element(VRF_NODE, &no_ip_msdp_mesh_group_member_cmd);
11290 install_element(CONFIG_NODE, &ip_msdp_mesh_group_source_cmd);
11291 install_element(VRF_NODE, &ip_msdp_mesh_group_source_cmd);
11292 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd);
11293 install_element(VRF_NODE, &no_ip_msdp_mesh_group_source_cmd);
11294 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_cmd);
11295 install_element(VRF_NODE, &no_ip_msdp_mesh_group_cmd);
11296 install_element(VIEW_NODE, &show_ip_msdp_peer_detail_cmd);
11297 install_element(VIEW_NODE, &show_ip_msdp_peer_detail_vrf_all_cmd);
11298 install_element(VIEW_NODE, &show_ip_msdp_sa_detail_cmd);
11299 install_element(VIEW_NODE, &show_ip_msdp_sa_detail_vrf_all_cmd);
11300 install_element(VIEW_NODE, &show_ip_msdp_sa_sg_cmd);
11301 install_element(VIEW_NODE, &show_ip_msdp_sa_sg_vrf_all_cmd);
11302 install_element(VIEW_NODE, &show_ip_msdp_mesh_group_cmd);
11303 install_element(VIEW_NODE, &show_ip_msdp_mesh_group_vrf_all_cmd);
11304 install_element(VIEW_NODE, &show_ip_pim_ssm_range_cmd);
11305 install_element(VIEW_NODE, &show_ip_pim_group_type_cmd);
11306 install_element(VIEW_NODE, &show_ip_pim_vxlan_sg_cmd);
11307 install_element(VIEW_NODE, &show_ip_pim_vxlan_sg_work_cmd);
11308 install_element(INTERFACE_NODE, &interface_pim_use_source_cmd);
11309 install_element(INTERFACE_NODE, &interface_no_pim_use_source_cmd);
11310 /* Install BSM command */
11311 install_element(INTERFACE_NODE, &ip_pim_bsm_cmd);
11312 install_element(INTERFACE_NODE, &no_ip_pim_bsm_cmd);
11313 install_element(INTERFACE_NODE, &ip_pim_ucast_bsm_cmd);
11314 install_element(INTERFACE_NODE, &no_ip_pim_ucast_bsm_cmd);
11315 /* Install BFD command */
11316 install_element(INTERFACE_NODE, &ip_pim_bfd_cmd);
11317 install_element(INTERFACE_NODE, &ip_pim_bfd_param_cmd);
11318 install_element(INTERFACE_NODE, &no_ip_pim_bfd_profile_cmd);
11319 install_element(INTERFACE_NODE, &no_ip_pim_bfd_cmd);
11320 #if HAVE_BFDD == 0
11321 install_element(INTERFACE_NODE, &no_ip_pim_bfd_param_cmd);
11322 #endif /* !HAVE_BFDD */
11323 }