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