]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_cmd.c
Merge pull request #9283 from ton31337/fix/documentation_for_aggregate-address
[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 (5-600)",
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 (5-600)",
7197 NO_STR
7198 IP_STR
7199 "pim multicast routing\n"
7200 "Join Prune Send Interval\n"
7201 "Seconds\n")
7202 {
7203 char jp_default_timer[5];
7204
7205 snprintf(jp_default_timer, sizeof(jp_default_timer), "%d",
7206 PIM_DEFAULT_T_PERIODIC);
7207
7208 nb_cli_enqueue_change(vty, "/frr-pim:pim/join-prune-interval",
7209 NB_OP_MODIFY, jp_default_timer);
7210
7211 return nb_cli_apply_changes(vty, NULL);
7212 }
7213
7214 DEFUN (ip_pim_register_suppress,
7215 ip_pim_register_suppress_cmd,
7216 "ip pim register-suppress-time (5-60000)",
7217 IP_STR
7218 "pim multicast routing\n"
7219 "Register Suppress Timer\n"
7220 "Seconds\n")
7221 {
7222 nb_cli_enqueue_change(vty, "/frr-pim:pim/register-suppress-time",
7223 NB_OP_MODIFY, argv[3]->arg);
7224
7225 return nb_cli_apply_changes(vty, NULL);
7226 }
7227
7228 DEFUN (no_ip_pim_register_suppress,
7229 no_ip_pim_register_suppress_cmd,
7230 "no ip pim register-suppress-time (5-60000)",
7231 NO_STR
7232 IP_STR
7233 "pim multicast routing\n"
7234 "Register Suppress Timer\n"
7235 "Seconds\n")
7236 {
7237 char rs_default_timer[5];
7238
7239 snprintf(rs_default_timer, sizeof(rs_default_timer), "%d",
7240 PIM_REGISTER_SUPPRESSION_TIME_DEFAULT);
7241
7242 nb_cli_enqueue_change(vty, "/frr-pim:pim/register-suppress-time",
7243 NB_OP_MODIFY, rs_default_timer);
7244
7245 return nb_cli_apply_changes(vty, NULL);
7246 }
7247
7248 DEFUN (ip_pim_rp_keep_alive,
7249 ip_pim_rp_keep_alive_cmd,
7250 "ip pim rp keep-alive-timer (31-60000)",
7251 IP_STR
7252 "pim multicast routing\n"
7253 "Rendevous Point\n"
7254 "Keep alive Timer\n"
7255 "Seconds\n")
7256 {
7257 const char *vrfname;
7258 char rp_ka_timer_xpath[XPATH_MAXLEN];
7259
7260 vrfname = pim_cli_get_vrf_name(vty);
7261 if (vrfname == NULL)
7262 return CMD_WARNING_CONFIG_FAILED;
7263
7264 snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
7265 FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname);
7266 strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
7267 sizeof(rp_ka_timer_xpath));
7268
7269 nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
7270 argv[4]->arg);
7271
7272 return nb_cli_apply_changes(vty, NULL);
7273 }
7274
7275 DEFUN (no_ip_pim_rp_keep_alive,
7276 no_ip_pim_rp_keep_alive_cmd,
7277 "no ip pim rp keep-alive-timer (31-60000)",
7278 NO_STR
7279 IP_STR
7280 "pim multicast routing\n"
7281 "Rendevous Point\n"
7282 "Keep alive Timer\n"
7283 "Seconds\n")
7284 {
7285 const char *vrfname;
7286 char rp_ka_timer[5];
7287 char rp_ka_timer_xpath[XPATH_MAXLEN];
7288
7289 snprintf(rp_ka_timer, sizeof(rp_ka_timer), "%d",
7290 PIM_RP_KEEPALIVE_PERIOD);
7291
7292 vrfname = pim_cli_get_vrf_name(vty);
7293 if (vrfname == NULL)
7294 return CMD_WARNING_CONFIG_FAILED;
7295
7296 snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
7297 FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname);
7298 strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
7299 sizeof(rp_ka_timer_xpath));
7300
7301 nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
7302 rp_ka_timer);
7303
7304 return nb_cli_apply_changes(vty, NULL);
7305 }
7306
7307 DEFUN (ip_pim_keep_alive,
7308 ip_pim_keep_alive_cmd,
7309 "ip pim keep-alive-timer (31-60000)",
7310 IP_STR
7311 "pim multicast routing\n"
7312 "Keep alive Timer\n"
7313 "Seconds\n")
7314 {
7315 const char *vrfname;
7316 char ka_timer_xpath[XPATH_MAXLEN];
7317
7318 vrfname = pim_cli_get_vrf_name(vty);
7319 if (vrfname == NULL)
7320 return CMD_WARNING_CONFIG_FAILED;
7321
7322 snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_XPATH,
7323 "frr-pim:pimd", "pim", vrfname);
7324 strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
7325
7326 nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_MODIFY,
7327 argv[3]->arg);
7328
7329 return nb_cli_apply_changes(vty, NULL);
7330 }
7331
7332 DEFUN (no_ip_pim_keep_alive,
7333 no_ip_pim_keep_alive_cmd,
7334 "no ip pim keep-alive-timer (31-60000)",
7335 NO_STR
7336 IP_STR
7337 "pim multicast routing\n"
7338 "Keep alive Timer\n"
7339 "Seconds\n")
7340 {
7341 const char *vrfname;
7342 char ka_timer[5];
7343 char ka_timer_xpath[XPATH_MAXLEN];
7344
7345 snprintf(ka_timer, sizeof(ka_timer), "%d", PIM_KEEPALIVE_PERIOD);
7346
7347 vrfname = pim_cli_get_vrf_name(vty);
7348 if (vrfname == NULL)
7349 return CMD_WARNING_CONFIG_FAILED;
7350
7351 snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_XPATH,
7352 "frr-pim:pimd", "pim", vrfname);
7353 strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
7354
7355 nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_MODIFY,
7356 ka_timer);
7357
7358 return nb_cli_apply_changes(vty, NULL);
7359 }
7360
7361 DEFUN (ip_pim_packets,
7362 ip_pim_packets_cmd,
7363 "ip pim packets (1-100)",
7364 IP_STR
7365 "pim multicast routing\n"
7366 "packets to process at one time per fd\n"
7367 "Number of packets\n")
7368 {
7369 nb_cli_enqueue_change(vty, "/frr-pim:pim/packets", NB_OP_MODIFY,
7370 argv[3]->arg);
7371
7372 return nb_cli_apply_changes(vty, NULL);
7373 }
7374
7375 DEFUN (no_ip_pim_packets,
7376 no_ip_pim_packets_cmd,
7377 "no ip pim packets (1-100)",
7378 NO_STR
7379 IP_STR
7380 "pim multicast routing\n"
7381 "packets to process at one time per fd\n"
7382 "Number of packets\n")
7383 {
7384 char default_packet[3];
7385
7386 snprintf(default_packet, sizeof(default_packet), "%d",
7387 PIM_DEFAULT_PACKET_PROCESS);
7388
7389 nb_cli_enqueue_change(vty, "/frr-pim:pim/packets", NB_OP_MODIFY,
7390 default_packet);
7391
7392 return nb_cli_apply_changes(vty, NULL);
7393 }
7394
7395 DEFPY (igmp_group_watermark,
7396 igmp_group_watermark_cmd,
7397 "ip igmp watermark-warn (10-60000)$limit",
7398 IP_STR
7399 IGMP_STR
7400 "Configure group limit for watermark warning\n"
7401 "Group count to generate watermark warning\n")
7402 {
7403 PIM_DECLVAR_CONTEXT(vrf, pim);
7404 pim->igmp_watermark_limit = limit;
7405
7406 return CMD_SUCCESS;
7407 }
7408
7409 DEFPY (no_igmp_group_watermark,
7410 no_igmp_group_watermark_cmd,
7411 "no ip igmp watermark-warn [(10-60000)$limit]",
7412 NO_STR
7413 IP_STR
7414 IGMP_STR
7415 "Unconfigure group limit for watermark warning\n"
7416 "Group count to generate watermark warning\n")
7417 {
7418 PIM_DECLVAR_CONTEXT(vrf, pim);
7419 pim->igmp_watermark_limit = 0;
7420
7421 return CMD_SUCCESS;
7422 }
7423
7424 DEFUN (ip_pim_v6_secondary,
7425 ip_pim_v6_secondary_cmd,
7426 "ip pim send-v6-secondary",
7427 IP_STR
7428 "pim multicast routing\n"
7429 "Send v6 secondary addresses\n")
7430 {
7431 const char *vrfname;
7432 char send_v6_secondary_xpath[XPATH_MAXLEN];
7433
7434 vrfname = pim_cli_get_vrf_name(vty);
7435 if (vrfname == NULL)
7436 return CMD_WARNING_CONFIG_FAILED;
7437
7438 snprintf(send_v6_secondary_xpath, sizeof(send_v6_secondary_xpath),
7439 FRR_PIM_AF_XPATH,
7440 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
7441 strlcat(send_v6_secondary_xpath, "/send-v6-secondary",
7442 sizeof(send_v6_secondary_xpath));
7443
7444 nb_cli_enqueue_change(vty, send_v6_secondary_xpath, NB_OP_MODIFY,
7445 "true");
7446
7447 return nb_cli_apply_changes(vty, NULL);
7448 }
7449
7450 DEFUN (no_ip_pim_v6_secondary,
7451 no_ip_pim_v6_secondary_cmd,
7452 "no ip pim send-v6-secondary",
7453 NO_STR
7454 IP_STR
7455 "pim multicast routing\n"
7456 "Send v6 secondary addresses\n")
7457 {
7458 const char *vrfname;
7459 char send_v6_secondary_xpath[XPATH_MAXLEN];
7460
7461 vrfname = pim_cli_get_vrf_name(vty);
7462 if (vrfname == NULL)
7463 return CMD_WARNING_CONFIG_FAILED;
7464
7465 snprintf(send_v6_secondary_xpath, sizeof(send_v6_secondary_xpath),
7466 FRR_PIM_AF_XPATH,
7467 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
7468 strlcat(send_v6_secondary_xpath, "/send-v6-secondary",
7469 sizeof(send_v6_secondary_xpath));
7470
7471 nb_cli_enqueue_change(vty, send_v6_secondary_xpath, NB_OP_MODIFY,
7472 "false");
7473
7474 return nb_cli_apply_changes(vty, NULL);
7475 }
7476
7477 DEFUN (ip_pim_rp,
7478 ip_pim_rp_cmd,
7479 "ip pim rp A.B.C.D [A.B.C.D/M]",
7480 IP_STR
7481 "pim multicast routing\n"
7482 "Rendevous Point\n"
7483 "ip address of RP\n"
7484 "Group Address range to cover\n")
7485 {
7486 const char *vrfname;
7487 int idx_rp = 3, idx_group = 4;
7488 char rp_group_xpath[XPATH_MAXLEN];
7489 int result = 0;
7490 struct prefix group;
7491 struct in_addr rp_addr;
7492 const char *group_str =
7493 (argc == 5) ? argv[idx_group]->arg : "224.0.0.0/4";
7494
7495 result = str2prefix(group_str, &group);
7496 if (result) {
7497 struct prefix temp;
7498
7499 prefix_copy(&temp, &group);
7500 apply_mask(&temp);
7501 if (!prefix_same(&group, &temp)) {
7502 vty_out(vty, "%% Inconsistent address and mask: %s\n",
7503 group_str);
7504 return CMD_WARNING_CONFIG_FAILED;
7505 }
7506 }
7507
7508 if (!result) {
7509 vty_out(vty, "%% Bad group address specified: %s\n",
7510 group_str);
7511 return CMD_WARNING_CONFIG_FAILED;
7512 }
7513
7514 result = inet_pton(AF_INET, argv[idx_rp]->arg, &rp_addr);
7515 if (result <= 0) {
7516 vty_out(vty, "%% Bad RP address specified: %s\n",
7517 argv[idx_rp]->arg);
7518 return CMD_WARNING_CONFIG_FAILED;
7519 }
7520
7521 vrfname = pim_cli_get_vrf_name(vty);
7522 if (vrfname == NULL)
7523 return CMD_WARNING_CONFIG_FAILED;
7524
7525 snprintf(rp_group_xpath, sizeof(rp_group_xpath),
7526 FRR_PIM_STATIC_RP_XPATH,
7527 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
7528 argv[idx_rp]->arg);
7529 strlcat(rp_group_xpath, "/group-list", sizeof(rp_group_xpath));
7530
7531 nb_cli_enqueue_change(vty, rp_group_xpath, NB_OP_CREATE, group_str);
7532
7533 return nb_cli_apply_changes(vty, NULL);
7534 }
7535
7536 DEFUN (ip_pim_rp_prefix_list,
7537 ip_pim_rp_prefix_list_cmd,
7538 "ip pim rp A.B.C.D prefix-list WORD",
7539 IP_STR
7540 "pim multicast routing\n"
7541 "Rendevous Point\n"
7542 "ip address of RP\n"
7543 "group prefix-list filter\n"
7544 "Name of a prefix-list\n")
7545 {
7546 int idx_rp = 3, idx_plist = 5;
7547 const char *vrfname;
7548 char rp_plist_xpath[XPATH_MAXLEN];
7549
7550 vrfname = pim_cli_get_vrf_name(vty);
7551 if (vrfname == NULL)
7552 return CMD_WARNING_CONFIG_FAILED;
7553
7554 snprintf(rp_plist_xpath, sizeof(rp_plist_xpath),
7555 FRR_PIM_STATIC_RP_XPATH,
7556 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
7557 argv[idx_rp]->arg);
7558 strlcat(rp_plist_xpath, "/prefix-list", sizeof(rp_plist_xpath));
7559
7560 nb_cli_enqueue_change(vty, rp_plist_xpath, NB_OP_MODIFY,
7561 argv[idx_plist]->arg);
7562
7563 return nb_cli_apply_changes(vty, NULL);
7564 }
7565
7566 DEFUN (no_ip_pim_rp,
7567 no_ip_pim_rp_cmd,
7568 "no ip pim rp A.B.C.D [A.B.C.D/M]",
7569 NO_STR
7570 IP_STR
7571 "pim multicast routing\n"
7572 "Rendevous Point\n"
7573 "ip address of RP\n"
7574 "Group Address range to cover\n")
7575 {
7576 int idx_rp = 4, idx_group = 5;
7577 const char *group_str =
7578 (argc == 6) ? argv[idx_group]->arg : "224.0.0.0/4";
7579 char group_list_xpath[XPATH_MAXLEN + 32];
7580 char group_xpath[XPATH_MAXLEN + 64];
7581 char rp_xpath[XPATH_MAXLEN];
7582 const char *vrfname;
7583 const struct lyd_node *group_dnode;
7584
7585 vrfname = pim_cli_get_vrf_name(vty);
7586 if (vrfname == NULL)
7587 return CMD_WARNING_CONFIG_FAILED;
7588
7589 snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
7590 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
7591 argv[idx_rp]->arg);
7592
7593 snprintf(group_list_xpath, sizeof(group_list_xpath), "%s/group-list",
7594 rp_xpath);
7595
7596 snprintf(group_xpath, sizeof(group_xpath), "%s[.='%s']",
7597 group_list_xpath, group_str);
7598
7599 if (!yang_dnode_exists(vty->candidate_config->dnode, group_xpath)) {
7600 vty_out(vty, "%% Unable to find specified RP\n");
7601 return NB_OK;
7602 }
7603
7604 group_dnode = yang_dnode_get(vty->candidate_config->dnode, group_xpath);
7605
7606 if (yang_is_last_list_dnode(group_dnode))
7607 nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
7608 else
7609 nb_cli_enqueue_change(vty, group_list_xpath, NB_OP_DESTROY,
7610 group_str);
7611
7612 return nb_cli_apply_changes(vty, NULL);
7613 }
7614
7615 DEFUN (no_ip_pim_rp_prefix_list,
7616 no_ip_pim_rp_prefix_list_cmd,
7617 "no ip pim rp A.B.C.D prefix-list WORD",
7618 NO_STR
7619 IP_STR
7620 "pim multicast routing\n"
7621 "Rendevous Point\n"
7622 "ip address of RP\n"
7623 "group prefix-list filter\n"
7624 "Name of a prefix-list\n")
7625 {
7626 int idx_rp = 4;
7627 int idx_plist = 6;
7628 char rp_xpath[XPATH_MAXLEN];
7629 char plist_xpath[XPATH_MAXLEN];
7630 const char *vrfname;
7631 const struct lyd_node *plist_dnode;
7632 const char *plist;
7633
7634 vrfname = pim_cli_get_vrf_name(vty);
7635 if (vrfname == NULL)
7636 return CMD_WARNING_CONFIG_FAILED;
7637
7638 snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
7639 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
7640 argv[idx_rp]->arg);
7641
7642 snprintf(plist_xpath, sizeof(plist_xpath), FRR_PIM_STATIC_RP_XPATH,
7643 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
7644 argv[idx_rp]->arg);
7645 strlcat(plist_xpath, "/prefix-list", sizeof(plist_xpath));
7646
7647 plist_dnode = yang_dnode_get(vty->candidate_config->dnode, plist_xpath);
7648 if (!plist_dnode) {
7649 vty_out(vty, "%% Unable to find specified RP\n");
7650 return NB_OK;
7651 }
7652
7653 plist = yang_dnode_get_string(plist_dnode, plist_xpath);
7654 if (strcmp(argv[idx_plist]->arg, plist)) {
7655 vty_out(vty, "%% Unable to find specified RP\n");
7656 return NB_OK;
7657 }
7658
7659 nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
7660
7661 return nb_cli_apply_changes(vty, NULL);
7662 }
7663
7664 DEFUN (ip_pim_ssm_prefix_list,
7665 ip_pim_ssm_prefix_list_cmd,
7666 "ip pim ssm prefix-list WORD",
7667 IP_STR
7668 "pim multicast routing\n"
7669 "Source Specific Multicast\n"
7670 "group range prefix-list filter\n"
7671 "Name of a prefix-list\n")
7672 {
7673 const char *vrfname;
7674 char ssm_plist_xpath[XPATH_MAXLEN];
7675
7676 vrfname = pim_cli_get_vrf_name(vty);
7677 if (vrfname == NULL)
7678 return CMD_WARNING_CONFIG_FAILED;
7679
7680 snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath), FRR_PIM_AF_XPATH,
7681 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
7682 strlcat(ssm_plist_xpath, "/ssm-prefix-list", sizeof(ssm_plist_xpath));
7683
7684 nb_cli_enqueue_change(vty, ssm_plist_xpath, NB_OP_MODIFY, argv[4]->arg);
7685
7686 return nb_cli_apply_changes(vty, NULL);
7687 }
7688
7689 DEFUN (no_ip_pim_ssm_prefix_list,
7690 no_ip_pim_ssm_prefix_list_cmd,
7691 "no ip pim ssm prefix-list",
7692 NO_STR
7693 IP_STR
7694 "pim multicast routing\n"
7695 "Source Specific Multicast\n"
7696 "group range prefix-list filter\n")
7697 {
7698 const char *vrfname;
7699 char ssm_plist_xpath[XPATH_MAXLEN];
7700
7701 vrfname = pim_cli_get_vrf_name(vty);
7702 if (vrfname == NULL)
7703 return CMD_WARNING_CONFIG_FAILED;
7704
7705 snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath),
7706 FRR_PIM_AF_XPATH,
7707 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
7708 strlcat(ssm_plist_xpath, "/ssm-prefix-list", sizeof(ssm_plist_xpath));
7709
7710 nb_cli_enqueue_change(vty, ssm_plist_xpath, NB_OP_DESTROY, NULL);
7711
7712 return nb_cli_apply_changes(vty, NULL);
7713 }
7714
7715 DEFUN (no_ip_pim_ssm_prefix_list_name,
7716 no_ip_pim_ssm_prefix_list_name_cmd,
7717 "no ip pim ssm prefix-list WORD",
7718 NO_STR
7719 IP_STR
7720 "pim multicast routing\n"
7721 "Source Specific Multicast\n"
7722 "group range prefix-list filter\n"
7723 "Name of a prefix-list\n")
7724 {
7725 const char *vrfname;
7726 const struct lyd_node *ssm_plist_dnode;
7727 char ssm_plist_xpath[XPATH_MAXLEN];
7728 const char *ssm_plist_name;
7729
7730 vrfname = pim_cli_get_vrf_name(vty);
7731 if (vrfname == NULL)
7732 return CMD_WARNING_CONFIG_FAILED;
7733
7734 snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath),
7735 FRR_PIM_AF_XPATH,
7736 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
7737 strlcat(ssm_plist_xpath, "/ssm-prefix-list", sizeof(ssm_plist_xpath));
7738 ssm_plist_dnode = yang_dnode_get(vty->candidate_config->dnode,
7739 ssm_plist_xpath);
7740
7741 if (!ssm_plist_dnode) {
7742 vty_out(vty,
7743 "%% pim ssm prefix-list %s doesn't exist\n",
7744 argv[5]->arg);
7745 return CMD_WARNING_CONFIG_FAILED;
7746 }
7747
7748 ssm_plist_name = yang_dnode_get_string(ssm_plist_dnode, ".");
7749
7750 if (ssm_plist_name && !strcmp(ssm_plist_name, argv[5]->arg)) {
7751 nb_cli_enqueue_change(vty, ssm_plist_xpath, NB_OP_DESTROY,
7752 NULL);
7753
7754 return nb_cli_apply_changes(vty, NULL);
7755 }
7756
7757 vty_out(vty, "%% pim ssm prefix-list %s doesn't exist\n", argv[5]->arg);
7758
7759 return CMD_WARNING_CONFIG_FAILED;
7760 }
7761
7762 static void ip_pim_ssm_show_group_range(struct pim_instance *pim,
7763 struct vty *vty, bool uj)
7764 {
7765 struct pim_ssm *ssm = pim->ssm_info;
7766 const char *range_str =
7767 ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
7768
7769 if (uj) {
7770 json_object *json;
7771 json = json_object_new_object();
7772 json_object_string_add(json, "ssmGroups", range_str);
7773 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7774 json, JSON_C_TO_STRING_PRETTY));
7775 json_object_free(json);
7776 } else
7777 vty_out(vty, "SSM group range : %s\n", range_str);
7778 }
7779
7780 DEFUN (show_ip_pim_ssm_range,
7781 show_ip_pim_ssm_range_cmd,
7782 "show ip pim [vrf NAME] group-type [json]",
7783 SHOW_STR
7784 IP_STR
7785 PIM_STR
7786 VRF_CMD_HELP_STR
7787 "PIM group type\n"
7788 JSON_STR)
7789 {
7790 int idx = 2;
7791 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
7792 bool uj = use_json(argc, argv);
7793
7794 if (!vrf)
7795 return CMD_WARNING;
7796
7797 ip_pim_ssm_show_group_range(vrf->info, vty, uj);
7798
7799 return CMD_SUCCESS;
7800 }
7801
7802 static void ip_pim_ssm_show_group_type(struct pim_instance *pim,
7803 struct vty *vty, bool uj,
7804 const char *group)
7805 {
7806 struct in_addr group_addr;
7807 const char *type_str;
7808 int result;
7809
7810 result = inet_pton(AF_INET, group, &group_addr);
7811 if (result <= 0)
7812 type_str = "invalid";
7813 else {
7814 if (pim_is_group_224_4(group_addr))
7815 type_str =
7816 pim_is_grp_ssm(pim, group_addr) ? "SSM" : "ASM";
7817 else
7818 type_str = "not-multicast";
7819 }
7820
7821 if (uj) {
7822 json_object *json;
7823 json = json_object_new_object();
7824 json_object_string_add(json, "groupType", type_str);
7825 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7826 json, JSON_C_TO_STRING_PRETTY));
7827 json_object_free(json);
7828 } else
7829 vty_out(vty, "Group type : %s\n", type_str);
7830 }
7831
7832 DEFUN (show_ip_pim_group_type,
7833 show_ip_pim_group_type_cmd,
7834 "show ip pim [vrf NAME] group-type A.B.C.D [json]",
7835 SHOW_STR
7836 IP_STR
7837 PIM_STR
7838 VRF_CMD_HELP_STR
7839 "multicast group type\n"
7840 "group address\n"
7841 JSON_STR)
7842 {
7843 int idx = 2;
7844 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
7845 bool uj = use_json(argc, argv);
7846
7847 if (!vrf)
7848 return CMD_WARNING;
7849
7850 argv_find(argv, argc, "A.B.C.D", &idx);
7851 ip_pim_ssm_show_group_type(vrf->info, vty, uj, argv[idx]->arg);
7852
7853 return CMD_SUCCESS;
7854 }
7855
7856 DEFUN (show_ip_pim_bsr,
7857 show_ip_pim_bsr_cmd,
7858 "show ip pim bsr [json]",
7859 SHOW_STR
7860 IP_STR
7861 PIM_STR
7862 "boot-strap router information\n"
7863 JSON_STR)
7864 {
7865 int idx = 2;
7866 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
7867 bool uj = use_json(argc, argv);
7868
7869 if (!vrf)
7870 return CMD_WARNING;
7871
7872 pim_show_bsr(vrf->info, vty, uj);
7873
7874 return CMD_SUCCESS;
7875 }
7876
7877 DEFUN (ip_ssmpingd,
7878 ip_ssmpingd_cmd,
7879 "ip ssmpingd [A.B.C.D]",
7880 IP_STR
7881 CONF_SSMPINGD_STR
7882 "Source address\n")
7883 {
7884 int idx_ipv4 = 2;
7885 const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0";
7886 const char *vrfname;
7887 char ssmpingd_ip_xpath[XPATH_MAXLEN];
7888
7889 vrfname = pim_cli_get_vrf_name(vty);
7890 if (vrfname == NULL)
7891 return CMD_WARNING_CONFIG_FAILED;
7892
7893 snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
7894 FRR_PIM_AF_XPATH,
7895 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
7896 strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
7897 sizeof(ssmpingd_ip_xpath));
7898
7899 nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, NB_OP_CREATE,
7900 source_str);
7901
7902 return nb_cli_apply_changes(vty, NULL);
7903 }
7904
7905 DEFUN (no_ip_ssmpingd,
7906 no_ip_ssmpingd_cmd,
7907 "no ip ssmpingd [A.B.C.D]",
7908 NO_STR
7909 IP_STR
7910 CONF_SSMPINGD_STR
7911 "Source address\n")
7912 {
7913 const char *vrfname;
7914 int idx_ipv4 = 3;
7915 const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0";
7916 char ssmpingd_ip_xpath[XPATH_MAXLEN];
7917
7918 vrfname = pim_cli_get_vrf_name(vty);
7919 if (vrfname == NULL)
7920 return CMD_WARNING_CONFIG_FAILED;
7921
7922 snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
7923 FRR_PIM_AF_XPATH,
7924 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
7925 strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
7926 sizeof(ssmpingd_ip_xpath));
7927
7928 nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, NB_OP_DESTROY,
7929 source_str);
7930
7931 return nb_cli_apply_changes(vty, NULL);
7932 }
7933
7934 DEFUN (ip_pim_ecmp,
7935 ip_pim_ecmp_cmd,
7936 "ip pim ecmp",
7937 IP_STR
7938 "pim multicast routing\n"
7939 "Enable PIM ECMP \n")
7940 {
7941 const char *vrfname;
7942 char ecmp_xpath[XPATH_MAXLEN];
7943
7944 vrfname = pim_cli_get_vrf_name(vty);
7945 if (vrfname == NULL)
7946 return CMD_WARNING_CONFIG_FAILED;
7947
7948 snprintf(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH,
7949 "frr-pim:pimd", "pim", vrfname);
7950 strlcat(ecmp_xpath, "/ecmp", sizeof(ecmp_xpath));
7951
7952 nb_cli_enqueue_change(vty, ecmp_xpath, NB_OP_MODIFY, "true");
7953 return nb_cli_apply_changes(vty, NULL);
7954 }
7955
7956 DEFUN (no_ip_pim_ecmp,
7957 no_ip_pim_ecmp_cmd,
7958 "no ip pim ecmp",
7959 NO_STR
7960 IP_STR
7961 "pim multicast routing\n"
7962 "Disable PIM ECMP \n")
7963 {
7964 const char *vrfname;
7965 char ecmp_xpath[XPATH_MAXLEN];
7966
7967 vrfname = pim_cli_get_vrf_name(vty);
7968 if (vrfname == NULL)
7969 return CMD_WARNING_CONFIG_FAILED;
7970
7971 snprintf(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH,
7972 "frr-pim:pimd", "pim", vrfname);
7973 strlcat(ecmp_xpath, "/ecmp", sizeof(ecmp_xpath));
7974
7975 nb_cli_enqueue_change(vty, ecmp_xpath, NB_OP_MODIFY, "false");
7976
7977 return nb_cli_apply_changes(vty, NULL);
7978 }
7979
7980 DEFUN (ip_pim_ecmp_rebalance,
7981 ip_pim_ecmp_rebalance_cmd,
7982 "ip pim ecmp rebalance",
7983 IP_STR
7984 "pim multicast routing\n"
7985 "Enable PIM ECMP \n"
7986 "Enable PIM ECMP Rebalance\n")
7987 {
7988 const char *vrfname;
7989 char ecmp_xpath[XPATH_MAXLEN];
7990 char ecmp_rebalance_xpath[XPATH_MAXLEN];
7991
7992 vrfname = pim_cli_get_vrf_name(vty);
7993 if (vrfname == NULL)
7994 return CMD_WARNING_CONFIG_FAILED;
7995
7996 snprintf(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH,
7997 "frr-pim:pimd", "pim", vrfname);
7998 strlcat(ecmp_xpath, "/ecmp", sizeof(ecmp_xpath));
7999 snprintf(ecmp_rebalance_xpath, sizeof(ecmp_rebalance_xpath),
8000 FRR_PIM_XPATH,
8001 "frr-pim:pimd", "pim", vrfname);
8002 strlcat(ecmp_rebalance_xpath, "/ecmp-rebalance",
8003 sizeof(ecmp_rebalance_xpath));
8004
8005 nb_cli_enqueue_change(vty, ecmp_xpath, NB_OP_MODIFY, "true");
8006 nb_cli_enqueue_change(vty, ecmp_rebalance_xpath, NB_OP_MODIFY, "true");
8007
8008 return nb_cli_apply_changes(vty, NULL);
8009 }
8010
8011 DEFUN (no_ip_pim_ecmp_rebalance,
8012 no_ip_pim_ecmp_rebalance_cmd,
8013 "no ip pim ecmp rebalance",
8014 NO_STR
8015 IP_STR
8016 "pim multicast routing\n"
8017 "Disable PIM ECMP \n"
8018 "Disable PIM ECMP Rebalance\n")
8019 {
8020 const char *vrfname;
8021 char ecmp_rebalance_xpath[XPATH_MAXLEN];
8022
8023 vrfname = pim_cli_get_vrf_name(vty);
8024 if (vrfname == NULL)
8025 return CMD_WARNING_CONFIG_FAILED;
8026
8027 snprintf(ecmp_rebalance_xpath, sizeof(ecmp_rebalance_xpath),
8028 FRR_PIM_XPATH,
8029 "frr-pim:pimd", "pim", vrfname);
8030 strlcat(ecmp_rebalance_xpath, "/ecmp-rebalance",
8031 sizeof(ecmp_rebalance_xpath));
8032
8033 nb_cli_enqueue_change(vty, ecmp_rebalance_xpath, NB_OP_MODIFY, "false");
8034
8035 return nb_cli_apply_changes(vty, NULL);
8036 }
8037
8038 DEFUN (interface_ip_igmp,
8039 interface_ip_igmp_cmd,
8040 "ip igmp",
8041 IP_STR
8042 IFACE_IGMP_STR)
8043 {
8044 nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY, "true");
8045
8046 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8047 }
8048
8049 DEFUN (interface_no_ip_igmp,
8050 interface_no_ip_igmp_cmd,
8051 "no ip igmp",
8052 NO_STR
8053 IP_STR
8054 IFACE_IGMP_STR)
8055 {
8056 const struct lyd_node *pim_enable_dnode;
8057 char pim_if_xpath[XPATH_MAXLEN + 20];
8058
8059 snprintf(pim_if_xpath, sizeof(pim_if_xpath),
8060 "%s/frr-pim:pim", VTY_CURR_XPATH);
8061
8062 pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
8063 "%s/pim-enable", pim_if_xpath);
8064 if (!pim_enable_dnode) {
8065 nb_cli_enqueue_change(vty, pim_if_xpath, NB_OP_DESTROY, NULL);
8066 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8067 } else {
8068 if (!yang_dnode_get_bool(pim_enable_dnode, ".")) {
8069 nb_cli_enqueue_change(vty, pim_if_xpath, NB_OP_DESTROY,
8070 NULL);
8071 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8072 } else
8073 nb_cli_enqueue_change(vty, "./igmp-enable",
8074 NB_OP_MODIFY, "false");
8075 }
8076
8077 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8078 }
8079
8080 DEFUN (interface_ip_igmp_join,
8081 interface_ip_igmp_join_cmd,
8082 "ip igmp join A.B.C.D [A.B.C.D]",
8083 IP_STR
8084 IFACE_IGMP_STR
8085 "IGMP join multicast group\n"
8086 "Multicast group address\n"
8087 "Source address\n")
8088 {
8089 int idx_group = 3;
8090 int idx_source = 4;
8091 const char *source_str;
8092 char xpath[XPATH_MAXLEN];
8093
8094 if (argc == 5) {
8095 source_str = argv[idx_source]->arg;
8096
8097 if (strcmp(source_str, "0.0.0.0") == 0) {
8098 vty_out(vty, "Bad source address %s\n",
8099 argv[idx_source]->arg);
8100 return CMD_WARNING_CONFIG_FAILED;
8101 }
8102 } else
8103 source_str = "0.0.0.0";
8104
8105 snprintf(xpath, sizeof(xpath), FRR_IGMP_JOIN_XPATH,
8106 "frr-routing:ipv4", argv[idx_group]->arg, source_str);
8107
8108 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
8109
8110 return nb_cli_apply_changes(vty, NULL);
8111 }
8112
8113 DEFUN (interface_no_ip_igmp_join,
8114 interface_no_ip_igmp_join_cmd,
8115 "no ip igmp join A.B.C.D [A.B.C.D]",
8116 NO_STR
8117 IP_STR
8118 IFACE_IGMP_STR
8119 "IGMP join multicast group\n"
8120 "Multicast group address\n"
8121 "Source address\n")
8122 {
8123 int idx_group = 4;
8124 int idx_source = 5;
8125 const char *source_str;
8126 char xpath[XPATH_MAXLEN];
8127
8128 if (argc == 6) {
8129 source_str = argv[idx_source]->arg;
8130
8131 if (strcmp(source_str, "0.0.0.0") == 0) {
8132 vty_out(vty, "Bad source address %s\n",
8133 argv[idx_source]->arg);
8134 return CMD_WARNING_CONFIG_FAILED;
8135 }
8136 } else
8137 source_str = "0.0.0.0";
8138
8139 snprintf(xpath, sizeof(xpath), FRR_IGMP_JOIN_XPATH,
8140 "frr-routing:ipv4", argv[idx_group]->arg, source_str);
8141
8142 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
8143
8144 return nb_cli_apply_changes(vty, NULL);
8145 }
8146
8147 DEFUN (interface_ip_igmp_query_interval,
8148 interface_ip_igmp_query_interval_cmd,
8149 "ip igmp query-interval (1-1800)",
8150 IP_STR
8151 IFACE_IGMP_STR
8152 IFACE_IGMP_QUERY_INTERVAL_STR
8153 "Query interval in seconds\n")
8154 {
8155 const struct lyd_node *pim_enable_dnode;
8156
8157 pim_enable_dnode =
8158 yang_dnode_getf(vty->candidate_config->dnode,
8159 "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH);
8160 if (!pim_enable_dnode) {
8161 nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
8162 "true");
8163 } else {
8164 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
8165 nb_cli_enqueue_change(vty, "./igmp-enable",
8166 NB_OP_MODIFY, "true");
8167 }
8168
8169 nb_cli_enqueue_change(vty, "./query-interval", NB_OP_MODIFY,
8170 argv[3]->arg);
8171
8172 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8173 }
8174
8175 DEFUN (interface_no_ip_igmp_query_interval,
8176 interface_no_ip_igmp_query_interval_cmd,
8177 "no ip igmp query-interval",
8178 NO_STR
8179 IP_STR
8180 IFACE_IGMP_STR
8181 IFACE_IGMP_QUERY_INTERVAL_STR)
8182 {
8183 char default_query_interval[5];
8184
8185 snprintf(default_query_interval, sizeof(default_query_interval), "%d",
8186 IGMP_GENERAL_QUERY_INTERVAL);
8187
8188 nb_cli_enqueue_change(vty, "./query-interval", NB_OP_MODIFY,
8189 default_query_interval);
8190
8191 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8192 }
8193
8194 DEFUN (interface_ip_igmp_version,
8195 interface_ip_igmp_version_cmd,
8196 "ip igmp version (2-3)",
8197 IP_STR
8198 IFACE_IGMP_STR
8199 "IGMP version\n"
8200 "IGMP version number\n")
8201 {
8202 nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
8203 "true");
8204 nb_cli_enqueue_change(vty, "./version", NB_OP_MODIFY, argv[3]->arg);
8205
8206 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8207 }
8208
8209 DEFUN (interface_no_ip_igmp_version,
8210 interface_no_ip_igmp_version_cmd,
8211 "no ip igmp version (2-3)",
8212 NO_STR
8213 IP_STR
8214 IFACE_IGMP_STR
8215 "IGMP version\n"
8216 "IGMP version number\n")
8217 {
8218 nb_cli_enqueue_change(vty, "./version", NB_OP_DESTROY, NULL);
8219
8220 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8221 }
8222
8223 DEFUN (interface_ip_igmp_query_max_response_time,
8224 interface_ip_igmp_query_max_response_time_cmd,
8225 "ip igmp query-max-response-time (10-250)",
8226 IP_STR
8227 IFACE_IGMP_STR
8228 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
8229 "Query response value in deci-seconds\n")
8230 {
8231 const struct lyd_node *pim_enable_dnode;
8232
8233 pim_enable_dnode =
8234 yang_dnode_getf(vty->candidate_config->dnode,
8235 "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH);
8236
8237 if (!pim_enable_dnode) {
8238 nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
8239 "true");
8240 } else {
8241 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
8242 nb_cli_enqueue_change(vty, "./igmp-enable",
8243 NB_OP_MODIFY, "true");
8244 }
8245
8246 nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
8247 argv[3]->arg);
8248
8249 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8250 }
8251
8252 DEFUN (interface_no_ip_igmp_query_max_response_time,
8253 interface_no_ip_igmp_query_max_response_time_cmd,
8254 "no ip igmp query-max-response-time (10-250)",
8255 NO_STR
8256 IP_STR
8257 IFACE_IGMP_STR
8258 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
8259 "Time for response in deci-seconds\n")
8260 {
8261 char default_query_max_response_time[4];
8262
8263 snprintf(default_query_max_response_time,
8264 sizeof(default_query_max_response_time),
8265 "%d", IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
8266
8267 nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
8268 default_query_max_response_time);
8269 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8270 }
8271
8272 DEFUN_HIDDEN (interface_ip_igmp_query_max_response_time_dsec,
8273 interface_ip_igmp_query_max_response_time_dsec_cmd,
8274 "ip igmp query-max-response-time-dsec (10-250)",
8275 IP_STR
8276 IFACE_IGMP_STR
8277 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR
8278 "Query response value in deciseconds\n")
8279 {
8280 const struct lyd_node *pim_enable_dnode;
8281
8282 pim_enable_dnode =
8283 yang_dnode_getf(vty->candidate_config->dnode,
8284 "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH);
8285 if (!pim_enable_dnode) {
8286 nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
8287 "true");
8288 } else {
8289 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
8290 nb_cli_enqueue_change(vty, "./igmp-enable",
8291 NB_OP_MODIFY, "true");
8292 }
8293
8294 nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
8295 argv[3]->arg);
8296
8297 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8298 }
8299
8300 DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec,
8301 interface_no_ip_igmp_query_max_response_time_dsec_cmd,
8302 "no ip igmp query-max-response-time-dsec",
8303 NO_STR
8304 IP_STR
8305 IFACE_IGMP_STR
8306 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR)
8307 {
8308 char default_query_max_response_time[4];
8309
8310 snprintf(default_query_max_response_time,
8311 sizeof(default_query_max_response_time),
8312 "%d", IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
8313
8314 nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
8315 default_query_max_response_time);
8316
8317 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8318 }
8319
8320 DEFUN (interface_ip_igmp_last_member_query_count,
8321 interface_ip_igmp_last_member_query_count_cmd,
8322 "ip igmp last-member-query-count (1-7)",
8323 IP_STR
8324 IFACE_IGMP_STR
8325 IFACE_IGMP_LAST_MEMBER_QUERY_COUNT_STR
8326 "Last member query count\n")
8327 {
8328 const struct lyd_node *pim_enable_dnode;
8329
8330 pim_enable_dnode =
8331 yang_dnode_getf(vty->candidate_config->dnode,
8332 "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH);
8333 if (!pim_enable_dnode) {
8334 nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
8335 "true");
8336 } else {
8337 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
8338 nb_cli_enqueue_change(vty, "./igmp-enable",
8339 NB_OP_MODIFY, "true");
8340 }
8341
8342 nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_MODIFY,
8343 argv[3]->arg);
8344
8345 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8346 }
8347
8348 DEFUN (interface_no_ip_igmp_last_member_query_count,
8349 interface_no_ip_igmp_last_member_query_count_cmd,
8350 "no ip igmp last-member-query-count [(1-7)]",
8351 NO_STR
8352 IP_STR
8353 IFACE_IGMP_STR
8354 IFACE_IGMP_LAST_MEMBER_QUERY_COUNT_STR
8355 "Last member query count\n")
8356 {
8357 char default_robustness[2];
8358
8359 snprintf(default_robustness, sizeof(default_robustness), "%d",
8360 IGMP_DEFAULT_ROBUSTNESS_VARIABLE);
8361
8362 nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_MODIFY,
8363 default_robustness);
8364
8365 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8366 }
8367
8368 DEFUN (interface_ip_igmp_last_member_query_interval,
8369 interface_ip_igmp_last_member_query_interval_cmd,
8370 "ip igmp last-member-query-interval (1-255)",
8371 IP_STR
8372 IFACE_IGMP_STR
8373 IFACE_IGMP_LAST_MEMBER_QUERY_INTERVAL_STR
8374 "Last member query interval in deciseconds\n")
8375 {
8376 const struct lyd_node *pim_enable_dnode;
8377
8378 pim_enable_dnode =
8379 yang_dnode_getf(vty->candidate_config->dnode,
8380 "%s/frr-pim:pim/pim-enable", VTY_CURR_XPATH);
8381 if (!pim_enable_dnode) {
8382 nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
8383 "true");
8384 } else {
8385 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
8386 nb_cli_enqueue_change(vty, "./igmp-enable",
8387 NB_OP_MODIFY, "true");
8388 }
8389
8390 nb_cli_enqueue_change(vty, "./last-member-query-interval", NB_OP_MODIFY,
8391 argv[3]->arg);
8392
8393 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8394 }
8395
8396 DEFUN (interface_no_ip_igmp_last_member_query_interval,
8397 interface_no_ip_igmp_last_member_query_interval_cmd,
8398 "no ip igmp last-member-query-interval [(1-255)]",
8399 NO_STR
8400 IP_STR
8401 IFACE_IGMP_STR
8402 IFACE_IGMP_LAST_MEMBER_QUERY_INTERVAL_STR
8403 "Last member query interval in deciseconds\n")
8404 {
8405 char default_last_member_query_count[4];
8406
8407 snprintf(default_last_member_query_count,
8408 sizeof(default_last_member_query_count),
8409 "%d", IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC);
8410
8411 nb_cli_enqueue_change(vty, "./last-member-query-interval", NB_OP_MODIFY,
8412 default_last_member_query_count);
8413
8414 return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
8415 }
8416
8417 DEFUN (interface_ip_pim_drprio,
8418 interface_ip_pim_drprio_cmd,
8419 "ip pim drpriority (1-4294967295)",
8420 IP_STR
8421 PIM_STR
8422 "Set the Designated Router Election Priority\n"
8423 "Value of the new DR Priority\n")
8424 {
8425 int idx_number = 3;
8426
8427 nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_MODIFY,
8428 argv[idx_number]->arg);
8429
8430 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8431 }
8432
8433 DEFUN (interface_no_ip_pim_drprio,
8434 interface_no_ip_pim_drprio_cmd,
8435 "no ip pim drpriority [(1-4294967295)]",
8436 NO_STR
8437 IP_STR
8438 PIM_STR
8439 "Revert the Designated Router Priority to default\n"
8440 "Old Value of the Priority\n")
8441 {
8442 char default_priority[10];
8443
8444 snprintf(default_priority, sizeof(default_priority), "%d",
8445 PIM_DEFAULT_DR_PRIORITY);
8446
8447 nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_MODIFY,
8448 default_priority);
8449
8450 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8451 }
8452
8453 DEFPY_HIDDEN (interface_ip_igmp_query_generate,
8454 interface_ip_igmp_query_generate_cmd,
8455 "ip igmp generate-query-once [version (2-3)]",
8456 IP_STR
8457 IFACE_IGMP_STR
8458 "Generate igmp general query once\n"
8459 "IGMP version\n"
8460 "IGMP version number\n")
8461 {
8462 VTY_DECLVAR_CONTEXT(interface, ifp);
8463 int igmp_version = 2;
8464
8465 if (!ifp->info) {
8466 vty_out(vty, "IGMP/PIM is not enabled on the interface %s\n",
8467 ifp->name);
8468 return CMD_WARNING_CONFIG_FAILED;
8469 }
8470
8471 if (argc > 3)
8472 igmp_version = atoi(argv[4]->arg);
8473
8474 igmp_send_query_on_intf(ifp, igmp_version);
8475
8476 return CMD_SUCCESS;
8477 }
8478
8479 DEFPY_HIDDEN (pim_test_sg_keepalive,
8480 pim_test_sg_keepalive_cmd,
8481 "test pim [vrf NAME$name] keepalive-reset A.B.C.D$source A.B.C.D$group",
8482 "Test code\n"
8483 PIM_STR
8484 VRF_CMD_HELP_STR
8485 "Reset the Keepalive Timer\n"
8486 "The Source we are resetting\n"
8487 "The Group we are resetting\n")
8488 {
8489 struct pim_upstream *up;
8490 struct pim_instance *pim;
8491 struct prefix_sg sg;
8492
8493 sg.src = source;
8494 sg.grp = group;
8495
8496 if (!name)
8497 pim = pim_get_pim_instance(VRF_DEFAULT);
8498 else {
8499 struct vrf *vrf = vrf_lookup_by_name(name);
8500
8501 if (!vrf) {
8502 vty_out(vty, "%% Vrf specified: %s does not exist\n",
8503 name);
8504 return CMD_WARNING;
8505 }
8506
8507 pim = pim_get_pim_instance(vrf->vrf_id);
8508 }
8509
8510 if (!pim) {
8511 vty_out(vty, "%% Unable to find pim instance\n");
8512 return CMD_WARNING;
8513 }
8514
8515 up = pim_upstream_find(pim, &sg);
8516 if (!up) {
8517 vty_out(vty, "%% Unable to find %s specified\n",
8518 pim_str_sg_dump(&sg));
8519 return CMD_WARNING;
8520 }
8521
8522 vty_out(vty, "Setting %s to current keep alive time: %d\n",
8523 pim_str_sg_dump(&sg), pim->keep_alive_time);
8524 pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
8525
8526 return CMD_SUCCESS;
8527 }
8528
8529 DEFPY (interface_ip_pim_activeactive,
8530 interface_ip_pim_activeactive_cmd,
8531 "[no$no] ip pim active-active",
8532 NO_STR
8533 IP_STR
8534 PIM_STR
8535 "Mark interface as Active-Active for MLAG operations, Hidden because not finished yet\n")
8536 {
8537 if (no)
8538 nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
8539 "false");
8540 else {
8541 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
8542 "true");
8543
8544 nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
8545 "true");
8546 }
8547
8548 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8549 }
8550
8551 DEFUN_HIDDEN (interface_ip_pim_ssm,
8552 interface_ip_pim_ssm_cmd,
8553 "ip pim ssm",
8554 IP_STR
8555 PIM_STR
8556 IFACE_PIM_STR)
8557 {
8558 int ret;
8559
8560 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
8561
8562 ret = nb_cli_apply_changes(vty, "./frr-pim:pim");
8563
8564 if (ret != NB_OK)
8565 return ret;
8566
8567 vty_out(vty,
8568 "WARN: Enabled PIM SM on interface; configure PIM SSM range if needed\n");
8569
8570 return NB_OK;
8571 }
8572
8573 DEFUN_HIDDEN (interface_ip_pim_sm,
8574 interface_ip_pim_sm_cmd,
8575 "ip pim sm",
8576 IP_STR
8577 PIM_STR
8578 IFACE_PIM_SM_STR)
8579 {
8580 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
8581
8582 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8583 }
8584
8585 DEFUN (interface_ip_pim,
8586 interface_ip_pim_cmd,
8587 "ip pim",
8588 IP_STR
8589 PIM_STR)
8590 {
8591 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
8592
8593 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8594 }
8595
8596 DEFUN_HIDDEN (interface_no_ip_pim_ssm,
8597 interface_no_ip_pim_ssm_cmd,
8598 "no ip pim ssm",
8599 NO_STR
8600 IP_STR
8601 PIM_STR
8602 IFACE_PIM_STR)
8603 {
8604 const struct lyd_node *igmp_enable_dnode;
8605 char igmp_if_xpath[XPATH_MAXLEN + 20];
8606
8607 snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
8608 "%s/frr-igmp:igmp", VTY_CURR_XPATH);
8609 igmp_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
8610 "%s/igmp-enable", igmp_if_xpath);
8611
8612 if (!igmp_enable_dnode) {
8613 nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY, NULL);
8614 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8615 } else {
8616 if (!yang_dnode_get_bool(igmp_enable_dnode, ".")) {
8617 nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY,
8618 NULL);
8619 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8620 } else
8621 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
8622 "false");
8623 }
8624
8625 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8626 }
8627
8628 DEFUN_HIDDEN (interface_no_ip_pim_sm,
8629 interface_no_ip_pim_sm_cmd,
8630 "no ip pim sm",
8631 NO_STR
8632 IP_STR
8633 PIM_STR
8634 IFACE_PIM_SM_STR)
8635 {
8636 const struct lyd_node *igmp_enable_dnode;
8637 char igmp_if_xpath[XPATH_MAXLEN + 20];
8638
8639 snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
8640 "%s/frr-igmp:igmp", VTY_CURR_XPATH);
8641 igmp_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
8642 "%s/igmp-enable", igmp_if_xpath);
8643
8644 if (!igmp_enable_dnode) {
8645 nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY, NULL);
8646 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8647 } else {
8648 if (!yang_dnode_get_bool(igmp_enable_dnode, ".")) {
8649 nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY,
8650 NULL);
8651 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8652 } else
8653 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
8654 "false");
8655 }
8656
8657 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8658 }
8659
8660 DEFUN (interface_no_ip_pim,
8661 interface_no_ip_pim_cmd,
8662 "no ip pim",
8663 NO_STR
8664 IP_STR
8665 PIM_STR)
8666 {
8667 const struct lyd_node *igmp_enable_dnode;
8668 char igmp_if_xpath[XPATH_MAXLEN + 20];
8669
8670 snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
8671 "%s/frr-igmp:igmp", VTY_CURR_XPATH);
8672 igmp_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
8673 "%s/igmp-enable", igmp_if_xpath);
8674
8675 if (!igmp_enable_dnode) {
8676 nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY, NULL);
8677 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8678 } else {
8679 if (!yang_dnode_get_bool(igmp_enable_dnode, ".")) {
8680 nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY,
8681 NULL);
8682 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8683 } else
8684 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
8685 "false");
8686 }
8687
8688 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8689 }
8690
8691 /* boundaries */
8692 DEFUN(interface_ip_pim_boundary_oil,
8693 interface_ip_pim_boundary_oil_cmd,
8694 "ip multicast boundary oil WORD",
8695 IP_STR
8696 "Generic multicast configuration options\n"
8697 "Define multicast boundary\n"
8698 "Filter OIL by group using prefix list\n"
8699 "Prefix list to filter OIL with\n")
8700 {
8701 nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_MODIFY,
8702 argv[4]->arg);
8703
8704 return nb_cli_apply_changes(vty,
8705 "./frr-pim:pim/address-family[address-family='%s']",
8706 "frr-routing:ipv4");
8707
8708 }
8709
8710 DEFUN(interface_no_ip_pim_boundary_oil,
8711 interface_no_ip_pim_boundary_oil_cmd,
8712 "no ip multicast boundary oil [WORD]",
8713 NO_STR
8714 IP_STR
8715 "Generic multicast configuration options\n"
8716 "Define multicast boundary\n"
8717 "Filter OIL by group using prefix list\n"
8718 "Prefix list to filter OIL with\n")
8719 {
8720 nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_DESTROY,
8721 NULL);
8722
8723 return nb_cli_apply_changes(vty,
8724 "./frr-pim:pim/address-family[address-family='%s']",
8725 "frr-routing:ipv4");
8726 }
8727
8728 DEFUN (interface_ip_mroute,
8729 interface_ip_mroute_cmd,
8730 "ip mroute INTERFACE A.B.C.D [A.B.C.D]",
8731 IP_STR
8732 "Add multicast route\n"
8733 "Outgoing interface name\n"
8734 "Group address\n"
8735 "Source address\n")
8736 {
8737 int idx_interface = 2;
8738 int idx_ipv4 = 3;
8739 const char *source_str;
8740
8741 if (argc == (idx_ipv4 + 1))
8742 source_str = "0.0.0.0";
8743 else
8744 source_str = argv[idx_ipv4 + 1]->arg;
8745
8746 nb_cli_enqueue_change(vty, "./oif", NB_OP_MODIFY,
8747 argv[idx_interface]->arg);
8748
8749 return nb_cli_apply_changes(vty,
8750 "./frr-pim:pim/address-family[address-family='%s']/mroute[source-addr='%s'][group-addr='%s']",
8751 "frr-routing:ipv4", source_str,
8752 argv[idx_ipv4]->arg);
8753 }
8754
8755 DEFUN (interface_no_ip_mroute,
8756 interface_no_ip_mroute_cmd,
8757 "no ip mroute INTERFACE A.B.C.D [A.B.C.D]",
8758 NO_STR
8759 IP_STR
8760 "Add multicast route\n"
8761 "Outgoing interface name\n"
8762 "Group Address\n"
8763 "Source Address\n")
8764 {
8765 int idx_ipv4 = 4;
8766 const char *source_str;
8767
8768 if (argc == (idx_ipv4 + 1))
8769 source_str = "0.0.0.0";
8770 else
8771 source_str = argv[idx_ipv4 + 1]->arg;
8772
8773 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8774
8775 return nb_cli_apply_changes(vty,
8776 "./frr-pim:pim/address-family[address-family='%s']/mroute[source-addr='%s'][group-addr='%s']",
8777 "frr-routing:ipv4", source_str,
8778 argv[idx_ipv4]->arg);
8779 }
8780
8781 DEFUN (interface_ip_pim_hello,
8782 interface_ip_pim_hello_cmd,
8783 "ip pim hello (1-180) [(1-630)]",
8784 IP_STR
8785 PIM_STR
8786 IFACE_PIM_HELLO_STR
8787 IFACE_PIM_HELLO_TIME_STR
8788 IFACE_PIM_HELLO_HOLD_STR)
8789 {
8790 int idx_time = 3;
8791 int idx_hold = 4;
8792 const struct lyd_node *igmp_enable_dnode;
8793
8794 igmp_enable_dnode =
8795 yang_dnode_getf(vty->candidate_config->dnode,
8796 "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH);
8797 if (!igmp_enable_dnode) {
8798 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
8799 "true");
8800 } else {
8801 if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
8802 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
8803 "true");
8804 }
8805
8806 nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_MODIFY,
8807 argv[idx_time]->arg);
8808
8809 if (argc == idx_hold + 1)
8810 nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_MODIFY,
8811 argv[idx_hold]->arg);
8812
8813 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8814 }
8815
8816 DEFUN (interface_no_ip_pim_hello,
8817 interface_no_ip_pim_hello_cmd,
8818 "no ip pim hello [(1-180) [(1-630)]]",
8819 NO_STR
8820 IP_STR
8821 PIM_STR
8822 IFACE_PIM_HELLO_STR
8823 IFACE_PIM_HELLO_TIME_STR
8824 IFACE_PIM_HELLO_HOLD_STR)
8825 {
8826 char hello_default_timer[3];
8827
8828 snprintf(hello_default_timer, sizeof(hello_default_timer), "%d",
8829 PIM_DEFAULT_HELLO_PERIOD);
8830
8831 nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_MODIFY,
8832 hello_default_timer);
8833 nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_DESTROY, NULL);
8834
8835 return nb_cli_apply_changes(vty, "./frr-pim:pim");
8836 }
8837
8838 DEFUN (debug_igmp,
8839 debug_igmp_cmd,
8840 "debug igmp",
8841 DEBUG_STR
8842 DEBUG_IGMP_STR)
8843 {
8844 PIM_DO_DEBUG_IGMP_EVENTS;
8845 PIM_DO_DEBUG_IGMP_PACKETS;
8846 PIM_DO_DEBUG_IGMP_TRACE;
8847 return CMD_SUCCESS;
8848 }
8849
8850 DEFUN (no_debug_igmp,
8851 no_debug_igmp_cmd,
8852 "no debug igmp",
8853 NO_STR
8854 DEBUG_STR
8855 DEBUG_IGMP_STR)
8856 {
8857 PIM_DONT_DEBUG_IGMP_EVENTS;
8858 PIM_DONT_DEBUG_IGMP_PACKETS;
8859 PIM_DONT_DEBUG_IGMP_TRACE;
8860 return CMD_SUCCESS;
8861 }
8862
8863
8864 DEFUN (debug_igmp_events,
8865 debug_igmp_events_cmd,
8866 "debug igmp events",
8867 DEBUG_STR
8868 DEBUG_IGMP_STR
8869 DEBUG_IGMP_EVENTS_STR)
8870 {
8871 PIM_DO_DEBUG_IGMP_EVENTS;
8872 return CMD_SUCCESS;
8873 }
8874
8875 DEFUN (no_debug_igmp_events,
8876 no_debug_igmp_events_cmd,
8877 "no debug igmp events",
8878 NO_STR
8879 DEBUG_STR
8880 DEBUG_IGMP_STR
8881 DEBUG_IGMP_EVENTS_STR)
8882 {
8883 PIM_DONT_DEBUG_IGMP_EVENTS;
8884 return CMD_SUCCESS;
8885 }
8886
8887
8888 DEFUN (debug_igmp_packets,
8889 debug_igmp_packets_cmd,
8890 "debug igmp packets",
8891 DEBUG_STR
8892 DEBUG_IGMP_STR
8893 DEBUG_IGMP_PACKETS_STR)
8894 {
8895 PIM_DO_DEBUG_IGMP_PACKETS;
8896 return CMD_SUCCESS;
8897 }
8898
8899 DEFUN (no_debug_igmp_packets,
8900 no_debug_igmp_packets_cmd,
8901 "no debug igmp packets",
8902 NO_STR
8903 DEBUG_STR
8904 DEBUG_IGMP_STR
8905 DEBUG_IGMP_PACKETS_STR)
8906 {
8907 PIM_DONT_DEBUG_IGMP_PACKETS;
8908 return CMD_SUCCESS;
8909 }
8910
8911
8912 DEFUN (debug_igmp_trace,
8913 debug_igmp_trace_cmd,
8914 "debug igmp trace",
8915 DEBUG_STR
8916 DEBUG_IGMP_STR
8917 DEBUG_IGMP_TRACE_STR)
8918 {
8919 PIM_DO_DEBUG_IGMP_TRACE;
8920 return CMD_SUCCESS;
8921 }
8922
8923 DEFUN (no_debug_igmp_trace,
8924 no_debug_igmp_trace_cmd,
8925 "no debug igmp trace",
8926 NO_STR
8927 DEBUG_STR
8928 DEBUG_IGMP_STR
8929 DEBUG_IGMP_TRACE_STR)
8930 {
8931 PIM_DONT_DEBUG_IGMP_TRACE;
8932 return CMD_SUCCESS;
8933 }
8934
8935
8936 DEFUN (debug_mroute,
8937 debug_mroute_cmd,
8938 "debug mroute",
8939 DEBUG_STR
8940 DEBUG_MROUTE_STR)
8941 {
8942 PIM_DO_DEBUG_MROUTE;
8943 return CMD_SUCCESS;
8944 }
8945
8946 DEFUN (debug_mroute_detail,
8947 debug_mroute_detail_cmd,
8948 "debug mroute detail",
8949 DEBUG_STR
8950 DEBUG_MROUTE_STR
8951 "detailed\n")
8952 {
8953 PIM_DO_DEBUG_MROUTE_DETAIL;
8954 return CMD_SUCCESS;
8955 }
8956
8957 DEFUN (no_debug_mroute,
8958 no_debug_mroute_cmd,
8959 "no debug mroute",
8960 NO_STR
8961 DEBUG_STR
8962 DEBUG_MROUTE_STR)
8963 {
8964 PIM_DONT_DEBUG_MROUTE;
8965 return CMD_SUCCESS;
8966 }
8967
8968 DEFUN (no_debug_mroute_detail,
8969 no_debug_mroute_detail_cmd,
8970 "no debug mroute detail",
8971 NO_STR
8972 DEBUG_STR
8973 DEBUG_MROUTE_STR
8974 "detailed\n")
8975 {
8976 PIM_DONT_DEBUG_MROUTE_DETAIL;
8977 return CMD_SUCCESS;
8978 }
8979
8980 DEFUN (debug_pim_static,
8981 debug_pim_static_cmd,
8982 "debug pim static",
8983 DEBUG_STR
8984 DEBUG_PIM_STR
8985 DEBUG_STATIC_STR)
8986 {
8987 PIM_DO_DEBUG_STATIC;
8988 return CMD_SUCCESS;
8989 }
8990
8991 DEFUN (no_debug_pim_static,
8992 no_debug_pim_static_cmd,
8993 "no debug pim static",
8994 NO_STR
8995 DEBUG_STR
8996 DEBUG_PIM_STR
8997 DEBUG_STATIC_STR)
8998 {
8999 PIM_DONT_DEBUG_STATIC;
9000 return CMD_SUCCESS;
9001 }
9002
9003
9004 DEFUN (debug_pim,
9005 debug_pim_cmd,
9006 "debug pim",
9007 DEBUG_STR
9008 DEBUG_PIM_STR)
9009 {
9010 PIM_DO_DEBUG_PIM_EVENTS;
9011 PIM_DO_DEBUG_PIM_PACKETS;
9012 PIM_DO_DEBUG_PIM_TRACE;
9013 PIM_DO_DEBUG_MSDP_EVENTS;
9014 PIM_DO_DEBUG_MSDP_PACKETS;
9015 PIM_DO_DEBUG_BSM;
9016 return CMD_SUCCESS;
9017 }
9018
9019 DEFUN (no_debug_pim,
9020 no_debug_pim_cmd,
9021 "no debug pim",
9022 NO_STR
9023 DEBUG_STR
9024 DEBUG_PIM_STR)
9025 {
9026 PIM_DONT_DEBUG_PIM_EVENTS;
9027 PIM_DONT_DEBUG_PIM_PACKETS;
9028 PIM_DONT_DEBUG_PIM_TRACE;
9029 PIM_DONT_DEBUG_MSDP_EVENTS;
9030 PIM_DONT_DEBUG_MSDP_PACKETS;
9031
9032 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
9033 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
9034 PIM_DONT_DEBUG_BSM;
9035
9036 return CMD_SUCCESS;
9037 }
9038
9039 DEFUN (debug_pim_nht,
9040 debug_pim_nht_cmd,
9041 "debug pim nht",
9042 DEBUG_STR
9043 DEBUG_PIM_STR
9044 "Nexthop Tracking\n")
9045 {
9046 PIM_DO_DEBUG_PIM_NHT;
9047 return CMD_SUCCESS;
9048 }
9049
9050 DEFUN (no_debug_pim_nht,
9051 no_debug_pim_nht_cmd,
9052 "no debug pim nht",
9053 NO_STR
9054 DEBUG_STR
9055 DEBUG_PIM_STR
9056 "Nexthop Tracking\n")
9057 {
9058 PIM_DONT_DEBUG_PIM_NHT;
9059 return CMD_SUCCESS;
9060 }
9061
9062 DEFUN (debug_pim_nht_rp,
9063 debug_pim_nht_rp_cmd,
9064 "debug pim nht rp",
9065 DEBUG_STR
9066 DEBUG_PIM_STR
9067 "Nexthop Tracking\n"
9068 "RP Nexthop Tracking\n")
9069 {
9070 PIM_DO_DEBUG_PIM_NHT_RP;
9071 return CMD_SUCCESS;
9072 }
9073
9074 DEFUN (no_debug_pim_nht_rp,
9075 no_debug_pim_nht_rp_cmd,
9076 "no debug pim nht rp",
9077 NO_STR
9078 DEBUG_STR
9079 DEBUG_PIM_STR
9080 "Nexthop Tracking\n"
9081 "RP Nexthop Tracking\n")
9082 {
9083 PIM_DONT_DEBUG_PIM_NHT_RP;
9084 return CMD_SUCCESS;
9085 }
9086
9087 DEFUN (debug_pim_events,
9088 debug_pim_events_cmd,
9089 "debug pim events",
9090 DEBUG_STR
9091 DEBUG_PIM_STR
9092 DEBUG_PIM_EVENTS_STR)
9093 {
9094 PIM_DO_DEBUG_PIM_EVENTS;
9095 return CMD_SUCCESS;
9096 }
9097
9098 DEFUN (no_debug_pim_events,
9099 no_debug_pim_events_cmd,
9100 "no debug pim events",
9101 NO_STR
9102 DEBUG_STR
9103 DEBUG_PIM_STR
9104 DEBUG_PIM_EVENTS_STR)
9105 {
9106 PIM_DONT_DEBUG_PIM_EVENTS;
9107 return CMD_SUCCESS;
9108 }
9109
9110 DEFUN (debug_pim_packets,
9111 debug_pim_packets_cmd,
9112 "debug pim packets [<hello|joins|register>]",
9113 DEBUG_STR
9114 DEBUG_PIM_STR
9115 DEBUG_PIM_PACKETS_STR
9116 DEBUG_PIM_HELLO_PACKETS_STR
9117 DEBUG_PIM_J_P_PACKETS_STR
9118 DEBUG_PIM_PIM_REG_PACKETS_STR)
9119 {
9120 int idx = 0;
9121 if (argv_find(argv, argc, "hello", &idx)) {
9122 PIM_DO_DEBUG_PIM_HELLO;
9123 vty_out(vty, "PIM Hello debugging is on\n");
9124 } else if (argv_find(argv, argc, "joins", &idx)) {
9125 PIM_DO_DEBUG_PIM_J_P;
9126 vty_out(vty, "PIM Join/Prune debugging is on\n");
9127 } else if (argv_find(argv, argc, "register", &idx)) {
9128 PIM_DO_DEBUG_PIM_REG;
9129 vty_out(vty, "PIM Register debugging is on\n");
9130 } else {
9131 PIM_DO_DEBUG_PIM_PACKETS;
9132 vty_out(vty, "PIM Packet debugging is on \n");
9133 }
9134 return CMD_SUCCESS;
9135 }
9136
9137 DEFUN (no_debug_pim_packets,
9138 no_debug_pim_packets_cmd,
9139 "no debug pim packets [<hello|joins|register>]",
9140 NO_STR
9141 DEBUG_STR
9142 DEBUG_PIM_STR
9143 DEBUG_PIM_PACKETS_STR
9144 DEBUG_PIM_HELLO_PACKETS_STR
9145 DEBUG_PIM_J_P_PACKETS_STR
9146 DEBUG_PIM_PIM_REG_PACKETS_STR)
9147 {
9148 int idx = 0;
9149 if (argv_find(argv, argc, "hello", &idx)) {
9150 PIM_DONT_DEBUG_PIM_HELLO;
9151 vty_out(vty, "PIM Hello debugging is off \n");
9152 } else if (argv_find(argv, argc, "joins", &idx)) {
9153 PIM_DONT_DEBUG_PIM_J_P;
9154 vty_out(vty, "PIM Join/Prune debugging is off \n");
9155 } else if (argv_find(argv, argc, "register", &idx)) {
9156 PIM_DONT_DEBUG_PIM_REG;
9157 vty_out(vty, "PIM Register debugging is off\n");
9158 } else
9159 PIM_DONT_DEBUG_PIM_PACKETS;
9160
9161 return CMD_SUCCESS;
9162 }
9163
9164
9165 DEFUN (debug_pim_packetdump_send,
9166 debug_pim_packetdump_send_cmd,
9167 "debug pim packet-dump send",
9168 DEBUG_STR
9169 DEBUG_PIM_STR
9170 DEBUG_PIM_PACKETDUMP_STR
9171 DEBUG_PIM_PACKETDUMP_SEND_STR)
9172 {
9173 PIM_DO_DEBUG_PIM_PACKETDUMP_SEND;
9174 return CMD_SUCCESS;
9175 }
9176
9177 DEFUN (no_debug_pim_packetdump_send,
9178 no_debug_pim_packetdump_send_cmd,
9179 "no debug pim packet-dump send",
9180 NO_STR
9181 DEBUG_STR
9182 DEBUG_PIM_STR
9183 DEBUG_PIM_PACKETDUMP_STR
9184 DEBUG_PIM_PACKETDUMP_SEND_STR)
9185 {
9186 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
9187 return CMD_SUCCESS;
9188 }
9189
9190 DEFUN (debug_pim_packetdump_recv,
9191 debug_pim_packetdump_recv_cmd,
9192 "debug pim packet-dump receive",
9193 DEBUG_STR
9194 DEBUG_PIM_STR
9195 DEBUG_PIM_PACKETDUMP_STR
9196 DEBUG_PIM_PACKETDUMP_RECV_STR)
9197 {
9198 PIM_DO_DEBUG_PIM_PACKETDUMP_RECV;
9199 return CMD_SUCCESS;
9200 }
9201
9202 DEFUN (no_debug_pim_packetdump_recv,
9203 no_debug_pim_packetdump_recv_cmd,
9204 "no debug pim packet-dump receive",
9205 NO_STR
9206 DEBUG_STR
9207 DEBUG_PIM_STR
9208 DEBUG_PIM_PACKETDUMP_STR
9209 DEBUG_PIM_PACKETDUMP_RECV_STR)
9210 {
9211 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
9212 return CMD_SUCCESS;
9213 }
9214
9215 DEFUN (debug_pim_trace,
9216 debug_pim_trace_cmd,
9217 "debug pim trace",
9218 DEBUG_STR
9219 DEBUG_PIM_STR
9220 DEBUG_PIM_TRACE_STR)
9221 {
9222 PIM_DO_DEBUG_PIM_TRACE;
9223 return CMD_SUCCESS;
9224 }
9225
9226 DEFUN (debug_pim_trace_detail,
9227 debug_pim_trace_detail_cmd,
9228 "debug pim trace detail",
9229 DEBUG_STR
9230 DEBUG_PIM_STR
9231 DEBUG_PIM_TRACE_STR
9232 "Detailed Information\n")
9233 {
9234 PIM_DO_DEBUG_PIM_TRACE_DETAIL;
9235 return CMD_SUCCESS;
9236 }
9237
9238 DEFUN (no_debug_pim_trace,
9239 no_debug_pim_trace_cmd,
9240 "no debug pim trace",
9241 NO_STR
9242 DEBUG_STR
9243 DEBUG_PIM_STR
9244 DEBUG_PIM_TRACE_STR)
9245 {
9246 PIM_DONT_DEBUG_PIM_TRACE;
9247 return CMD_SUCCESS;
9248 }
9249
9250 DEFUN (no_debug_pim_trace_detail,
9251 no_debug_pim_trace_detail_cmd,
9252 "no debug pim trace detail",
9253 NO_STR
9254 DEBUG_STR
9255 DEBUG_PIM_STR
9256 DEBUG_PIM_TRACE_STR
9257 "Detailed Information\n")
9258 {
9259 PIM_DONT_DEBUG_PIM_TRACE_DETAIL;
9260 return CMD_SUCCESS;
9261 }
9262
9263 DEFUN (debug_ssmpingd,
9264 debug_ssmpingd_cmd,
9265 "debug ssmpingd",
9266 DEBUG_STR
9267 DEBUG_SSMPINGD_STR)
9268 {
9269 PIM_DO_DEBUG_SSMPINGD;
9270 return CMD_SUCCESS;
9271 }
9272
9273 DEFUN (no_debug_ssmpingd,
9274 no_debug_ssmpingd_cmd,
9275 "no debug ssmpingd",
9276 NO_STR
9277 DEBUG_STR
9278 DEBUG_SSMPINGD_STR)
9279 {
9280 PIM_DONT_DEBUG_SSMPINGD;
9281 return CMD_SUCCESS;
9282 }
9283
9284 DEFUN (debug_pim_zebra,
9285 debug_pim_zebra_cmd,
9286 "debug pim zebra",
9287 DEBUG_STR
9288 DEBUG_PIM_STR
9289 DEBUG_PIM_ZEBRA_STR)
9290 {
9291 PIM_DO_DEBUG_ZEBRA;
9292 return CMD_SUCCESS;
9293 }
9294
9295 DEFUN (no_debug_pim_zebra,
9296 no_debug_pim_zebra_cmd,
9297 "no debug pim zebra",
9298 NO_STR
9299 DEBUG_STR
9300 DEBUG_PIM_STR
9301 DEBUG_PIM_ZEBRA_STR)
9302 {
9303 PIM_DONT_DEBUG_ZEBRA;
9304 return CMD_SUCCESS;
9305 }
9306
9307 DEFUN(debug_pim_mlag, debug_pim_mlag_cmd, "debug pim mlag",
9308 DEBUG_STR DEBUG_PIM_STR DEBUG_PIM_MLAG_STR)
9309 {
9310 PIM_DO_DEBUG_MLAG;
9311 return CMD_SUCCESS;
9312 }
9313
9314 DEFUN(no_debug_pim_mlag, no_debug_pim_mlag_cmd, "no debug pim mlag",
9315 NO_STR DEBUG_STR DEBUG_PIM_STR DEBUG_PIM_MLAG_STR)
9316 {
9317 PIM_DONT_DEBUG_MLAG;
9318 return CMD_SUCCESS;
9319 }
9320
9321 DEFUN (debug_pim_vxlan,
9322 debug_pim_vxlan_cmd,
9323 "debug pim vxlan",
9324 DEBUG_STR
9325 DEBUG_PIM_STR
9326 DEBUG_PIM_VXLAN_STR)
9327 {
9328 PIM_DO_DEBUG_VXLAN;
9329 return CMD_SUCCESS;
9330 }
9331
9332 DEFUN (no_debug_pim_vxlan,
9333 no_debug_pim_vxlan_cmd,
9334 "no debug pim vxlan",
9335 NO_STR
9336 DEBUG_STR
9337 DEBUG_PIM_STR
9338 DEBUG_PIM_VXLAN_STR)
9339 {
9340 PIM_DONT_DEBUG_VXLAN;
9341 return CMD_SUCCESS;
9342 }
9343
9344 DEFUN (debug_msdp,
9345 debug_msdp_cmd,
9346 "debug msdp",
9347 DEBUG_STR
9348 DEBUG_MSDP_STR)
9349 {
9350 PIM_DO_DEBUG_MSDP_EVENTS;
9351 PIM_DO_DEBUG_MSDP_PACKETS;
9352 return CMD_SUCCESS;
9353 }
9354
9355 DEFUN (no_debug_msdp,
9356 no_debug_msdp_cmd,
9357 "no debug msdp",
9358 NO_STR
9359 DEBUG_STR
9360 DEBUG_MSDP_STR)
9361 {
9362 PIM_DONT_DEBUG_MSDP_EVENTS;
9363 PIM_DONT_DEBUG_MSDP_PACKETS;
9364 return CMD_SUCCESS;
9365 }
9366
9367 DEFUN (debug_msdp_events,
9368 debug_msdp_events_cmd,
9369 "debug msdp events",
9370 DEBUG_STR
9371 DEBUG_MSDP_STR
9372 DEBUG_MSDP_EVENTS_STR)
9373 {
9374 PIM_DO_DEBUG_MSDP_EVENTS;
9375 return CMD_SUCCESS;
9376 }
9377
9378 DEFUN (no_debug_msdp_events,
9379 no_debug_msdp_events_cmd,
9380 "no debug msdp events",
9381 NO_STR
9382 DEBUG_STR
9383 DEBUG_MSDP_STR
9384 DEBUG_MSDP_EVENTS_STR)
9385 {
9386 PIM_DONT_DEBUG_MSDP_EVENTS;
9387 return CMD_SUCCESS;
9388 }
9389
9390 DEFUN (debug_msdp_packets,
9391 debug_msdp_packets_cmd,
9392 "debug msdp packets",
9393 DEBUG_STR
9394 DEBUG_MSDP_STR
9395 DEBUG_MSDP_PACKETS_STR)
9396 {
9397 PIM_DO_DEBUG_MSDP_PACKETS;
9398 return CMD_SUCCESS;
9399 }
9400
9401 DEFUN (no_debug_msdp_packets,
9402 no_debug_msdp_packets_cmd,
9403 "no debug msdp packets",
9404 NO_STR
9405 DEBUG_STR
9406 DEBUG_MSDP_STR
9407 DEBUG_MSDP_PACKETS_STR)
9408 {
9409 PIM_DONT_DEBUG_MSDP_PACKETS;
9410 return CMD_SUCCESS;
9411 }
9412
9413 DEFUN (debug_mtrace,
9414 debug_mtrace_cmd,
9415 "debug mtrace",
9416 DEBUG_STR
9417 DEBUG_MTRACE_STR)
9418 {
9419 PIM_DO_DEBUG_MTRACE;
9420 return CMD_SUCCESS;
9421 }
9422
9423 DEFUN (no_debug_mtrace,
9424 no_debug_mtrace_cmd,
9425 "no debug mtrace",
9426 NO_STR
9427 DEBUG_STR
9428 DEBUG_MTRACE_STR)
9429 {
9430 PIM_DONT_DEBUG_MTRACE;
9431 return CMD_SUCCESS;
9432 }
9433
9434 DEFUN (debug_bsm,
9435 debug_bsm_cmd,
9436 "debug pim bsm",
9437 DEBUG_STR
9438 DEBUG_PIM_STR
9439 DEBUG_PIM_BSM_STR)
9440 {
9441 PIM_DO_DEBUG_BSM;
9442 return CMD_SUCCESS;
9443 }
9444
9445 DEFUN (no_debug_bsm,
9446 no_debug_bsm_cmd,
9447 "no debug pim bsm",
9448 NO_STR
9449 DEBUG_STR
9450 DEBUG_PIM_STR
9451 DEBUG_PIM_BSM_STR)
9452 {
9453 PIM_DONT_DEBUG_BSM;
9454 return CMD_SUCCESS;
9455 }
9456
9457
9458 DEFUN_NOSH (show_debugging_pim,
9459 show_debugging_pim_cmd,
9460 "show debugging [pim]",
9461 SHOW_STR
9462 DEBUG_STR
9463 PIM_STR)
9464 {
9465 vty_out(vty, "PIM debugging status\n");
9466
9467 pim_debug_config_write(vty);
9468
9469 return CMD_SUCCESS;
9470 }
9471
9472 DEFUN (interface_pim_use_source,
9473 interface_pim_use_source_cmd,
9474 "ip pim use-source A.B.C.D",
9475 IP_STR
9476 PIM_STR
9477 "Configure primary IP address\n"
9478 "source ip address\n")
9479 {
9480 nb_cli_enqueue_change(vty, "./use-source", NB_OP_MODIFY, argv[3]->arg);
9481
9482 return nb_cli_apply_changes(vty,
9483 "./frr-pim:pim/address-family[address-family='%s']",
9484 "frr-routing:ipv4");
9485 }
9486
9487 DEFUN (interface_no_pim_use_source,
9488 interface_no_pim_use_source_cmd,
9489 "no ip pim use-source [A.B.C.D]",
9490 NO_STR
9491 IP_STR
9492 PIM_STR
9493 "Delete source IP address\n"
9494 "source ip address\n")
9495 {
9496 nb_cli_enqueue_change(vty, "./use-source", NB_OP_MODIFY, "0.0.0.0");
9497
9498 return nb_cli_apply_changes(vty,
9499 "./frr-pim:pim/address-family[address-family='%s']",
9500 "frr-routing:ipv4");
9501 }
9502
9503 DEFPY (ip_pim_bfd,
9504 ip_pim_bfd_cmd,
9505 "ip pim bfd [profile BFDPROF$prof]",
9506 IP_STR
9507 PIM_STR
9508 "Enables BFD support\n"
9509 "Use BFD profile\n"
9510 "Use BFD profile name\n")
9511 {
9512 const struct lyd_node *igmp_enable_dnode;
9513
9514 igmp_enable_dnode =
9515 yang_dnode_getf(vty->candidate_config->dnode,
9516 "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH);
9517 if (!igmp_enable_dnode)
9518 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9519 "true");
9520 else {
9521 if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
9522 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9523 "true");
9524 }
9525
9526 nb_cli_enqueue_change(vty, "./bfd", NB_OP_CREATE, NULL);
9527 if (prof)
9528 nb_cli_enqueue_change(vty, "./bfd/profile", NB_OP_MODIFY, prof);
9529
9530 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9531 }
9532
9533 DEFPY(no_ip_pim_bfd_profile, no_ip_pim_bfd_profile_cmd,
9534 "no ip pim bfd profile [BFDPROF]",
9535 NO_STR
9536 IP_STR
9537 PIM_STR
9538 "Enables BFD support\n"
9539 "Disable BFD profile\n"
9540 "BFD Profile name\n")
9541 {
9542 nb_cli_enqueue_change(vty, "./bfd/profile", NB_OP_DESTROY, NULL);
9543
9544 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9545 }
9546
9547 DEFUN (no_ip_pim_bfd,
9548 no_ip_pim_bfd_cmd,
9549 "no ip pim bfd",
9550 NO_STR
9551 IP_STR
9552 PIM_STR
9553 "Disables BFD support\n")
9554 {
9555 nb_cli_enqueue_change(vty, "./bfd", NB_OP_DESTROY, NULL);
9556
9557 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9558 }
9559
9560 DEFUN (ip_pim_bsm,
9561 ip_pim_bsm_cmd,
9562 "ip pim bsm",
9563 IP_STR
9564 PIM_STR
9565 "Enables BSM support on the interface\n")
9566 {
9567 const struct lyd_node *igmp_enable_dnode;
9568
9569 igmp_enable_dnode =
9570 yang_dnode_getf(vty->candidate_config->dnode,
9571 "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH);
9572 if (!igmp_enable_dnode)
9573 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9574 "true");
9575 else {
9576 if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
9577 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9578 "true");
9579 }
9580
9581 nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "true");
9582
9583 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9584 }
9585
9586 DEFUN (no_ip_pim_bsm,
9587 no_ip_pim_bsm_cmd,
9588 "no ip pim bsm",
9589 NO_STR
9590 IP_STR
9591 PIM_STR
9592 "Disables BSM support\n")
9593 {
9594 nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "false");
9595
9596 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9597 }
9598
9599 DEFUN (ip_pim_ucast_bsm,
9600 ip_pim_ucast_bsm_cmd,
9601 "ip pim unicast-bsm",
9602 IP_STR
9603 PIM_STR
9604 "Accept/Send unicast BSM on the interface\n")
9605 {
9606 const struct lyd_node *igmp_enable_dnode;
9607
9608 igmp_enable_dnode =
9609 yang_dnode_getf(vty->candidate_config->dnode,
9610 "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH);
9611 if (!igmp_enable_dnode)
9612 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9613 "true");
9614 else {
9615 if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
9616 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9617 "true");
9618 }
9619
9620 nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "true");
9621
9622 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9623 }
9624
9625 DEFUN (no_ip_pim_ucast_bsm,
9626 no_ip_pim_ucast_bsm_cmd,
9627 "no ip pim unicast-bsm",
9628 NO_STR
9629 IP_STR
9630 PIM_STR
9631 "Block send/receive unicast BSM on this interface\n")
9632 {
9633 nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "false");
9634
9635 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9636 }
9637
9638 #if HAVE_BFDD > 0
9639 DEFUN_HIDDEN(
9640 ip_pim_bfd_param,
9641 ip_pim_bfd_param_cmd,
9642 "ip pim bfd (2-255) (50-60000) (50-60000)",
9643 IP_STR
9644 PIM_STR
9645 "Enables BFD support\n"
9646 "Detect Multiplier\n"
9647 "Required min receive interval\n"
9648 "Desired min transmit interval\n")
9649 #else
9650 DEFUN(
9651 ip_pim_bfd_param,
9652 ip_pim_bfd_param_cmd,
9653 "ip pim bfd (2-255) (50-60000) (50-60000)",
9654 IP_STR
9655 PIM_STR
9656 "Enables BFD support\n"
9657 "Detect Multiplier\n"
9658 "Required min receive interval\n"
9659 "Desired min transmit interval\n")
9660 #endif /* HAVE_BFDD */
9661 {
9662 int idx_number = 3;
9663 int idx_number_2 = 4;
9664 int idx_number_3 = 5;
9665 const struct lyd_node *igmp_enable_dnode;
9666
9667 igmp_enable_dnode =
9668 yang_dnode_getf(vty->candidate_config->dnode,
9669 "%s/frr-igmp:igmp/igmp-enable", VTY_CURR_XPATH);
9670 if (!igmp_enable_dnode)
9671 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9672 "true");
9673 else {
9674 if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
9675 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
9676 "true");
9677 }
9678
9679 nb_cli_enqueue_change(vty, "./bfd", NB_OP_CREATE, NULL);
9680 nb_cli_enqueue_change(vty, "./bfd/min-rx-interval", NB_OP_MODIFY,
9681 argv[idx_number_2]->arg);
9682 nb_cli_enqueue_change(vty, "./bfd/min-tx-interval", NB_OP_MODIFY,
9683 argv[idx_number_3]->arg);
9684 nb_cli_enqueue_change(vty, "./bfd/detect_mult", NB_OP_MODIFY,
9685 argv[idx_number]->arg);
9686
9687 return nb_cli_apply_changes(vty, "./frr-pim:pim");
9688 }
9689
9690 #if HAVE_BFDD == 0
9691 ALIAS(no_ip_pim_bfd, no_ip_pim_bfd_param_cmd,
9692 "no ip pim bfd (2-255) (50-60000) (50-60000)", NO_STR IP_STR PIM_STR
9693 "Enables BFD support\n"
9694 "Detect Multiplier\n"
9695 "Required min receive interval\n"
9696 "Desired min transmit interval\n")
9697 #endif /* !HAVE_BFDD */
9698
9699 DEFPY(ip_msdp_peer, ip_msdp_peer_cmd,
9700 "ip msdp peer A.B.C.D$peer source A.B.C.D$source",
9701 IP_STR
9702 CFG_MSDP_STR
9703 "Configure MSDP peer\n"
9704 "Peer IP address\n"
9705 "Source address for TCP connection\n"
9706 "Local IP address\n")
9707 {
9708 const char *vrfname;
9709 char temp_xpath[XPATH_MAXLEN];
9710 char msdp_peer_source_xpath[XPATH_MAXLEN];
9711
9712 vrfname = pim_cli_get_vrf_name(vty);
9713 if (vrfname == NULL)
9714 return CMD_WARNING_CONFIG_FAILED;
9715
9716 snprintf(msdp_peer_source_xpath, sizeof(msdp_peer_source_xpath),
9717 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
9718 "frr-routing:ipv4");
9719 snprintf(temp_xpath, sizeof(temp_xpath),
9720 "/msdp-peer[peer-ip='%s']/source-ip", peer_str);
9721 strlcat(msdp_peer_source_xpath, temp_xpath,
9722 sizeof(msdp_peer_source_xpath));
9723
9724 nb_cli_enqueue_change(vty, msdp_peer_source_xpath, NB_OP_MODIFY,
9725 source_str);
9726
9727 return nb_cli_apply_changes(vty, NULL);
9728 }
9729
9730 DEFPY(ip_msdp_timers, ip_msdp_timers_cmd,
9731 "ip msdp timers (2-600)$keepalive (3-600)$holdtime [(1-600)$connretry]",
9732 IP_STR
9733 CFG_MSDP_STR
9734 "MSDP timers configuration\n"
9735 "Keep alive period (in seconds)\n"
9736 "Hold time period (in seconds)\n"
9737 "Connection retry period (in seconds)\n")
9738 {
9739 const char *vrfname;
9740 char xpath[XPATH_MAXLEN];
9741
9742 vrfname = pim_cli_get_vrf_name(vty);
9743 if (vrfname == NULL)
9744 return CMD_WARNING_CONFIG_FAILED;
9745
9746 snprintf(xpath, sizeof(xpath), FRR_PIM_MSDP_XPATH, "frr-pim:pimd",
9747 "pim", vrfname, "frr-routing:ipv4");
9748 nb_cli_enqueue_change(vty, "./hold-time", NB_OP_MODIFY, holdtime_str);
9749 nb_cli_enqueue_change(vty, "./keep-alive", NB_OP_MODIFY, keepalive_str);
9750 if (connretry_str)
9751 nb_cli_enqueue_change(vty, "./connection-retry", NB_OP_MODIFY,
9752 connretry_str);
9753 else
9754 nb_cli_enqueue_change(vty, "./connection-retry", NB_OP_DESTROY,
9755 NULL);
9756
9757 nb_cli_apply_changes(vty, xpath);
9758
9759 return CMD_SUCCESS;
9760 }
9761
9762 DEFUN (no_ip_msdp_peer,
9763 no_ip_msdp_peer_cmd,
9764 "no ip msdp peer A.B.C.D",
9765 NO_STR
9766 IP_STR
9767 CFG_MSDP_STR
9768 "Delete MSDP peer\n"
9769 "peer ip address\n")
9770 {
9771 const char *vrfname;
9772 char msdp_peer_xpath[XPATH_MAXLEN];
9773 char temp_xpath[XPATH_MAXLEN];
9774
9775 vrfname = pim_cli_get_vrf_name(vty);
9776 if (vrfname == NULL)
9777 return CMD_WARNING_CONFIG_FAILED;
9778
9779 snprintf(msdp_peer_xpath, sizeof(msdp_peer_xpath),
9780 FRR_PIM_AF_XPATH,
9781 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
9782 snprintf(temp_xpath, sizeof(temp_xpath),
9783 "/msdp-peer[peer-ip='%s']",
9784 argv[4]->arg);
9785
9786 strlcat(msdp_peer_xpath, temp_xpath, sizeof(msdp_peer_xpath));
9787
9788 nb_cli_enqueue_change(vty, msdp_peer_xpath, NB_OP_DESTROY, NULL);
9789
9790 return nb_cli_apply_changes(vty, NULL);
9791 }
9792
9793 DEFPY(ip_msdp_mesh_group_member,
9794 ip_msdp_mesh_group_member_cmd,
9795 "ip msdp mesh-group WORD$gname member A.B.C.D$maddr",
9796 IP_STR
9797 CFG_MSDP_STR
9798 "Configure MSDP mesh-group\n"
9799 "Mesh group name\n"
9800 "Mesh group member\n"
9801 "Peer IP address\n")
9802 {
9803 const char *vrfname;
9804 char xpath_value[XPATH_MAXLEN];
9805
9806 vrfname = pim_cli_get_vrf_name(vty);
9807 if (vrfname == NULL)
9808 return CMD_WARNING_CONFIG_FAILED;
9809
9810 /* Create mesh group. */
9811 snprintf(xpath_value, sizeof(xpath_value),
9812 FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']",
9813 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname);
9814 nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL);
9815
9816 /* Create mesh group member. */
9817 strlcat(xpath_value, "/members[address='", sizeof(xpath_value));
9818 strlcat(xpath_value, maddr_str, sizeof(xpath_value));
9819 strlcat(xpath_value, "']", sizeof(xpath_value));
9820 nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL);
9821
9822 return nb_cli_apply_changes(vty, NULL);
9823 }
9824
9825 DEFPY(no_ip_msdp_mesh_group_member,
9826 no_ip_msdp_mesh_group_member_cmd,
9827 "no ip msdp mesh-group WORD$gname member A.B.C.D$maddr",
9828 NO_STR
9829 IP_STR
9830 CFG_MSDP_STR
9831 "Delete MSDP mesh-group member\n"
9832 "Mesh group name\n"
9833 "Mesh group member\n"
9834 "Peer IP address\n")
9835 {
9836 const char *vrfname;
9837 char xpath_value[XPATH_MAXLEN];
9838 char xpath_member_value[XPATH_MAXLEN];
9839
9840 vrfname = pim_cli_get_vrf_name(vty);
9841 if (vrfname == NULL)
9842 return CMD_WARNING_CONFIG_FAILED;
9843
9844 /* Get mesh group base XPath. */
9845 snprintf(xpath_value, sizeof(xpath_value),
9846 FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']",
9847 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname);
9848
9849 if (!yang_dnode_exists(vty->candidate_config->dnode, xpath_value)) {
9850 vty_out(vty, "%% mesh-group does not exist\n");
9851 return CMD_WARNING_CONFIG_FAILED;
9852 }
9853
9854 /* Remove mesh group member. */
9855 strlcpy(xpath_member_value, xpath_value, sizeof(xpath_member_value));
9856 strlcat(xpath_member_value, "/members[address='",
9857 sizeof(xpath_member_value));
9858 strlcat(xpath_member_value, maddr_str, sizeof(xpath_member_value));
9859 strlcat(xpath_member_value, "']", sizeof(xpath_member_value));
9860 if (!yang_dnode_exists(vty->candidate_config->dnode,
9861 xpath_member_value)) {
9862 vty_out(vty, "%% mesh-group member does not exist\n");
9863 return CMD_WARNING_CONFIG_FAILED;
9864 }
9865
9866 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL);
9867
9868 /*
9869 * If this is the last member, then we must remove the group altogether
9870 * to not break legacy CLI behaviour.
9871 */
9872 pim_cli_legacy_mesh_group_behavior(vty, gname);
9873
9874 return nb_cli_apply_changes(vty, NULL);
9875 }
9876
9877 DEFPY(ip_msdp_mesh_group_source,
9878 ip_msdp_mesh_group_source_cmd,
9879 "ip msdp mesh-group WORD$gname source A.B.C.D$saddr",
9880 IP_STR
9881 CFG_MSDP_STR
9882 "Configure MSDP mesh-group\n"
9883 "Mesh group name\n"
9884 "Mesh group local address\n"
9885 "Source IP address for the TCP connection\n")
9886 {
9887 const char *vrfname;
9888 char xpath_value[XPATH_MAXLEN];
9889
9890 vrfname = pim_cli_get_vrf_name(vty);
9891 if (vrfname == NULL)
9892 return CMD_WARNING_CONFIG_FAILED;
9893
9894 /* Create mesh group. */
9895 snprintf(xpath_value, sizeof(xpath_value),
9896 FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']",
9897 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname);
9898 nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL);
9899
9900 /* Create mesh group member. */
9901 strlcat(xpath_value, "/source", sizeof(xpath_value));
9902 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, saddr_str);
9903
9904 return nb_cli_apply_changes(vty, NULL);
9905 }
9906
9907 DEFPY(no_ip_msdp_mesh_group_source,
9908 no_ip_msdp_mesh_group_source_cmd,
9909 "no ip msdp mesh-group WORD$gname source [A.B.C.D]",
9910 NO_STR
9911 IP_STR
9912 CFG_MSDP_STR
9913 "Delete MSDP mesh-group source\n"
9914 "Mesh group name\n"
9915 "Mesh group source\n"
9916 "Mesh group local address\n")
9917 {
9918 const char *vrfname;
9919 char xpath_value[XPATH_MAXLEN];
9920
9921 vrfname = pim_cli_get_vrf_name(vty);
9922 if (vrfname == NULL)
9923 return CMD_WARNING_CONFIG_FAILED;
9924
9925 /* Get mesh group base XPath. */
9926 snprintf(xpath_value, sizeof(xpath_value),
9927 FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']",
9928 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname);
9929 nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL);
9930
9931 /* Create mesh group member. */
9932 strlcat(xpath_value, "/source", sizeof(xpath_value));
9933 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL);
9934
9935 /*
9936 * If this is the last member, then we must remove the group altogether
9937 * to not break legacy CLI behaviour.
9938 */
9939 pim_cli_legacy_mesh_group_behavior(vty, gname);
9940
9941 return nb_cli_apply_changes(vty, NULL);
9942 }
9943
9944 DEFPY(no_ip_msdp_mesh_group,
9945 no_ip_msdp_mesh_group_cmd,
9946 "no ip msdp mesh-group WORD$gname",
9947 NO_STR
9948 IP_STR
9949 CFG_MSDP_STR
9950 "Delete MSDP mesh-group\n"
9951 "Mesh group name")
9952 {
9953 const char *vrfname;
9954 char xpath_value[XPATH_MAXLEN];
9955
9956 vrfname = pim_cli_get_vrf_name(vty);
9957 if (vrfname == NULL)
9958 return CMD_WARNING_CONFIG_FAILED;
9959
9960 /* Get mesh group base XPath. */
9961 snprintf(xpath_value, sizeof(xpath_value),
9962 FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']",
9963 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname);
9964 if (!yang_dnode_exists(vty->candidate_config->dnode, xpath_value))
9965 return CMD_SUCCESS;
9966
9967 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL);
9968 return nb_cli_apply_changes(vty, NULL);
9969 }
9970
9971 static void ip_msdp_show_mesh_group(struct vty *vty, struct pim_msdp_mg *mg,
9972 struct json_object *json)
9973 {
9974 struct listnode *mbrnode;
9975 struct pim_msdp_mg_mbr *mbr;
9976 char mbr_str[INET_ADDRSTRLEN];
9977 char src_str[INET_ADDRSTRLEN];
9978 char state_str[PIM_MSDP_STATE_STRLEN];
9979 enum pim_msdp_peer_state state;
9980 json_object *json_mg_row = NULL;
9981 json_object *json_members = NULL;
9982 json_object *json_row = NULL;
9983
9984 pim_inet4_dump("<source?>", mg->src_ip, src_str, sizeof(src_str));
9985 if (json) {
9986 /* currently there is only one mesh group but we should still
9987 * make
9988 * it a dict with mg-name as key */
9989 json_mg_row = json_object_new_object();
9990 json_object_string_add(json_mg_row, "name",
9991 mg->mesh_group_name);
9992 json_object_string_add(json_mg_row, "source", src_str);
9993 } else {
9994 vty_out(vty, "Mesh group : %s\n", mg->mesh_group_name);
9995 vty_out(vty, " Source : %s\n", src_str);
9996 vty_out(vty, " Member State\n");
9997 }
9998
9999 for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) {
10000 pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str));
10001 if (mbr->mp) {
10002 state = mbr->mp->state;
10003 } else {
10004 state = PIM_MSDP_DISABLED;
10005 }
10006 pim_msdp_state_dump(state, state_str, sizeof(state_str));
10007 if (json) {
10008 json_row = json_object_new_object();
10009 json_object_string_add(json_row, "member", mbr_str);
10010 json_object_string_add(json_row, "state", state_str);
10011 if (!json_members) {
10012 json_members = json_object_new_object();
10013 json_object_object_add(json_mg_row, "members",
10014 json_members);
10015 }
10016 json_object_object_add(json_members, mbr_str, json_row);
10017 } else {
10018 vty_out(vty, " %-15s %11s\n", mbr_str, state_str);
10019 }
10020 }
10021
10022 if (json)
10023 json_object_object_add(json, mg->mesh_group_name, json_mg_row);
10024 }
10025
10026 DEFUN (show_ip_msdp_mesh_group,
10027 show_ip_msdp_mesh_group_cmd,
10028 "show ip msdp [vrf NAME] mesh-group [json]",
10029 SHOW_STR
10030 IP_STR
10031 MSDP_STR
10032 VRF_CMD_HELP_STR
10033 "MSDP mesh-group information\n"
10034 JSON_STR)
10035 {
10036 bool uj = use_json(argc, argv);
10037 int idx = 2;
10038 struct pim_msdp_mg *mg;
10039 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10040 struct pim_instance *pim = vrf->info;
10041 struct json_object *json = NULL;
10042
10043 if (!vrf)
10044 return CMD_WARNING;
10045
10046 /* Quick case: list is empty. */
10047 if (SLIST_EMPTY(&pim->msdp.mglist)) {
10048 if (uj)
10049 vty_out(vty, "{}\n");
10050
10051 return CMD_SUCCESS;
10052 }
10053
10054 if (uj)
10055 json = json_object_new_object();
10056
10057 SLIST_FOREACH (mg, &pim->msdp.mglist, mg_entry)
10058 ip_msdp_show_mesh_group(vty, mg, json);
10059
10060 if (uj) {
10061 vty_out(vty, "%s\n",
10062 json_object_to_json_string_ext(
10063 json, JSON_C_TO_STRING_PRETTY));
10064 json_object_free(json);
10065 }
10066
10067 return CMD_SUCCESS;
10068 }
10069
10070 DEFUN (show_ip_msdp_mesh_group_vrf_all,
10071 show_ip_msdp_mesh_group_vrf_all_cmd,
10072 "show ip msdp vrf all mesh-group [json]",
10073 SHOW_STR
10074 IP_STR
10075 MSDP_STR
10076 VRF_CMD_HELP_STR
10077 "MSDP mesh-group information\n"
10078 JSON_STR)
10079 {
10080 bool uj = use_json(argc, argv);
10081 struct json_object *json = NULL, *vrf_json = NULL;
10082 struct pim_instance *pim;
10083 struct pim_msdp_mg *mg;
10084 struct vrf *vrf;
10085
10086 if (uj)
10087 json = json_object_new_object();
10088
10089 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
10090 if (uj) {
10091 vrf_json = json_object_new_object();
10092 json_object_object_add(json, vrf->name, vrf_json);
10093 } else
10094 vty_out(vty, "VRF: %s\n", vrf->name);
10095
10096 pim = vrf->info;
10097 SLIST_FOREACH (mg, &pim->msdp.mglist, mg_entry)
10098 ip_msdp_show_mesh_group(vty, mg, vrf_json);
10099 }
10100
10101 if (uj) {
10102 vty_out(vty, "%s\n",
10103 json_object_to_json_string_ext(
10104 json, JSON_C_TO_STRING_PRETTY));
10105 json_object_free(json);
10106 }
10107
10108 return CMD_SUCCESS;
10109 }
10110
10111 static void ip_msdp_show_peers(struct pim_instance *pim, struct vty *vty,
10112 bool uj)
10113 {
10114 struct listnode *mpnode;
10115 struct pim_msdp_peer *mp;
10116 char peer_str[INET_ADDRSTRLEN];
10117 char local_str[INET_ADDRSTRLEN];
10118 char state_str[PIM_MSDP_STATE_STRLEN];
10119 char timebuf[PIM_MSDP_UPTIME_STRLEN];
10120 int64_t now;
10121 json_object *json = NULL;
10122 json_object *json_row = NULL;
10123
10124
10125 if (uj) {
10126 json = json_object_new_object();
10127 } else {
10128 vty_out(vty,
10129 "Peer Local State Uptime SaCnt\n");
10130 }
10131
10132 for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, mpnode, mp)) {
10133 if (mp->state == PIM_MSDP_ESTABLISHED) {
10134 now = pim_time_monotonic_sec();
10135 pim_time_uptime(timebuf, sizeof(timebuf),
10136 now - mp->uptime);
10137 } else {
10138 strlcpy(timebuf, "-", sizeof(timebuf));
10139 }
10140 pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
10141 pim_inet4_dump("<local?>", mp->local, local_str,
10142 sizeof(local_str));
10143 pim_msdp_state_dump(mp->state, state_str, sizeof(state_str));
10144 if (uj) {
10145 json_row = json_object_new_object();
10146 json_object_string_add(json_row, "peer", peer_str);
10147 json_object_string_add(json_row, "local", local_str);
10148 json_object_string_add(json_row, "state", state_str);
10149 json_object_string_add(json_row, "upTime", timebuf);
10150 json_object_int_add(json_row, "saCount", mp->sa_cnt);
10151 json_object_object_add(json, peer_str, json_row);
10152 } else {
10153 vty_out(vty, "%-15s %15s %11s %8s %6d\n", peer_str,
10154 local_str, state_str, timebuf, mp->sa_cnt);
10155 }
10156 }
10157
10158 if (uj) {
10159 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10160 json, JSON_C_TO_STRING_PRETTY));
10161 json_object_free(json);
10162 }
10163 }
10164
10165 static void ip_msdp_show_peers_detail(struct pim_instance *pim, struct vty *vty,
10166 const char *peer, bool uj)
10167 {
10168 struct listnode *mpnode;
10169 struct pim_msdp_peer *mp;
10170 char peer_str[INET_ADDRSTRLEN];
10171 char local_str[INET_ADDRSTRLEN];
10172 char state_str[PIM_MSDP_STATE_STRLEN];
10173 char timebuf[PIM_MSDP_UPTIME_STRLEN];
10174 char katimer[PIM_MSDP_TIMER_STRLEN];
10175 char crtimer[PIM_MSDP_TIMER_STRLEN];
10176 char holdtimer[PIM_MSDP_TIMER_STRLEN];
10177 int64_t now;
10178 json_object *json = NULL;
10179 json_object *json_row = NULL;
10180
10181 if (uj) {
10182 json = json_object_new_object();
10183 }
10184
10185 for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, mpnode, mp)) {
10186 pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
10187 if (strcmp(peer, "detail") && strcmp(peer, peer_str))
10188 continue;
10189
10190 if (mp->state == PIM_MSDP_ESTABLISHED) {
10191 now = pim_time_monotonic_sec();
10192 pim_time_uptime(timebuf, sizeof(timebuf),
10193 now - mp->uptime);
10194 } else {
10195 strlcpy(timebuf, "-", sizeof(timebuf));
10196 }
10197 pim_inet4_dump("<local?>", mp->local, local_str,
10198 sizeof(local_str));
10199 pim_msdp_state_dump(mp->state, state_str, sizeof(state_str));
10200 pim_time_timer_to_hhmmss(katimer, sizeof(katimer),
10201 mp->ka_timer);
10202 pim_time_timer_to_hhmmss(crtimer, sizeof(crtimer),
10203 mp->cr_timer);
10204 pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer),
10205 mp->hold_timer);
10206
10207 if (uj) {
10208 json_row = json_object_new_object();
10209 json_object_string_add(json_row, "peer", peer_str);
10210 json_object_string_add(json_row, "local", local_str);
10211 if (mp->flags & PIM_MSDP_PEERF_IN_GROUP)
10212 json_object_string_add(json_row,
10213 "meshGroupName",
10214 mp->mesh_group_name);
10215 json_object_string_add(json_row, "state", state_str);
10216 json_object_string_add(json_row, "upTime", timebuf);
10217 json_object_string_add(json_row, "keepAliveTimer",
10218 katimer);
10219 json_object_string_add(json_row, "connRetryTimer",
10220 crtimer);
10221 json_object_string_add(json_row, "holdTimer",
10222 holdtimer);
10223 json_object_string_add(json_row, "lastReset",
10224 mp->last_reset);
10225 json_object_int_add(json_row, "connAttempts",
10226 mp->conn_attempts);
10227 json_object_int_add(json_row, "establishedChanges",
10228 mp->est_flaps);
10229 json_object_int_add(json_row, "saCount", mp->sa_cnt);
10230 json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt);
10231 json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt);
10232 json_object_int_add(json_row, "saSent", mp->sa_tx_cnt);
10233 json_object_int_add(json_row, "saRcvd", mp->sa_rx_cnt);
10234 json_object_object_add(json, peer_str, json_row);
10235 } else {
10236 vty_out(vty, "Peer : %s\n", peer_str);
10237 vty_out(vty, " Local : %s\n", local_str);
10238 if (mp->flags & PIM_MSDP_PEERF_IN_GROUP)
10239 vty_out(vty, " Mesh Group : %s\n",
10240 mp->mesh_group_name);
10241 vty_out(vty, " State : %s\n", state_str);
10242 vty_out(vty, " Uptime : %s\n", timebuf);
10243
10244 vty_out(vty, " Keepalive Timer : %s\n", katimer);
10245 vty_out(vty, " Conn Retry Timer : %s\n", crtimer);
10246 vty_out(vty, " Hold Timer : %s\n", holdtimer);
10247 vty_out(vty, " Last Reset : %s\n",
10248 mp->last_reset);
10249 vty_out(vty, " Conn Attempts : %d\n",
10250 mp->conn_attempts);
10251 vty_out(vty, " Established Changes : %d\n",
10252 mp->est_flaps);
10253 vty_out(vty, " SA Count : %d\n",
10254 mp->sa_cnt);
10255 vty_out(vty, " Statistics :\n");
10256 vty_out(vty,
10257 " Sent Rcvd\n");
10258 vty_out(vty, " Keepalives : %10d %10d\n",
10259 mp->ka_tx_cnt, mp->ka_rx_cnt);
10260 vty_out(vty, " SAs : %10d %10d\n",
10261 mp->sa_tx_cnt, mp->sa_rx_cnt);
10262 vty_out(vty, "\n");
10263 }
10264 }
10265
10266 if (uj) {
10267 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10268 json, JSON_C_TO_STRING_PRETTY));
10269 json_object_free(json);
10270 }
10271 }
10272
10273 DEFUN (show_ip_msdp_peer_detail,
10274 show_ip_msdp_peer_detail_cmd,
10275 "show ip msdp [vrf NAME] peer [detail|A.B.C.D] [json]",
10276 SHOW_STR
10277 IP_STR
10278 MSDP_STR
10279 VRF_CMD_HELP_STR
10280 "MSDP peer information\n"
10281 "Detailed output\n"
10282 "peer ip address\n"
10283 JSON_STR)
10284 {
10285 bool uj = use_json(argc, argv);
10286 int idx = 2;
10287 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10288
10289 if (!vrf)
10290 return CMD_WARNING;
10291
10292 char *arg = NULL;
10293
10294 if (argv_find(argv, argc, "detail", &idx))
10295 arg = argv[idx]->text;
10296 else if (argv_find(argv, argc, "A.B.C.D", &idx))
10297 arg = argv[idx]->arg;
10298
10299 if (arg)
10300 ip_msdp_show_peers_detail(vrf->info, vty, argv[idx]->arg, uj);
10301 else
10302 ip_msdp_show_peers(vrf->info, vty, uj);
10303
10304 return CMD_SUCCESS;
10305 }
10306
10307 DEFUN (show_ip_msdp_peer_detail_vrf_all,
10308 show_ip_msdp_peer_detail_vrf_all_cmd,
10309 "show ip msdp vrf all peer [detail|A.B.C.D] [json]",
10310 SHOW_STR
10311 IP_STR
10312 MSDP_STR
10313 VRF_CMD_HELP_STR
10314 "MSDP peer information\n"
10315 "Detailed output\n"
10316 "peer ip address\n"
10317 JSON_STR)
10318 {
10319 int idx = 2;
10320 bool uj = use_json(argc, argv);
10321 struct vrf *vrf;
10322 bool first = true;
10323
10324 if (uj)
10325 vty_out(vty, "{ ");
10326 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
10327 if (uj) {
10328 if (!first)
10329 vty_out(vty, ", ");
10330 vty_out(vty, " \"%s\": ", vrf->name);
10331 first = false;
10332 } else
10333 vty_out(vty, "VRF: %s\n", vrf->name);
10334 if (argv_find(argv, argc, "detail", &idx)
10335 || argv_find(argv, argc, "A.B.C.D", &idx))
10336 ip_msdp_show_peers_detail(vrf->info, vty,
10337 argv[idx]->arg, uj);
10338 else
10339 ip_msdp_show_peers(vrf->info, vty, uj);
10340 }
10341 if (uj)
10342 vty_out(vty, "}\n");
10343
10344 return CMD_SUCCESS;
10345 }
10346
10347 static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty, bool uj)
10348 {
10349 struct listnode *sanode;
10350 struct pim_msdp_sa *sa;
10351 char src_str[INET_ADDRSTRLEN];
10352 char grp_str[INET_ADDRSTRLEN];
10353 char rp_str[INET_ADDRSTRLEN];
10354 char timebuf[PIM_MSDP_UPTIME_STRLEN];
10355 char spt_str[8];
10356 char local_str[8];
10357 int64_t now;
10358 json_object *json = NULL;
10359 json_object *json_group = NULL;
10360 json_object *json_row = NULL;
10361
10362 if (uj) {
10363 json = json_object_new_object();
10364 } else {
10365 vty_out(vty,
10366 "Source Group RP Local SPT Uptime\n");
10367 }
10368
10369 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
10370 now = pim_time_monotonic_sec();
10371 pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime);
10372 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
10373 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
10374 if (sa->flags & PIM_MSDP_SAF_PEER) {
10375 pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
10376 if (sa->up) {
10377 strlcpy(spt_str, "yes", sizeof(spt_str));
10378 } else {
10379 strlcpy(spt_str, "no", sizeof(spt_str));
10380 }
10381 } else {
10382 strlcpy(rp_str, "-", sizeof(rp_str));
10383 strlcpy(spt_str, "-", sizeof(spt_str));
10384 }
10385 if (sa->flags & PIM_MSDP_SAF_LOCAL) {
10386 strlcpy(local_str, "yes", sizeof(local_str));
10387 } else {
10388 strlcpy(local_str, "no", sizeof(local_str));
10389 }
10390 if (uj) {
10391 json_object_object_get_ex(json, grp_str, &json_group);
10392
10393 if (!json_group) {
10394 json_group = json_object_new_object();
10395 json_object_object_add(json, grp_str,
10396 json_group);
10397 }
10398
10399 json_row = json_object_new_object();
10400 json_object_string_add(json_row, "source", src_str);
10401 json_object_string_add(json_row, "group", grp_str);
10402 json_object_string_add(json_row, "rp", rp_str);
10403 json_object_string_add(json_row, "local", local_str);
10404 json_object_string_add(json_row, "sptSetup", spt_str);
10405 json_object_string_add(json_row, "upTime", timebuf);
10406 json_object_object_add(json_group, src_str, json_row);
10407 } else {
10408 vty_out(vty, "%-15s %15s %15s %5c %3c %8s\n",
10409 src_str, grp_str, rp_str, local_str[0],
10410 spt_str[0], timebuf);
10411 }
10412 }
10413
10414 if (uj) {
10415 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10416 json, JSON_C_TO_STRING_PRETTY));
10417 json_object_free(json);
10418 }
10419 }
10420
10421 static void ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa,
10422 const char *src_str,
10423 const char *grp_str, struct vty *vty,
10424 bool uj, json_object *json)
10425 {
10426 char rp_str[INET_ADDRSTRLEN];
10427 char peer_str[INET_ADDRSTRLEN];
10428 char timebuf[PIM_MSDP_UPTIME_STRLEN];
10429 char spt_str[8];
10430 char local_str[8];
10431 char statetimer[PIM_MSDP_TIMER_STRLEN];
10432 int64_t now;
10433 json_object *json_group = NULL;
10434 json_object *json_row = NULL;
10435
10436 now = pim_time_monotonic_sec();
10437 pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime);
10438 if (sa->flags & PIM_MSDP_SAF_PEER) {
10439 pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
10440 pim_inet4_dump("<peer?>", sa->peer, peer_str, sizeof(peer_str));
10441 if (sa->up) {
10442 strlcpy(spt_str, "yes", sizeof(spt_str));
10443 } else {
10444 strlcpy(spt_str, "no", sizeof(spt_str));
10445 }
10446 } else {
10447 strlcpy(rp_str, "-", sizeof(rp_str));
10448 strlcpy(peer_str, "-", sizeof(peer_str));
10449 strlcpy(spt_str, "-", sizeof(spt_str));
10450 }
10451 if (sa->flags & PIM_MSDP_SAF_LOCAL) {
10452 strlcpy(local_str, "yes", sizeof(local_str));
10453 } else {
10454 strlcpy(local_str, "no", sizeof(local_str));
10455 }
10456 pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer),
10457 sa->sa_state_timer);
10458 if (uj) {
10459 json_object_object_get_ex(json, grp_str, &json_group);
10460
10461 if (!json_group) {
10462 json_group = json_object_new_object();
10463 json_object_object_add(json, grp_str, json_group);
10464 }
10465
10466 json_row = json_object_new_object();
10467 json_object_string_add(json_row, "source", src_str);
10468 json_object_string_add(json_row, "group", grp_str);
10469 json_object_string_add(json_row, "rp", rp_str);
10470 json_object_string_add(json_row, "local", local_str);
10471 json_object_string_add(json_row, "sptSetup", spt_str);
10472 json_object_string_add(json_row, "upTime", timebuf);
10473 json_object_string_add(json_row, "stateTimer", statetimer);
10474 json_object_object_add(json_group, src_str, json_row);
10475 } else {
10476 vty_out(vty, "SA : %s\n", sa->sg_str);
10477 vty_out(vty, " RP : %s\n", rp_str);
10478 vty_out(vty, " Peer : %s\n", peer_str);
10479 vty_out(vty, " Local : %s\n", local_str);
10480 vty_out(vty, " SPT Setup : %s\n", spt_str);
10481 vty_out(vty, " Uptime : %s\n", timebuf);
10482 vty_out(vty, " State Timer : %s\n", statetimer);
10483 vty_out(vty, "\n");
10484 }
10485 }
10486
10487 static void ip_msdp_show_sa_detail(struct pim_instance *pim, struct vty *vty,
10488 bool uj)
10489 {
10490 struct listnode *sanode;
10491 struct pim_msdp_sa *sa;
10492 char src_str[INET_ADDRSTRLEN];
10493 char grp_str[INET_ADDRSTRLEN];
10494 json_object *json = NULL;
10495
10496 if (uj) {
10497 json = json_object_new_object();
10498 }
10499
10500 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
10501 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
10502 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
10503 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj,
10504 json);
10505 }
10506
10507 if (uj) {
10508 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10509 json, JSON_C_TO_STRING_PRETTY));
10510 json_object_free(json);
10511 }
10512 }
10513
10514 DEFUN (show_ip_msdp_sa_detail,
10515 show_ip_msdp_sa_detail_cmd,
10516 "show ip msdp [vrf NAME] sa detail [json]",
10517 SHOW_STR
10518 IP_STR
10519 MSDP_STR
10520 VRF_CMD_HELP_STR
10521 "MSDP active-source information\n"
10522 "Detailed output\n"
10523 JSON_STR)
10524 {
10525 bool uj = use_json(argc, argv);
10526 int idx = 2;
10527 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10528
10529 if (!vrf)
10530 return CMD_WARNING;
10531
10532 ip_msdp_show_sa_detail(vrf->info, vty, uj);
10533
10534 return CMD_SUCCESS;
10535 }
10536
10537 DEFUN (show_ip_msdp_sa_detail_vrf_all,
10538 show_ip_msdp_sa_detail_vrf_all_cmd,
10539 "show ip msdp vrf all sa detail [json]",
10540 SHOW_STR
10541 IP_STR
10542 MSDP_STR
10543 VRF_CMD_HELP_STR
10544 "MSDP active-source information\n"
10545 "Detailed output\n"
10546 JSON_STR)
10547 {
10548 bool uj = use_json(argc, argv);
10549 struct vrf *vrf;
10550 bool first = true;
10551
10552 if (uj)
10553 vty_out(vty, "{ ");
10554 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
10555 if (uj) {
10556 if (!first)
10557 vty_out(vty, ", ");
10558 vty_out(vty, " \"%s\": ", vrf->name);
10559 first = false;
10560 } else
10561 vty_out(vty, "VRF: %s\n", vrf->name);
10562 ip_msdp_show_sa_detail(vrf->info, vty, uj);
10563 }
10564 if (uj)
10565 vty_out(vty, "}\n");
10566
10567 return CMD_SUCCESS;
10568 }
10569
10570 static void ip_msdp_show_sa_addr(struct pim_instance *pim, struct vty *vty,
10571 const char *addr, bool uj)
10572 {
10573 struct listnode *sanode;
10574 struct pim_msdp_sa *sa;
10575 char src_str[INET_ADDRSTRLEN];
10576 char grp_str[INET_ADDRSTRLEN];
10577 json_object *json = NULL;
10578
10579 if (uj) {
10580 json = json_object_new_object();
10581 }
10582
10583 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
10584 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
10585 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
10586 if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) {
10587 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty,
10588 uj, json);
10589 }
10590 }
10591
10592 if (uj) {
10593 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10594 json, JSON_C_TO_STRING_PRETTY));
10595 json_object_free(json);
10596 }
10597 }
10598
10599 static void ip_msdp_show_sa_sg(struct pim_instance *pim, struct vty *vty,
10600 const char *src, const char *grp, bool uj)
10601 {
10602 struct listnode *sanode;
10603 struct pim_msdp_sa *sa;
10604 char src_str[INET_ADDRSTRLEN];
10605 char grp_str[INET_ADDRSTRLEN];
10606 json_object *json = NULL;
10607
10608 if (uj) {
10609 json = json_object_new_object();
10610 }
10611
10612 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
10613 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
10614 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
10615 if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) {
10616 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty,
10617 uj, json);
10618 }
10619 }
10620
10621 if (uj) {
10622 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10623 json, JSON_C_TO_STRING_PRETTY));
10624 json_object_free(json);
10625 }
10626 }
10627
10628 DEFUN (show_ip_msdp_sa_sg,
10629 show_ip_msdp_sa_sg_cmd,
10630 "show ip msdp [vrf NAME] sa [A.B.C.D [A.B.C.D]] [json]",
10631 SHOW_STR
10632 IP_STR
10633 MSDP_STR
10634 VRF_CMD_HELP_STR
10635 "MSDP active-source information\n"
10636 "source or group ip\n"
10637 "group ip\n"
10638 JSON_STR)
10639 {
10640 bool uj = use_json(argc, argv);
10641 struct vrf *vrf;
10642 int idx = 2;
10643
10644 vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10645
10646 if (!vrf)
10647 return CMD_WARNING;
10648
10649 char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg
10650 : NULL;
10651 char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx)
10652 ? argv[idx]->arg
10653 : NULL;
10654
10655 if (src_ip && grp_ip)
10656 ip_msdp_show_sa_sg(vrf->info, vty, src_ip, grp_ip, uj);
10657 else if (src_ip)
10658 ip_msdp_show_sa_addr(vrf->info, vty, src_ip, uj);
10659 else
10660 ip_msdp_show_sa(vrf->info, vty, uj);
10661
10662 return CMD_SUCCESS;
10663 }
10664
10665 DEFUN (show_ip_msdp_sa_sg_vrf_all,
10666 show_ip_msdp_sa_sg_vrf_all_cmd,
10667 "show ip msdp vrf all sa [A.B.C.D [A.B.C.D]] [json]",
10668 SHOW_STR
10669 IP_STR
10670 MSDP_STR
10671 VRF_CMD_HELP_STR
10672 "MSDP active-source information\n"
10673 "source or group ip\n"
10674 "group ip\n"
10675 JSON_STR)
10676 {
10677 bool uj = use_json(argc, argv);
10678 struct vrf *vrf;
10679 bool first = true;
10680 int idx = 2;
10681
10682 char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg
10683 : NULL;
10684 char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx)
10685 ? argv[idx]->arg
10686 : NULL;
10687
10688 if (uj)
10689 vty_out(vty, "{ ");
10690 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
10691 if (uj) {
10692 if (!first)
10693 vty_out(vty, ", ");
10694 vty_out(vty, " \"%s\": ", vrf->name);
10695 first = false;
10696 } else
10697 vty_out(vty, "VRF: %s\n", vrf->name);
10698
10699 if (src_ip && grp_ip)
10700 ip_msdp_show_sa_sg(vrf->info, vty, src_ip, grp_ip, uj);
10701 else if (src_ip)
10702 ip_msdp_show_sa_addr(vrf->info, vty, src_ip, uj);
10703 else
10704 ip_msdp_show_sa(vrf->info, vty, uj);
10705 }
10706 if (uj)
10707 vty_out(vty, "}\n");
10708
10709 return CMD_SUCCESS;
10710 }
10711
10712 struct pim_sg_cache_walk_data {
10713 struct vty *vty;
10714 json_object *json;
10715 json_object *json_group;
10716 struct in_addr addr;
10717 bool addr_match;
10718 };
10719
10720 static void pim_show_vxlan_sg_entry(struct pim_vxlan_sg *vxlan_sg,
10721 struct pim_sg_cache_walk_data *cwd)
10722 {
10723 struct vty *vty = cwd->vty;
10724 json_object *json = cwd->json;
10725 char src_str[INET_ADDRSTRLEN];
10726 char grp_str[INET_ADDRSTRLEN];
10727 json_object *json_row;
10728 bool installed = (vxlan_sg->up) ? true : false;
10729 const char *iif_name = vxlan_sg->iif?vxlan_sg->iif->name:"-";
10730 const char *oif_name;
10731
10732 if (pim_vxlan_is_orig_mroute(vxlan_sg))
10733 oif_name = vxlan_sg->orig_oif?vxlan_sg->orig_oif->name:"";
10734 else
10735 oif_name = vxlan_sg->term_oif?vxlan_sg->term_oif->name:"";
10736
10737 if (cwd->addr_match && (vxlan_sg->sg.src.s_addr != cwd->addr.s_addr) &&
10738 (vxlan_sg->sg.grp.s_addr != cwd->addr.s_addr)) {
10739 return;
10740 }
10741 pim_inet4_dump("<src?>", vxlan_sg->sg.src, src_str, sizeof(src_str));
10742 pim_inet4_dump("<grp?>", vxlan_sg->sg.grp, grp_str, sizeof(grp_str));
10743 if (json) {
10744 json_object_object_get_ex(json, grp_str, &cwd->json_group);
10745
10746 if (!cwd->json_group) {
10747 cwd->json_group = json_object_new_object();
10748 json_object_object_add(json, grp_str,
10749 cwd->json_group);
10750 }
10751
10752 json_row = json_object_new_object();
10753 json_object_string_add(json_row, "source", src_str);
10754 json_object_string_add(json_row, "group", grp_str);
10755 json_object_string_add(json_row, "input", iif_name);
10756 json_object_string_add(json_row, "output", oif_name);
10757 if (installed)
10758 json_object_boolean_true_add(json_row, "installed");
10759 else
10760 json_object_boolean_false_add(json_row, "installed");
10761 json_object_object_add(cwd->json_group, src_str, json_row);
10762 } else {
10763 vty_out(vty, "%-15s %-15s %-15s %-15s %-5s\n",
10764 src_str, grp_str, iif_name, oif_name,
10765 installed?"I":"");
10766 }
10767 }
10768
10769 static void pim_show_vxlan_sg_hash_entry(struct hash_bucket *bucket, void *arg)
10770 {
10771 pim_show_vxlan_sg_entry((struct pim_vxlan_sg *)bucket->data,
10772 (struct pim_sg_cache_walk_data *)arg);
10773 }
10774
10775 static void pim_show_vxlan_sg(struct pim_instance *pim,
10776 struct vty *vty, bool uj)
10777 {
10778 json_object *json = NULL;
10779 struct pim_sg_cache_walk_data cwd;
10780
10781 if (uj) {
10782 json = json_object_new_object();
10783 } else {
10784 vty_out(vty, "Codes: I -> installed\n");
10785 vty_out(vty,
10786 "Source Group Input Output Flags\n");
10787 }
10788
10789 memset(&cwd, 0, sizeof(cwd));
10790 cwd.vty = vty;
10791 cwd.json = json;
10792 hash_iterate(pim->vxlan.sg_hash, pim_show_vxlan_sg_hash_entry, &cwd);
10793
10794 if (uj) {
10795 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10796 json, JSON_C_TO_STRING_PRETTY));
10797 json_object_free(json);
10798 }
10799 }
10800
10801 static void pim_show_vxlan_sg_match_addr(struct pim_instance *pim,
10802 struct vty *vty, char *addr_str,
10803 bool uj)
10804 {
10805 json_object *json = NULL;
10806 struct pim_sg_cache_walk_data cwd;
10807 int result = 0;
10808
10809 memset(&cwd, 0, sizeof(cwd));
10810 result = inet_pton(AF_INET, addr_str, &cwd.addr);
10811 if (result <= 0) {
10812 vty_out(vty, "Bad address %s: errno=%d: %s\n", addr_str,
10813 errno, safe_strerror(errno));
10814 return;
10815 }
10816
10817 if (uj) {
10818 json = json_object_new_object();
10819 } else {
10820 vty_out(vty, "Codes: I -> installed\n");
10821 vty_out(vty,
10822 "Source Group Input Output Flags\n");
10823 }
10824
10825 cwd.vty = vty;
10826 cwd.json = json;
10827 cwd.addr_match = true;
10828 hash_iterate(pim->vxlan.sg_hash, pim_show_vxlan_sg_hash_entry, &cwd);
10829
10830 if (uj) {
10831 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10832 json, JSON_C_TO_STRING_PRETTY));
10833 json_object_free(json);
10834 }
10835 }
10836
10837 static void pim_show_vxlan_sg_one(struct pim_instance *pim,
10838 struct vty *vty, char *src_str, char *grp_str,
10839 bool uj)
10840 {
10841 json_object *json = NULL;
10842 struct prefix_sg sg;
10843 int result = 0;
10844 struct pim_vxlan_sg *vxlan_sg;
10845 const char *iif_name;
10846 bool installed;
10847 const char *oif_name;
10848
10849 result = inet_pton(AF_INET, src_str, &sg.src);
10850 if (result <= 0) {
10851 vty_out(vty, "Bad src address %s: errno=%d: %s\n", src_str,
10852 errno, safe_strerror(errno));
10853 return;
10854 }
10855 result = inet_pton(AF_INET, grp_str, &sg.grp);
10856 if (result <= 0) {
10857 vty_out(vty, "Bad grp address %s: errno=%d: %s\n", grp_str,
10858 errno, safe_strerror(errno));
10859 return;
10860 }
10861
10862 sg.family = AF_INET;
10863 sg.prefixlen = IPV4_MAX_BITLEN;
10864 if (uj)
10865 json = json_object_new_object();
10866
10867 vxlan_sg = pim_vxlan_sg_find(pim, &sg);
10868 if (vxlan_sg) {
10869 installed = (vxlan_sg->up) ? true : false;
10870 iif_name = vxlan_sg->iif?vxlan_sg->iif->name:"-";
10871
10872 if (pim_vxlan_is_orig_mroute(vxlan_sg))
10873 oif_name =
10874 vxlan_sg->orig_oif?vxlan_sg->orig_oif->name:"";
10875 else
10876 oif_name =
10877 vxlan_sg->term_oif?vxlan_sg->term_oif->name:"";
10878
10879 if (uj) {
10880 json_object_string_add(json, "source", src_str);
10881 json_object_string_add(json, "group", grp_str);
10882 json_object_string_add(json, "input", iif_name);
10883 json_object_string_add(json, "output", oif_name);
10884 if (installed)
10885 json_object_boolean_true_add(json, "installed");
10886 else
10887 json_object_boolean_false_add(json,
10888 "installed");
10889 } else {
10890 vty_out(vty, "SG : %s\n", vxlan_sg->sg_str);
10891 vty_out(vty, " Input : %s\n", iif_name);
10892 vty_out(vty, " Output : %s\n", oif_name);
10893 vty_out(vty, " installed : %s\n",
10894 installed?"yes":"no");
10895 }
10896 }
10897
10898 if (uj) {
10899 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10900 json, JSON_C_TO_STRING_PRETTY));
10901 json_object_free(json);
10902 }
10903 }
10904
10905 DEFUN (show_ip_pim_vxlan_sg,
10906 show_ip_pim_vxlan_sg_cmd,
10907 "show ip pim [vrf NAME] vxlan-groups [A.B.C.D [A.B.C.D]] [json]",
10908 SHOW_STR
10909 IP_STR
10910 PIM_STR
10911 VRF_CMD_HELP_STR
10912 "VxLAN BUM groups\n"
10913 "source or group ip\n"
10914 "group ip\n"
10915 JSON_STR)
10916 {
10917 bool uj = use_json(argc, argv);
10918 struct vrf *vrf;
10919 int idx = 2;
10920
10921 vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10922
10923 if (!vrf)
10924 return CMD_WARNING;
10925
10926 char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ?
10927 argv[idx++]->arg:NULL;
10928 char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx) ?
10929 argv[idx]->arg:NULL;
10930
10931 if (src_ip && grp_ip)
10932 pim_show_vxlan_sg_one(vrf->info, vty, src_ip, grp_ip, uj);
10933 else if (src_ip)
10934 pim_show_vxlan_sg_match_addr(vrf->info, vty, src_ip, uj);
10935 else
10936 pim_show_vxlan_sg(vrf->info, vty, uj);
10937
10938 return CMD_SUCCESS;
10939 }
10940
10941 static void pim_show_vxlan_sg_work(struct pim_instance *pim,
10942 struct vty *vty, bool uj)
10943 {
10944 json_object *json = NULL;
10945 struct pim_sg_cache_walk_data cwd;
10946 struct listnode *node;
10947 struct pim_vxlan_sg *vxlan_sg;
10948
10949 if (uj) {
10950 json = json_object_new_object();
10951 } else {
10952 vty_out(vty, "Codes: I -> installed\n");
10953 vty_out(vty,
10954 "Source Group Input Flags\n");
10955 }
10956
10957 memset(&cwd, 0, sizeof(cwd));
10958 cwd.vty = vty;
10959 cwd.json = json;
10960 for (ALL_LIST_ELEMENTS_RO(pim_vxlan_p->work_list, node, vxlan_sg))
10961 pim_show_vxlan_sg_entry(vxlan_sg, &cwd);
10962
10963 if (uj) {
10964 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10965 json, JSON_C_TO_STRING_PRETTY));
10966 json_object_free(json);
10967 }
10968 }
10969
10970 DEFUN_HIDDEN (show_ip_pim_vxlan_sg_work,
10971 show_ip_pim_vxlan_sg_work_cmd,
10972 "show ip pim [vrf NAME] vxlan-work [json]",
10973 SHOW_STR
10974 IP_STR
10975 PIM_STR
10976 VRF_CMD_HELP_STR
10977 "VxLAN work list\n"
10978 JSON_STR)
10979 {
10980 bool uj = use_json(argc, argv);
10981 struct vrf *vrf;
10982 int idx = 2;
10983
10984 vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10985
10986 if (!vrf)
10987 return CMD_WARNING;
10988
10989 pim_show_vxlan_sg_work(vrf->info, vty, uj);
10990
10991 return CMD_SUCCESS;
10992 }
10993
10994 DEFUN_HIDDEN (no_ip_pim_mlag,
10995 no_ip_pim_mlag_cmd,
10996 "no ip pim mlag",
10997 NO_STR
10998 IP_STR
10999 PIM_STR
11000 "MLAG\n")
11001 {
11002 char mlag_xpath[XPATH_MAXLEN];
11003
11004 snprintf(mlag_xpath, sizeof(mlag_xpath), FRR_PIM_AF_XPATH,
11005 "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
11006 strlcat(mlag_xpath, "/mlag", sizeof(mlag_xpath));
11007
11008 nb_cli_enqueue_change(vty, mlag_xpath, NB_OP_DESTROY, NULL);
11009
11010
11011 return nb_cli_apply_changes(vty, NULL);
11012 }
11013
11014 DEFUN_HIDDEN (ip_pim_mlag,
11015 ip_pim_mlag_cmd,
11016 "ip pim mlag INTERFACE role [primary|secondary] state [up|down] addr A.B.C.D",
11017 IP_STR
11018 PIM_STR
11019 "MLAG\n"
11020 "peerlink sub interface\n"
11021 "MLAG role\n"
11022 "MLAG role primary\n"
11023 "MLAG role secondary\n"
11024 "peer session state\n"
11025 "peer session state up\n"
11026 "peer session state down\n"
11027 "configure PIP\n"
11028 "unique ip address\n")
11029 {
11030 int idx;
11031 char mlag_peerlink_rif_xpath[XPATH_MAXLEN];
11032 char mlag_my_role_xpath[XPATH_MAXLEN];
11033 char mlag_peer_state_xpath[XPATH_MAXLEN];
11034 char mlag_reg_address_xpath[XPATH_MAXLEN];
11035
11036 snprintf(mlag_peerlink_rif_xpath, sizeof(mlag_peerlink_rif_xpath),
11037 FRR_PIM_AF_XPATH,
11038 "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
11039 strlcat(mlag_peerlink_rif_xpath, "/mlag/peerlink-rif",
11040 sizeof(mlag_peerlink_rif_xpath));
11041
11042 idx = 3;
11043 nb_cli_enqueue_change(vty, mlag_peerlink_rif_xpath, NB_OP_MODIFY,
11044 argv[idx]->arg);
11045
11046 snprintf(mlag_my_role_xpath, sizeof(mlag_my_role_xpath),
11047 FRR_PIM_AF_XPATH,
11048 "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
11049 strlcat(mlag_my_role_xpath, "/mlag/my-role",
11050 sizeof(mlag_my_role_xpath));
11051
11052 idx += 2;
11053 if (!strcmp(argv[idx]->arg, "primary")) {
11054 nb_cli_enqueue_change(vty, mlag_my_role_xpath, NB_OP_MODIFY,
11055 "MLAG_ROLE_PRIMARY");
11056
11057 } else if (!strcmp(argv[idx]->arg, "secondary")) {
11058 nb_cli_enqueue_change(vty, mlag_my_role_xpath, NB_OP_MODIFY,
11059 "MLAG_ROLE_SECONDARY");
11060
11061 } else {
11062 vty_out(vty, "unknown MLAG role %s\n", argv[idx]->arg);
11063 return CMD_WARNING;
11064 }
11065
11066 snprintf(mlag_peer_state_xpath, sizeof(mlag_peer_state_xpath),
11067 FRR_PIM_AF_XPATH,
11068 "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
11069 strlcat(mlag_peer_state_xpath, "/mlag/peer-state",
11070 sizeof(mlag_peer_state_xpath));
11071
11072 idx += 2;
11073 if (!strcmp(argv[idx]->arg, "up")) {
11074 nb_cli_enqueue_change(vty, mlag_peer_state_xpath, NB_OP_MODIFY,
11075 "true");
11076
11077 } else if (strcmp(argv[idx]->arg, "down")) {
11078 nb_cli_enqueue_change(vty, mlag_peer_state_xpath, NB_OP_MODIFY,
11079 "false");
11080
11081 } else {
11082 vty_out(vty, "unknown MLAG state %s\n", argv[idx]->arg);
11083 return CMD_WARNING;
11084 }
11085
11086 snprintf(mlag_reg_address_xpath, sizeof(mlag_reg_address_xpath),
11087 FRR_PIM_AF_XPATH,
11088 "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
11089 strlcat(mlag_reg_address_xpath, "/mlag/reg-address",
11090 sizeof(mlag_reg_address_xpath));
11091
11092 idx += 2;
11093 nb_cli_enqueue_change(vty, mlag_reg_address_xpath, NB_OP_MODIFY,
11094 argv[idx]->arg);
11095
11096 return nb_cli_apply_changes(vty, NULL);
11097 }
11098
11099 void pim_cmd_init(void)
11100 {
11101 if_cmd_init(pim_interface_config_write);
11102
11103 install_node(&debug_node);
11104
11105 install_element(ENABLE_NODE, &pim_test_sg_keepalive_cmd);
11106
11107 install_element(CONFIG_NODE, &ip_pim_rp_cmd);
11108 install_element(VRF_NODE, &ip_pim_rp_cmd);
11109 install_element(CONFIG_NODE, &no_ip_pim_rp_cmd);
11110 install_element(VRF_NODE, &no_ip_pim_rp_cmd);
11111 install_element(CONFIG_NODE, &ip_pim_rp_prefix_list_cmd);
11112 install_element(VRF_NODE, &ip_pim_rp_prefix_list_cmd);
11113 install_element(CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd);
11114 install_element(VRF_NODE, &no_ip_pim_rp_prefix_list_cmd);
11115 install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd);
11116 install_element(VRF_NODE, &no_ip_pim_ssm_prefix_list_cmd);
11117 install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
11118 install_element(VRF_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
11119 install_element(CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd);
11120 install_element(VRF_NODE, &ip_pim_ssm_prefix_list_cmd);
11121 install_element(CONFIG_NODE, &ip_pim_register_suppress_cmd);
11122 install_element(CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
11123 install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd);
11124 install_element(VRF_NODE, &ip_pim_spt_switchover_infinity_cmd);
11125 install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
11126 install_element(VRF_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
11127 install_element(CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
11128 install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
11129 install_element(CONFIG_NODE,
11130 &no_ip_pim_spt_switchover_infinity_plist_cmd);
11131 install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd);
11132 install_element(CONFIG_NODE, &pim_register_accept_list_cmd);
11133 install_element(VRF_NODE, &pim_register_accept_list_cmd);
11134 install_element(CONFIG_NODE, &ip_pim_joinprune_time_cmd);
11135 install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
11136 install_element(CONFIG_NODE, &ip_pim_keep_alive_cmd);
11137 install_element(VRF_NODE, &ip_pim_keep_alive_cmd);
11138 install_element(CONFIG_NODE, &ip_pim_rp_keep_alive_cmd);
11139 install_element(VRF_NODE, &ip_pim_rp_keep_alive_cmd);
11140 install_element(CONFIG_NODE, &no_ip_pim_keep_alive_cmd);
11141 install_element(VRF_NODE, &no_ip_pim_keep_alive_cmd);
11142 install_element(CONFIG_NODE, &no_ip_pim_rp_keep_alive_cmd);
11143 install_element(VRF_NODE, &no_ip_pim_rp_keep_alive_cmd);
11144 install_element(CONFIG_NODE, &ip_pim_packets_cmd);
11145 install_element(CONFIG_NODE, &no_ip_pim_packets_cmd);
11146 install_element(CONFIG_NODE, &ip_pim_v6_secondary_cmd);
11147 install_element(VRF_NODE, &ip_pim_v6_secondary_cmd);
11148 install_element(CONFIG_NODE, &no_ip_pim_v6_secondary_cmd);
11149 install_element(VRF_NODE, &no_ip_pim_v6_secondary_cmd);
11150 install_element(CONFIG_NODE, &ip_ssmpingd_cmd);
11151 install_element(VRF_NODE, &ip_ssmpingd_cmd);
11152 install_element(CONFIG_NODE, &no_ip_ssmpingd_cmd);
11153 install_element(VRF_NODE, &no_ip_ssmpingd_cmd);
11154 install_element(CONFIG_NODE, &ip_msdp_peer_cmd);
11155 install_element(VRF_NODE, &ip_msdp_peer_cmd);
11156 install_element(CONFIG_NODE, &no_ip_msdp_peer_cmd);
11157 install_element(VRF_NODE, &no_ip_msdp_peer_cmd);
11158 install_element(CONFIG_NODE, &ip_pim_ecmp_cmd);
11159 install_element(VRF_NODE, &ip_pim_ecmp_cmd);
11160 install_element(CONFIG_NODE, &no_ip_pim_ecmp_cmd);
11161 install_element(VRF_NODE, &no_ip_pim_ecmp_cmd);
11162 install_element(CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd);
11163 install_element(VRF_NODE, &ip_pim_ecmp_rebalance_cmd);
11164 install_element(CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd);
11165 install_element(VRF_NODE, &no_ip_pim_ecmp_rebalance_cmd);
11166 install_element(CONFIG_NODE, &ip_pim_mlag_cmd);
11167 install_element(CONFIG_NODE, &no_ip_pim_mlag_cmd);
11168 install_element(CONFIG_NODE, &igmp_group_watermark_cmd);
11169 install_element(VRF_NODE, &igmp_group_watermark_cmd);
11170 install_element(CONFIG_NODE, &no_igmp_group_watermark_cmd);
11171 install_element(VRF_NODE, &no_igmp_group_watermark_cmd);
11172
11173 install_element(INTERFACE_NODE, &interface_ip_igmp_cmd);
11174 install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd);
11175 install_element(INTERFACE_NODE, &interface_ip_igmp_join_cmd);
11176 install_element(INTERFACE_NODE, &interface_no_ip_igmp_join_cmd);
11177 install_element(INTERFACE_NODE, &interface_ip_igmp_version_cmd);
11178 install_element(INTERFACE_NODE, &interface_no_ip_igmp_version_cmd);
11179 install_element(INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd);
11180 install_element(INTERFACE_NODE,
11181 &interface_no_ip_igmp_query_interval_cmd);
11182 install_element(INTERFACE_NODE,
11183 &interface_ip_igmp_query_max_response_time_cmd);
11184 install_element(INTERFACE_NODE,
11185 &interface_no_ip_igmp_query_max_response_time_cmd);
11186 install_element(INTERFACE_NODE,
11187 &interface_ip_igmp_query_max_response_time_dsec_cmd);
11188 install_element(INTERFACE_NODE,
11189 &interface_no_ip_igmp_query_max_response_time_dsec_cmd);
11190 install_element(INTERFACE_NODE,
11191 &interface_ip_igmp_last_member_query_count_cmd);
11192 install_element(INTERFACE_NODE,
11193 &interface_no_ip_igmp_last_member_query_count_cmd);
11194 install_element(INTERFACE_NODE,
11195 &interface_ip_igmp_last_member_query_interval_cmd);
11196 install_element(INTERFACE_NODE,
11197 &interface_no_ip_igmp_last_member_query_interval_cmd);
11198 install_element(INTERFACE_NODE, &interface_ip_pim_activeactive_cmd);
11199 install_element(INTERFACE_NODE, &interface_ip_pim_ssm_cmd);
11200 install_element(INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd);
11201 install_element(INTERFACE_NODE, &interface_ip_pim_sm_cmd);
11202 install_element(INTERFACE_NODE, &interface_no_ip_pim_sm_cmd);
11203 install_element(INTERFACE_NODE, &interface_ip_pim_cmd);
11204 install_element(INTERFACE_NODE, &interface_no_ip_pim_cmd);
11205 install_element(INTERFACE_NODE, &interface_ip_pim_drprio_cmd);
11206 install_element(INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd);
11207 install_element(INTERFACE_NODE, &interface_ip_pim_hello_cmd);
11208 install_element(INTERFACE_NODE, &interface_no_ip_pim_hello_cmd);
11209 install_element(INTERFACE_NODE, &interface_ip_pim_boundary_oil_cmd);
11210 install_element(INTERFACE_NODE, &interface_no_ip_pim_boundary_oil_cmd);
11211 install_element(INTERFACE_NODE, &interface_ip_igmp_query_generate_cmd);
11212
11213 // Static mroutes NEB
11214 install_element(INTERFACE_NODE, &interface_ip_mroute_cmd);
11215 install_element(INTERFACE_NODE, &interface_no_ip_mroute_cmd);
11216
11217 install_element(VIEW_NODE, &show_ip_igmp_interface_cmd);
11218 install_element(VIEW_NODE, &show_ip_igmp_interface_vrf_all_cmd);
11219 install_element(VIEW_NODE, &show_ip_igmp_join_cmd);
11220 install_element(VIEW_NODE, &show_ip_igmp_join_vrf_all_cmd);
11221 install_element(VIEW_NODE, &show_ip_igmp_groups_cmd);
11222 install_element(VIEW_NODE, &show_ip_igmp_groups_vrf_all_cmd);
11223 install_element(VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd);
11224 install_element(VIEW_NODE, &show_ip_igmp_sources_cmd);
11225 install_element(VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd);
11226 install_element(VIEW_NODE, &show_ip_igmp_statistics_cmd);
11227 install_element(VIEW_NODE, &show_ip_pim_assert_cmd);
11228 install_element(VIEW_NODE, &show_ip_pim_assert_internal_cmd);
11229 install_element(VIEW_NODE, &show_ip_pim_assert_metric_cmd);
11230 install_element(VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd);
11231 install_element(VIEW_NODE, &show_ip_pim_interface_traffic_cmd);
11232 install_element(VIEW_NODE, &show_ip_pim_interface_cmd);
11233 install_element(VIEW_NODE, &show_ip_pim_interface_vrf_all_cmd);
11234 install_element(VIEW_NODE, &show_ip_pim_join_cmd);
11235 install_element(VIEW_NODE, &show_ip_pim_join_vrf_all_cmd);
11236 install_element(VIEW_NODE, &show_ip_pim_jp_agg_cmd);
11237 install_element(VIEW_NODE, &show_ip_pim_local_membership_cmd);
11238 install_element(VIEW_NODE, &show_ip_pim_mlag_summary_cmd);
11239 install_element(VIEW_NODE, &show_ip_pim_mlag_up_cmd);
11240 install_element(VIEW_NODE, &show_ip_pim_mlag_up_vrf_all_cmd);
11241 install_element(VIEW_NODE, &show_ip_pim_neighbor_cmd);
11242 install_element(VIEW_NODE, &show_ip_pim_neighbor_vrf_all_cmd);
11243 install_element(VIEW_NODE, &show_ip_pim_rpf_cmd);
11244 install_element(VIEW_NODE, &show_ip_pim_rpf_vrf_all_cmd);
11245 install_element(VIEW_NODE, &show_ip_pim_secondary_cmd);
11246 install_element(VIEW_NODE, &show_ip_pim_state_cmd);
11247 install_element(VIEW_NODE, &show_ip_pim_state_vrf_all_cmd);
11248 install_element(VIEW_NODE, &show_ip_pim_upstream_cmd);
11249 install_element(VIEW_NODE, &show_ip_pim_upstream_vrf_all_cmd);
11250 install_element(VIEW_NODE, &show_ip_pim_channel_cmd);
11251 install_element(VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd);
11252 install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd);
11253 install_element(VIEW_NODE, &show_ip_pim_rp_cmd);
11254 install_element(VIEW_NODE, &show_ip_pim_rp_vrf_all_cmd);
11255 install_element(VIEW_NODE, &show_ip_pim_bsr_cmd);
11256 install_element(VIEW_NODE, &show_ip_multicast_cmd);
11257 install_element(VIEW_NODE, &show_ip_multicast_vrf_all_cmd);
11258 install_element(VIEW_NODE, &show_ip_multicast_count_cmd);
11259 install_element(VIEW_NODE, &show_ip_multicast_count_vrf_all_cmd);
11260 install_element(VIEW_NODE, &show_ip_mroute_cmd);
11261 install_element(VIEW_NODE, &show_ip_mroute_vrf_all_cmd);
11262 install_element(VIEW_NODE, &show_ip_mroute_count_cmd);
11263 install_element(VIEW_NODE, &show_ip_mroute_count_vrf_all_cmd);
11264 install_element(VIEW_NODE, &show_ip_mroute_summary_cmd);
11265 install_element(VIEW_NODE, &show_ip_mroute_summary_vrf_all_cmd);
11266 install_element(VIEW_NODE, &show_ip_rib_cmd);
11267 install_element(VIEW_NODE, &show_ip_ssmpingd_cmd);
11268 install_element(VIEW_NODE, &show_ip_pim_nexthop_cmd);
11269 install_element(VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd);
11270 install_element(VIEW_NODE, &show_ip_pim_bsrp_cmd);
11271 install_element(VIEW_NODE, &show_ip_pim_bsm_db_cmd);
11272 install_element(VIEW_NODE, &show_ip_pim_statistics_cmd);
11273
11274 install_element(ENABLE_NODE, &clear_ip_mroute_count_cmd);
11275 install_element(ENABLE_NODE, &clear_ip_interfaces_cmd);
11276 install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd);
11277 install_element(ENABLE_NODE, &clear_ip_mroute_cmd);
11278 install_element(ENABLE_NODE, &clear_ip_pim_interfaces_cmd);
11279 install_element(ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd);
11280 install_element(ENABLE_NODE, &clear_ip_pim_oil_cmd);
11281 install_element(ENABLE_NODE, &clear_ip_pim_statistics_cmd);
11282 install_element(ENABLE_NODE, &clear_ip_pim_bsr_db_cmd);
11283
11284 install_element(ENABLE_NODE, &show_debugging_pim_cmd);
11285
11286 install_element(ENABLE_NODE, &debug_igmp_cmd);
11287 install_element(ENABLE_NODE, &no_debug_igmp_cmd);
11288 install_element(ENABLE_NODE, &debug_igmp_events_cmd);
11289 install_element(ENABLE_NODE, &no_debug_igmp_events_cmd);
11290 install_element(ENABLE_NODE, &debug_igmp_packets_cmd);
11291 install_element(ENABLE_NODE, &no_debug_igmp_packets_cmd);
11292 install_element(ENABLE_NODE, &debug_igmp_trace_cmd);
11293 install_element(ENABLE_NODE, &no_debug_igmp_trace_cmd);
11294 install_element(ENABLE_NODE, &debug_mroute_cmd);
11295 install_element(ENABLE_NODE, &debug_mroute_detail_cmd);
11296 install_element(ENABLE_NODE, &no_debug_mroute_cmd);
11297 install_element(ENABLE_NODE, &no_debug_mroute_detail_cmd);
11298 install_element(ENABLE_NODE, &debug_pim_static_cmd);
11299 install_element(ENABLE_NODE, &no_debug_pim_static_cmd);
11300 install_element(ENABLE_NODE, &debug_pim_cmd);
11301 install_element(ENABLE_NODE, &no_debug_pim_cmd);
11302 install_element(ENABLE_NODE, &debug_pim_nht_cmd);
11303 install_element(ENABLE_NODE, &no_debug_pim_nht_cmd);
11304 install_element(ENABLE_NODE, &debug_pim_nht_rp_cmd);
11305 install_element(ENABLE_NODE, &no_debug_pim_nht_rp_cmd);
11306 install_element(ENABLE_NODE, &debug_pim_events_cmd);
11307 install_element(ENABLE_NODE, &no_debug_pim_events_cmd);
11308 install_element(ENABLE_NODE, &debug_pim_packets_cmd);
11309 install_element(ENABLE_NODE, &no_debug_pim_packets_cmd);
11310 install_element(ENABLE_NODE, &debug_pim_packetdump_send_cmd);
11311 install_element(ENABLE_NODE, &no_debug_pim_packetdump_send_cmd);
11312 install_element(ENABLE_NODE, &debug_pim_packetdump_recv_cmd);
11313 install_element(ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd);
11314 install_element(ENABLE_NODE, &debug_pim_trace_cmd);
11315 install_element(ENABLE_NODE, &no_debug_pim_trace_cmd);
11316 install_element(ENABLE_NODE, &debug_pim_trace_detail_cmd);
11317 install_element(ENABLE_NODE, &no_debug_pim_trace_detail_cmd);
11318 install_element(ENABLE_NODE, &debug_ssmpingd_cmd);
11319 install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd);
11320 install_element(ENABLE_NODE, &debug_pim_zebra_cmd);
11321 install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd);
11322 install_element(ENABLE_NODE, &debug_pim_mlag_cmd);
11323 install_element(ENABLE_NODE, &no_debug_pim_mlag_cmd);
11324 install_element(ENABLE_NODE, &debug_pim_vxlan_cmd);
11325 install_element(ENABLE_NODE, &no_debug_pim_vxlan_cmd);
11326 install_element(ENABLE_NODE, &debug_msdp_cmd);
11327 install_element(ENABLE_NODE, &no_debug_msdp_cmd);
11328 install_element(ENABLE_NODE, &debug_msdp_events_cmd);
11329 install_element(ENABLE_NODE, &no_debug_msdp_events_cmd);
11330 install_element(ENABLE_NODE, &debug_msdp_packets_cmd);
11331 install_element(ENABLE_NODE, &no_debug_msdp_packets_cmd);
11332 install_element(ENABLE_NODE, &debug_mtrace_cmd);
11333 install_element(ENABLE_NODE, &no_debug_mtrace_cmd);
11334 install_element(ENABLE_NODE, &debug_bsm_cmd);
11335 install_element(ENABLE_NODE, &no_debug_bsm_cmd);
11336
11337 install_element(CONFIG_NODE, &debug_igmp_cmd);
11338 install_element(CONFIG_NODE, &no_debug_igmp_cmd);
11339 install_element(CONFIG_NODE, &debug_igmp_events_cmd);
11340 install_element(CONFIG_NODE, &no_debug_igmp_events_cmd);
11341 install_element(CONFIG_NODE, &debug_igmp_packets_cmd);
11342 install_element(CONFIG_NODE, &no_debug_igmp_packets_cmd);
11343 install_element(CONFIG_NODE, &debug_igmp_trace_cmd);
11344 install_element(CONFIG_NODE, &no_debug_igmp_trace_cmd);
11345 install_element(CONFIG_NODE, &debug_mroute_cmd);
11346 install_element(CONFIG_NODE, &debug_mroute_detail_cmd);
11347 install_element(CONFIG_NODE, &no_debug_mroute_cmd);
11348 install_element(CONFIG_NODE, &no_debug_mroute_detail_cmd);
11349 install_element(CONFIG_NODE, &debug_pim_static_cmd);
11350 install_element(CONFIG_NODE, &no_debug_pim_static_cmd);
11351 install_element(CONFIG_NODE, &debug_pim_cmd);
11352 install_element(CONFIG_NODE, &no_debug_pim_cmd);
11353 install_element(CONFIG_NODE, &debug_pim_nht_cmd);
11354 install_element(CONFIG_NODE, &no_debug_pim_nht_cmd);
11355 install_element(CONFIG_NODE, &debug_pim_nht_rp_cmd);
11356 install_element(CONFIG_NODE, &no_debug_pim_nht_rp_cmd);
11357 install_element(CONFIG_NODE, &debug_pim_events_cmd);
11358 install_element(CONFIG_NODE, &no_debug_pim_events_cmd);
11359 install_element(CONFIG_NODE, &debug_pim_packets_cmd);
11360 install_element(CONFIG_NODE, &no_debug_pim_packets_cmd);
11361 install_element(CONFIG_NODE, &debug_pim_trace_cmd);
11362 install_element(CONFIG_NODE, &no_debug_pim_trace_cmd);
11363 install_element(CONFIG_NODE, &debug_pim_trace_detail_cmd);
11364 install_element(CONFIG_NODE, &no_debug_pim_trace_detail_cmd);
11365 install_element(CONFIG_NODE, &debug_ssmpingd_cmd);
11366 install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd);
11367 install_element(CONFIG_NODE, &debug_pim_zebra_cmd);
11368 install_element(CONFIG_NODE, &no_debug_pim_zebra_cmd);
11369 install_element(CONFIG_NODE, &debug_pim_mlag_cmd);
11370 install_element(CONFIG_NODE, &no_debug_pim_mlag_cmd);
11371 install_element(CONFIG_NODE, &debug_pim_vxlan_cmd);
11372 install_element(CONFIG_NODE, &no_debug_pim_vxlan_cmd);
11373 install_element(CONFIG_NODE, &debug_msdp_cmd);
11374 install_element(CONFIG_NODE, &no_debug_msdp_cmd);
11375 install_element(CONFIG_NODE, &debug_msdp_events_cmd);
11376 install_element(CONFIG_NODE, &no_debug_msdp_events_cmd);
11377 install_element(CONFIG_NODE, &debug_msdp_packets_cmd);
11378 install_element(CONFIG_NODE, &no_debug_msdp_packets_cmd);
11379 install_element(CONFIG_NODE, &debug_mtrace_cmd);
11380 install_element(CONFIG_NODE, &no_debug_mtrace_cmd);
11381 install_element(CONFIG_NODE, &debug_bsm_cmd);
11382 install_element(CONFIG_NODE, &no_debug_bsm_cmd);
11383
11384 install_element(CONFIG_NODE, &ip_msdp_timers_cmd);
11385 install_element(VRF_NODE, &ip_msdp_timers_cmd);
11386 install_element(CONFIG_NODE, &ip_msdp_mesh_group_member_cmd);
11387 install_element(VRF_NODE, &ip_msdp_mesh_group_member_cmd);
11388 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd);
11389 install_element(VRF_NODE, &no_ip_msdp_mesh_group_member_cmd);
11390 install_element(CONFIG_NODE, &ip_msdp_mesh_group_source_cmd);
11391 install_element(VRF_NODE, &ip_msdp_mesh_group_source_cmd);
11392 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd);
11393 install_element(VRF_NODE, &no_ip_msdp_mesh_group_source_cmd);
11394 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_cmd);
11395 install_element(VRF_NODE, &no_ip_msdp_mesh_group_cmd);
11396 install_element(VIEW_NODE, &show_ip_msdp_peer_detail_cmd);
11397 install_element(VIEW_NODE, &show_ip_msdp_peer_detail_vrf_all_cmd);
11398 install_element(VIEW_NODE, &show_ip_msdp_sa_detail_cmd);
11399 install_element(VIEW_NODE, &show_ip_msdp_sa_detail_vrf_all_cmd);
11400 install_element(VIEW_NODE, &show_ip_msdp_sa_sg_cmd);
11401 install_element(VIEW_NODE, &show_ip_msdp_sa_sg_vrf_all_cmd);
11402 install_element(VIEW_NODE, &show_ip_msdp_mesh_group_cmd);
11403 install_element(VIEW_NODE, &show_ip_msdp_mesh_group_vrf_all_cmd);
11404 install_element(VIEW_NODE, &show_ip_pim_ssm_range_cmd);
11405 install_element(VIEW_NODE, &show_ip_pim_group_type_cmd);
11406 install_element(VIEW_NODE, &show_ip_pim_vxlan_sg_cmd);
11407 install_element(VIEW_NODE, &show_ip_pim_vxlan_sg_work_cmd);
11408 install_element(INTERFACE_NODE, &interface_pim_use_source_cmd);
11409 install_element(INTERFACE_NODE, &interface_no_pim_use_source_cmd);
11410 /* Install BSM command */
11411 install_element(INTERFACE_NODE, &ip_pim_bsm_cmd);
11412 install_element(INTERFACE_NODE, &no_ip_pim_bsm_cmd);
11413 install_element(INTERFACE_NODE, &ip_pim_ucast_bsm_cmd);
11414 install_element(INTERFACE_NODE, &no_ip_pim_ucast_bsm_cmd);
11415 /* Install BFD command */
11416 install_element(INTERFACE_NODE, &ip_pim_bfd_cmd);
11417 install_element(INTERFACE_NODE, &ip_pim_bfd_param_cmd);
11418 install_element(INTERFACE_NODE, &no_ip_pim_bfd_profile_cmd);
11419 install_element(INTERFACE_NODE, &no_ip_pim_bfd_cmd);
11420 #if HAVE_BFDD == 0
11421 install_element(INTERFACE_NODE, &no_ip_pim_bfd_param_cmd);
11422 #endif /* !HAVE_BFDD */
11423 }