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