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