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