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