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