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