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