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