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