]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_cmd.c
*: move "show debugging ..." commands to enable node
[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, P: Peer Entry\n");
4983 }
4984 }
4985
4986
4987 DEFUN(show_ip_pim_mlag_up, show_ip_pim_mlag_up_cmd,
4988 "show ip pim [vrf NAME] mlag upstream [A.B.C.D [A.B.C.D]] [json]",
4989 SHOW_STR
4990 IP_STR
4991 PIM_STR
4992 VRF_CMD_HELP_STR
4993 "MLAG\n"
4994 "upstream\n"
4995 "Unicast or Multicast address\n"
4996 "Multicast address\n" JSON_STR)
4997 {
4998 const char *src_or_group = NULL;
4999 const char *group = NULL;
5000 int idx = 2;
5001 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5002 bool uj = use_json(argc, argv);
5003
5004 if (!vrf || !vrf->info) {
5005 vty_out(vty, "%s: VRF or Info missing\n", __func__);
5006 return CMD_WARNING;
5007 }
5008
5009 if (uj)
5010 argc--;
5011
5012 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
5013 src_or_group = argv[idx]->arg;
5014 if (idx + 1 < argc)
5015 group = argv[idx + 1]->arg;
5016 }
5017
5018 pim_show_mlag_help_string(vty, uj);
5019
5020 if (src_or_group)
5021 pim_show_mlag_up_detail(vrf, vty, src_or_group, group, uj);
5022 else
5023 pim_show_mlag_up_vrf(vrf, vty, uj);
5024
5025 return CMD_SUCCESS;
5026 }
5027
5028
5029 DEFUN(show_ip_pim_mlag_up_vrf_all, show_ip_pim_mlag_up_vrf_all_cmd,
5030 "show ip pim vrf all mlag upstream [json]",
5031 SHOW_STR IP_STR PIM_STR VRF_CMD_HELP_STR
5032 "MLAG\n"
5033 "upstream\n" JSON_STR)
5034 {
5035 struct vrf *vrf;
5036 bool uj = use_json(argc, argv);
5037
5038 pim_show_mlag_help_string(vty, uj);
5039 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5040 pim_show_mlag_up_vrf(vrf, vty, uj);
5041 }
5042
5043 return CMD_SUCCESS;
5044 }
5045
5046 DEFUN (show_ip_pim_neighbor,
5047 show_ip_pim_neighbor_cmd,
5048 "show ip pim [vrf NAME] neighbor [detail|WORD] [json]",
5049 SHOW_STR
5050 IP_STR
5051 PIM_STR
5052 VRF_CMD_HELP_STR
5053 "PIM neighbor information\n"
5054 "Detailed output\n"
5055 "Name of interface or neighbor\n"
5056 JSON_STR)
5057 {
5058 int idx = 2;
5059 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5060 bool uj = use_json(argc, argv);
5061
5062 if (!vrf)
5063 return CMD_WARNING;
5064
5065 if (argv_find(argv, argc, "detail", &idx)
5066 || argv_find(argv, argc, "WORD", &idx))
5067 pim_show_neighbors_single(vrf->info, vty, argv[idx]->arg, uj);
5068 else
5069 pim_show_neighbors(vrf->info, vty, uj);
5070
5071 return CMD_SUCCESS;
5072 }
5073
5074 DEFUN (show_ip_pim_neighbor_vrf_all,
5075 show_ip_pim_neighbor_vrf_all_cmd,
5076 "show ip pim vrf all neighbor [detail|WORD] [json]",
5077 SHOW_STR
5078 IP_STR
5079 PIM_STR
5080 VRF_CMD_HELP_STR
5081 "PIM neighbor information\n"
5082 "Detailed output\n"
5083 "Name of interface or neighbor\n"
5084 JSON_STR)
5085 {
5086 int idx = 2;
5087 bool uj = use_json(argc, argv);
5088 struct vrf *vrf;
5089 bool first = true;
5090
5091 if (uj)
5092 vty_out(vty, "{ ");
5093 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5094 if (uj) {
5095 if (!first)
5096 vty_out(vty, ", ");
5097 vty_out(vty, " \"%s\": ", vrf->name);
5098 first = false;
5099 } else
5100 vty_out(vty, "VRF: %s\n", vrf->name);
5101 if (argv_find(argv, argc, "detail", &idx)
5102 || argv_find(argv, argc, "WORD", &idx))
5103 pim_show_neighbors_single(vrf->info, vty,
5104 argv[idx]->arg, uj);
5105 else
5106 pim_show_neighbors(vrf->info, vty, uj);
5107 }
5108 if (uj)
5109 vty_out(vty, "}\n");
5110
5111 return CMD_SUCCESS;
5112 }
5113
5114 DEFUN (show_ip_pim_secondary,
5115 show_ip_pim_secondary_cmd,
5116 "show ip pim [vrf NAME] secondary",
5117 SHOW_STR
5118 IP_STR
5119 PIM_STR
5120 VRF_CMD_HELP_STR
5121 "PIM neighbor addresses\n")
5122 {
5123 int idx = 2;
5124 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5125
5126 if (!vrf)
5127 return CMD_WARNING;
5128
5129 pim_show_neighbors_secondary(vrf->info, vty);
5130
5131 return CMD_SUCCESS;
5132 }
5133
5134 DEFUN (show_ip_pim_state,
5135 show_ip_pim_state_cmd,
5136 "show ip pim [vrf NAME] state [A.B.C.D [A.B.C.D]] [json]",
5137 SHOW_STR
5138 IP_STR
5139 PIM_STR
5140 VRF_CMD_HELP_STR
5141 "PIM state information\n"
5142 "Unicast or Multicast address\n"
5143 "Multicast address\n"
5144 JSON_STR)
5145 {
5146 const char *src_or_group = NULL;
5147 const char *group = NULL;
5148 int idx = 2;
5149 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5150 bool uj = use_json(argc, argv);
5151
5152 if (!vrf)
5153 return CMD_WARNING;
5154
5155 if (uj)
5156 argc--;
5157
5158 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
5159 src_or_group = argv[idx]->arg;
5160 if (idx + 1 < argc)
5161 group = argv[idx + 1]->arg;
5162 }
5163
5164 pim_show_state(vrf->info, vty, src_or_group, group, uj);
5165
5166 return CMD_SUCCESS;
5167 }
5168
5169 DEFUN (show_ip_pim_state_vrf_all,
5170 show_ip_pim_state_vrf_all_cmd,
5171 "show ip pim vrf all state [A.B.C.D [A.B.C.D]] [json]",
5172 SHOW_STR
5173 IP_STR
5174 PIM_STR
5175 VRF_CMD_HELP_STR
5176 "PIM state information\n"
5177 "Unicast or Multicast address\n"
5178 "Multicast address\n"
5179 JSON_STR)
5180 {
5181 const char *src_or_group = NULL;
5182 const char *group = NULL;
5183 int idx = 2;
5184 bool uj = use_json(argc, argv);
5185 struct vrf *vrf;
5186 bool first = true;
5187
5188 if (uj) {
5189 vty_out(vty, "{ ");
5190 argc--;
5191 }
5192
5193 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
5194 src_or_group = argv[idx]->arg;
5195 if (idx + 1 < argc)
5196 group = argv[idx + 1]->arg;
5197 }
5198
5199 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5200 if (uj) {
5201 if (!first)
5202 vty_out(vty, ", ");
5203 vty_out(vty, " \"%s\": ", vrf->name);
5204 first = false;
5205 } else
5206 vty_out(vty, "VRF: %s\n", vrf->name);
5207 pim_show_state(vrf->info, vty, src_or_group, group, uj);
5208 }
5209 if (uj)
5210 vty_out(vty, "}\n");
5211
5212 return CMD_SUCCESS;
5213 }
5214
5215 DEFPY (show_ip_pim_upstream,
5216 show_ip_pim_upstream_cmd,
5217 "show ip pim [vrf NAME] upstream [A.B.C.D$s_or_g [A.B.C.D$g]] [json$json]",
5218 SHOW_STR
5219 IP_STR
5220 PIM_STR
5221 VRF_CMD_HELP_STR
5222 "PIM upstream information\n"
5223 "The Source or Group\n"
5224 "The Group\n"
5225 JSON_STR)
5226 {
5227 struct prefix_sg sg = {0};
5228 struct vrf *v;
5229 bool uj = !!json;
5230 struct pim_instance *pim;
5231
5232 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
5233
5234 if (!v) {
5235 vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
5236 return CMD_WARNING;
5237 }
5238 pim = pim_get_pim_instance(v->vrf_id);
5239
5240 if (!pim) {
5241 vty_out(vty, "%% Unable to find pim instance\n");
5242 return CMD_WARNING;
5243 }
5244
5245 if (s_or_g.s_addr != 0) {
5246 if (g.s_addr != 0) {
5247 sg.src = s_or_g;
5248 sg.grp = g;
5249 } else
5250 sg.grp = s_or_g;
5251 }
5252 pim_show_upstream(pim, vty, &sg, uj);
5253
5254 return CMD_SUCCESS;
5255 }
5256
5257 DEFUN (show_ip_pim_upstream_vrf_all,
5258 show_ip_pim_upstream_vrf_all_cmd,
5259 "show ip pim vrf all upstream [json]",
5260 SHOW_STR
5261 IP_STR
5262 PIM_STR
5263 VRF_CMD_HELP_STR
5264 "PIM upstream information\n"
5265 JSON_STR)
5266 {
5267 struct prefix_sg sg = {0};
5268 bool uj = use_json(argc, argv);
5269 struct vrf *vrf;
5270 bool first = true;
5271
5272 if (uj)
5273 vty_out(vty, "{ ");
5274 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5275 if (uj) {
5276 if (!first)
5277 vty_out(vty, ", ");
5278 vty_out(vty, " \"%s\": ", vrf->name);
5279 first = false;
5280 } else
5281 vty_out(vty, "VRF: %s\n", vrf->name);
5282 pim_show_upstream(vrf->info, vty, &sg, uj);
5283 }
5284
5285 return CMD_SUCCESS;
5286 }
5287
5288 DEFUN (show_ip_pim_channel,
5289 show_ip_pim_channel_cmd,
5290 "show ip pim [vrf NAME] channel [json]",
5291 SHOW_STR
5292 IP_STR
5293 PIM_STR
5294 VRF_CMD_HELP_STR
5295 "PIM downstream channel info\n"
5296 JSON_STR)
5297 {
5298 int idx = 2;
5299 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5300 bool uj = use_json(argc, argv);
5301
5302 if (!vrf)
5303 return CMD_WARNING;
5304
5305 pim_show_channel(vrf->info, vty, uj);
5306
5307 return CMD_SUCCESS;
5308 }
5309
5310 DEFUN (show_ip_pim_upstream_join_desired,
5311 show_ip_pim_upstream_join_desired_cmd,
5312 "show ip pim [vrf NAME] upstream-join-desired [json]",
5313 SHOW_STR
5314 IP_STR
5315 PIM_STR
5316 VRF_CMD_HELP_STR
5317 "PIM upstream join-desired\n"
5318 JSON_STR)
5319 {
5320 int idx = 2;
5321 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5322 bool uj = use_json(argc, argv);
5323
5324 if (!vrf)
5325 return CMD_WARNING;
5326
5327 pim_show_join_desired(vrf->info, vty, uj);
5328
5329 return CMD_SUCCESS;
5330 }
5331
5332 DEFUN (show_ip_pim_upstream_rpf,
5333 show_ip_pim_upstream_rpf_cmd,
5334 "show ip pim [vrf NAME] upstream-rpf [json]",
5335 SHOW_STR
5336 IP_STR
5337 PIM_STR
5338 VRF_CMD_HELP_STR
5339 "PIM upstream source rpf\n"
5340 JSON_STR)
5341 {
5342 int idx = 2;
5343 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5344 bool uj = use_json(argc, argv);
5345
5346 if (!vrf)
5347 return CMD_WARNING;
5348
5349 pim_show_upstream_rpf(vrf->info, vty, uj);
5350
5351 return CMD_SUCCESS;
5352 }
5353
5354 DEFUN (show_ip_pim_rp,
5355 show_ip_pim_rp_cmd,
5356 "show ip pim [vrf NAME] rp-info [json]",
5357 SHOW_STR
5358 IP_STR
5359 PIM_STR
5360 VRF_CMD_HELP_STR
5361 "PIM RP information\n"
5362 JSON_STR)
5363 {
5364 int idx = 2;
5365 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5366 bool uj = use_json(argc, argv);
5367
5368 if (!vrf)
5369 return CMD_WARNING;
5370
5371 pim_rp_show_information(vrf->info, vty, uj);
5372
5373 return CMD_SUCCESS;
5374 }
5375
5376 DEFUN (show_ip_pim_rp_vrf_all,
5377 show_ip_pim_rp_vrf_all_cmd,
5378 "show ip pim vrf all rp-info [json]",
5379 SHOW_STR
5380 IP_STR
5381 PIM_STR
5382 VRF_CMD_HELP_STR
5383 "PIM RP information\n"
5384 JSON_STR)
5385 {
5386 bool uj = use_json(argc, argv);
5387 struct vrf *vrf;
5388 bool first = true;
5389
5390 if (uj)
5391 vty_out(vty, "{ ");
5392 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5393 if (uj) {
5394 if (!first)
5395 vty_out(vty, ", ");
5396 vty_out(vty, " \"%s\": ", vrf->name);
5397 first = false;
5398 } else
5399 vty_out(vty, "VRF: %s\n", vrf->name);
5400 pim_rp_show_information(vrf->info, vty, uj);
5401 }
5402 if (uj)
5403 vty_out(vty, "}\n");
5404
5405 return CMD_SUCCESS;
5406 }
5407
5408 DEFUN (show_ip_pim_rpf,
5409 show_ip_pim_rpf_cmd,
5410 "show ip pim [vrf NAME] rpf [json]",
5411 SHOW_STR
5412 IP_STR
5413 PIM_STR
5414 VRF_CMD_HELP_STR
5415 "PIM cached source rpf information\n"
5416 JSON_STR)
5417 {
5418 int idx = 2;
5419 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5420 bool uj = use_json(argc, argv);
5421
5422 if (!vrf)
5423 return CMD_WARNING;
5424
5425 pim_show_rpf(vrf->info, vty, uj);
5426
5427 return CMD_SUCCESS;
5428 }
5429
5430 DEFUN (show_ip_pim_rpf_vrf_all,
5431 show_ip_pim_rpf_vrf_all_cmd,
5432 "show ip pim vrf all rpf [json]",
5433 SHOW_STR
5434 IP_STR
5435 PIM_STR
5436 VRF_CMD_HELP_STR
5437 "PIM cached source rpf information\n"
5438 JSON_STR)
5439 {
5440 bool uj = use_json(argc, argv);
5441 struct vrf *vrf;
5442 bool first = true;
5443
5444 if (uj)
5445 vty_out(vty, "{ ");
5446 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5447 if (uj) {
5448 if (!first)
5449 vty_out(vty, ", ");
5450 vty_out(vty, " \"%s\": ", vrf->name);
5451 first = false;
5452 } else
5453 vty_out(vty, "VRF: %s\n", vrf->name);
5454 pim_show_rpf(vrf->info, vty, uj);
5455 }
5456 if (uj)
5457 vty_out(vty, "}\n");
5458
5459 return CMD_SUCCESS;
5460 }
5461
5462 DEFUN (show_ip_pim_nexthop,
5463 show_ip_pim_nexthop_cmd,
5464 "show ip pim [vrf NAME] nexthop",
5465 SHOW_STR
5466 IP_STR
5467 PIM_STR
5468 VRF_CMD_HELP_STR
5469 "PIM cached nexthop rpf information\n")
5470 {
5471 int idx = 2;
5472 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5473
5474 if (!vrf)
5475 return CMD_WARNING;
5476
5477 pim_show_nexthop(vrf->info, vty);
5478
5479 return CMD_SUCCESS;
5480 }
5481
5482 DEFUN (show_ip_pim_nexthop_lookup,
5483 show_ip_pim_nexthop_lookup_cmd,
5484 "show ip pim [vrf NAME] nexthop-lookup A.B.C.D A.B.C.D",
5485 SHOW_STR
5486 IP_STR
5487 PIM_STR
5488 VRF_CMD_HELP_STR
5489 "PIM cached nexthop rpf lookup\n"
5490 "Source/RP address\n"
5491 "Multicast Group address\n")
5492 {
5493 struct prefix nht_p;
5494 int result = 0;
5495 struct in_addr src_addr, grp_addr;
5496 struct in_addr vif_source;
5497 const char *addr_str, *addr_str1;
5498 struct prefix grp;
5499 struct pim_nexthop nexthop;
5500 char nexthop_addr_str[PREFIX_STRLEN];
5501 char grp_str[PREFIX_STRLEN];
5502 int idx = 2;
5503 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5504
5505 if (!vrf)
5506 return CMD_WARNING;
5507
5508 argv_find(argv, argc, "A.B.C.D", &idx);
5509 addr_str = argv[idx]->arg;
5510 result = inet_pton(AF_INET, addr_str, &src_addr);
5511 if (result <= 0) {
5512 vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str,
5513 errno, safe_strerror(errno));
5514 return CMD_WARNING;
5515 }
5516
5517 if (pim_is_group_224_4(src_addr)) {
5518 vty_out(vty,
5519 "Invalid argument. Expected Valid Source Address.\n");
5520 return CMD_WARNING;
5521 }
5522
5523 addr_str1 = argv[idx + 1]->arg;
5524 result = inet_pton(AF_INET, addr_str1, &grp_addr);
5525 if (result <= 0) {
5526 vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str,
5527 errno, safe_strerror(errno));
5528 return CMD_WARNING;
5529 }
5530
5531 if (!pim_is_group_224_4(grp_addr)) {
5532 vty_out(vty,
5533 "Invalid argument. Expected Valid Multicast Group Address.\n");
5534 return CMD_WARNING;
5535 }
5536
5537 if (!pim_rp_set_upstream_addr(vrf->info, &vif_source, src_addr,
5538 grp_addr))
5539 return CMD_SUCCESS;
5540
5541 nht_p.family = AF_INET;
5542 nht_p.prefixlen = IPV4_MAX_BITLEN;
5543 nht_p.u.prefix4 = vif_source;
5544 grp.family = AF_INET;
5545 grp.prefixlen = IPV4_MAX_BITLEN;
5546 grp.u.prefix4 = grp_addr;
5547 memset(&nexthop, 0, sizeof(nexthop));
5548
5549 result = pim_ecmp_nexthop_lookup(vrf->info, &nexthop, &nht_p, &grp, 0);
5550
5551 if (!result) {
5552 vty_out(vty,
5553 "Nexthop Lookup failed, no usable routes returned.\n");
5554 return CMD_SUCCESS;
5555 }
5556
5557 pim_addr_dump("<grp?>", &grp, grp_str, sizeof(grp_str));
5558 pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr,
5559 nexthop_addr_str, sizeof(nexthop_addr_str));
5560 vty_out(vty, "Group %s --- Nexthop %s Interface %s \n", grp_str,
5561 nexthop_addr_str, nexthop.interface->name);
5562
5563 return CMD_SUCCESS;
5564 }
5565
5566 DEFUN (show_ip_pim_interface_traffic,
5567 show_ip_pim_interface_traffic_cmd,
5568 "show ip pim [vrf NAME] interface traffic [WORD] [json]",
5569 SHOW_STR
5570 IP_STR
5571 PIM_STR
5572 VRF_CMD_HELP_STR
5573 "PIM interface information\n"
5574 "Protocol Packet counters\n"
5575 "Interface name\n"
5576 JSON_STR)
5577 {
5578 int idx = 2;
5579 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5580 bool uj = use_json(argc, argv);
5581
5582 if (!vrf)
5583 return CMD_WARNING;
5584
5585 if (argv_find(argv, argc, "WORD", &idx))
5586 pim_show_interface_traffic_single(vrf->info, vty,
5587 argv[idx]->arg, uj);
5588 else
5589 pim_show_interface_traffic(vrf->info, vty, uj);
5590
5591 return CMD_SUCCESS;
5592 }
5593
5594 DEFUN (show_ip_pim_bsm_db,
5595 show_ip_pim_bsm_db_cmd,
5596 "show ip pim bsm-database [vrf NAME] [json]",
5597 SHOW_STR
5598 IP_STR
5599 PIM_STR
5600 "PIM cached bsm packets information\n"
5601 VRF_CMD_HELP_STR
5602 JSON_STR)
5603 {
5604 int idx = 2;
5605 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5606 bool uj = use_json(argc, argv);
5607
5608 if (!vrf)
5609 return CMD_WARNING;
5610
5611 pim_show_bsm_db(vrf->info, vty, uj);
5612 return CMD_SUCCESS;
5613 }
5614
5615 DEFUN (show_ip_pim_bsrp,
5616 show_ip_pim_bsrp_cmd,
5617 "show ip pim bsrp-info [vrf NAME] [json]",
5618 SHOW_STR
5619 IP_STR
5620 PIM_STR
5621 "PIM cached group-rp mappings information\n"
5622 VRF_CMD_HELP_STR
5623 JSON_STR)
5624 {
5625 int idx = 2;
5626 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5627 bool uj = use_json(argc, argv);
5628
5629 if (!vrf)
5630 return CMD_WARNING;
5631
5632 pim_show_group_rp_mappings_info(vrf->info, vty, uj);
5633
5634 return CMD_SUCCESS;
5635 }
5636
5637 DEFUN (show_ip_pim_statistics,
5638 show_ip_pim_statistics_cmd,
5639 "show ip pim [vrf NAME] statistics [interface WORD] [json]",
5640 SHOW_STR
5641 IP_STR
5642 PIM_STR
5643 VRF_CMD_HELP_STR
5644 "PIM statistics\n"
5645 INTERFACE_STR
5646 "PIM interface\n"
5647 JSON_STR)
5648 {
5649 int idx = 2;
5650 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5651 bool uj = use_json(argc, argv);
5652
5653 if (!vrf)
5654 return CMD_WARNING;
5655
5656 if (argv_find(argv, argc, "WORD", &idx))
5657 pim_show_statistics(vrf->info, vty, argv[idx]->arg, uj);
5658 else
5659 pim_show_statistics(vrf->info, vty, NULL, uj);
5660
5661 return CMD_SUCCESS;
5662 }
5663
5664 static void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty,
5665 bool uj)
5666 {
5667 struct interface *ifp;
5668 json_object *json = NULL;
5669 json_object *json_row = NULL;
5670
5671 vty_out(vty, "\n");
5672
5673 if (uj)
5674 json = json_object_new_object();
5675 else
5676 vty_out(vty,
5677 "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut\n");
5678
5679 FOR_ALL_INTERFACES (pim->vrf, ifp) {
5680 struct pim_interface *pim_ifp;
5681 struct in_addr ifaddr;
5682 struct sioc_vif_req vreq;
5683
5684 pim_ifp = ifp->info;
5685
5686 if (!pim_ifp)
5687 continue;
5688
5689 memset(&vreq, 0, sizeof(vreq));
5690 vreq.vifi = pim_ifp->mroute_vif_index;
5691
5692 if (ioctl(pim->mroute_socket, SIOCGETVIFCNT, &vreq)) {
5693 zlog_warn(
5694 "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
5695 (unsigned long)SIOCGETVIFCNT, ifp->name,
5696 pim_ifp->mroute_vif_index, errno,
5697 safe_strerror(errno));
5698 }
5699
5700 ifaddr = pim_ifp->primary_address;
5701 if (uj) {
5702 json_row = json_object_new_object();
5703 json_object_string_add(json_row, "name", ifp->name);
5704 json_object_string_add(json_row, "state",
5705 if_is_up(ifp) ? "up" : "down");
5706 json_object_string_add(
5707 json_row, "address",
5708 inet_ntoa(pim_ifp->primary_address));
5709 json_object_int_add(json_row, "ifIndex", ifp->ifindex);
5710 json_object_int_add(json_row, "vif",
5711 pim_ifp->mroute_vif_index);
5712 json_object_int_add(json_row, "pktsIn",
5713 (unsigned long)vreq.icount);
5714 json_object_int_add(json_row, "pktsOut",
5715 (unsigned long)vreq.ocount);
5716 json_object_int_add(json_row, "bytesIn",
5717 (unsigned long)vreq.ibytes);
5718 json_object_int_add(json_row, "bytesOut",
5719 (unsigned long)vreq.obytes);
5720 json_object_object_add(json, ifp->name, json_row);
5721 } else {
5722 vty_out(vty,
5723 "%-16s %-15s %3d %3d %7lu %7lu %10lu %10lu\n",
5724 ifp->name, inet_ntoa(ifaddr), ifp->ifindex,
5725 pim_ifp->mroute_vif_index,
5726 (unsigned long)vreq.icount,
5727 (unsigned long)vreq.ocount,
5728 (unsigned long)vreq.ibytes,
5729 (unsigned long)vreq.obytes);
5730 }
5731 }
5732
5733 if (uj) {
5734 vty_out(vty, "%s\n",
5735 json_object_to_json_string_ext(
5736 json, JSON_C_TO_STRING_PRETTY));
5737 json_object_free(json);
5738 }
5739 }
5740
5741 static void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim,
5742 struct vty *vty)
5743 {
5744 struct vrf *vrf = pim->vrf;
5745 time_t now = pim_time_monotonic_sec();
5746 char uptime[10];
5747 char mlag_role[80];
5748
5749 pim = vrf->info;
5750
5751 vty_out(vty, "Router MLAG Role: %s\n",
5752 mlag_role2str(router->mlag_role, mlag_role, sizeof(mlag_role)));
5753 vty_out(vty, "Mroute socket descriptor:");
5754
5755 vty_out(vty, " %d(%s)\n", pim->mroute_socket, vrf->name);
5756
5757 pim_time_uptime(uptime, sizeof(uptime),
5758 now - pim->mroute_socket_creation);
5759 vty_out(vty, "Mroute socket uptime: %s\n", uptime);
5760
5761 vty_out(vty, "\n");
5762
5763 pim_zebra_zclient_update(vty);
5764 pim_zlookup_show_ip_multicast(vty);
5765
5766 vty_out(vty, "\n");
5767 vty_out(vty, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS);
5768
5769 vty_out(vty, "\n");
5770 vty_out(vty, "Upstream Join Timer: %d secs\n", router->t_periodic);
5771 vty_out(vty, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME);
5772 vty_out(vty, "PIM ECMP: %s\n", pim->ecmp_enable ? "Enable" : "Disable");
5773 vty_out(vty, "PIM ECMP Rebalance: %s\n",
5774 pim->ecmp_rebalance_enable ? "Enable" : "Disable");
5775
5776 vty_out(vty, "\n");
5777
5778 show_rpf_refresh_stats(vty, pim, now, NULL);
5779
5780 vty_out(vty, "\n");
5781
5782 show_scan_oil_stats(pim, vty, now);
5783
5784 show_multicast_interfaces(pim, vty, false);
5785 }
5786
5787 DEFUN (show_ip_multicast,
5788 show_ip_multicast_cmd,
5789 "show ip multicast [vrf NAME]",
5790 SHOW_STR
5791 IP_STR
5792 VRF_CMD_HELP_STR
5793 "Multicast global information\n")
5794 {
5795 int idx = 2;
5796 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5797
5798 if (!vrf)
5799 return CMD_WARNING;
5800
5801 pim_cmd_show_ip_multicast_helper(vrf->info, vty);
5802
5803 return CMD_SUCCESS;
5804 }
5805
5806 DEFUN (show_ip_multicast_vrf_all,
5807 show_ip_multicast_vrf_all_cmd,
5808 "show ip multicast vrf all",
5809 SHOW_STR
5810 IP_STR
5811 VRF_CMD_HELP_STR
5812 "Multicast global information\n")
5813 {
5814 bool uj = use_json(argc, argv);
5815 struct vrf *vrf;
5816 bool first = true;
5817
5818 if (uj)
5819 vty_out(vty, "{ ");
5820 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5821 if (uj) {
5822 if (!first)
5823 vty_out(vty, ", ");
5824 vty_out(vty, " \"%s\": ", vrf->name);
5825 first = false;
5826 } else
5827 vty_out(vty, "VRF: %s\n", vrf->name);
5828 pim_cmd_show_ip_multicast_helper(vrf->info, vty);
5829 }
5830 if (uj)
5831 vty_out(vty, "}\n");
5832
5833 return CMD_SUCCESS;
5834 }
5835
5836 DEFUN(show_ip_multicast_count,
5837 show_ip_multicast_count_cmd,
5838 "show ip multicast count [vrf NAME] [json]",
5839 SHOW_STR IP_STR
5840 "Multicast global information\n"
5841 "Data packet count\n"
5842 VRF_CMD_HELP_STR JSON_STR)
5843 {
5844 int idx = 3;
5845 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5846 bool uj = use_json(argc, argv);
5847
5848 if (!vrf)
5849 return CMD_WARNING;
5850
5851 show_multicast_interfaces(vrf->info, vty, uj);
5852
5853 return CMD_SUCCESS;
5854 }
5855
5856 DEFUN(show_ip_multicast_count_vrf_all,
5857 show_ip_multicast_count_vrf_all_cmd,
5858 "show ip multicast count vrf all [json]",
5859 SHOW_STR IP_STR
5860 "Multicast global information\n"
5861 "Data packet count\n"
5862 VRF_CMD_HELP_STR JSON_STR)
5863 {
5864 bool uj = use_json(argc, argv);
5865 struct vrf *vrf;
5866 bool first = true;
5867
5868 if (uj)
5869 vty_out(vty, "{ ");
5870
5871 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5872 if (uj) {
5873 if (!first)
5874 vty_out(vty, ", ");
5875
5876 vty_out(vty, " \"%s\": ", vrf->name);
5877 first = false;
5878 } else
5879 vty_out(vty, "VRF: %s\n", vrf->name);
5880
5881 show_multicast_interfaces(vrf->info, vty, uj);
5882 }
5883
5884 if (uj)
5885 vty_out(vty, "}\n");
5886
5887 return CMD_SUCCESS;
5888 }
5889
5890 static void show_mroute(struct pim_instance *pim, struct vty *vty,
5891 struct prefix_sg *sg, bool fill, bool uj)
5892 {
5893 struct listnode *node;
5894 struct channel_oil *c_oil;
5895 struct static_route *s_route;
5896 time_t now;
5897 json_object *json = NULL;
5898 json_object *json_group = NULL;
5899 json_object *json_source = NULL;
5900 json_object *json_oil = NULL;
5901 json_object *json_ifp_out = NULL;
5902 int found_oif;
5903 int first;
5904 char grp_str[INET_ADDRSTRLEN];
5905 char src_str[INET_ADDRSTRLEN];
5906 char in_ifname[INTERFACE_NAMSIZ + 1];
5907 char out_ifname[INTERFACE_NAMSIZ + 1];
5908 int oif_vif_index;
5909 struct interface *ifp_in;
5910 char proto[100];
5911 char state_str[PIM_REG_STATE_STR_LEN];
5912 char mroute_uptime[10];
5913
5914 if (uj) {
5915 json = json_object_new_object();
5916 } else {
5917 vty_out(vty, "IP Multicast Routing Table\n");
5918 vty_out(vty, "Flags: S - Sparse, C - Connected, P - Pruned\n");
5919 vty_out(vty,
5920 " R - RP-bit set, F - Register flag, T - SPT-bit set\n");
5921 vty_out(vty,
5922 "\nSource Group Flags Proto Input Output TTL Uptime\n");
5923 }
5924
5925 now = pim_time_monotonic_sec();
5926
5927 /* print list of PIM and IGMP routes */
5928 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
5929 found_oif = 0;
5930 first = 1;
5931 if (!c_oil->installed)
5932 continue;
5933
5934 if (sg->grp.s_addr != 0 &&
5935 sg->grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr)
5936 continue;
5937 if (sg->src.s_addr != 0 &&
5938 sg->src.s_addr != c_oil->oil.mfcc_origin.s_addr)
5939 continue;
5940
5941 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str,
5942 sizeof(grp_str));
5943 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str,
5944 sizeof(src_str));
5945
5946 strlcpy(state_str, "S", sizeof(state_str));
5947 /* When a non DR receives a igmp join, it creates a (*,G)
5948 * channel_oil without any upstream creation */
5949 if (c_oil->up) {
5950 if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil->up->flags))
5951 strlcat(state_str, "C", sizeof(state_str));
5952 if (pim_upstream_is_sg_rpt(c_oil->up))
5953 strlcat(state_str, "R", sizeof(state_str));
5954 if (PIM_UPSTREAM_FLAG_TEST_FHR(c_oil->up->flags))
5955 strlcat(state_str, "F", sizeof(state_str));
5956 if (c_oil->up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
5957 strlcat(state_str, "T", sizeof(state_str));
5958 }
5959 if (pim_channel_oil_empty(c_oil))
5960 strlcat(state_str, "P", sizeof(state_str));
5961
5962 ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent);
5963
5964 if (ifp_in)
5965 strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
5966 else
5967 strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
5968
5969
5970 pim_time_uptime(mroute_uptime, sizeof(mroute_uptime),
5971 now - c_oil->mroute_creation);
5972
5973 if (uj) {
5974
5975 /* Find the group, create it if it doesn't exist */
5976 json_object_object_get_ex(json, grp_str, &json_group);
5977
5978 if (!json_group) {
5979 json_group = json_object_new_object();
5980 json_object_object_add(json, grp_str,
5981 json_group);
5982 }
5983
5984 /* Find the source nested under the group, create it if
5985 * it doesn't exist
5986 */
5987 json_object_object_get_ex(json_group, src_str,
5988 &json_source);
5989
5990 if (!json_source) {
5991 json_source = json_object_new_object();
5992 json_object_object_add(json_group, src_str,
5993 json_source);
5994 }
5995
5996 /* Find the inbound interface nested under the source,
5997 * create it if it doesn't exist */
5998 json_object_int_add(json_source, "installed",
5999 c_oil->installed);
6000 json_object_int_add(json_source, "refCount",
6001 c_oil->oil_ref_count);
6002 json_object_int_add(json_source, "oilSize",
6003 c_oil->oil_size);
6004 json_object_int_add(json_source, "OilInheritedRescan",
6005 c_oil->oil_inherited_rescan);
6006 json_object_string_add(json_source, "iif", in_ifname);
6007 json_object_string_add(json_source, "upTime",
6008 mroute_uptime);
6009 json_oil = NULL;
6010 }
6011
6012 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
6013 ++oif_vif_index) {
6014 struct interface *ifp_out;
6015 int ttl;
6016
6017 ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
6018 if (ttl < 1)
6019 continue;
6020
6021 /* do not display muted OIFs */
6022 if (c_oil->oif_flags[oif_vif_index]
6023 & PIM_OIF_FLAG_MUTE)
6024 continue;
6025
6026 if (c_oil->oil.mfcc_parent == oif_vif_index &&
6027 !pim_mroute_allow_iif_in_oil(c_oil,
6028 oif_vif_index))
6029 continue;
6030
6031 ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
6032 found_oif = 1;
6033
6034 if (ifp_out)
6035 strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname));
6036 else
6037 strlcpy(out_ifname, "<oif?>", sizeof(out_ifname));
6038
6039 if (uj) {
6040 json_ifp_out = json_object_new_object();
6041 json_object_string_add(json_ifp_out, "source",
6042 src_str);
6043 json_object_string_add(json_ifp_out, "group",
6044 grp_str);
6045
6046 if (c_oil->oif_flags[oif_vif_index]
6047 & PIM_OIF_FLAG_PROTO_PIM)
6048 json_object_boolean_true_add(
6049 json_ifp_out, "protocolPim");
6050
6051 if (c_oil->oif_flags[oif_vif_index]
6052 & PIM_OIF_FLAG_PROTO_IGMP)
6053 json_object_boolean_true_add(
6054 json_ifp_out, "protocolIgmp");
6055
6056 if (c_oil->oif_flags[oif_vif_index]
6057 & PIM_OIF_FLAG_PROTO_VXLAN)
6058 json_object_boolean_true_add(
6059 json_ifp_out, "protocolVxlan");
6060
6061 if (c_oil->oif_flags[oif_vif_index]
6062 & PIM_OIF_FLAG_PROTO_STAR)
6063 json_object_boolean_true_add(
6064 json_ifp_out,
6065 "protocolInherited");
6066
6067 json_object_string_add(json_ifp_out,
6068 "inboundInterface",
6069 in_ifname);
6070 json_object_int_add(json_ifp_out, "iVifI",
6071 c_oil->oil.mfcc_parent);
6072 json_object_string_add(json_ifp_out,
6073 "outboundInterface",
6074 out_ifname);
6075 json_object_int_add(json_ifp_out, "oVifI",
6076 oif_vif_index);
6077 json_object_int_add(json_ifp_out, "ttl", ttl);
6078 json_object_string_add(json_ifp_out, "upTime",
6079 mroute_uptime);
6080 json_object_string_add(json_source, "flags",
6081 state_str);
6082 if (!json_oil) {
6083 json_oil = json_object_new_object();
6084 json_object_object_add(json_source,
6085 "oil", json_oil);
6086 }
6087 json_object_object_add(json_oil, out_ifname,
6088 json_ifp_out);
6089 } else {
6090 if (c_oil->oif_flags[oif_vif_index]
6091 & PIM_OIF_FLAG_PROTO_PIM) {
6092 strlcpy(proto, "PIM", sizeof(proto));
6093 }
6094
6095 if (c_oil->oif_flags[oif_vif_index]
6096 & PIM_OIF_FLAG_PROTO_IGMP) {
6097 strlcpy(proto, "IGMP", sizeof(proto));
6098 }
6099
6100 if (c_oil->oif_flags[oif_vif_index]
6101 & PIM_OIF_FLAG_PROTO_VXLAN) {
6102 strlcpy(proto, "VxLAN", sizeof(proto));
6103 }
6104
6105 if (c_oil->oif_flags[oif_vif_index]
6106 & PIM_OIF_FLAG_PROTO_STAR) {
6107 strlcpy(proto, "STAR", sizeof(proto));
6108 }
6109
6110 vty_out(vty,
6111 "%-15s %-15s %-15s %-6s %-16s %-16s %-3d %8s\n",
6112 src_str, grp_str, state_str, proto,
6113 in_ifname, out_ifname, ttl,
6114 mroute_uptime);
6115
6116 if (first) {
6117 src_str[0] = '\0';
6118 grp_str[0] = '\0';
6119 in_ifname[0] = '\0';
6120 state_str[0] = '\0';
6121 mroute_uptime[0] = '\0';
6122 first = 0;
6123 }
6124 }
6125 }
6126
6127 if (!uj && !found_oif) {
6128 vty_out(vty,
6129 "%-15s %-15s %-15s %-6s %-16s %-16s %-3d %8s\n",
6130 src_str, grp_str, state_str, "none", in_ifname,
6131 "none", 0, "--:--:--");
6132 }
6133 }
6134
6135 /* Print list of static routes */
6136 for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
6137 first = 1;
6138
6139 if (!s_route->c_oil.installed)
6140 continue;
6141
6142 pim_inet4_dump("<group?>", s_route->group, grp_str,
6143 sizeof(grp_str));
6144 pim_inet4_dump("<source?>", s_route->source, src_str,
6145 sizeof(src_str));
6146 ifp_in = pim_if_find_by_vif_index(pim, s_route->iif);
6147 found_oif = 0;
6148
6149 if (ifp_in)
6150 strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
6151 else
6152 strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
6153
6154 if (uj) {
6155
6156 /* Find the group, create it if it doesn't exist */
6157 json_object_object_get_ex(json, grp_str, &json_group);
6158
6159 if (!json_group) {
6160 json_group = json_object_new_object();
6161 json_object_object_add(json, grp_str,
6162 json_group);
6163 }
6164
6165 /* Find the source nested under the group, create it if
6166 * it doesn't exist */
6167 json_object_object_get_ex(json_group, src_str,
6168 &json_source);
6169
6170 if (!json_source) {
6171 json_source = json_object_new_object();
6172 json_object_object_add(json_group, src_str,
6173 json_source);
6174 }
6175
6176 json_object_string_add(json_source, "iif", in_ifname);
6177 json_oil = NULL;
6178 } else {
6179 strlcpy(proto, "STATIC", sizeof(proto));
6180 }
6181
6182 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
6183 ++oif_vif_index) {
6184 struct interface *ifp_out;
6185 char oif_uptime[10];
6186 int ttl;
6187
6188 ttl = s_route->oif_ttls[oif_vif_index];
6189 if (ttl < 1)
6190 continue;
6191
6192 ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
6193 pim_time_uptime(
6194 oif_uptime, sizeof(oif_uptime),
6195 now
6196 - s_route->c_oil
6197 .oif_creation[oif_vif_index]);
6198 found_oif = 1;
6199
6200 if (ifp_out)
6201 strlcpy(out_ifname, ifp_out->name, sizeof(out_ifname));
6202 else
6203 strlcpy(out_ifname, "<oif?>", sizeof(out_ifname));
6204
6205 if (uj) {
6206 json_ifp_out = json_object_new_object();
6207 json_object_string_add(json_ifp_out, "source",
6208 src_str);
6209 json_object_string_add(json_ifp_out, "group",
6210 grp_str);
6211 json_object_boolean_true_add(json_ifp_out,
6212 "protocolStatic");
6213 json_object_string_add(json_ifp_out,
6214 "inboundInterface",
6215 in_ifname);
6216 json_object_int_add(
6217 json_ifp_out, "iVifI",
6218 s_route->c_oil.oil.mfcc_parent);
6219 json_object_string_add(json_ifp_out,
6220 "outboundInterface",
6221 out_ifname);
6222 json_object_int_add(json_ifp_out, "oVifI",
6223 oif_vif_index);
6224 json_object_int_add(json_ifp_out, "ttl", ttl);
6225 json_object_string_add(json_ifp_out, "upTime",
6226 oif_uptime);
6227 if (!json_oil) {
6228 json_oil = json_object_new_object();
6229 json_object_object_add(json_source,
6230 "oil", json_oil);
6231 }
6232 json_object_object_add(json_oil, out_ifname,
6233 json_ifp_out);
6234 } else {
6235 vty_out(vty,
6236 "%-15s %-15s %-6s %-16s %-16s %-3d %8s %s\n",
6237 src_str, grp_str, proto, in_ifname,
6238 out_ifname, ttl, oif_uptime,
6239 pim->vrf->name);
6240 if (first && !fill) {
6241 src_str[0] = '\0';
6242 grp_str[0] = '\0';
6243 in_ifname[0] = '\0';
6244 first = 0;
6245 }
6246 }
6247 }
6248
6249 if (!uj && !found_oif) {
6250 vty_out(vty,
6251 "%-15s %-15s %-6s %-16s %-16s %-3d %8s %s\n",
6252 src_str, grp_str, proto, in_ifname, "none", 0,
6253 "--:--:--", pim->vrf->name);
6254 }
6255 }
6256
6257 if (uj) {
6258 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6259 json, JSON_C_TO_STRING_PRETTY));
6260 json_object_free(json);
6261 }
6262 }
6263
6264 DEFPY (show_ip_mroute,
6265 show_ip_mroute_cmd,
6266 "show ip mroute [vrf NAME] [A.B.C.D$s_or_g [A.B.C.D$g]] [fill$fill] [json$json]",
6267 SHOW_STR
6268 IP_STR
6269 MROUTE_STR
6270 VRF_CMD_HELP_STR
6271 "The Source or Group\n"
6272 "The Group\n"
6273 "Fill in Assumed data\n"
6274 JSON_STR)
6275 {
6276 struct prefix_sg sg = {0};
6277 struct pim_instance *pim;
6278 struct vrf *v;
6279
6280 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
6281
6282 if (!v) {
6283 vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
6284 return CMD_WARNING;
6285 }
6286 pim = pim_get_pim_instance(v->vrf_id);
6287
6288 if (!pim) {
6289 vty_out(vty, "%% Unable to find pim instance\n");
6290 return CMD_WARNING;
6291 }
6292
6293 if (s_or_g.s_addr != 0) {
6294 if (g.s_addr != 0) {
6295 sg.src = s_or_g;
6296 sg.grp = g;
6297 } else
6298 sg.grp = s_or_g;
6299 }
6300 show_mroute(pim, vty, &sg, !!fill, !!json);
6301 return CMD_SUCCESS;
6302 }
6303
6304 DEFUN (show_ip_mroute_vrf_all,
6305 show_ip_mroute_vrf_all_cmd,
6306 "show ip mroute vrf all [fill] [json]",
6307 SHOW_STR
6308 IP_STR
6309 MROUTE_STR
6310 VRF_CMD_HELP_STR
6311 "Fill in Assumed data\n"
6312 JSON_STR)
6313 {
6314 struct prefix_sg sg = {0};
6315 bool uj = use_json(argc, argv);
6316 int idx = 4;
6317 struct vrf *vrf;
6318 bool first = true;
6319 bool fill = false;
6320
6321 if (argv_find(argv, argc, "fill", &idx))
6322 fill = true;
6323
6324 if (uj)
6325 vty_out(vty, "{ ");
6326 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
6327 if (uj) {
6328 if (!first)
6329 vty_out(vty, ", ");
6330 vty_out(vty, " \"%s\": ", vrf->name);
6331 first = false;
6332 } else
6333 vty_out(vty, "VRF: %s\n", vrf->name);
6334 show_mroute(vrf->info, vty, &sg, fill, uj);
6335 }
6336 if (uj)
6337 vty_out(vty, "}\n");
6338
6339 return CMD_SUCCESS;
6340 }
6341
6342 DEFUN (clear_ip_mroute_count,
6343 clear_ip_mroute_count_cmd,
6344 "clear ip mroute [vrf NAME] count",
6345 CLEAR_STR
6346 IP_STR
6347 MROUTE_STR
6348 VRF_CMD_HELP_STR
6349 "Route and packet count data\n")
6350 {
6351 int idx = 2;
6352 struct listnode *node;
6353 struct channel_oil *c_oil;
6354 struct static_route *sr;
6355 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
6356 struct pim_instance *pim;
6357
6358 if (!vrf)
6359 return CMD_WARNING;
6360
6361 pim = vrf->info;
6362 frr_each(rb_pim_oil, &pim->channel_oil_head, c_oil) {
6363 if (!c_oil->installed)
6364 continue;
6365
6366 pim_mroute_update_counters(c_oil);
6367 c_oil->cc.origpktcnt = c_oil->cc.pktcnt;
6368 c_oil->cc.origbytecnt = c_oil->cc.bytecnt;
6369 c_oil->cc.origwrong_if = c_oil->cc.wrong_if;
6370 }
6371
6372 for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr)) {
6373 if (!sr->c_oil.installed)
6374 continue;
6375
6376 pim_mroute_update_counters(&sr->c_oil);
6377
6378 sr->c_oil.cc.origpktcnt = sr->c_oil.cc.pktcnt;
6379 sr->c_oil.cc.origbytecnt = sr->c_oil.cc.bytecnt;
6380 sr->c_oil.cc.origwrong_if = sr->c_oil.cc.wrong_if;
6381 }
6382 return CMD_SUCCESS;
6383 }
6384
6385 static void show_mroute_count_per_channel_oil(struct channel_oil *c_oil,
6386 json_object *json,
6387 struct vty *vty)
6388 {
6389 char group_str[INET_ADDRSTRLEN];
6390 char source_str[INET_ADDRSTRLEN];
6391 json_object *json_group = NULL;
6392 json_object *json_source = NULL;
6393
6394 if (!c_oil->installed)
6395 return;
6396
6397 pim_mroute_update_counters(c_oil);
6398
6399 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str,
6400 sizeof(group_str));
6401 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str,
6402 sizeof(source_str));
6403
6404 if (json) {
6405 json_object_object_get_ex(json, group_str, &json_group);
6406
6407 if (!json_group) {
6408 json_group = json_object_new_object();
6409 json_object_object_add(json, group_str, json_group);
6410 }
6411
6412 json_source = json_object_new_object();
6413 json_object_object_add(json_group, source_str, json_source);
6414 json_object_int_add(json_source, "lastUsed",
6415 c_oil->cc.lastused / 100);
6416 json_object_int_add(json_source, "packets", c_oil->cc.pktcnt);
6417 json_object_int_add(json_source, "bytes", c_oil->cc.bytecnt);
6418 json_object_int_add(json_source, "wrongIf", c_oil->cc.wrong_if);
6419
6420 } else {
6421 vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n",
6422 source_str, group_str, c_oil->cc.lastused / 100,
6423 c_oil->cc.pktcnt - c_oil->cc.origpktcnt,
6424 c_oil->cc.bytecnt - c_oil->cc.origbytecnt,
6425 c_oil->cc.wrong_if - c_oil->cc.origwrong_if);
6426 }
6427 }
6428
6429 static void show_mroute_count(struct pim_instance *pim, struct vty *vty,
6430 bool uj)
6431 {
6432 struct listnode *node;
6433 struct channel_oil *c_oil;
6434 struct static_route *sr;
6435 json_object *json = NULL;
6436
6437 if (uj)
6438 json = json_object_new_object();
6439 else {
6440 vty_out(vty, "\n");
6441
6442 vty_out(vty,
6443 "Source Group LastUsed Packets Bytes WrongIf \n");
6444 }
6445
6446 /* Print PIM and IGMP route counts */
6447 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
6448 show_mroute_count_per_channel_oil(c_oil, json, vty);
6449
6450 for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr))
6451 show_mroute_count_per_channel_oil(&sr->c_oil, json, vty);
6452
6453 if (uj) {
6454 vty_out(vty, "%s\n",
6455 json_object_to_json_string_ext(
6456 json, JSON_C_TO_STRING_PRETTY));
6457 json_object_free(json);
6458 }
6459 }
6460
6461 DEFUN (show_ip_mroute_count,
6462 show_ip_mroute_count_cmd,
6463 "show ip mroute [vrf NAME] count [json]",
6464 SHOW_STR
6465 IP_STR
6466 MROUTE_STR
6467 VRF_CMD_HELP_STR
6468 "Route and packet count data\n"
6469 JSON_STR)
6470 {
6471 int idx = 2;
6472 bool uj = use_json(argc, argv);
6473 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
6474
6475 if (!vrf)
6476 return CMD_WARNING;
6477
6478 show_mroute_count(vrf->info, vty, uj);
6479 return CMD_SUCCESS;
6480 }
6481
6482 DEFUN (show_ip_mroute_count_vrf_all,
6483 show_ip_mroute_count_vrf_all_cmd,
6484 "show ip mroute vrf all count [json]",
6485 SHOW_STR
6486 IP_STR
6487 MROUTE_STR
6488 VRF_CMD_HELP_STR
6489 "Route and packet count data\n"
6490 JSON_STR)
6491 {
6492 bool uj = use_json(argc, argv);
6493 struct vrf *vrf;
6494 bool first = true;
6495
6496 if (uj)
6497 vty_out(vty, "{ ");
6498 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
6499 if (uj) {
6500 if (!first)
6501 vty_out(vty, ", ");
6502 vty_out(vty, " \"%s\": ", vrf->name);
6503 first = false;
6504 } else
6505 vty_out(vty, "VRF: %s\n", vrf->name);
6506 show_mroute_count(vrf->info, vty, uj);
6507 }
6508 if (uj)
6509 vty_out(vty, "}\n");
6510
6511 return CMD_SUCCESS;
6512 }
6513
6514 static void show_mroute_summary(struct pim_instance *pim, struct vty *vty,
6515 json_object *json)
6516 {
6517 struct listnode *node;
6518 struct channel_oil *c_oil;
6519 struct static_route *s_route;
6520 uint32_t starg_sw_mroute_cnt = 0;
6521 uint32_t sg_sw_mroute_cnt = 0;
6522 uint32_t starg_hw_mroute_cnt = 0;
6523 uint32_t sg_hw_mroute_cnt = 0;
6524 json_object *json_starg = NULL;
6525 json_object *json_sg = NULL;
6526
6527 if (!json)
6528 vty_out(vty, "Mroute Type Installed/Total\n");
6529
6530 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
6531 if (!c_oil->installed) {
6532 if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
6533 starg_sw_mroute_cnt++;
6534 else
6535 sg_sw_mroute_cnt++;
6536 } else {
6537 if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
6538 starg_hw_mroute_cnt++;
6539 else
6540 sg_hw_mroute_cnt++;
6541 }
6542 }
6543
6544 for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
6545 if (!s_route->c_oil.installed) {
6546 if (s_route->c_oil.oil.mfcc_origin.s_addr == INADDR_ANY)
6547 starg_sw_mroute_cnt++;
6548 else
6549 sg_sw_mroute_cnt++;
6550 } else {
6551 if (s_route->c_oil.oil.mfcc_origin.s_addr == INADDR_ANY)
6552 starg_hw_mroute_cnt++;
6553 else
6554 sg_hw_mroute_cnt++;
6555 }
6556 }
6557
6558 if (!json) {
6559 vty_out(vty, "%-20s %u/%u\n", "(*, G)", starg_hw_mroute_cnt,
6560 starg_sw_mroute_cnt + starg_hw_mroute_cnt);
6561 vty_out(vty, "%-20s %u/%u\n", "(S, G)", sg_hw_mroute_cnt,
6562 sg_sw_mroute_cnt + sg_hw_mroute_cnt);
6563 vty_out(vty, "------\n");
6564 vty_out(vty, "%-20s %u/%u\n", "Total",
6565 (starg_hw_mroute_cnt + sg_hw_mroute_cnt),
6566 (starg_sw_mroute_cnt + starg_hw_mroute_cnt
6567 + sg_sw_mroute_cnt + sg_hw_mroute_cnt));
6568 } else {
6569 /* (*,G) route details */
6570 json_starg = json_object_new_object();
6571 json_object_object_add(json, "wildcardGroup", json_starg);
6572
6573 json_object_int_add(json_starg, "installed",
6574 starg_hw_mroute_cnt);
6575 json_object_int_add(json_starg, "total",
6576 starg_sw_mroute_cnt + starg_hw_mroute_cnt);
6577
6578 /* (S, G) route details */
6579 json_sg = json_object_new_object();
6580 json_object_object_add(json, "sourceGroup", json_sg);
6581
6582 json_object_int_add(json_sg, "installed", sg_hw_mroute_cnt);
6583 json_object_int_add(json_sg, "total",
6584 sg_sw_mroute_cnt + sg_hw_mroute_cnt);
6585
6586 json_object_int_add(json, "totalNumOfInstalledMroutes",
6587 starg_hw_mroute_cnt + sg_hw_mroute_cnt);
6588 json_object_int_add(json, "totalNumOfMroutes",
6589 starg_sw_mroute_cnt + starg_hw_mroute_cnt
6590 + sg_sw_mroute_cnt
6591 + sg_hw_mroute_cnt);
6592 }
6593 }
6594
6595 DEFUN (show_ip_mroute_summary,
6596 show_ip_mroute_summary_cmd,
6597 "show ip mroute [vrf NAME] summary [json]",
6598 SHOW_STR
6599 IP_STR
6600 MROUTE_STR
6601 VRF_CMD_HELP_STR
6602 "Summary of all mroutes\n"
6603 JSON_STR)
6604 {
6605 int idx = 2;
6606 bool uj = use_json(argc, argv);
6607 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
6608 json_object *json = NULL;
6609
6610 if (uj)
6611 json = json_object_new_object();
6612
6613 if (!vrf)
6614 return CMD_WARNING;
6615
6616 show_mroute_summary(vrf->info, vty, json);
6617
6618 if (uj) {
6619 vty_out(vty, "%s\n",
6620 json_object_to_json_string_ext(
6621 json, JSON_C_TO_STRING_PRETTY));
6622 json_object_free(json);
6623 }
6624 return CMD_SUCCESS;
6625 }
6626
6627 DEFUN (show_ip_mroute_summary_vrf_all,
6628 show_ip_mroute_summary_vrf_all_cmd,
6629 "show ip mroute vrf all summary [json]",
6630 SHOW_STR
6631 IP_STR
6632 MROUTE_STR
6633 VRF_CMD_HELP_STR
6634 "Summary of all mroutes\n"
6635 JSON_STR)
6636 {
6637 struct vrf *vrf;
6638 bool uj = use_json(argc, argv);
6639 json_object *json = NULL;
6640 json_object *json_vrf = NULL;
6641
6642 if (uj)
6643 json = json_object_new_object();
6644
6645 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
6646 if (uj)
6647 json_vrf = json_object_new_object();
6648 else
6649 vty_out(vty, "VRF: %s\n", vrf->name);
6650
6651 show_mroute_summary(vrf->info, vty, json_vrf);
6652
6653 if (uj)
6654 json_object_object_add(json, vrf->name, json_vrf);
6655 }
6656
6657 if (uj) {
6658 vty_out(vty, "%s\n",
6659 json_object_to_json_string_ext(
6660 json, JSON_C_TO_STRING_PRETTY));
6661 json_object_free(json);
6662 }
6663
6664 return CMD_SUCCESS;
6665 }
6666
6667 DEFUN (show_ip_rib,
6668 show_ip_rib_cmd,
6669 "show ip rib [vrf NAME] A.B.C.D",
6670 SHOW_STR
6671 IP_STR
6672 RIB_STR
6673 VRF_CMD_HELP_STR
6674 "Unicast address\n")
6675 {
6676 int idx = 2;
6677 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
6678 struct in_addr addr;
6679 const char *addr_str;
6680 struct pim_nexthop nexthop;
6681 char nexthop_addr_str[PREFIX_STRLEN];
6682 int result;
6683
6684 if (!vrf)
6685 return CMD_WARNING;
6686
6687 memset(&nexthop, 0, sizeof(nexthop));
6688 argv_find(argv, argc, "A.B.C.D", &idx);
6689 addr_str = argv[idx]->arg;
6690 result = inet_pton(AF_INET, addr_str, &addr);
6691 if (result <= 0) {
6692 vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str,
6693 errno, safe_strerror(errno));
6694 return CMD_WARNING;
6695 }
6696
6697 if (!pim_nexthop_lookup(vrf->info, &nexthop, addr, 0)) {
6698 vty_out(vty,
6699 "Failure querying RIB nexthop for unicast address %s\n",
6700 addr_str);
6701 return CMD_WARNING;
6702 }
6703
6704 vty_out(vty,
6705 "Address NextHop Interface Metric Preference\n");
6706
6707 pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr,
6708 nexthop_addr_str, sizeof(nexthop_addr_str));
6709
6710 vty_out(vty, "%-15s %-15s %-9s %6d %10d\n", addr_str, nexthop_addr_str,
6711 nexthop.interface ? nexthop.interface->name : "<ifname?>",
6712 nexthop.mrib_route_metric, nexthop.mrib_metric_preference);
6713
6714 return CMD_SUCCESS;
6715 }
6716
6717 static void show_ssmpingd(struct pim_instance *pim, struct vty *vty)
6718 {
6719 struct listnode *node;
6720 struct ssmpingd_sock *ss;
6721 time_t now;
6722
6723 vty_out(vty,
6724 "Source Socket Address Port Uptime Requests\n");
6725
6726 if (!pim->ssmpingd_list)
6727 return;
6728
6729 now = pim_time_monotonic_sec();
6730
6731 for (ALL_LIST_ELEMENTS_RO(pim->ssmpingd_list, node, ss)) {
6732 char source_str[INET_ADDRSTRLEN];
6733 char ss_uptime[10];
6734 struct sockaddr_in bind_addr;
6735 socklen_t len = sizeof(bind_addr);
6736 char bind_addr_str[INET_ADDRSTRLEN];
6737
6738 pim_inet4_dump("<src?>", ss->source_addr, source_str,
6739 sizeof(source_str));
6740
6741 if (pim_socket_getsockname(
6742 ss->sock_fd, (struct sockaddr *)&bind_addr, &len)) {
6743 vty_out(vty,
6744 "%% Failure reading socket name for ssmpingd source %s on fd=%d\n",
6745 source_str, ss->sock_fd);
6746 }
6747
6748 pim_inet4_dump("<addr?>", bind_addr.sin_addr, bind_addr_str,
6749 sizeof(bind_addr_str));
6750 pim_time_uptime(ss_uptime, sizeof(ss_uptime),
6751 now - ss->creation);
6752
6753 vty_out(vty, "%-15s %6d %-15s %5d %8s %8lld\n", source_str,
6754 ss->sock_fd, bind_addr_str, ntohs(bind_addr.sin_port),
6755 ss_uptime, (long long)ss->requests);
6756 }
6757 }
6758
6759 DEFUN (show_ip_ssmpingd,
6760 show_ip_ssmpingd_cmd,
6761 "show ip ssmpingd [vrf NAME]",
6762 SHOW_STR
6763 IP_STR
6764 SHOW_SSMPINGD_STR
6765 VRF_CMD_HELP_STR)
6766 {
6767 int idx = 2;
6768 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
6769
6770 if (!vrf)
6771 return CMD_WARNING;
6772
6773 show_ssmpingd(vrf->info, vty);
6774 return CMD_SUCCESS;
6775 }
6776
6777 static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty,
6778 const char *rp, const char *group,
6779 const char *plist)
6780 {
6781 int result;
6782
6783 result = pim_rp_new_config(pim, rp, group, plist);
6784
6785 if (result == PIM_GROUP_BAD_ADDR_MASK_COMBO) {
6786 vty_out(vty, "%% Inconsistent address and mask: %s\n",
6787 group ? group : "No Group Address");
6788 return CMD_WARNING_CONFIG_FAILED;
6789 }
6790
6791 if (result == PIM_GROUP_BAD_ADDRESS) {
6792 vty_out(vty, "%% Bad group address specified: %s\n",
6793 group ? group : "No Group Address");
6794 return CMD_WARNING_CONFIG_FAILED;
6795 }
6796
6797 if (result == PIM_RP_BAD_ADDRESS) {
6798 vty_out(vty, "%% Bad RP address specified: %s\n", rp);
6799 return CMD_WARNING_CONFIG_FAILED;
6800 }
6801
6802 if (result == PIM_RP_NO_PATH) {
6803 vty_out(vty, "%% No Path to RP address specified: %s\n", rp);
6804 return CMD_WARNING;
6805 }
6806
6807 if (result == PIM_GROUP_OVERLAP) {
6808 vty_out(vty,
6809 "%% Group range specified cannot exact match another\n");
6810 return CMD_WARNING_CONFIG_FAILED;
6811 }
6812
6813 if (result == PIM_GROUP_PFXLIST_OVERLAP) {
6814 vty_out(vty,
6815 "%% This group is already covered by a RP prefix-list\n");
6816 return CMD_WARNING_CONFIG_FAILED;
6817 }
6818
6819 if (result == PIM_RP_PFXLIST_IN_USE) {
6820 vty_out(vty,
6821 "%% The same prefix-list cannot be applied to multiple RPs\n");
6822 return CMD_WARNING_CONFIG_FAILED;
6823 }
6824
6825 return CMD_SUCCESS;
6826 }
6827
6828 static int pim_cmd_spt_switchover(struct pim_instance *pim,
6829 enum pim_spt_switchover spt,
6830 const char *plist)
6831 {
6832 pim->spt.switchover = spt;
6833
6834 switch (pim->spt.switchover) {
6835 case PIM_SPT_IMMEDIATE:
6836 XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
6837
6838 pim_upstream_add_lhr_star_pimreg(pim);
6839 break;
6840 case PIM_SPT_INFINITY:
6841 pim_upstream_remove_lhr_star_pimreg(pim, plist);
6842
6843 XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
6844
6845 if (plist)
6846 pim->spt.plist =
6847 XSTRDUP(MTYPE_PIM_PLIST_NAME, plist);
6848 break;
6849 }
6850
6851 return CMD_SUCCESS;
6852 }
6853
6854 DEFUN (ip_pim_spt_switchover_infinity,
6855 ip_pim_spt_switchover_infinity_cmd,
6856 "ip pim spt-switchover infinity-and-beyond",
6857 IP_STR
6858 PIM_STR
6859 "SPT-Switchover\n"
6860 "Never switch to SPT Tree\n")
6861 {
6862 PIM_DECLVAR_CONTEXT(vrf, pim);
6863 return pim_cmd_spt_switchover(pim, PIM_SPT_INFINITY, NULL);
6864 }
6865
6866 DEFUN (ip_pim_spt_switchover_infinity_plist,
6867 ip_pim_spt_switchover_infinity_plist_cmd,
6868 "ip pim spt-switchover infinity-and-beyond prefix-list WORD",
6869 IP_STR
6870 PIM_STR
6871 "SPT-Switchover\n"
6872 "Never switch to SPT Tree\n"
6873 "Prefix-List to control which groups to switch\n"
6874 "Prefix-List name\n")
6875 {
6876 PIM_DECLVAR_CONTEXT(vrf, pim);
6877 return pim_cmd_spt_switchover(pim, PIM_SPT_INFINITY, argv[5]->arg);
6878 }
6879
6880 DEFUN (no_ip_pim_spt_switchover_infinity,
6881 no_ip_pim_spt_switchover_infinity_cmd,
6882 "no ip pim spt-switchover infinity-and-beyond",
6883 NO_STR
6884 IP_STR
6885 PIM_STR
6886 "SPT_Switchover\n"
6887 "Never switch to SPT Tree\n")
6888 {
6889 PIM_DECLVAR_CONTEXT(vrf, pim);
6890 return pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL);
6891 }
6892
6893 DEFUN (no_ip_pim_spt_switchover_infinity_plist,
6894 no_ip_pim_spt_switchover_infinity_plist_cmd,
6895 "no ip pim spt-switchover infinity-and-beyond prefix-list WORD",
6896 NO_STR
6897 IP_STR
6898 PIM_STR
6899 "SPT_Switchover\n"
6900 "Never switch to SPT Tree\n"
6901 "Prefix-List to control which groups to switch\n"
6902 "Prefix-List name\n")
6903 {
6904 PIM_DECLVAR_CONTEXT(vrf, pim);
6905 return pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL);
6906 }
6907
6908 DEFPY (pim_register_accept_list,
6909 pim_register_accept_list_cmd,
6910 "[no] ip pim register-accept-list WORD$word",
6911 NO_STR
6912 IP_STR
6913 PIM_STR
6914 "Only accept registers from a specific source prefix list\n"
6915 "Prefix-List name\n")
6916 {
6917 PIM_DECLVAR_CONTEXT(vrf, pim);
6918
6919 if (no)
6920 XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
6921 else {
6922 XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
6923 pim->register_plist = XSTRDUP(MTYPE_PIM_PLIST_NAME, word);
6924 }
6925 return CMD_SUCCESS;
6926 }
6927
6928 DEFUN (ip_pim_joinprune_time,
6929 ip_pim_joinprune_time_cmd,
6930 "ip pim join-prune-interval (60-600)",
6931 IP_STR
6932 "pim multicast routing\n"
6933 "Join Prune Send Interval\n"
6934 "Seconds\n")
6935 {
6936 PIM_DECLVAR_CONTEXT(vrf, pim);
6937 router->t_periodic = atoi(argv[3]->arg);
6938 return CMD_SUCCESS;
6939 }
6940
6941 DEFUN (no_ip_pim_joinprune_time,
6942 no_ip_pim_joinprune_time_cmd,
6943 "no ip pim join-prune-interval (60-600)",
6944 NO_STR
6945 IP_STR
6946 "pim multicast routing\n"
6947 "Join Prune Send Interval\n"
6948 "Seconds\n")
6949 {
6950 PIM_DECLVAR_CONTEXT(vrf, pim);
6951 router->t_periodic = PIM_DEFAULT_T_PERIODIC;
6952 return CMD_SUCCESS;
6953 }
6954
6955 DEFUN (ip_pim_register_suppress,
6956 ip_pim_register_suppress_cmd,
6957 "ip pim register-suppress-time (5-60000)",
6958 IP_STR
6959 "pim multicast routing\n"
6960 "Register Suppress Timer\n"
6961 "Seconds\n")
6962 {
6963 PIM_DECLVAR_CONTEXT(vrf, pim);
6964 router->register_suppress_time = atoi(argv[3]->arg);
6965 return CMD_SUCCESS;
6966 }
6967
6968 DEFUN (no_ip_pim_register_suppress,
6969 no_ip_pim_register_suppress_cmd,
6970 "no ip pim register-suppress-time (5-60000)",
6971 NO_STR
6972 IP_STR
6973 "pim multicast routing\n"
6974 "Register Suppress Timer\n"
6975 "Seconds\n")
6976 {
6977 PIM_DECLVAR_CONTEXT(vrf, pim);
6978 router->register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT;
6979 return CMD_SUCCESS;
6980 }
6981
6982 DEFUN (ip_pim_rp_keep_alive,
6983 ip_pim_rp_keep_alive_cmd,
6984 "ip pim rp keep-alive-timer (31-60000)",
6985 IP_STR
6986 "pim multicast routing\n"
6987 "Rendevous Point\n"
6988 "Keep alive Timer\n"
6989 "Seconds\n")
6990 {
6991 PIM_DECLVAR_CONTEXT(vrf, pim);
6992 pim->rp_keep_alive_time = atoi(argv[4]->arg);
6993 return CMD_SUCCESS;
6994 }
6995
6996 DEFUN (no_ip_pim_rp_keep_alive,
6997 no_ip_pim_rp_keep_alive_cmd,
6998 "no ip pim rp keep-alive-timer (31-60000)",
6999 NO_STR
7000 IP_STR
7001 "pim multicast routing\n"
7002 "Rendevous Point\n"
7003 "Keep alive Timer\n"
7004 "Seconds\n")
7005 {
7006 PIM_DECLVAR_CONTEXT(vrf, pim);
7007 pim->rp_keep_alive_time = PIM_KEEPALIVE_PERIOD;
7008 return CMD_SUCCESS;
7009 }
7010
7011 DEFUN (ip_pim_keep_alive,
7012 ip_pim_keep_alive_cmd,
7013 "ip pim keep-alive-timer (31-60000)",
7014 IP_STR
7015 "pim multicast routing\n"
7016 "Keep alive Timer\n"
7017 "Seconds\n")
7018 {
7019 PIM_DECLVAR_CONTEXT(vrf, pim);
7020 pim->keep_alive_time = atoi(argv[3]->arg);
7021 return CMD_SUCCESS;
7022 }
7023
7024 DEFUN (no_ip_pim_keep_alive,
7025 no_ip_pim_keep_alive_cmd,
7026 "no ip pim keep-alive-timer (31-60000)",
7027 NO_STR
7028 IP_STR
7029 "pim multicast routing\n"
7030 "Keep alive Timer\n"
7031 "Seconds\n")
7032 {
7033 PIM_DECLVAR_CONTEXT(vrf, pim);
7034 pim->keep_alive_time = PIM_KEEPALIVE_PERIOD;
7035 return CMD_SUCCESS;
7036 }
7037
7038 DEFUN (ip_pim_packets,
7039 ip_pim_packets_cmd,
7040 "ip pim packets (1-100)",
7041 IP_STR
7042 "pim multicast routing\n"
7043 "packets to process at one time per fd\n"
7044 "Number of packets\n")
7045 {
7046 PIM_DECLVAR_CONTEXT(vrf, pim);
7047 router->packet_process = atoi(argv[3]->arg);
7048 return CMD_SUCCESS;
7049 }
7050
7051 DEFUN (no_ip_pim_packets,
7052 no_ip_pim_packets_cmd,
7053 "no ip pim packets (1-100)",
7054 NO_STR
7055 IP_STR
7056 "pim multicast routing\n"
7057 "packets to process at one time per fd\n"
7058 "Number of packets\n")
7059 {
7060 PIM_DECLVAR_CONTEXT(vrf, pim);
7061 router->packet_process = PIM_DEFAULT_PACKET_PROCESS;
7062 return CMD_SUCCESS;
7063 }
7064
7065 DEFPY (igmp_group_watermark,
7066 igmp_group_watermark_cmd,
7067 "ip igmp watermark-warn (10-60000)$limit",
7068 IP_STR
7069 IGMP_STR
7070 "Configure group limit for watermark warning\n"
7071 "Group count to generate watermark warning\n")
7072 {
7073 PIM_DECLVAR_CONTEXT(vrf, pim);
7074 pim->igmp_watermark_limit = limit;
7075
7076 return CMD_SUCCESS;
7077 }
7078
7079 DEFPY (no_igmp_group_watermark,
7080 no_igmp_group_watermark_cmd,
7081 "no ip igmp watermark-warn [(10-60000)$limit]",
7082 NO_STR
7083 IP_STR
7084 IGMP_STR
7085 "Unconfigure group limit for watermark warning\n"
7086 "Group count to generate watermark warning\n")
7087 {
7088 PIM_DECLVAR_CONTEXT(vrf, pim);
7089 pim->igmp_watermark_limit = 0;
7090
7091 return CMD_SUCCESS;
7092 }
7093
7094 DEFUN (ip_pim_v6_secondary,
7095 ip_pim_v6_secondary_cmd,
7096 "ip pim send-v6-secondary",
7097 IP_STR
7098 "pim multicast routing\n"
7099 "Send v6 secondary addresses\n")
7100 {
7101 PIM_DECLVAR_CONTEXT(vrf, pim);
7102 pim->send_v6_secondary = 1;
7103
7104 return CMD_SUCCESS;
7105 }
7106
7107 DEFUN (no_ip_pim_v6_secondary,
7108 no_ip_pim_v6_secondary_cmd,
7109 "no ip pim send-v6-secondary",
7110 NO_STR
7111 IP_STR
7112 "pim multicast routing\n"
7113 "Send v6 secondary addresses\n")
7114 {
7115 PIM_DECLVAR_CONTEXT(vrf, pim);
7116 pim->send_v6_secondary = 0;
7117
7118 return CMD_SUCCESS;
7119 }
7120
7121 DEFUN (ip_pim_rp,
7122 ip_pim_rp_cmd,
7123 "ip pim rp A.B.C.D [A.B.C.D/M]",
7124 IP_STR
7125 "pim multicast routing\n"
7126 "Rendevous Point\n"
7127 "ip address of RP\n"
7128 "Group Address range to cover\n")
7129 {
7130 PIM_DECLVAR_CONTEXT(vrf, pim);
7131 int idx_ipv4 = 3;
7132
7133 if (argc == (idx_ipv4 + 1))
7134 return pim_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg, NULL,
7135 NULL);
7136 else
7137 return pim_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg,
7138 argv[idx_ipv4 + 1]->arg, NULL);
7139 }
7140
7141 DEFUN (ip_pim_rp_prefix_list,
7142 ip_pim_rp_prefix_list_cmd,
7143 "ip pim rp A.B.C.D prefix-list WORD",
7144 IP_STR
7145 "pim multicast routing\n"
7146 "Rendevous Point\n"
7147 "ip address of RP\n"
7148 "group prefix-list filter\n"
7149 "Name of a prefix-list\n")
7150 {
7151 PIM_DECLVAR_CONTEXT(vrf, pim);
7152 return pim_rp_cmd_worker(pim, vty, argv[3]->arg, NULL, argv[5]->arg);
7153 }
7154
7155 static int pim_no_rp_cmd_worker(struct pim_instance *pim, struct vty *vty,
7156 const char *rp, const char *group,
7157 const char *plist)
7158 {
7159 int result = pim_rp_del_config(pim, rp, group, plist);
7160
7161 if (result == PIM_GROUP_BAD_ADDRESS) {
7162 vty_out(vty, "%% Bad group address specified: %s\n",
7163 group ? group : "No Group Address");
7164 return CMD_WARNING_CONFIG_FAILED;
7165 }
7166
7167 if (result == PIM_RP_BAD_ADDRESS) {
7168 vty_out(vty, "%% Bad RP address specified: %s\n", rp);
7169 return CMD_WARNING_CONFIG_FAILED;
7170 }
7171
7172 if (result == PIM_RP_NOT_FOUND) {
7173 vty_out(vty, "%% Unable to find specified RP\n");
7174 return CMD_WARNING_CONFIG_FAILED;
7175 }
7176
7177 return CMD_SUCCESS;
7178 }
7179
7180 DEFUN (no_ip_pim_rp,
7181 no_ip_pim_rp_cmd,
7182 "no ip pim rp A.B.C.D [A.B.C.D/M]",
7183 NO_STR
7184 IP_STR
7185 "pim multicast routing\n"
7186 "Rendevous Point\n"
7187 "ip address of RP\n"
7188 "Group Address range to cover\n")
7189 {
7190 PIM_DECLVAR_CONTEXT(vrf, pim);
7191 int idx_ipv4 = 4, idx_group = 0;
7192
7193 if (argv_find(argv, argc, "A.B.C.D/M", &idx_group))
7194 return pim_no_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg,
7195 argv[idx_group]->arg, NULL);
7196 else
7197 return pim_no_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg, NULL,
7198 NULL);
7199 }
7200
7201 DEFUN (no_ip_pim_rp_prefix_list,
7202 no_ip_pim_rp_prefix_list_cmd,
7203 "no ip pim rp A.B.C.D prefix-list WORD",
7204 NO_STR
7205 IP_STR
7206 "pim multicast routing\n"
7207 "Rendevous Point\n"
7208 "ip address of RP\n"
7209 "group prefix-list filter\n"
7210 "Name of a prefix-list\n")
7211 {
7212 PIM_DECLVAR_CONTEXT(vrf, pim);
7213 return pim_no_rp_cmd_worker(pim, vty, argv[4]->arg, NULL, argv[6]->arg);
7214 }
7215
7216 static int pim_ssm_cmd_worker(struct pim_instance *pim, struct vty *vty,
7217 const char *plist)
7218 {
7219 int result = pim_ssm_range_set(pim, pim->vrf_id, plist);
7220 int ret = CMD_WARNING_CONFIG_FAILED;
7221
7222 if (result == PIM_SSM_ERR_NONE)
7223 return CMD_SUCCESS;
7224
7225 switch (result) {
7226 case PIM_SSM_ERR_NO_VRF:
7227 vty_out(vty, "%% VRF doesn't exist\n");
7228 break;
7229 case PIM_SSM_ERR_DUP:
7230 vty_out(vty, "%% duplicate config\n");
7231 ret = CMD_WARNING;
7232 break;
7233 default:
7234 vty_out(vty, "%% ssm range config failed\n");
7235 }
7236
7237 return ret;
7238 }
7239
7240 DEFUN (ip_pim_ssm_prefix_list,
7241 ip_pim_ssm_prefix_list_cmd,
7242 "ip pim ssm prefix-list WORD",
7243 IP_STR
7244 "pim multicast routing\n"
7245 "Source Specific Multicast\n"
7246 "group range prefix-list filter\n"
7247 "Name of a prefix-list\n")
7248 {
7249 PIM_DECLVAR_CONTEXT(vrf, pim);
7250 return pim_ssm_cmd_worker(pim, vty, argv[4]->arg);
7251 }
7252
7253 DEFUN (no_ip_pim_ssm_prefix_list,
7254 no_ip_pim_ssm_prefix_list_cmd,
7255 "no ip pim ssm prefix-list",
7256 NO_STR
7257 IP_STR
7258 "pim multicast routing\n"
7259 "Source Specific Multicast\n"
7260 "group range prefix-list filter\n")
7261 {
7262 PIM_DECLVAR_CONTEXT(vrf, pim);
7263 return pim_ssm_cmd_worker(pim, vty, NULL);
7264 }
7265
7266 DEFUN (no_ip_pim_ssm_prefix_list_name,
7267 no_ip_pim_ssm_prefix_list_name_cmd,
7268 "no ip pim ssm prefix-list WORD",
7269 NO_STR
7270 IP_STR
7271 "pim multicast routing\n"
7272 "Source Specific Multicast\n"
7273 "group range prefix-list filter\n"
7274 "Name of a prefix-list\n")
7275 {
7276 PIM_DECLVAR_CONTEXT(vrf, pim);
7277 struct pim_ssm *ssm = pim->ssm_info;
7278
7279 if (ssm->plist_name && !strcmp(ssm->plist_name, argv[5]->arg))
7280 return pim_ssm_cmd_worker(pim, vty, NULL);
7281
7282 vty_out(vty, "%% pim ssm prefix-list %s doesn't exist\n", argv[5]->arg);
7283
7284 return CMD_WARNING_CONFIG_FAILED;
7285 }
7286
7287 static void ip_pim_ssm_show_group_range(struct pim_instance *pim,
7288 struct vty *vty, bool uj)
7289 {
7290 struct pim_ssm *ssm = pim->ssm_info;
7291 const char *range_str =
7292 ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
7293
7294 if (uj) {
7295 json_object *json;
7296 json = json_object_new_object();
7297 json_object_string_add(json, "ssmGroups", range_str);
7298 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7299 json, JSON_C_TO_STRING_PRETTY));
7300 json_object_free(json);
7301 } else
7302 vty_out(vty, "SSM group range : %s\n", range_str);
7303 }
7304
7305 DEFUN (show_ip_pim_ssm_range,
7306 show_ip_pim_ssm_range_cmd,
7307 "show ip pim [vrf NAME] group-type [json]",
7308 SHOW_STR
7309 IP_STR
7310 PIM_STR
7311 VRF_CMD_HELP_STR
7312 "PIM group type\n"
7313 JSON_STR)
7314 {
7315 int idx = 2;
7316 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
7317 bool uj = use_json(argc, argv);
7318
7319 if (!vrf)
7320 return CMD_WARNING;
7321
7322 ip_pim_ssm_show_group_range(vrf->info, vty, uj);
7323
7324 return CMD_SUCCESS;
7325 }
7326
7327 static void ip_pim_ssm_show_group_type(struct pim_instance *pim,
7328 struct vty *vty, bool uj,
7329 const char *group)
7330 {
7331 struct in_addr group_addr;
7332 const char *type_str;
7333 int result;
7334
7335 result = inet_pton(AF_INET, group, &group_addr);
7336 if (result <= 0)
7337 type_str = "invalid";
7338 else {
7339 if (pim_is_group_224_4(group_addr))
7340 type_str =
7341 pim_is_grp_ssm(pim, group_addr) ? "SSM" : "ASM";
7342 else
7343 type_str = "not-multicast";
7344 }
7345
7346 if (uj) {
7347 json_object *json;
7348 json = json_object_new_object();
7349 json_object_string_add(json, "groupType", type_str);
7350 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7351 json, JSON_C_TO_STRING_PRETTY));
7352 json_object_free(json);
7353 } else
7354 vty_out(vty, "Group type : %s\n", type_str);
7355 }
7356
7357 DEFUN (show_ip_pim_group_type,
7358 show_ip_pim_group_type_cmd,
7359 "show ip pim [vrf NAME] group-type A.B.C.D [json]",
7360 SHOW_STR
7361 IP_STR
7362 PIM_STR
7363 VRF_CMD_HELP_STR
7364 "multicast group type\n"
7365 "group address\n"
7366 JSON_STR)
7367 {
7368 int idx = 2;
7369 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
7370 bool uj = use_json(argc, argv);
7371
7372 if (!vrf)
7373 return CMD_WARNING;
7374
7375 argv_find(argv, argc, "A.B.C.D", &idx);
7376 ip_pim_ssm_show_group_type(vrf->info, vty, uj, argv[idx]->arg);
7377
7378 return CMD_SUCCESS;
7379 }
7380
7381 DEFUN (show_ip_pim_bsr,
7382 show_ip_pim_bsr_cmd,
7383 "show ip pim bsr [json]",
7384 SHOW_STR
7385 IP_STR
7386 PIM_STR
7387 "boot-strap router information\n"
7388 JSON_STR)
7389 {
7390 int idx = 2;
7391 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
7392 bool uj = use_json(argc, argv);
7393
7394 if (!vrf)
7395 return CMD_WARNING;
7396
7397 pim_show_bsr(vrf->info, vty, uj);
7398
7399 return CMD_SUCCESS;
7400 }
7401
7402 DEFUN (ip_ssmpingd,
7403 ip_ssmpingd_cmd,
7404 "ip ssmpingd [A.B.C.D]",
7405 IP_STR
7406 CONF_SSMPINGD_STR
7407 "Source address\n")
7408 {
7409 PIM_DECLVAR_CONTEXT(vrf, pim);
7410 int idx_ipv4 = 2;
7411 int result;
7412 struct in_addr source_addr;
7413 const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0";
7414
7415 result = inet_pton(AF_INET, source_str, &source_addr);
7416 if (result <= 0) {
7417 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n",
7418 source_str, errno, safe_strerror(errno));
7419 return CMD_WARNING_CONFIG_FAILED;
7420 }
7421
7422 result = pim_ssmpingd_start(pim, source_addr);
7423 if (result) {
7424 vty_out(vty, "%% Failure starting ssmpingd for source %s: %d\n",
7425 source_str, result);
7426 return CMD_WARNING_CONFIG_FAILED;
7427 }
7428
7429 return CMD_SUCCESS;
7430 }
7431
7432 DEFUN (no_ip_ssmpingd,
7433 no_ip_ssmpingd_cmd,
7434 "no ip ssmpingd [A.B.C.D]",
7435 NO_STR
7436 IP_STR
7437 CONF_SSMPINGD_STR
7438 "Source address\n")
7439 {
7440 PIM_DECLVAR_CONTEXT(vrf, pim);
7441 int idx_ipv4 = 3;
7442 int result;
7443 struct in_addr source_addr;
7444 const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0";
7445
7446 result = inet_pton(AF_INET, source_str, &source_addr);
7447 if (result <= 0) {
7448 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n",
7449 source_str, errno, safe_strerror(errno));
7450 return CMD_WARNING_CONFIG_FAILED;
7451 }
7452
7453 result = pim_ssmpingd_stop(pim, source_addr);
7454 if (result) {
7455 vty_out(vty, "%% Failure stopping ssmpingd for source %s: %d\n",
7456 source_str, result);
7457 return CMD_WARNING_CONFIG_FAILED;
7458 }
7459
7460 return CMD_SUCCESS;
7461 }
7462
7463 DEFUN (ip_pim_ecmp,
7464 ip_pim_ecmp_cmd,
7465 "ip pim ecmp",
7466 IP_STR
7467 "pim multicast routing\n"
7468 "Enable PIM ECMP \n")
7469 {
7470 PIM_DECLVAR_CONTEXT(vrf, pim);
7471 pim->ecmp_enable = true;
7472
7473 return CMD_SUCCESS;
7474 }
7475
7476 DEFUN (no_ip_pim_ecmp,
7477 no_ip_pim_ecmp_cmd,
7478 "no ip pim ecmp",
7479 NO_STR
7480 IP_STR
7481 "pim multicast routing\n"
7482 "Disable PIM ECMP \n")
7483 {
7484 PIM_DECLVAR_CONTEXT(vrf, pim);
7485 pim->ecmp_enable = false;
7486
7487 return CMD_SUCCESS;
7488 }
7489
7490 DEFUN (ip_pim_ecmp_rebalance,
7491 ip_pim_ecmp_rebalance_cmd,
7492 "ip pim ecmp rebalance",
7493 IP_STR
7494 "pim multicast routing\n"
7495 "Enable PIM ECMP \n"
7496 "Enable PIM ECMP Rebalance\n")
7497 {
7498 PIM_DECLVAR_CONTEXT(vrf, pim);
7499 pim->ecmp_enable = true;
7500 pim->ecmp_rebalance_enable = true;
7501
7502 return CMD_SUCCESS;
7503 }
7504
7505 DEFUN (no_ip_pim_ecmp_rebalance,
7506 no_ip_pim_ecmp_rebalance_cmd,
7507 "no ip pim ecmp rebalance",
7508 NO_STR
7509 IP_STR
7510 "pim multicast routing\n"
7511 "Disable PIM ECMP \n"
7512 "Disable PIM ECMP Rebalance\n")
7513 {
7514 PIM_DECLVAR_CONTEXT(vrf, pim);
7515 pim->ecmp_rebalance_enable = false;
7516
7517 return CMD_SUCCESS;
7518 }
7519
7520 static int pim_cmd_igmp_start(struct vty *vty, struct interface *ifp)
7521 {
7522 struct pim_interface *pim_ifp;
7523 struct pim_instance *pim;
7524 uint8_t need_startup = 0;
7525
7526 pim_ifp = ifp->info;
7527
7528 if (!pim_ifp) {
7529 pim = pim_get_pim_instance(ifp->vrf_id);
7530 /* Limit mcast interfaces to number of vifs available */
7531 if (pim->mcast_if_count == MAXVIFS) {
7532 vty_out(vty,
7533 "Max multicast interfaces(%d) Reached. Could not enable IGMP on interface %s\n",
7534 MAXVIFS, ifp->name);
7535 return CMD_WARNING_CONFIG_FAILED;
7536 }
7537 (void)pim_if_new(ifp, true, false, false, false);
7538 need_startup = 1;
7539 } else {
7540 if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
7541 PIM_IF_DO_IGMP(pim_ifp->options);
7542 need_startup = 1;
7543 }
7544 }
7545
7546 /* 'ip igmp' executed multiple times, with need_startup
7547 avoid multiple if add all and membership refresh */
7548 if (need_startup) {
7549 pim_if_addr_add_all(ifp);
7550 pim_if_membership_refresh(ifp);
7551 }
7552
7553 return CMD_SUCCESS;
7554 }
7555
7556 DEFUN (interface_ip_igmp,
7557 interface_ip_igmp_cmd,
7558 "ip igmp",
7559 IP_STR
7560 IFACE_IGMP_STR)
7561 {
7562 VTY_DECLVAR_CONTEXT(interface, ifp);
7563
7564 return pim_cmd_igmp_start(vty, ifp);
7565 }
7566
7567 DEFUN (interface_no_ip_igmp,
7568 interface_no_ip_igmp_cmd,
7569 "no ip igmp",
7570 NO_STR
7571 IP_STR
7572 IFACE_IGMP_STR)
7573 {
7574 VTY_DECLVAR_CONTEXT(interface, ifp);
7575 struct pim_interface *pim_ifp = ifp->info;
7576
7577 if (!pim_ifp)
7578 return CMD_SUCCESS;
7579
7580 PIM_IF_DONT_IGMP(pim_ifp->options);
7581
7582 pim_if_membership_clear(ifp);
7583
7584 pim_if_addr_del_all_igmp(ifp);
7585
7586 if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
7587 pim_if_delete(ifp);
7588 }
7589
7590 return CMD_SUCCESS;
7591 }
7592
7593 DEFUN (interface_ip_igmp_join,
7594 interface_ip_igmp_join_cmd,
7595 "ip igmp join A.B.C.D [A.B.C.D]",
7596 IP_STR
7597 IFACE_IGMP_STR
7598 "IGMP join multicast group\n"
7599 "Multicast group address\n"
7600 "Source address\n")
7601 {
7602 VTY_DECLVAR_CONTEXT(interface, ifp);
7603 int idx_ipv4 = 3;
7604 int idx_ipv4_2 = 4;
7605 const char *group_str;
7606 const char *source_str;
7607 struct in_addr group_addr;
7608 struct in_addr source_addr;
7609 int result;
7610
7611 /* Group address */
7612 group_str = argv[idx_ipv4]->arg;
7613 result = inet_pton(AF_INET, group_str, &group_addr);
7614 if (result <= 0) {
7615 vty_out(vty, "Bad group address %s: errno=%d: %s\n", group_str,
7616 errno, safe_strerror(errno));
7617 return CMD_WARNING_CONFIG_FAILED;
7618 }
7619
7620 /* Source address */
7621 if (argc == (idx_ipv4_2 + 1)) {
7622 source_str = argv[idx_ipv4_2]->arg;
7623 result = inet_pton(AF_INET, source_str, &source_addr);
7624 if (result <= 0) {
7625 vty_out(vty, "Bad source address %s: errno=%d: %s\n",
7626 source_str, errno, safe_strerror(errno));
7627 return CMD_WARNING_CONFIG_FAILED;
7628 }
7629 /* Reject 0.0.0.0. Reserved for any source. */
7630 if (source_addr.s_addr == INADDR_ANY) {
7631 vty_out(vty, "Bad source address %s\n", source_str);
7632 return CMD_WARNING_CONFIG_FAILED;
7633 }
7634 } else {
7635 source_addr.s_addr = INADDR_ANY;
7636 }
7637
7638 CMD_FERR_RETURN(pim_if_igmp_join_add(ifp, group_addr, source_addr),
7639 "Failure joining IGMP group: $ERR");
7640
7641 return CMD_SUCCESS;
7642 }
7643
7644 DEFUN (interface_no_ip_igmp_join,
7645 interface_no_ip_igmp_join_cmd,
7646 "no ip igmp join A.B.C.D [A.B.C.D]",
7647 NO_STR
7648 IP_STR
7649 IFACE_IGMP_STR
7650 "IGMP join multicast group\n"
7651 "Multicast group address\n"
7652 "Source address\n")
7653 {
7654 VTY_DECLVAR_CONTEXT(interface, ifp);
7655 int idx_ipv4 = 4;
7656 int idx_ipv4_2 = 5;
7657 const char *group_str;
7658 const char *source_str;
7659 struct in_addr group_addr;
7660 struct in_addr source_addr;
7661 int result;
7662
7663 /* Group address */
7664 group_str = argv[idx_ipv4]->arg;
7665 result = inet_pton(AF_INET, group_str, &group_addr);
7666 if (result <= 0) {
7667 vty_out(vty, "Bad group address %s: errno=%d: %s\n", group_str,
7668 errno, safe_strerror(errno));
7669 return CMD_WARNING_CONFIG_FAILED;
7670 }
7671
7672 /* Source address */
7673 if (argc == (idx_ipv4_2 + 1)) {
7674 source_str = argv[idx_ipv4_2]->arg;
7675 result = inet_pton(AF_INET, source_str, &source_addr);
7676 if (result <= 0) {
7677 vty_out(vty, "Bad source address %s: errno=%d: %s\n",
7678 source_str, errno, safe_strerror(errno));
7679 return CMD_WARNING_CONFIG_FAILED;
7680 }
7681 /* Reject 0.0.0.0. Reserved for any source. */
7682 if (source_addr.s_addr == INADDR_ANY) {
7683 vty_out(vty, "Bad source address %s\n", source_str);
7684 return CMD_WARNING_CONFIG_FAILED;
7685 }
7686 } else {
7687 source_str = "*";
7688 source_addr.s_addr = INADDR_ANY;
7689 }
7690
7691 result = pim_if_igmp_join_del(ifp, group_addr, source_addr);
7692 if (result) {
7693 vty_out(vty,
7694 "%% Failure leaving IGMP group %s source %s on interface %s: %d\n",
7695 group_str, source_str, ifp->name, result);
7696 return CMD_WARNING_CONFIG_FAILED;
7697 }
7698
7699 return CMD_SUCCESS;
7700 }
7701
7702 /*
7703 CLI reconfiguration affects the interface level (struct pim_interface).
7704 This function propagates the reconfiguration to every active socket
7705 for that interface.
7706 */
7707 static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp)
7708 {
7709 struct interface *ifp;
7710 struct pim_interface *pim_ifp;
7711
7712 zassert(igmp);
7713
7714 /* other querier present? */
7715
7716 if (igmp->t_other_querier_timer)
7717 return;
7718
7719 /* this is the querier */
7720
7721 zassert(igmp->interface);
7722 zassert(igmp->interface->info);
7723
7724 ifp = igmp->interface;
7725 pim_ifp = ifp->info;
7726
7727 if (PIM_DEBUG_IGMP_TRACE) {
7728 char ifaddr_str[INET_ADDRSTRLEN];
7729 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
7730 sizeof(ifaddr_str));
7731 zlog_debug("%s: Querier %s on %s reconfig query_interval=%d",
7732 __func__, ifaddr_str, ifp->name,
7733 pim_ifp->igmp_default_query_interval);
7734 }
7735
7736 /*
7737 igmp_startup_mode_on() will reset QQI:
7738
7739 igmp->querier_query_interval = pim_ifp->igmp_default_query_interval;
7740 */
7741 igmp_startup_mode_on(igmp);
7742 }
7743
7744 static void igmp_sock_query_reschedule(struct igmp_sock *igmp)
7745 {
7746 if (igmp->mtrace_only)
7747 return;
7748
7749 if (igmp->t_igmp_query_timer) {
7750 /* other querier present */
7751 zassert(igmp->t_igmp_query_timer);
7752 zassert(!igmp->t_other_querier_timer);
7753
7754 pim_igmp_general_query_off(igmp);
7755 pim_igmp_general_query_on(igmp);
7756
7757 zassert(igmp->t_igmp_query_timer);
7758 zassert(!igmp->t_other_querier_timer);
7759 } else {
7760 /* this is the querier */
7761
7762 zassert(!igmp->t_igmp_query_timer);
7763 zassert(igmp->t_other_querier_timer);
7764
7765 pim_igmp_other_querier_timer_off(igmp);
7766 pim_igmp_other_querier_timer_on(igmp);
7767
7768 zassert(!igmp->t_igmp_query_timer);
7769 zassert(igmp->t_other_querier_timer);
7770 }
7771 }
7772
7773 static void change_query_interval(struct pim_interface *pim_ifp,
7774 int query_interval)
7775 {
7776 struct listnode *sock_node;
7777 struct igmp_sock *igmp;
7778
7779 pim_ifp->igmp_default_query_interval = query_interval;
7780
7781 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
7782 igmp_sock_query_interval_reconfig(igmp);
7783 igmp_sock_query_reschedule(igmp);
7784 }
7785 }
7786
7787 static void change_query_max_response_time(struct pim_interface *pim_ifp,
7788 int query_max_response_time_dsec)
7789 {
7790 struct listnode *sock_node;
7791 struct igmp_sock *igmp;
7792
7793 pim_ifp->igmp_query_max_response_time_dsec =
7794 query_max_response_time_dsec;
7795
7796 /*
7797 Below we modify socket/group/source timers in order to quickly
7798 reflect the change. Otherwise, those timers would eventually catch
7799 up.
7800 */
7801
7802 /* scan all sockets */
7803 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
7804 struct listnode *grp_node;
7805 struct igmp_group *grp;
7806
7807 /* reschedule socket general query */
7808 igmp_sock_query_reschedule(igmp);
7809
7810 /* scan socket groups */
7811 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node,
7812 grp)) {
7813 struct listnode *src_node;
7814 struct igmp_source *src;
7815
7816 /* reset group timers for groups in EXCLUDE mode */
7817 if (grp->group_filtermode_isexcl) {
7818 igmp_group_reset_gmi(grp);
7819 }
7820
7821 /* scan group sources */
7822 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list,
7823 src_node, src)) {
7824
7825 /* reset source timers for sources with running
7826 * timers */
7827 if (src->t_source_timer) {
7828 igmp_source_reset_gmi(igmp, grp, src);
7829 }
7830 }
7831 }
7832 }
7833 }
7834
7835 #define IGMP_QUERY_INTERVAL_MIN (1)
7836 #define IGMP_QUERY_INTERVAL_MAX (1800)
7837
7838 DEFUN (interface_ip_igmp_query_interval,
7839 interface_ip_igmp_query_interval_cmd,
7840 "ip igmp query-interval (1-1800)",
7841 IP_STR
7842 IFACE_IGMP_STR
7843 IFACE_IGMP_QUERY_INTERVAL_STR
7844 "Query interval in seconds\n")
7845 {
7846 VTY_DECLVAR_CONTEXT(interface, ifp);
7847 struct pim_interface *pim_ifp = ifp->info;
7848 int query_interval;
7849 int query_interval_dsec;
7850 int ret;
7851
7852 if (!pim_ifp) {
7853 ret = pim_cmd_igmp_start(vty, ifp);
7854 if (ret != CMD_SUCCESS)
7855 return ret;
7856 pim_ifp = ifp->info;
7857 }
7858
7859 query_interval = atoi(argv[3]->arg);
7860 query_interval_dsec = 10 * query_interval;
7861
7862 /*
7863 It seems we don't need to check bounds since command.c does it
7864 already, but we verify them anyway for extra safety.
7865 */
7866 if (query_interval < IGMP_QUERY_INTERVAL_MIN) {
7867 vty_out(vty,
7868 "General query interval %d lower than minimum %d\n",
7869 query_interval, IGMP_QUERY_INTERVAL_MIN);
7870 return CMD_WARNING_CONFIG_FAILED;
7871 }
7872 if (query_interval > IGMP_QUERY_INTERVAL_MAX) {
7873 vty_out(vty,
7874 "General query interval %d higher than maximum %d\n",
7875 query_interval, IGMP_QUERY_INTERVAL_MAX);
7876 return CMD_WARNING_CONFIG_FAILED;
7877 }
7878
7879 if (query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) {
7880 vty_out(vty,
7881 "Can't set general query interval %d dsec <= query max response time %d dsec.\n",
7882 query_interval_dsec,
7883 pim_ifp->igmp_query_max_response_time_dsec);
7884 return CMD_WARNING_CONFIG_FAILED;
7885 }
7886
7887 change_query_interval(pim_ifp, query_interval);
7888
7889 return CMD_SUCCESS;
7890 }
7891
7892 DEFUN (interface_no_ip_igmp_query_interval,
7893 interface_no_ip_igmp_query_interval_cmd,
7894 "no ip igmp query-interval",
7895 NO_STR
7896 IP_STR
7897 IFACE_IGMP_STR
7898 IFACE_IGMP_QUERY_INTERVAL_STR)
7899 {
7900 VTY_DECLVAR_CONTEXT(interface, ifp);
7901 struct pim_interface *pim_ifp = ifp->info;
7902 int default_query_interval_dsec;
7903
7904 if (!pim_ifp)
7905 return CMD_SUCCESS;
7906
7907 default_query_interval_dsec = IGMP_GENERAL_QUERY_INTERVAL * 10;
7908
7909 if (default_query_interval_dsec
7910 <= pim_ifp->igmp_query_max_response_time_dsec) {
7911 vty_out(vty,
7912 "Can't set default general query interval %d dsec <= query max response time %d dsec.\n",
7913 default_query_interval_dsec,
7914 pim_ifp->igmp_query_max_response_time_dsec);
7915 return CMD_WARNING_CONFIG_FAILED;
7916 }
7917
7918 change_query_interval(pim_ifp, IGMP_GENERAL_QUERY_INTERVAL);
7919
7920 return CMD_SUCCESS;
7921 }
7922
7923 DEFUN (interface_ip_igmp_version,
7924 interface_ip_igmp_version_cmd,
7925 "ip igmp version (2-3)",
7926 IP_STR
7927 IFACE_IGMP_STR
7928 "IGMP version\n"
7929 "IGMP version number\n")
7930 {
7931 VTY_DECLVAR_CONTEXT(interface, ifp);
7932 struct pim_interface *pim_ifp = ifp->info;
7933 int igmp_version, old_version = 0;
7934 int ret;
7935
7936 if (!pim_ifp) {
7937 ret = pim_cmd_igmp_start(vty, ifp);
7938 if (ret != CMD_SUCCESS)
7939 return ret;
7940 pim_ifp = ifp->info;
7941 }
7942
7943 igmp_version = atoi(argv[3]->arg);
7944 old_version = pim_ifp->igmp_version;
7945 pim_ifp->igmp_version = igmp_version;
7946
7947 // Check if IGMP is Enabled otherwise, enable on interface
7948 if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
7949 PIM_IF_DO_IGMP(pim_ifp->options);
7950 pim_if_addr_add_all(ifp);
7951 pim_if_membership_refresh(ifp);
7952 old_version = igmp_version;
7953 // avoid refreshing membership again.
7954 }
7955 /* Current and new version is different refresh existing
7956 membership. Going from 3 -> 2 or 2 -> 3. */
7957 if (old_version != igmp_version)
7958 pim_if_membership_refresh(ifp);
7959
7960 return CMD_SUCCESS;
7961 }
7962
7963 DEFUN (interface_no_ip_igmp_version,
7964 interface_no_ip_igmp_version_cmd,
7965 "no ip igmp version (2-3)",
7966 NO_STR
7967 IP_STR
7968 IFACE_IGMP_STR
7969 "IGMP version\n"
7970 "IGMP version number\n")
7971 {
7972 VTY_DECLVAR_CONTEXT(interface, ifp);
7973 struct pim_interface *pim_ifp = ifp->info;
7974
7975 if (!pim_ifp)
7976 return CMD_SUCCESS;
7977
7978 pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
7979
7980 return CMD_SUCCESS;
7981 }
7982
7983 #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10)
7984 #define IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC (250)
7985
7986 DEFUN (interface_ip_igmp_query_max_response_time,
7987 interface_ip_igmp_query_max_response_time_cmd,
7988 "ip igmp query-max-response-time (10-250)",
7989 IP_STR
7990 IFACE_IGMP_STR
7991 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
7992 "Query response value in deci-seconds\n")
7993 {
7994 VTY_DECLVAR_CONTEXT(interface, ifp);
7995 struct pim_interface *pim_ifp = ifp->info;
7996 int query_max_response_time;
7997 int ret;
7998
7999 if (!pim_ifp) {
8000 ret = pim_cmd_igmp_start(vty, ifp);
8001 if (ret != CMD_SUCCESS)
8002 return ret;
8003 pim_ifp = ifp->info;
8004 }
8005
8006 query_max_response_time = atoi(argv[3]->arg);
8007
8008 if (query_max_response_time
8009 >= pim_ifp->igmp_default_query_interval * 10) {
8010 vty_out(vty,
8011 "Can't set query max response time %d sec >= general query interval %d sec\n",
8012 query_max_response_time,
8013 pim_ifp->igmp_default_query_interval);
8014 return CMD_WARNING_CONFIG_FAILED;
8015 }
8016
8017 change_query_max_response_time(pim_ifp, query_max_response_time);
8018
8019 return CMD_SUCCESS;
8020 }
8021
8022 DEFUN (interface_no_ip_igmp_query_max_response_time,
8023 interface_no_ip_igmp_query_max_response_time_cmd,
8024 "no ip igmp query-max-response-time (10-250)",
8025 NO_STR
8026 IP_STR
8027 IFACE_IGMP_STR
8028 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
8029 "Time for response in deci-seconds\n")
8030 {
8031 VTY_DECLVAR_CONTEXT(interface, ifp);
8032 struct pim_interface *pim_ifp = ifp->info;
8033
8034 if (!pim_ifp)
8035 return CMD_SUCCESS;
8036
8037 change_query_max_response_time(pim_ifp,
8038 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
8039
8040 return CMD_SUCCESS;
8041 }
8042
8043 #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10)
8044 #define IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC (250)
8045
8046 DEFUN_HIDDEN (interface_ip_igmp_query_max_response_time_dsec,
8047 interface_ip_igmp_query_max_response_time_dsec_cmd,
8048 "ip igmp query-max-response-time-dsec (10-250)",
8049 IP_STR
8050 IFACE_IGMP_STR
8051 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR
8052 "Query response value in deciseconds\n")
8053 {
8054 VTY_DECLVAR_CONTEXT(interface, ifp);
8055 struct pim_interface *pim_ifp = ifp->info;
8056 int query_max_response_time_dsec;
8057 int default_query_interval_dsec;
8058 int ret;
8059
8060 if (!pim_ifp) {
8061 ret = pim_cmd_igmp_start(vty, ifp);
8062 if (ret != CMD_SUCCESS)
8063 return ret;
8064 pim_ifp = ifp->info;
8065 }
8066
8067 query_max_response_time_dsec = atoi(argv[4]->arg);
8068
8069 default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
8070
8071 if (query_max_response_time_dsec >= default_query_interval_dsec) {
8072 vty_out(vty,
8073 "Can't set query max response time %d dsec >= general query interval %d dsec\n",
8074 query_max_response_time_dsec,
8075 default_query_interval_dsec);
8076 return CMD_WARNING_CONFIG_FAILED;
8077 }
8078
8079 change_query_max_response_time(pim_ifp, query_max_response_time_dsec);
8080
8081 return CMD_SUCCESS;
8082 }
8083
8084 DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec,
8085 interface_no_ip_igmp_query_max_response_time_dsec_cmd,
8086 "no ip igmp query-max-response-time-dsec",
8087 NO_STR
8088 IP_STR
8089 IFACE_IGMP_STR
8090 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR)
8091 {
8092 VTY_DECLVAR_CONTEXT(interface, ifp);
8093 struct pim_interface *pim_ifp = ifp->info;
8094
8095 if (!pim_ifp)
8096 return CMD_SUCCESS;
8097
8098 change_query_max_response_time(pim_ifp,
8099 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
8100
8101 return CMD_SUCCESS;
8102 }
8103
8104 #define IGMP_LAST_MEMBER_QUERY_COUNT_MIN (1)
8105 #define IGMP_LAST_MEMBER_QUERY_COUNT_MAX (7)
8106
8107 DEFUN (interface_ip_igmp_last_member_query_count,
8108 interface_ip_igmp_last_member_query_count_cmd,
8109 "ip igmp last-member-query-count (1-7)",
8110 IP_STR
8111 IFACE_IGMP_STR
8112 IFACE_IGMP_LAST_MEMBER_QUERY_COUNT_STR
8113 "Last member query count\n")
8114 {
8115 VTY_DECLVAR_CONTEXT(interface, ifp);
8116 struct pim_interface *pim_ifp = ifp->info;
8117 int last_member_query_count;
8118 int ret;
8119
8120 if (!pim_ifp) {
8121 ret = pim_cmd_igmp_start(vty, ifp);
8122 if (ret != CMD_SUCCESS)
8123 return ret;
8124 pim_ifp = ifp->info;
8125 }
8126
8127 last_member_query_count = atoi(argv[3]->arg);
8128
8129 pim_ifp->igmp_last_member_query_count = last_member_query_count;
8130
8131 return CMD_SUCCESS;
8132 }
8133
8134 DEFUN (interface_no_ip_igmp_last_member_query_count,
8135 interface_no_ip_igmp_last_member_query_count_cmd,
8136 "no ip igmp last-member-query-count",
8137 NO_STR
8138 IP_STR
8139 IFACE_IGMP_STR
8140 IFACE_IGMP_LAST_MEMBER_QUERY_COUNT_STR)
8141 {
8142 VTY_DECLVAR_CONTEXT(interface, ifp);
8143 struct pim_interface *pim_ifp = ifp->info;
8144
8145 if (!pim_ifp)
8146 return CMD_SUCCESS;
8147
8148 pim_ifp->igmp_last_member_query_count =
8149 IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
8150
8151 return CMD_SUCCESS;
8152 }
8153
8154 #define IGMP_LAST_MEMBER_QUERY_INTERVAL_MIN (1)
8155 #define IGMP_LAST_MEMBER_QUERY_INTERVAL_MAX (255)
8156
8157 DEFUN (interface_ip_igmp_last_member_query_interval,
8158 interface_ip_igmp_last_member_query_interval_cmd,
8159 "ip igmp last-member-query-interval (1-255)",
8160 IP_STR
8161 IFACE_IGMP_STR
8162 IFACE_IGMP_LAST_MEMBER_QUERY_INTERVAL_STR
8163 "Last member query interval in deciseconds\n")
8164 {
8165 VTY_DECLVAR_CONTEXT(interface, ifp);
8166 struct pim_interface *pim_ifp = ifp->info;
8167 int last_member_query_interval;
8168 int ret;
8169
8170 if (!pim_ifp) {
8171 ret = pim_cmd_igmp_start(vty, ifp);
8172 if (ret != CMD_SUCCESS)
8173 return ret;
8174 pim_ifp = ifp->info;
8175 }
8176
8177 last_member_query_interval = atoi(argv[3]->arg);
8178 pim_ifp->igmp_specific_query_max_response_time_dsec
8179 = last_member_query_interval;
8180
8181 return CMD_SUCCESS;
8182 }
8183
8184 DEFUN (interface_no_ip_igmp_last_member_query_interval,
8185 interface_no_ip_igmp_last_member_query_interval_cmd,
8186 "no ip igmp last-member-query-interval",
8187 NO_STR
8188 IP_STR
8189 IFACE_IGMP_STR
8190 IFACE_IGMP_LAST_MEMBER_QUERY_INTERVAL_STR)
8191 {
8192 VTY_DECLVAR_CONTEXT(interface, ifp);
8193 struct pim_interface *pim_ifp = ifp->info;
8194
8195 if (!pim_ifp)
8196 return CMD_SUCCESS;
8197
8198 pim_ifp->igmp_specific_query_max_response_time_dsec =
8199 IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
8200
8201 return CMD_SUCCESS;
8202 }
8203
8204 DEFUN (interface_ip_pim_drprio,
8205 interface_ip_pim_drprio_cmd,
8206 "ip pim drpriority (1-4294967295)",
8207 IP_STR
8208 PIM_STR
8209 "Set the Designated Router Election Priority\n"
8210 "Value of the new DR Priority\n")
8211 {
8212 VTY_DECLVAR_CONTEXT(interface, ifp);
8213 int idx_number = 3;
8214 struct pim_interface *pim_ifp = ifp->info;
8215 uint32_t old_dr_prio;
8216
8217 if (!pim_ifp) {
8218 vty_out(vty, "Please enable PIM on interface, first\n");
8219 return CMD_WARNING_CONFIG_FAILED;
8220 }
8221
8222 old_dr_prio = pim_ifp->pim_dr_priority;
8223
8224 pim_ifp->pim_dr_priority = strtol(argv[idx_number]->arg, NULL, 10);
8225
8226 if (old_dr_prio != pim_ifp->pim_dr_priority) {
8227 pim_if_dr_election(ifp);
8228 pim_hello_restart_now(ifp);
8229 }
8230
8231 return CMD_SUCCESS;
8232 }
8233
8234 DEFUN (interface_no_ip_pim_drprio,
8235 interface_no_ip_pim_drprio_cmd,
8236 "no ip pim drpriority [(1-4294967295)]",
8237 NO_STR
8238 IP_STR
8239 PIM_STR
8240 "Revert the Designated Router Priority to default\n"
8241 "Old Value of the Priority\n")
8242 {
8243 VTY_DECLVAR_CONTEXT(interface, ifp);
8244 struct pim_interface *pim_ifp = ifp->info;
8245
8246 if (!pim_ifp) {
8247 vty_out(vty, "Pim not enabled on this interface\n");
8248 return CMD_WARNING_CONFIG_FAILED;
8249 }
8250
8251 if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) {
8252 pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY;
8253 pim_if_dr_election(ifp);
8254 pim_hello_restart_now(ifp);
8255 }
8256
8257 return CMD_SUCCESS;
8258 }
8259
8260 DEFPY_HIDDEN (interface_ip_igmp_query_generate,
8261 interface_ip_igmp_query_generate_cmd,
8262 "ip igmp generate-query-once [version (2-3)]",
8263 IP_STR
8264 IFACE_IGMP_STR
8265 "Generate igmp general query once\n"
8266 "IGMP version\n"
8267 "IGMP version number\n")
8268 {
8269 VTY_DECLVAR_CONTEXT(interface, ifp);
8270 int igmp_version = 2;
8271
8272 if (!ifp->info) {
8273 vty_out(vty, "IGMP/PIM is not enabled on the interface %s\n",
8274 ifp->name);
8275 return CMD_WARNING_CONFIG_FAILED;
8276 }
8277
8278 if (argc > 3)
8279 igmp_version = atoi(argv[4]->arg);
8280
8281 igmp_send_query_on_intf(ifp, igmp_version);
8282
8283 return CMD_SUCCESS;
8284 }
8285
8286 static int pim_cmd_interface_add(struct vty *vty, struct interface *ifp)
8287 {
8288 struct pim_interface *pim_ifp = ifp->info;
8289 struct pim_instance *pim;
8290
8291 if (!pim_ifp) {
8292 pim = pim_get_pim_instance(ifp->vrf_id);
8293 /* Limiting mcast interfaces to number of VIFs */
8294 if (pim->mcast_if_count == MAXVIFS) {
8295 vty_out(vty, "Max multicast interfaces(%d) reached.",
8296 MAXVIFS);
8297 return 0;
8298 }
8299 pim_ifp = pim_if_new(ifp, false, true, false, false);
8300 } else
8301 PIM_IF_DO_PIM(pim_ifp->options);
8302
8303 pim_if_addr_add_all(ifp);
8304 pim_if_membership_refresh(ifp);
8305
8306 pim_if_create_pimreg(pim_ifp->pim);
8307 return 1;
8308 }
8309
8310 DEFPY_HIDDEN (pim_test_sg_keepalive,
8311 pim_test_sg_keepalive_cmd,
8312 "test pim [vrf NAME$name] keepalive-reset A.B.C.D$source A.B.C.D$group",
8313 "Test code\n"
8314 PIM_STR
8315 VRF_CMD_HELP_STR
8316 "Reset the Keepalive Timer\n"
8317 "The Source we are resetting\n"
8318 "The Group we are resetting\n")
8319 {
8320 struct pim_upstream *up;
8321 struct pim_instance *pim;
8322 struct prefix_sg sg;
8323
8324 sg.src = source;
8325 sg.grp = group;
8326
8327 if (!name)
8328 pim = pim_get_pim_instance(VRF_DEFAULT);
8329 else {
8330 struct vrf *vrf = vrf_lookup_by_name(name);
8331
8332 if (!vrf) {
8333 vty_out(vty, "%% Vrf specified: %s does not exist\n",
8334 name);
8335 return CMD_WARNING;
8336 }
8337
8338 pim = pim_get_pim_instance(vrf->vrf_id);
8339 }
8340
8341 if (!pim) {
8342 vty_out(vty, "%% Unable to find pim instance\n");
8343 return CMD_WARNING;
8344 }
8345
8346 up = pim_upstream_find(pim, &sg);
8347 if (!up) {
8348 vty_out(vty, "%% Unable to find %s specified\n",
8349 pim_str_sg_dump(&sg));
8350 return CMD_WARNING;
8351 }
8352
8353 vty_out(vty, "Setting %s to current keep alive time: %d\n",
8354 pim_str_sg_dump(&sg), pim->keep_alive_time);
8355 pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
8356
8357 return CMD_SUCCESS;
8358 }
8359
8360 DEFPY (interface_ip_pim_activeactive,
8361 interface_ip_pim_activeactive_cmd,
8362 "[no$no] ip pim active-active",
8363 NO_STR
8364 IP_STR
8365 PIM_STR
8366 "Mark interface as Active-Active for MLAG operations, Hidden because not finished yet\n")
8367 {
8368 VTY_DECLVAR_CONTEXT(interface, ifp);
8369 struct pim_interface *pim_ifp;
8370
8371 if (!no && !pim_cmd_interface_add(vty, ifp)) {
8372 vty_out(vty,
8373 "Could not enable PIM SM active-active on interface %s\n",
8374 ifp->name);
8375 return CMD_WARNING_CONFIG_FAILED;
8376 }
8377
8378
8379 if (PIM_DEBUG_MLAG)
8380 zlog_debug("%sConfiguring PIM active-active on Interface: %s",
8381 no ? "Un-" : " ", ifp->name);
8382
8383 pim_ifp = ifp->info;
8384 if (no)
8385 pim_if_unconfigure_mlag_dualactive(pim_ifp);
8386 else
8387 pim_if_configure_mlag_dualactive(pim_ifp);
8388
8389 return CMD_SUCCESS;
8390 }
8391
8392 DEFUN_HIDDEN (interface_ip_pim_ssm,
8393 interface_ip_pim_ssm_cmd,
8394 "ip pim ssm",
8395 IP_STR
8396 PIM_STR
8397 IFACE_PIM_STR)
8398 {
8399 VTY_DECLVAR_CONTEXT(interface, ifp);
8400
8401 if (!pim_cmd_interface_add(vty, ifp)) {
8402 vty_out(vty, "Could not enable PIM SM on interface %s\n",
8403 ifp->name);
8404 return CMD_WARNING_CONFIG_FAILED;
8405 }
8406
8407 vty_out(vty,
8408 "WARN: Enabled PIM SM on interface; configure PIM SSM range if needed\n");
8409 return CMD_SUCCESS;
8410 }
8411
8412 static int interface_ip_pim_helper(struct vty *vty)
8413 {
8414 struct pim_interface *pim_ifp;
8415
8416 VTY_DECLVAR_CONTEXT(interface, ifp);
8417
8418 if (!pim_cmd_interface_add(vty, ifp)) {
8419 vty_out(vty, "Could not enable PIM SM on interface %s\n",
8420 ifp->name);
8421 return CMD_WARNING_CONFIG_FAILED;
8422 }
8423
8424 pim_ifp = ifp->info;
8425
8426 pim_if_create_pimreg(pim_ifp->pim);
8427
8428 return CMD_SUCCESS;
8429 }
8430
8431 DEFUN_HIDDEN (interface_ip_pim_sm,
8432 interface_ip_pim_sm_cmd,
8433 "ip pim sm",
8434 IP_STR
8435 PIM_STR
8436 IFACE_PIM_SM_STR)
8437 {
8438 return interface_ip_pim_helper(vty);
8439 }
8440
8441 DEFUN (interface_ip_pim,
8442 interface_ip_pim_cmd,
8443 "ip pim",
8444 IP_STR
8445 PIM_STR)
8446 {
8447 return interface_ip_pim_helper(vty);
8448 }
8449
8450 static int pim_cmd_interface_delete(struct interface *ifp)
8451 {
8452 struct pim_interface *pim_ifp = ifp->info;
8453
8454 if (!pim_ifp)
8455 return 1;
8456
8457 PIM_IF_DONT_PIM(pim_ifp->options);
8458
8459 pim_if_membership_clear(ifp);
8460
8461 /*
8462 pim_sock_delete() removes all neighbors from
8463 pim_ifp->pim_neighbor_list.
8464 */
8465 pim_sock_delete(ifp, "pim unconfigured on interface");
8466
8467 if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
8468 pim_if_addr_del_all(ifp);
8469 pim_if_delete(ifp);
8470 }
8471
8472 return 1;
8473 }
8474
8475 static int interface_no_ip_pim_helper(struct vty *vty)
8476 {
8477 VTY_DECLVAR_CONTEXT(interface, ifp);
8478 if (!pim_cmd_interface_delete(ifp)) {
8479 vty_out(vty, "Unable to delete interface information\n");
8480 return CMD_WARNING_CONFIG_FAILED;
8481 }
8482
8483 return CMD_SUCCESS;
8484 }
8485
8486 DEFUN_HIDDEN (interface_no_ip_pim_ssm,
8487 interface_no_ip_pim_ssm_cmd,
8488 "no ip pim ssm",
8489 NO_STR
8490 IP_STR
8491 PIM_STR
8492 IFACE_PIM_STR)
8493 {
8494 return interface_no_ip_pim_helper(vty);
8495 }
8496
8497 DEFUN_HIDDEN (interface_no_ip_pim_sm,
8498 interface_no_ip_pim_sm_cmd,
8499 "no ip pim sm",
8500 NO_STR
8501 IP_STR
8502 PIM_STR
8503 IFACE_PIM_SM_STR)
8504 {
8505 return interface_no_ip_pim_helper(vty);
8506 }
8507
8508 DEFUN (interface_no_ip_pim,
8509 interface_no_ip_pim_cmd,
8510 "no ip pim",
8511 NO_STR
8512 IP_STR
8513 PIM_STR)
8514 {
8515 return interface_no_ip_pim_helper(vty);
8516 }
8517
8518 /* boundaries */
8519 DEFUN(interface_ip_pim_boundary_oil,
8520 interface_ip_pim_boundary_oil_cmd,
8521 "ip multicast boundary oil WORD",
8522 IP_STR
8523 "Generic multicast configuration options\n"
8524 "Define multicast boundary\n"
8525 "Filter OIL by group using prefix list\n"
8526 "Prefix list to filter OIL with\n")
8527 {
8528 VTY_DECLVAR_CONTEXT(interface, iif);
8529 struct pim_interface *pim_ifp;
8530 int idx = 0;
8531
8532 argv_find(argv, argc, "WORD", &idx);
8533
8534 PIM_GET_PIM_INTERFACE(pim_ifp, iif);
8535
8536 if (pim_ifp->boundary_oil_plist)
8537 XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
8538
8539 pim_ifp->boundary_oil_plist =
8540 XSTRDUP(MTYPE_PIM_INTERFACE, argv[idx]->arg);
8541
8542 /* Interface will be pruned from OIL on next Join */
8543 return CMD_SUCCESS;
8544 }
8545
8546 DEFUN(interface_no_ip_pim_boundary_oil,
8547 interface_no_ip_pim_boundary_oil_cmd,
8548 "no ip multicast boundary oil [WORD]",
8549 NO_STR
8550 IP_STR
8551 "Generic multicast configuration options\n"
8552 "Define multicast boundary\n"
8553 "Filter OIL by group using prefix list\n"
8554 "Prefix list to filter OIL with\n")
8555 {
8556 VTY_DECLVAR_CONTEXT(interface, iif);
8557 struct pim_interface *pim_ifp;
8558 int idx = 0;
8559
8560 argv_find(argv, argc, "WORD", &idx);
8561
8562 PIM_GET_PIM_INTERFACE(pim_ifp, iif);
8563
8564 if (pim_ifp->boundary_oil_plist)
8565 XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
8566
8567 return CMD_SUCCESS;
8568 }
8569
8570 DEFUN (interface_ip_mroute,
8571 interface_ip_mroute_cmd,
8572 "ip mroute INTERFACE A.B.C.D [A.B.C.D]",
8573 IP_STR
8574 "Add multicast route\n"
8575 "Outgoing interface name\n"
8576 "Group address\n"
8577 "Source address\n")
8578 {
8579 VTY_DECLVAR_CONTEXT(interface, iif);
8580 struct pim_interface *pim_ifp;
8581 struct pim_instance *pim;
8582 int idx_interface = 2;
8583 int idx_ipv4 = 3;
8584 struct interface *oif;
8585 const char *oifname;
8586 const char *grp_str;
8587 struct in_addr grp_addr;
8588 const char *src_str;
8589 struct in_addr src_addr;
8590 int result;
8591
8592 PIM_GET_PIM_INTERFACE(pim_ifp, iif);
8593 pim = pim_ifp->pim;
8594
8595 oifname = argv[idx_interface]->arg;
8596 oif = if_lookup_by_name(oifname, pim->vrf_id);
8597 if (!oif) {
8598 vty_out(vty, "No such interface name %s\n", oifname);
8599 return CMD_WARNING;
8600 }
8601
8602 grp_str = argv[idx_ipv4]->arg;
8603 result = inet_pton(AF_INET, grp_str, &grp_addr);
8604 if (result <= 0) {
8605 vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
8606 errno, safe_strerror(errno));
8607 return CMD_WARNING;
8608 }
8609
8610 if (argc == (idx_ipv4 + 1)) {
8611 src_addr.s_addr = INADDR_ANY;
8612 }
8613 else {
8614 src_str = argv[idx_ipv4 + 1]->arg;
8615 result = inet_pton(AF_INET, src_str, &src_addr);
8616 if (result <= 0) {
8617 vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str,
8618 errno, safe_strerror(errno));
8619 return CMD_WARNING;
8620 }
8621 }
8622
8623 if (pim_static_add(pim, iif, oif, grp_addr, src_addr)) {
8624 vty_out(vty, "Failed to add static mroute\n");
8625 return CMD_WARNING;
8626 }
8627
8628 return CMD_SUCCESS;
8629 }
8630
8631 DEFUN (interface_no_ip_mroute,
8632 interface_no_ip_mroute_cmd,
8633 "no ip mroute INTERFACE A.B.C.D [A.B.C.D]",
8634 NO_STR
8635 IP_STR
8636 "Add multicast route\n"
8637 "Outgoing interface name\n"
8638 "Group Address\n"
8639 "Source Address\n")
8640 {
8641 VTY_DECLVAR_CONTEXT(interface, iif);
8642 struct pim_interface *pim_ifp;
8643 struct pim_instance *pim;
8644 int idx_interface = 3;
8645 int idx_ipv4 = 4;
8646 struct interface *oif;
8647 const char *oifname;
8648 const char *grp_str;
8649 struct in_addr grp_addr;
8650 const char *src_str;
8651 struct in_addr src_addr;
8652 int result;
8653
8654 PIM_GET_PIM_INTERFACE(pim_ifp, iif);
8655 pim = pim_ifp->pim;
8656
8657 oifname = argv[idx_interface]->arg;
8658 oif = if_lookup_by_name(oifname, pim->vrf_id);
8659 if (!oif) {
8660 vty_out(vty, "No such interface name %s\n", oifname);
8661 return CMD_WARNING;
8662 }
8663
8664 grp_str = argv[idx_ipv4]->arg;
8665 result = inet_pton(AF_INET, grp_str, &grp_addr);
8666 if (result <= 0) {
8667 vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
8668 errno, safe_strerror(errno));
8669 return CMD_WARNING;
8670 }
8671
8672 if (argc == (idx_ipv4 + 1)) {
8673 src_addr.s_addr = INADDR_ANY;
8674 }
8675 else {
8676 src_str = argv[idx_ipv4 + 1]->arg;
8677 result = inet_pton(AF_INET, src_str, &src_addr);
8678 if (result <= 0) {
8679 vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str,
8680 errno, safe_strerror(errno));
8681 return CMD_WARNING;
8682 }
8683 }
8684
8685 if (pim_static_del(pim, iif, oif, grp_addr, src_addr)) {
8686 vty_out(vty, "Failed to remove static mroute\n");
8687 return CMD_WARNING;
8688 }
8689
8690 return CMD_SUCCESS;
8691 }
8692
8693 DEFUN (interface_ip_pim_hello,
8694 interface_ip_pim_hello_cmd,
8695 "ip pim hello (1-180) [(1-180)]",
8696 IP_STR
8697 PIM_STR
8698 IFACE_PIM_HELLO_STR
8699 IFACE_PIM_HELLO_TIME_STR
8700 IFACE_PIM_HELLO_HOLD_STR)
8701 {
8702 VTY_DECLVAR_CONTEXT(interface, ifp);
8703 int idx_time = 3;
8704 int idx_hold = 4;
8705 struct pim_interface *pim_ifp = ifp->info;
8706
8707 if (!pim_ifp) {
8708 if (!pim_cmd_interface_add(vty, ifp)) {
8709 vty_out(vty,
8710 "Could not enable PIM SM on interface %s\n",
8711 ifp->name);
8712 return CMD_WARNING_CONFIG_FAILED;
8713 }
8714 }
8715
8716 pim_ifp = ifp->info;
8717 pim_ifp->pim_hello_period = strtol(argv[idx_time]->arg, NULL, 10);
8718
8719 if (argc == idx_hold + 1)
8720 pim_ifp->pim_default_holdtime =
8721 strtol(argv[idx_hold]->arg, NULL, 10);
8722
8723 return CMD_SUCCESS;
8724 }
8725
8726 DEFUN (interface_no_ip_pim_hello,
8727 interface_no_ip_pim_hello_cmd,
8728 "no ip pim hello [(1-180) (1-180)]",
8729 NO_STR
8730 IP_STR
8731 PIM_STR
8732 IFACE_PIM_HELLO_STR
8733 IFACE_PIM_HELLO_TIME_STR
8734 IFACE_PIM_HELLO_HOLD_STR)
8735 {
8736 VTY_DECLVAR_CONTEXT(interface, ifp);
8737 struct pim_interface *pim_ifp = ifp->info;
8738
8739 if (!pim_ifp) {
8740 vty_out(vty, "Pim not enabled on this interface\n");
8741 return CMD_WARNING_CONFIG_FAILED;
8742 }
8743
8744 pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD;
8745 pim_ifp->pim_default_holdtime = -1;
8746
8747 return CMD_SUCCESS;
8748 }
8749
8750 DEFUN (debug_igmp,
8751 debug_igmp_cmd,
8752 "debug igmp",
8753 DEBUG_STR
8754 DEBUG_IGMP_STR)
8755 {
8756 PIM_DO_DEBUG_IGMP_EVENTS;
8757 PIM_DO_DEBUG_IGMP_PACKETS;
8758 PIM_DO_DEBUG_IGMP_TRACE;
8759 return CMD_SUCCESS;
8760 }
8761
8762 DEFUN (no_debug_igmp,
8763 no_debug_igmp_cmd,
8764 "no debug igmp",
8765 NO_STR
8766 DEBUG_STR
8767 DEBUG_IGMP_STR)
8768 {
8769 PIM_DONT_DEBUG_IGMP_EVENTS;
8770 PIM_DONT_DEBUG_IGMP_PACKETS;
8771 PIM_DONT_DEBUG_IGMP_TRACE;
8772 return CMD_SUCCESS;
8773 }
8774
8775
8776 DEFUN (debug_igmp_events,
8777 debug_igmp_events_cmd,
8778 "debug igmp events",
8779 DEBUG_STR
8780 DEBUG_IGMP_STR
8781 DEBUG_IGMP_EVENTS_STR)
8782 {
8783 PIM_DO_DEBUG_IGMP_EVENTS;
8784 return CMD_SUCCESS;
8785 }
8786
8787 DEFUN (no_debug_igmp_events,
8788 no_debug_igmp_events_cmd,
8789 "no debug igmp events",
8790 NO_STR
8791 DEBUG_STR
8792 DEBUG_IGMP_STR
8793 DEBUG_IGMP_EVENTS_STR)
8794 {
8795 PIM_DONT_DEBUG_IGMP_EVENTS;
8796 return CMD_SUCCESS;
8797 }
8798
8799
8800 DEFUN (debug_igmp_packets,
8801 debug_igmp_packets_cmd,
8802 "debug igmp packets",
8803 DEBUG_STR
8804 DEBUG_IGMP_STR
8805 DEBUG_IGMP_PACKETS_STR)
8806 {
8807 PIM_DO_DEBUG_IGMP_PACKETS;
8808 return CMD_SUCCESS;
8809 }
8810
8811 DEFUN (no_debug_igmp_packets,
8812 no_debug_igmp_packets_cmd,
8813 "no debug igmp packets",
8814 NO_STR
8815 DEBUG_STR
8816 DEBUG_IGMP_STR
8817 DEBUG_IGMP_PACKETS_STR)
8818 {
8819 PIM_DONT_DEBUG_IGMP_PACKETS;
8820 return CMD_SUCCESS;
8821 }
8822
8823
8824 DEFUN (debug_igmp_trace,
8825 debug_igmp_trace_cmd,
8826 "debug igmp trace",
8827 DEBUG_STR
8828 DEBUG_IGMP_STR
8829 DEBUG_IGMP_TRACE_STR)
8830 {
8831 PIM_DO_DEBUG_IGMP_TRACE;
8832 return CMD_SUCCESS;
8833 }
8834
8835 DEFUN (no_debug_igmp_trace,
8836 no_debug_igmp_trace_cmd,
8837 "no debug igmp trace",
8838 NO_STR
8839 DEBUG_STR
8840 DEBUG_IGMP_STR
8841 DEBUG_IGMP_TRACE_STR)
8842 {
8843 PIM_DONT_DEBUG_IGMP_TRACE;
8844 return CMD_SUCCESS;
8845 }
8846
8847
8848 DEFUN (debug_mroute,
8849 debug_mroute_cmd,
8850 "debug mroute",
8851 DEBUG_STR
8852 DEBUG_MROUTE_STR)
8853 {
8854 PIM_DO_DEBUG_MROUTE;
8855 return CMD_SUCCESS;
8856 }
8857
8858 DEFUN (debug_mroute_detail,
8859 debug_mroute_detail_cmd,
8860 "debug mroute detail",
8861 DEBUG_STR
8862 DEBUG_MROUTE_STR
8863 "detailed\n")
8864 {
8865 PIM_DO_DEBUG_MROUTE_DETAIL;
8866 return CMD_SUCCESS;
8867 }
8868
8869 DEFUN (no_debug_mroute,
8870 no_debug_mroute_cmd,
8871 "no debug mroute",
8872 NO_STR
8873 DEBUG_STR
8874 DEBUG_MROUTE_STR)
8875 {
8876 PIM_DONT_DEBUG_MROUTE;
8877 return CMD_SUCCESS;
8878 }
8879
8880 DEFUN (no_debug_mroute_detail,
8881 no_debug_mroute_detail_cmd,
8882 "no debug mroute detail",
8883 NO_STR
8884 DEBUG_STR
8885 DEBUG_MROUTE_STR
8886 "detailed\n")
8887 {
8888 PIM_DONT_DEBUG_MROUTE_DETAIL;
8889 return CMD_SUCCESS;
8890 }
8891
8892 DEFUN (debug_pim_static,
8893 debug_pim_static_cmd,
8894 "debug pim static",
8895 DEBUG_STR
8896 DEBUG_PIM_STR
8897 DEBUG_STATIC_STR)
8898 {
8899 PIM_DO_DEBUG_STATIC;
8900 return CMD_SUCCESS;
8901 }
8902
8903 DEFUN (no_debug_pim_static,
8904 no_debug_pim_static_cmd,
8905 "no debug pim static",
8906 NO_STR
8907 DEBUG_STR
8908 DEBUG_PIM_STR
8909 DEBUG_STATIC_STR)
8910 {
8911 PIM_DONT_DEBUG_STATIC;
8912 return CMD_SUCCESS;
8913 }
8914
8915
8916 DEFUN (debug_pim,
8917 debug_pim_cmd,
8918 "debug pim",
8919 DEBUG_STR
8920 DEBUG_PIM_STR)
8921 {
8922 PIM_DO_DEBUG_PIM_EVENTS;
8923 PIM_DO_DEBUG_PIM_PACKETS;
8924 PIM_DO_DEBUG_PIM_TRACE;
8925 PIM_DO_DEBUG_MSDP_EVENTS;
8926 PIM_DO_DEBUG_MSDP_PACKETS;
8927 PIM_DO_DEBUG_BSM;
8928 return CMD_SUCCESS;
8929 }
8930
8931 DEFUN (no_debug_pim,
8932 no_debug_pim_cmd,
8933 "no debug pim",
8934 NO_STR
8935 DEBUG_STR
8936 DEBUG_PIM_STR)
8937 {
8938 PIM_DONT_DEBUG_PIM_EVENTS;
8939 PIM_DONT_DEBUG_PIM_PACKETS;
8940 PIM_DONT_DEBUG_PIM_TRACE;
8941 PIM_DONT_DEBUG_MSDP_EVENTS;
8942 PIM_DONT_DEBUG_MSDP_PACKETS;
8943
8944 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
8945 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
8946 PIM_DONT_DEBUG_BSM;
8947
8948 return CMD_SUCCESS;
8949 }
8950
8951 DEFUN (debug_pim_nht,
8952 debug_pim_nht_cmd,
8953 "debug pim nht",
8954 DEBUG_STR
8955 DEBUG_PIM_STR
8956 "Nexthop Tracking\n")
8957 {
8958 PIM_DO_DEBUG_PIM_NHT;
8959 return CMD_SUCCESS;
8960 }
8961
8962 DEFUN (no_debug_pim_nht,
8963 no_debug_pim_nht_cmd,
8964 "no debug pim nht",
8965 NO_STR
8966 DEBUG_STR
8967 DEBUG_PIM_STR
8968 "Nexthop Tracking\n")
8969 {
8970 PIM_DONT_DEBUG_PIM_NHT;
8971 return CMD_SUCCESS;
8972 }
8973
8974 DEFUN (debug_pim_nht_rp,
8975 debug_pim_nht_rp_cmd,
8976 "debug pim nht rp",
8977 DEBUG_STR
8978 DEBUG_PIM_STR
8979 "Nexthop Tracking\n"
8980 "RP Nexthop Tracking\n")
8981 {
8982 PIM_DO_DEBUG_PIM_NHT_RP;
8983 return CMD_SUCCESS;
8984 }
8985
8986 DEFUN (no_debug_pim_nht_rp,
8987 no_debug_pim_nht_rp_cmd,
8988 "no debug pim nht rp",
8989 NO_STR
8990 DEBUG_STR
8991 DEBUG_PIM_STR
8992 "Nexthop Tracking\n"
8993 "RP Nexthop Tracking\n")
8994 {
8995 PIM_DONT_DEBUG_PIM_NHT_RP;
8996 return CMD_SUCCESS;
8997 }
8998
8999 DEFUN (debug_pim_events,
9000 debug_pim_events_cmd,
9001 "debug pim events",
9002 DEBUG_STR
9003 DEBUG_PIM_STR
9004 DEBUG_PIM_EVENTS_STR)
9005 {
9006 PIM_DO_DEBUG_PIM_EVENTS;
9007 return CMD_SUCCESS;
9008 }
9009
9010 DEFUN (no_debug_pim_events,
9011 no_debug_pim_events_cmd,
9012 "no debug pim events",
9013 NO_STR
9014 DEBUG_STR
9015 DEBUG_PIM_STR
9016 DEBUG_PIM_EVENTS_STR)
9017 {
9018 PIM_DONT_DEBUG_PIM_EVENTS;
9019 return CMD_SUCCESS;
9020 }
9021
9022 DEFUN (debug_pim_packets,
9023 debug_pim_packets_cmd,
9024 "debug pim packets [<hello|joins|register>]",
9025 DEBUG_STR
9026 DEBUG_PIM_STR
9027 DEBUG_PIM_PACKETS_STR
9028 DEBUG_PIM_HELLO_PACKETS_STR
9029 DEBUG_PIM_J_P_PACKETS_STR
9030 DEBUG_PIM_PIM_REG_PACKETS_STR)
9031 {
9032 int idx = 0;
9033 if (argv_find(argv, argc, "hello", &idx)) {
9034 PIM_DO_DEBUG_PIM_HELLO;
9035 vty_out(vty, "PIM Hello debugging is on\n");
9036 } else if (argv_find(argv, argc, "joins", &idx)) {
9037 PIM_DO_DEBUG_PIM_J_P;
9038 vty_out(vty, "PIM Join/Prune debugging is on\n");
9039 } else if (argv_find(argv, argc, "register", &idx)) {
9040 PIM_DO_DEBUG_PIM_REG;
9041 vty_out(vty, "PIM Register debugging is on\n");
9042 } else {
9043 PIM_DO_DEBUG_PIM_PACKETS;
9044 vty_out(vty, "PIM Packet debugging is on \n");
9045 }
9046 return CMD_SUCCESS;
9047 }
9048
9049 DEFUN (no_debug_pim_packets,
9050 no_debug_pim_packets_cmd,
9051 "no debug pim packets [<hello|joins|register>]",
9052 NO_STR
9053 DEBUG_STR
9054 DEBUG_PIM_STR
9055 DEBUG_PIM_PACKETS_STR
9056 DEBUG_PIM_HELLO_PACKETS_STR
9057 DEBUG_PIM_J_P_PACKETS_STR
9058 DEBUG_PIM_PIM_REG_PACKETS_STR)
9059 {
9060 int idx = 0;
9061 if (argv_find(argv, argc, "hello", &idx)) {
9062 PIM_DONT_DEBUG_PIM_HELLO;
9063 vty_out(vty, "PIM Hello debugging is off \n");
9064 } else if (argv_find(argv, argc, "joins", &idx)) {
9065 PIM_DONT_DEBUG_PIM_J_P;
9066 vty_out(vty, "PIM Join/Prune debugging is off \n");
9067 } else if (argv_find(argv, argc, "register", &idx)) {
9068 PIM_DONT_DEBUG_PIM_REG;
9069 vty_out(vty, "PIM Register debugging is off\n");
9070 } else
9071 PIM_DONT_DEBUG_PIM_PACKETS;
9072
9073 return CMD_SUCCESS;
9074 }
9075
9076
9077 DEFUN (debug_pim_packetdump_send,
9078 debug_pim_packetdump_send_cmd,
9079 "debug pim packet-dump send",
9080 DEBUG_STR
9081 DEBUG_PIM_STR
9082 DEBUG_PIM_PACKETDUMP_STR
9083 DEBUG_PIM_PACKETDUMP_SEND_STR)
9084 {
9085 PIM_DO_DEBUG_PIM_PACKETDUMP_SEND;
9086 return CMD_SUCCESS;
9087 }
9088
9089 DEFUN (no_debug_pim_packetdump_send,
9090 no_debug_pim_packetdump_send_cmd,
9091 "no debug pim packet-dump send",
9092 NO_STR
9093 DEBUG_STR
9094 DEBUG_PIM_STR
9095 DEBUG_PIM_PACKETDUMP_STR
9096 DEBUG_PIM_PACKETDUMP_SEND_STR)
9097 {
9098 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
9099 return CMD_SUCCESS;
9100 }
9101
9102 DEFUN (debug_pim_packetdump_recv,
9103 debug_pim_packetdump_recv_cmd,
9104 "debug pim packet-dump receive",
9105 DEBUG_STR
9106 DEBUG_PIM_STR
9107 DEBUG_PIM_PACKETDUMP_STR
9108 DEBUG_PIM_PACKETDUMP_RECV_STR)
9109 {
9110 PIM_DO_DEBUG_PIM_PACKETDUMP_RECV;
9111 return CMD_SUCCESS;
9112 }
9113
9114 DEFUN (no_debug_pim_packetdump_recv,
9115 no_debug_pim_packetdump_recv_cmd,
9116 "no debug pim packet-dump receive",
9117 NO_STR
9118 DEBUG_STR
9119 DEBUG_PIM_STR
9120 DEBUG_PIM_PACKETDUMP_STR
9121 DEBUG_PIM_PACKETDUMP_RECV_STR)
9122 {
9123 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
9124 return CMD_SUCCESS;
9125 }
9126
9127 DEFUN (debug_pim_trace,
9128 debug_pim_trace_cmd,
9129 "debug pim trace",
9130 DEBUG_STR
9131 DEBUG_PIM_STR
9132 DEBUG_PIM_TRACE_STR)
9133 {
9134 PIM_DO_DEBUG_PIM_TRACE;
9135 return CMD_SUCCESS;
9136 }
9137
9138 DEFUN (debug_pim_trace_detail,
9139 debug_pim_trace_detail_cmd,
9140 "debug pim trace detail",
9141 DEBUG_STR
9142 DEBUG_PIM_STR
9143 DEBUG_PIM_TRACE_STR
9144 "Detailed Information\n")
9145 {
9146 PIM_DO_DEBUG_PIM_TRACE_DETAIL;
9147 return CMD_SUCCESS;
9148 }
9149
9150 DEFUN (no_debug_pim_trace,
9151 no_debug_pim_trace_cmd,
9152 "no debug pim trace",
9153 NO_STR
9154 DEBUG_STR
9155 DEBUG_PIM_STR
9156 DEBUG_PIM_TRACE_STR)
9157 {
9158 PIM_DONT_DEBUG_PIM_TRACE;
9159 return CMD_SUCCESS;
9160 }
9161
9162 DEFUN (no_debug_pim_trace_detail,
9163 no_debug_pim_trace_detail_cmd,
9164 "no debug pim trace detail",
9165 NO_STR
9166 DEBUG_STR
9167 DEBUG_PIM_STR
9168 DEBUG_PIM_TRACE_STR
9169 "Detailed Information\n")
9170 {
9171 PIM_DONT_DEBUG_PIM_TRACE_DETAIL;
9172 return CMD_SUCCESS;
9173 }
9174
9175 DEFUN (debug_ssmpingd,
9176 debug_ssmpingd_cmd,
9177 "debug ssmpingd",
9178 DEBUG_STR
9179 DEBUG_SSMPINGD_STR)
9180 {
9181 PIM_DO_DEBUG_SSMPINGD;
9182 return CMD_SUCCESS;
9183 }
9184
9185 DEFUN (no_debug_ssmpingd,
9186 no_debug_ssmpingd_cmd,
9187 "no debug ssmpingd",
9188 NO_STR
9189 DEBUG_STR
9190 DEBUG_SSMPINGD_STR)
9191 {
9192 PIM_DONT_DEBUG_SSMPINGD;
9193 return CMD_SUCCESS;
9194 }
9195
9196 DEFUN (debug_pim_zebra,
9197 debug_pim_zebra_cmd,
9198 "debug pim zebra",
9199 DEBUG_STR
9200 DEBUG_PIM_STR
9201 DEBUG_PIM_ZEBRA_STR)
9202 {
9203 PIM_DO_DEBUG_ZEBRA;
9204 return CMD_SUCCESS;
9205 }
9206
9207 DEFUN (no_debug_pim_zebra,
9208 no_debug_pim_zebra_cmd,
9209 "no debug pim zebra",
9210 NO_STR
9211 DEBUG_STR
9212 DEBUG_PIM_STR
9213 DEBUG_PIM_ZEBRA_STR)
9214 {
9215 PIM_DONT_DEBUG_ZEBRA;
9216 return CMD_SUCCESS;
9217 }
9218
9219 DEFUN(debug_pim_mlag, debug_pim_mlag_cmd, "debug pim mlag",
9220 DEBUG_STR DEBUG_PIM_STR DEBUG_PIM_MLAG_STR)
9221 {
9222 PIM_DO_DEBUG_MLAG;
9223 return CMD_SUCCESS;
9224 }
9225
9226 DEFUN(no_debug_pim_mlag, no_debug_pim_mlag_cmd, "no debug pim mlag",
9227 NO_STR DEBUG_STR DEBUG_PIM_STR DEBUG_PIM_MLAG_STR)
9228 {
9229 PIM_DONT_DEBUG_MLAG;
9230 return CMD_SUCCESS;
9231 }
9232
9233 DEFUN (debug_pim_vxlan,
9234 debug_pim_vxlan_cmd,
9235 "debug pim vxlan",
9236 DEBUG_STR
9237 DEBUG_PIM_STR
9238 DEBUG_PIM_VXLAN_STR)
9239 {
9240 PIM_DO_DEBUG_VXLAN;
9241 return CMD_SUCCESS;
9242 }
9243
9244 DEFUN (no_debug_pim_vxlan,
9245 no_debug_pim_vxlan_cmd,
9246 "no debug pim vxlan",
9247 NO_STR
9248 DEBUG_STR
9249 DEBUG_PIM_STR
9250 DEBUG_PIM_VXLAN_STR)
9251 {
9252 PIM_DONT_DEBUG_VXLAN;
9253 return CMD_SUCCESS;
9254 }
9255
9256 DEFUN (debug_msdp,
9257 debug_msdp_cmd,
9258 "debug msdp",
9259 DEBUG_STR
9260 DEBUG_MSDP_STR)
9261 {
9262 PIM_DO_DEBUG_MSDP_EVENTS;
9263 PIM_DO_DEBUG_MSDP_PACKETS;
9264 return CMD_SUCCESS;
9265 }
9266
9267 DEFUN (no_debug_msdp,
9268 no_debug_msdp_cmd,
9269 "no debug msdp",
9270 NO_STR
9271 DEBUG_STR
9272 DEBUG_MSDP_STR)
9273 {
9274 PIM_DONT_DEBUG_MSDP_EVENTS;
9275 PIM_DONT_DEBUG_MSDP_PACKETS;
9276 return CMD_SUCCESS;
9277 }
9278
9279 DEFUN (debug_msdp_events,
9280 debug_msdp_events_cmd,
9281 "debug msdp events",
9282 DEBUG_STR
9283 DEBUG_MSDP_STR
9284 DEBUG_MSDP_EVENTS_STR)
9285 {
9286 PIM_DO_DEBUG_MSDP_EVENTS;
9287 return CMD_SUCCESS;
9288 }
9289
9290 DEFUN (no_debug_msdp_events,
9291 no_debug_msdp_events_cmd,
9292 "no debug msdp events",
9293 NO_STR
9294 DEBUG_STR
9295 DEBUG_MSDP_STR
9296 DEBUG_MSDP_EVENTS_STR)
9297 {
9298 PIM_DONT_DEBUG_MSDP_EVENTS;
9299 return CMD_SUCCESS;
9300 }
9301
9302 DEFUN (debug_msdp_packets,
9303 debug_msdp_packets_cmd,
9304 "debug msdp packets",
9305 DEBUG_STR
9306 DEBUG_MSDP_STR
9307 DEBUG_MSDP_PACKETS_STR)
9308 {
9309 PIM_DO_DEBUG_MSDP_PACKETS;
9310 return CMD_SUCCESS;
9311 }
9312
9313 DEFUN (no_debug_msdp_packets,
9314 no_debug_msdp_packets_cmd,
9315 "no debug msdp packets",
9316 NO_STR
9317 DEBUG_STR
9318 DEBUG_MSDP_STR
9319 DEBUG_MSDP_PACKETS_STR)
9320 {
9321 PIM_DONT_DEBUG_MSDP_PACKETS;
9322 return CMD_SUCCESS;
9323 }
9324
9325 DEFUN (debug_mtrace,
9326 debug_mtrace_cmd,
9327 "debug mtrace",
9328 DEBUG_STR
9329 DEBUG_MTRACE_STR)
9330 {
9331 PIM_DO_DEBUG_MTRACE;
9332 return CMD_SUCCESS;
9333 }
9334
9335 DEFUN (no_debug_mtrace,
9336 no_debug_mtrace_cmd,
9337 "no debug mtrace",
9338 NO_STR
9339 DEBUG_STR
9340 DEBUG_MTRACE_STR)
9341 {
9342 PIM_DONT_DEBUG_MTRACE;
9343 return CMD_SUCCESS;
9344 }
9345
9346 DEFUN (debug_bsm,
9347 debug_bsm_cmd,
9348 "debug pim bsm",
9349 DEBUG_STR
9350 DEBUG_PIM_STR
9351 DEBUG_PIM_BSM_STR)
9352 {
9353 PIM_DO_DEBUG_BSM;
9354 return CMD_SUCCESS;
9355 }
9356
9357 DEFUN (no_debug_bsm,
9358 no_debug_bsm_cmd,
9359 "no debug pim bsm",
9360 NO_STR
9361 DEBUG_STR
9362 DEBUG_PIM_STR
9363 DEBUG_PIM_BSM_STR)
9364 {
9365 PIM_DONT_DEBUG_BSM;
9366 return CMD_SUCCESS;
9367 }
9368
9369
9370 DEFUN_NOSH (show_debugging_pim,
9371 show_debugging_pim_cmd,
9372 "show debugging [pim]",
9373 SHOW_STR
9374 DEBUG_STR
9375 PIM_STR)
9376 {
9377 vty_out(vty, "PIM debugging status\n");
9378
9379 pim_debug_config_write(vty);
9380
9381 return CMD_SUCCESS;
9382 }
9383
9384 static int interface_pim_use_src_cmd_worker(struct vty *vty, const char *source)
9385 {
9386 int result;
9387 struct in_addr source_addr;
9388 int ret = CMD_SUCCESS;
9389 VTY_DECLVAR_CONTEXT(interface, ifp);
9390
9391 result = inet_pton(AF_INET, source, &source_addr);
9392 if (result <= 0) {
9393 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", source,
9394 errno, safe_strerror(errno));
9395 return CMD_WARNING_CONFIG_FAILED;
9396 }
9397
9398 result = pim_update_source_set(ifp, source_addr);
9399 switch (result) {
9400 case PIM_SUCCESS:
9401 break;
9402 case PIM_IFACE_NOT_FOUND:
9403 ret = CMD_WARNING_CONFIG_FAILED;
9404 vty_out(vty, "Pim not enabled on this interface\n");
9405 break;
9406 case PIM_UPDATE_SOURCE_DUP:
9407 ret = CMD_WARNING;
9408 vty_out(vty, "%% Source already set to %s\n", source);
9409 break;
9410 default:
9411 ret = CMD_WARNING_CONFIG_FAILED;
9412 vty_out(vty, "%% Source set failed\n");
9413 }
9414
9415 return ret;
9416 }
9417
9418 DEFUN (interface_pim_use_source,
9419 interface_pim_use_source_cmd,
9420 "ip pim use-source A.B.C.D",
9421 IP_STR
9422 PIM_STR
9423 "Configure primary IP address\n"
9424 "source ip address\n")
9425 {
9426 return interface_pim_use_src_cmd_worker(vty, argv[3]->arg);
9427 }
9428
9429 DEFUN (interface_no_pim_use_source,
9430 interface_no_pim_use_source_cmd,
9431 "no ip pim use-source [A.B.C.D]",
9432 NO_STR
9433 IP_STR
9434 PIM_STR
9435 "Delete source IP address\n"
9436 "source ip address\n")
9437 {
9438 return interface_pim_use_src_cmd_worker(vty, "0.0.0.0");
9439 }
9440
9441 DEFUN (ip_pim_bfd,
9442 ip_pim_bfd_cmd,
9443 "ip pim bfd",
9444 IP_STR
9445 PIM_STR
9446 "Enables BFD support\n")
9447 {
9448 VTY_DECLVAR_CONTEXT(interface, ifp);
9449 struct pim_interface *pim_ifp = ifp->info;
9450 struct bfd_info *bfd_info = NULL;
9451
9452 if (!pim_ifp) {
9453 if (!pim_cmd_interface_add(vty, ifp)) {
9454 vty_out(vty,
9455 "Could not enable PIM SM on interface %s\n",
9456 ifp->name);
9457 return CMD_WARNING;
9458 }
9459 }
9460 pim_ifp = ifp->info;
9461
9462 bfd_info = pim_ifp->bfd_info;
9463
9464 if (!bfd_info || !CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG))
9465 pim_bfd_if_param_set(ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
9466 BFD_DEF_DETECT_MULT, 1);
9467
9468 return CMD_SUCCESS;
9469 }
9470
9471 DEFUN (no_ip_pim_bfd,
9472 no_ip_pim_bfd_cmd,
9473 "no ip pim bfd",
9474 NO_STR
9475 IP_STR
9476 PIM_STR
9477 "Disables BFD support\n")
9478 {
9479 VTY_DECLVAR_CONTEXT(interface, ifp);
9480 struct pim_interface *pim_ifp = ifp->info;
9481
9482 if (!pim_ifp) {
9483 vty_out(vty, "Pim not enabled on this interface\n");
9484 return CMD_WARNING;
9485 }
9486
9487 if (pim_ifp->bfd_info) {
9488 pim_bfd_reg_dereg_all_nbr(ifp, ZEBRA_BFD_DEST_DEREGISTER);
9489 bfd_info_free(&(pim_ifp->bfd_info));
9490 }
9491
9492 return CMD_SUCCESS;
9493 }
9494
9495 DEFUN (ip_pim_bsm,
9496 ip_pim_bsm_cmd,
9497 "ip pim bsm",
9498 IP_STR
9499 PIM_STR
9500 "Enables BSM support on the interface\n")
9501 {
9502 VTY_DECLVAR_CONTEXT(interface, ifp);
9503 struct pim_interface *pim_ifp = ifp->info;
9504
9505 if (!pim_ifp) {
9506 if (!pim_cmd_interface_add(vty, ifp)) {
9507 vty_out(vty,
9508 "Could not enable PIM SM on interface %s\n",
9509 ifp->name);
9510 return CMD_WARNING;
9511 }
9512 }
9513
9514 pim_ifp = ifp->info;
9515 pim_ifp->bsm_enable = true;
9516
9517 return CMD_SUCCESS;
9518 }
9519
9520 DEFUN (no_ip_pim_bsm,
9521 no_ip_pim_bsm_cmd,
9522 "no ip pim bsm",
9523 NO_STR
9524 IP_STR
9525 PIM_STR
9526 "Disables BSM support\n")
9527 {
9528 VTY_DECLVAR_CONTEXT(interface, ifp);
9529 struct pim_interface *pim_ifp = ifp->info;
9530
9531 if (!pim_ifp) {
9532 vty_out(vty, "Pim not enabled on this interface\n");
9533 return CMD_WARNING;
9534 }
9535
9536 pim_ifp->bsm_enable = false;
9537
9538 return CMD_SUCCESS;
9539 }
9540
9541 DEFUN (ip_pim_ucast_bsm,
9542 ip_pim_ucast_bsm_cmd,
9543 "ip pim unicast-bsm",
9544 IP_STR
9545 PIM_STR
9546 "Accept/Send unicast BSM on the interface\n")
9547 {
9548 VTY_DECLVAR_CONTEXT(interface, ifp);
9549 struct pim_interface *pim_ifp = ifp->info;
9550
9551 if (!pim_ifp) {
9552 if (!pim_cmd_interface_add(vty, ifp)) {
9553 vty_out(vty,
9554 "Could not enable PIM SM on interface %s\n",
9555 ifp->name);
9556 return CMD_WARNING;
9557 }
9558 }
9559
9560 pim_ifp = ifp->info;
9561 pim_ifp->ucast_bsm_accept = true;
9562
9563 return CMD_SUCCESS;
9564 }
9565
9566 DEFUN (no_ip_pim_ucast_bsm,
9567 no_ip_pim_ucast_bsm_cmd,
9568 "no ip pim unicast-bsm",
9569 NO_STR
9570 IP_STR
9571 PIM_STR
9572 "Block send/receive unicast BSM on this interface\n")
9573 {
9574 VTY_DECLVAR_CONTEXT(interface, ifp);
9575 struct pim_interface *pim_ifp = ifp->info;
9576
9577 if (!pim_ifp) {
9578 vty_out(vty, "Pim not enabled on this interface\n");
9579 return CMD_WARNING;
9580 }
9581
9582 pim_ifp->ucast_bsm_accept = false;
9583
9584 return CMD_SUCCESS;
9585 }
9586
9587 #if HAVE_BFDD > 0
9588 DEFUN_HIDDEN(
9589 ip_pim_bfd_param,
9590 ip_pim_bfd_param_cmd,
9591 "ip pim bfd (2-255) (50-60000) (50-60000)",
9592 IP_STR
9593 PIM_STR
9594 "Enables BFD support\n"
9595 "Detect Multiplier\n"
9596 "Required min receive interval\n"
9597 "Desired min transmit interval\n")
9598 #else
9599 DEFUN(
9600 ip_pim_bfd_param,
9601 ip_pim_bfd_param_cmd,
9602 "ip pim bfd (2-255) (50-60000) (50-60000)",
9603 IP_STR
9604 PIM_STR
9605 "Enables BFD support\n"
9606 "Detect Multiplier\n"
9607 "Required min receive interval\n"
9608 "Desired min transmit interval\n")
9609 #endif /* HAVE_BFDD */
9610 {
9611 VTY_DECLVAR_CONTEXT(interface, ifp);
9612 int idx_number = 3;
9613 int idx_number_2 = 4;
9614 int idx_number_3 = 5;
9615 uint32_t rx_val;
9616 uint32_t tx_val;
9617 uint8_t dm_val;
9618 int ret;
9619 struct pim_interface *pim_ifp = ifp->info;
9620
9621 if (!pim_ifp) {
9622 if (!pim_cmd_interface_add(vty, ifp)) {
9623 vty_out(vty,
9624 "Could not enable PIM SM on interface %s\n",
9625 ifp->name);
9626 return CMD_WARNING;
9627 }
9628 }
9629
9630 if ((ret = bfd_validate_param(
9631 vty, argv[idx_number]->arg, argv[idx_number_2]->arg,
9632 argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val))
9633 != CMD_SUCCESS)
9634 return ret;
9635
9636 pim_bfd_if_param_set(ifp, rx_val, tx_val, dm_val, 0);
9637
9638 return CMD_SUCCESS;
9639 }
9640
9641 #if HAVE_BFDD == 0
9642 ALIAS(no_ip_pim_bfd, no_ip_pim_bfd_param_cmd,
9643 "no ip pim bfd (2-255) (50-60000) (50-60000)", NO_STR IP_STR PIM_STR
9644 "Enables BFD support\n"
9645 "Detect Multiplier\n"
9646 "Required min receive interval\n"
9647 "Desired min transmit interval\n")
9648 #endif /* !HAVE_BFDD */
9649
9650 static int ip_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty,
9651 const char *peer, const char *local)
9652 {
9653 enum pim_msdp_err result;
9654 struct in_addr peer_addr;
9655 struct in_addr local_addr;
9656 int ret = CMD_SUCCESS;
9657
9658 result = inet_pton(AF_INET, peer, &peer_addr);
9659 if (result <= 0) {
9660 vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer,
9661 errno, safe_strerror(errno));
9662 return CMD_WARNING_CONFIG_FAILED;
9663 }
9664
9665 result = inet_pton(AF_INET, local, &local_addr);
9666 if (result <= 0) {
9667 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", local,
9668 errno, safe_strerror(errno));
9669 return CMD_WARNING_CONFIG_FAILED;
9670 }
9671
9672 result = pim_msdp_peer_add(pim, peer_addr, local_addr, "default",
9673 NULL /* mp_p */);
9674 switch (result) {
9675 case PIM_MSDP_ERR_NONE:
9676 break;
9677 case PIM_MSDP_ERR_OOM:
9678 ret = CMD_WARNING_CONFIG_FAILED;
9679 vty_out(vty, "%% Out of memory\n");
9680 break;
9681 case PIM_MSDP_ERR_PEER_EXISTS:
9682 ret = CMD_WARNING;
9683 vty_out(vty, "%% Peer exists\n");
9684 break;
9685 case PIM_MSDP_ERR_MAX_MESH_GROUPS:
9686 ret = CMD_WARNING_CONFIG_FAILED;
9687 vty_out(vty, "%% Only one mesh-group allowed currently\n");
9688 break;
9689 default:
9690 ret = CMD_WARNING_CONFIG_FAILED;
9691 vty_out(vty, "%% peer add failed\n");
9692 }
9693
9694 return ret;
9695 }
9696
9697 DEFUN_HIDDEN (ip_msdp_peer,
9698 ip_msdp_peer_cmd,
9699 "ip msdp peer A.B.C.D source A.B.C.D",
9700 IP_STR
9701 CFG_MSDP_STR
9702 "Configure MSDP peer\n"
9703 "peer ip address\n"
9704 "Source address for TCP connection\n"
9705 "local ip address\n")
9706 {
9707 PIM_DECLVAR_CONTEXT(vrf, pim);
9708 return ip_msdp_peer_cmd_worker(pim, vty, argv[3]->arg, argv[5]->arg);
9709 }
9710
9711 static int ip_no_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty,
9712 const char *peer)
9713 {
9714 enum pim_msdp_err result;
9715 struct in_addr peer_addr;
9716
9717 result = inet_pton(AF_INET, peer, &peer_addr);
9718 if (result <= 0) {
9719 vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer,
9720 errno, safe_strerror(errno));
9721 return CMD_WARNING_CONFIG_FAILED;
9722 }
9723
9724 result = pim_msdp_peer_del(pim, peer_addr);
9725 switch (result) {
9726 case PIM_MSDP_ERR_NONE:
9727 break;
9728 case PIM_MSDP_ERR_NO_PEER:
9729 vty_out(vty, "%% Peer does not exist\n");
9730 break;
9731 default:
9732 vty_out(vty, "%% peer del failed\n");
9733 }
9734
9735 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
9736 }
9737
9738 DEFUN_HIDDEN (no_ip_msdp_peer,
9739 no_ip_msdp_peer_cmd,
9740 "no ip msdp peer A.B.C.D",
9741 NO_STR
9742 IP_STR
9743 CFG_MSDP_STR
9744 "Delete MSDP peer\n"
9745 "peer ip address\n")
9746 {
9747 PIM_DECLVAR_CONTEXT(vrf, pim);
9748 return ip_no_msdp_peer_cmd_worker(pim, vty, argv[4]->arg);
9749 }
9750
9751 static int ip_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim,
9752 struct vty *vty, const char *mg,
9753 const char *mbr)
9754 {
9755 enum pim_msdp_err result;
9756 struct in_addr mbr_ip;
9757 int ret = CMD_SUCCESS;
9758
9759 result = inet_pton(AF_INET, mbr, &mbr_ip);
9760 if (result <= 0) {
9761 vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr,
9762 errno, safe_strerror(errno));
9763 return CMD_WARNING_CONFIG_FAILED;
9764 }
9765
9766 result = pim_msdp_mg_mbr_add(pim, mg, mbr_ip);
9767 switch (result) {
9768 case PIM_MSDP_ERR_NONE:
9769 break;
9770 case PIM_MSDP_ERR_OOM:
9771 ret = CMD_WARNING_CONFIG_FAILED;
9772 vty_out(vty, "%% Out of memory\n");
9773 break;
9774 case PIM_MSDP_ERR_MG_MBR_EXISTS:
9775 ret = CMD_WARNING;
9776 vty_out(vty, "%% mesh-group member exists\n");
9777 break;
9778 case PIM_MSDP_ERR_MAX_MESH_GROUPS:
9779 ret = CMD_WARNING_CONFIG_FAILED;
9780 vty_out(vty, "%% Only one mesh-group allowed currently\n");
9781 break;
9782 default:
9783 ret = CMD_WARNING_CONFIG_FAILED;
9784 vty_out(vty, "%% member add failed\n");
9785 }
9786
9787 return ret;
9788 }
9789
9790 DEFUN (ip_msdp_mesh_group_member,
9791 ip_msdp_mesh_group_member_cmd,
9792 "ip msdp mesh-group WORD member A.B.C.D",
9793 IP_STR
9794 CFG_MSDP_STR
9795 "Configure MSDP mesh-group\n"
9796 "mesh group name\n"
9797 "mesh group member\n"
9798 "peer ip address\n")
9799 {
9800 PIM_DECLVAR_CONTEXT(vrf, pim);
9801 return ip_msdp_mesh_group_member_cmd_worker(pim, vty, argv[3]->arg,
9802 argv[5]->arg);
9803 }
9804
9805 static int ip_no_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim,
9806 struct vty *vty,
9807 const char *mg,
9808 const char *mbr)
9809 {
9810 enum pim_msdp_err result;
9811 struct in_addr mbr_ip;
9812
9813 result = inet_pton(AF_INET, mbr, &mbr_ip);
9814 if (result <= 0) {
9815 vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr,
9816 errno, safe_strerror(errno));
9817 return CMD_WARNING_CONFIG_FAILED;
9818 }
9819
9820 result = pim_msdp_mg_mbr_del(pim, mg, mbr_ip);
9821 switch (result) {
9822 case PIM_MSDP_ERR_NONE:
9823 break;
9824 case PIM_MSDP_ERR_NO_MG:
9825 vty_out(vty, "%% mesh-group does not exist\n");
9826 break;
9827 case PIM_MSDP_ERR_NO_MG_MBR:
9828 vty_out(vty, "%% mesh-group member does not exist\n");
9829 break;
9830 default:
9831 vty_out(vty, "%% mesh-group member del failed\n");
9832 }
9833
9834 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
9835 }
9836 DEFUN (no_ip_msdp_mesh_group_member,
9837 no_ip_msdp_mesh_group_member_cmd,
9838 "no ip msdp mesh-group WORD member A.B.C.D",
9839 NO_STR
9840 IP_STR
9841 CFG_MSDP_STR
9842 "Delete MSDP mesh-group member\n"
9843 "mesh group name\n"
9844 "mesh group member\n"
9845 "peer ip address\n")
9846 {
9847 PIM_DECLVAR_CONTEXT(vrf, pim);
9848 return ip_no_msdp_mesh_group_member_cmd_worker(pim, vty, argv[4]->arg,
9849 argv[6]->arg);
9850 }
9851
9852 static int ip_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim,
9853 struct vty *vty, const char *mg,
9854 const char *src)
9855 {
9856 enum pim_msdp_err result;
9857 struct in_addr src_ip;
9858
9859 result = inet_pton(AF_INET, src, &src_ip);
9860 if (result <= 0) {
9861 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", src,
9862 errno, safe_strerror(errno));
9863 return CMD_WARNING_CONFIG_FAILED;
9864 }
9865
9866 result = pim_msdp_mg_src_add(pim, mg, src_ip);
9867 switch (result) {
9868 case PIM_MSDP_ERR_NONE:
9869 break;
9870 case PIM_MSDP_ERR_OOM:
9871 vty_out(vty, "%% Out of memory\n");
9872 break;
9873 case PIM_MSDP_ERR_MAX_MESH_GROUPS:
9874 vty_out(vty, "%% Only one mesh-group allowed currently\n");
9875 break;
9876 default:
9877 vty_out(vty, "%% source add failed\n");
9878 }
9879
9880 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
9881 }
9882
9883
9884 DEFUN (ip_msdp_mesh_group_source,
9885 ip_msdp_mesh_group_source_cmd,
9886 "ip msdp mesh-group WORD source A.B.C.D",
9887 IP_STR
9888 CFG_MSDP_STR
9889 "Configure MSDP mesh-group\n"
9890 "mesh group name\n"
9891 "mesh group local address\n"
9892 "source ip address for the TCP connection\n")
9893 {
9894 PIM_DECLVAR_CONTEXT(vrf, pim);
9895 return ip_msdp_mesh_group_source_cmd_worker(pim, vty, argv[3]->arg,
9896 argv[5]->arg);
9897 }
9898
9899 static int ip_no_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim,
9900 struct vty *vty,
9901 const char *mg)
9902 {
9903 enum pim_msdp_err result;
9904
9905 result = pim_msdp_mg_src_del(pim, mg);
9906 switch (result) {
9907 case PIM_MSDP_ERR_NONE:
9908 break;
9909 case PIM_MSDP_ERR_NO_MG:
9910 vty_out(vty, "%% mesh-group does not exist\n");
9911 break;
9912 default:
9913 vty_out(vty, "%% mesh-group source del failed\n");
9914 }
9915
9916 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
9917 }
9918
9919 static int ip_no_msdp_mesh_group_cmd_worker(struct pim_instance *pim,
9920 struct vty *vty, const char *mg)
9921 {
9922 enum pim_msdp_err result;
9923
9924 result = pim_msdp_mg_del(pim, mg);
9925 switch (result) {
9926 case PIM_MSDP_ERR_NONE:
9927 break;
9928 case PIM_MSDP_ERR_NO_MG:
9929 vty_out(vty, "%% mesh-group does not exist\n");
9930 break;
9931 default:
9932 vty_out(vty, "%% mesh-group source del failed\n");
9933 }
9934
9935 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
9936 }
9937
9938 DEFUN (no_ip_msdp_mesh_group_source,
9939 no_ip_msdp_mesh_group_source_cmd,
9940 "no ip msdp mesh-group WORD source [A.B.C.D]",
9941 NO_STR
9942 IP_STR
9943 CFG_MSDP_STR
9944 "Delete MSDP mesh-group source\n"
9945 "mesh group name\n"
9946 "mesh group source\n"
9947 "mesh group local address\n")
9948 {
9949 PIM_DECLVAR_CONTEXT(vrf, pim);
9950
9951 return ip_no_msdp_mesh_group_source_cmd_worker(pim, vty, argv[4]->arg);
9952 }
9953
9954 DEFUN (no_ip_msdp_mesh_group,
9955 no_ip_msdp_mesh_group_cmd,
9956 "no ip msdp mesh-group [WORD]",
9957 NO_STR
9958 IP_STR
9959 CFG_MSDP_STR
9960 "Delete MSDP mesh-group\n"
9961 "mesh group name")
9962 {
9963 PIM_DECLVAR_CONTEXT(vrf, pim);
9964
9965 if (argc == 5)
9966 return ip_no_msdp_mesh_group_cmd_worker(pim, vty, argv[4]->arg);
9967 else
9968 return ip_no_msdp_mesh_group_cmd_worker(pim, vty, NULL);
9969 }
9970
9971 static void print_empty_json_obj(struct vty *vty)
9972 {
9973 json_object *json;
9974 json = json_object_new_object();
9975 vty_out(vty, "%s\n",
9976 json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
9977 json_object_free(json);
9978 }
9979
9980 static void ip_msdp_show_mesh_group(struct pim_instance *pim, struct vty *vty,
9981 bool uj)
9982 {
9983 struct listnode *mbrnode;
9984 struct pim_msdp_mg_mbr *mbr;
9985 struct pim_msdp_mg *mg = pim->msdp.mg;
9986 char mbr_str[INET_ADDRSTRLEN];
9987 char src_str[INET_ADDRSTRLEN];
9988 char state_str[PIM_MSDP_STATE_STRLEN];
9989 enum pim_msdp_peer_state state;
9990 json_object *json = NULL;
9991 json_object *json_mg_row = NULL;
9992 json_object *json_members = NULL;
9993 json_object *json_row = NULL;
9994
9995 if (!mg) {
9996 if (uj)
9997 print_empty_json_obj(vty);
9998 return;
9999 }
10000
10001 pim_inet4_dump("<source?>", mg->src_ip, src_str, sizeof(src_str));
10002 if (uj) {
10003 json = json_object_new_object();
10004 /* currently there is only one mesh group but we should still
10005 * make
10006 * it a dict with mg-name as key */
10007 json_mg_row = json_object_new_object();
10008 json_object_string_add(json_mg_row, "name",
10009 mg->mesh_group_name);
10010 json_object_string_add(json_mg_row, "source", src_str);
10011 } else {
10012 vty_out(vty, "Mesh group : %s\n", mg->mesh_group_name);
10013 vty_out(vty, " Source : %s\n", src_str);
10014 vty_out(vty, " Member State\n");
10015 }
10016
10017 for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) {
10018 pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str));
10019 if (mbr->mp) {
10020 state = mbr->mp->state;
10021 } else {
10022 state = PIM_MSDP_DISABLED;
10023 }
10024 pim_msdp_state_dump(state, state_str, sizeof(state_str));
10025 if (uj) {
10026 json_row = json_object_new_object();
10027 json_object_string_add(json_row, "member", mbr_str);
10028 json_object_string_add(json_row, "state", state_str);
10029 if (!json_members) {
10030 json_members = json_object_new_object();
10031 json_object_object_add(json_mg_row, "members",
10032 json_members);
10033 }
10034 json_object_object_add(json_members, mbr_str, json_row);
10035 } else {
10036 vty_out(vty, " %-15s %11s\n", mbr_str, state_str);
10037 }
10038 }
10039
10040 if (uj) {
10041 json_object_object_add(json, mg->mesh_group_name, json_mg_row);
10042 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10043 json, JSON_C_TO_STRING_PRETTY));
10044 json_object_free(json);
10045 }
10046 }
10047
10048 DEFUN (show_ip_msdp_mesh_group,
10049 show_ip_msdp_mesh_group_cmd,
10050 "show ip msdp [vrf NAME] mesh-group [json]",
10051 SHOW_STR
10052 IP_STR
10053 MSDP_STR
10054 VRF_CMD_HELP_STR
10055 "MSDP mesh-group information\n"
10056 JSON_STR)
10057 {
10058 bool uj = use_json(argc, argv);
10059 int idx = 2;
10060 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10061
10062 if (!vrf)
10063 return CMD_WARNING;
10064
10065 ip_msdp_show_mesh_group(vrf->info, vty, uj);
10066
10067 return CMD_SUCCESS;
10068 }
10069
10070 DEFUN (show_ip_msdp_mesh_group_vrf_all,
10071 show_ip_msdp_mesh_group_vrf_all_cmd,
10072 "show ip msdp vrf all mesh-group [json]",
10073 SHOW_STR
10074 IP_STR
10075 MSDP_STR
10076 VRF_CMD_HELP_STR
10077 "MSDP mesh-group information\n"
10078 JSON_STR)
10079 {
10080 bool uj = use_json(argc, argv);
10081 struct vrf *vrf;
10082 bool first = true;
10083
10084 if (uj)
10085 vty_out(vty, "{ ");
10086 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
10087 if (uj) {
10088 if (!first)
10089 vty_out(vty, ", ");
10090 vty_out(vty, " \"%s\": ", vrf->name);
10091 first = false;
10092 } else
10093 vty_out(vty, "VRF: %s\n", vrf->name);
10094 ip_msdp_show_mesh_group(vrf->info, vty, uj);
10095 }
10096 if (uj)
10097 vty_out(vty, "}\n");
10098
10099 return CMD_SUCCESS;
10100 }
10101
10102 static void ip_msdp_show_peers(struct pim_instance *pim, struct vty *vty,
10103 bool uj)
10104 {
10105 struct listnode *mpnode;
10106 struct pim_msdp_peer *mp;
10107 char peer_str[INET_ADDRSTRLEN];
10108 char local_str[INET_ADDRSTRLEN];
10109 char state_str[PIM_MSDP_STATE_STRLEN];
10110 char timebuf[PIM_MSDP_UPTIME_STRLEN];
10111 int64_t now;
10112 json_object *json = NULL;
10113 json_object *json_row = NULL;
10114
10115
10116 if (uj) {
10117 json = json_object_new_object();
10118 } else {
10119 vty_out(vty,
10120 "Peer Local State Uptime SaCnt\n");
10121 }
10122
10123 for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, mpnode, mp)) {
10124 if (mp->state == PIM_MSDP_ESTABLISHED) {
10125 now = pim_time_monotonic_sec();
10126 pim_time_uptime(timebuf, sizeof(timebuf),
10127 now - mp->uptime);
10128 } else {
10129 strlcpy(timebuf, "-", sizeof(timebuf));
10130 }
10131 pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
10132 pim_inet4_dump("<local?>", mp->local, local_str,
10133 sizeof(local_str));
10134 pim_msdp_state_dump(mp->state, state_str, sizeof(state_str));
10135 if (uj) {
10136 json_row = json_object_new_object();
10137 json_object_string_add(json_row, "peer", peer_str);
10138 json_object_string_add(json_row, "local", local_str);
10139 json_object_string_add(json_row, "state", state_str);
10140 json_object_string_add(json_row, "upTime", timebuf);
10141 json_object_int_add(json_row, "saCount", mp->sa_cnt);
10142 json_object_object_add(json, peer_str, json_row);
10143 } else {
10144 vty_out(vty, "%-15s %15s %11s %8s %6d\n", peer_str,
10145 local_str, state_str, timebuf, mp->sa_cnt);
10146 }
10147 }
10148
10149 if (uj) {
10150 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10151 json, JSON_C_TO_STRING_PRETTY));
10152 json_object_free(json);
10153 }
10154 }
10155
10156 static void ip_msdp_show_peers_detail(struct pim_instance *pim, struct vty *vty,
10157 const char *peer, bool uj)
10158 {
10159 struct listnode *mpnode;
10160 struct pim_msdp_peer *mp;
10161 char peer_str[INET_ADDRSTRLEN];
10162 char local_str[INET_ADDRSTRLEN];
10163 char state_str[PIM_MSDP_STATE_STRLEN];
10164 char timebuf[PIM_MSDP_UPTIME_STRLEN];
10165 char katimer[PIM_MSDP_TIMER_STRLEN];
10166 char crtimer[PIM_MSDP_TIMER_STRLEN];
10167 char holdtimer[PIM_MSDP_TIMER_STRLEN];
10168 int64_t now;
10169 json_object *json = NULL;
10170 json_object *json_row = NULL;
10171
10172 if (uj) {
10173 json = json_object_new_object();
10174 }
10175
10176 for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, mpnode, mp)) {
10177 pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
10178 if (strcmp(peer, "detail") && strcmp(peer, peer_str))
10179 continue;
10180
10181 if (mp->state == PIM_MSDP_ESTABLISHED) {
10182 now = pim_time_monotonic_sec();
10183 pim_time_uptime(timebuf, sizeof(timebuf),
10184 now - mp->uptime);
10185 } else {
10186 strlcpy(timebuf, "-", sizeof(timebuf));
10187 }
10188 pim_inet4_dump("<local?>", mp->local, local_str,
10189 sizeof(local_str));
10190 pim_msdp_state_dump(mp->state, state_str, sizeof(state_str));
10191 pim_time_timer_to_hhmmss(katimer, sizeof(katimer),
10192 mp->ka_timer);
10193 pim_time_timer_to_hhmmss(crtimer, sizeof(crtimer),
10194 mp->cr_timer);
10195 pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer),
10196 mp->hold_timer);
10197
10198 if (uj) {
10199 json_row = json_object_new_object();
10200 json_object_string_add(json_row, "peer", peer_str);
10201 json_object_string_add(json_row, "local", local_str);
10202 json_object_string_add(json_row, "meshGroupName",
10203 mp->mesh_group_name);
10204 json_object_string_add(json_row, "state", state_str);
10205 json_object_string_add(json_row, "upTime", timebuf);
10206 json_object_string_add(json_row, "keepAliveTimer",
10207 katimer);
10208 json_object_string_add(json_row, "connRetryTimer",
10209 crtimer);
10210 json_object_string_add(json_row, "holdTimer",
10211 holdtimer);
10212 json_object_string_add(json_row, "lastReset",
10213 mp->last_reset);
10214 json_object_int_add(json_row, "connAttempts",
10215 mp->conn_attempts);
10216 json_object_int_add(json_row, "establishedChanges",
10217 mp->est_flaps);
10218 json_object_int_add(json_row, "saCount", mp->sa_cnt);
10219 json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt);
10220 json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt);
10221 json_object_int_add(json_row, "saSent", mp->sa_tx_cnt);
10222 json_object_int_add(json_row, "saRcvd", mp->sa_rx_cnt);
10223 json_object_object_add(json, peer_str, json_row);
10224 } else {
10225 vty_out(vty, "Peer : %s\n", peer_str);
10226 vty_out(vty, " Local : %s\n", local_str);
10227 vty_out(vty, " Mesh Group : %s\n",
10228 mp->mesh_group_name);
10229 vty_out(vty, " State : %s\n", state_str);
10230 vty_out(vty, " Uptime : %s\n", timebuf);
10231
10232 vty_out(vty, " Keepalive Timer : %s\n", katimer);
10233 vty_out(vty, " Conn Retry Timer : %s\n", crtimer);
10234 vty_out(vty, " Hold Timer : %s\n", holdtimer);
10235 vty_out(vty, " Last Reset : %s\n",
10236 mp->last_reset);
10237 vty_out(vty, " Conn Attempts : %d\n",
10238 mp->conn_attempts);
10239 vty_out(vty, " Established Changes : %d\n",
10240 mp->est_flaps);
10241 vty_out(vty, " SA Count : %d\n",
10242 mp->sa_cnt);
10243 vty_out(vty, " Statistics :\n");
10244 vty_out(vty,
10245 " Sent Rcvd\n");
10246 vty_out(vty, " Keepalives : %10d %10d\n",
10247 mp->ka_tx_cnt, mp->ka_rx_cnt);
10248 vty_out(vty, " SAs : %10d %10d\n",
10249 mp->sa_tx_cnt, mp->sa_rx_cnt);
10250 vty_out(vty, "\n");
10251 }
10252 }
10253
10254 if (uj) {
10255 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10256 json, JSON_C_TO_STRING_PRETTY));
10257 json_object_free(json);
10258 }
10259 }
10260
10261 DEFUN (show_ip_msdp_peer_detail,
10262 show_ip_msdp_peer_detail_cmd,
10263 "show ip msdp [vrf NAME] peer [detail|A.B.C.D] [json]",
10264 SHOW_STR
10265 IP_STR
10266 MSDP_STR
10267 VRF_CMD_HELP_STR
10268 "MSDP peer information\n"
10269 "Detailed output\n"
10270 "peer ip address\n"
10271 JSON_STR)
10272 {
10273 bool uj = use_json(argc, argv);
10274 int idx = 2;
10275 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10276
10277 if (!vrf)
10278 return CMD_WARNING;
10279
10280 char *arg = NULL;
10281
10282 if (argv_find(argv, argc, "detail", &idx))
10283 arg = argv[idx]->text;
10284 else if (argv_find(argv, argc, "A.B.C.D", &idx))
10285 arg = argv[idx]->arg;
10286
10287 if (arg)
10288 ip_msdp_show_peers_detail(vrf->info, vty, argv[idx]->arg, uj);
10289 else
10290 ip_msdp_show_peers(vrf->info, vty, uj);
10291
10292 return CMD_SUCCESS;
10293 }
10294
10295 DEFUN (show_ip_msdp_peer_detail_vrf_all,
10296 show_ip_msdp_peer_detail_vrf_all_cmd,
10297 "show ip msdp vrf all peer [detail|A.B.C.D] [json]",
10298 SHOW_STR
10299 IP_STR
10300 MSDP_STR
10301 VRF_CMD_HELP_STR
10302 "MSDP peer information\n"
10303 "Detailed output\n"
10304 "peer ip address\n"
10305 JSON_STR)
10306 {
10307 int idx = 2;
10308 bool uj = use_json(argc, argv);
10309 struct vrf *vrf;
10310 bool first = true;
10311
10312 if (uj)
10313 vty_out(vty, "{ ");
10314 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
10315 if (uj) {
10316 if (!first)
10317 vty_out(vty, ", ");
10318 vty_out(vty, " \"%s\": ", vrf->name);
10319 first = false;
10320 } else
10321 vty_out(vty, "VRF: %s\n", vrf->name);
10322 if (argv_find(argv, argc, "detail", &idx)
10323 || argv_find(argv, argc, "A.B.C.D", &idx))
10324 ip_msdp_show_peers_detail(vrf->info, vty,
10325 argv[idx]->arg, uj);
10326 else
10327 ip_msdp_show_peers(vrf->info, vty, uj);
10328 }
10329 if (uj)
10330 vty_out(vty, "}\n");
10331
10332 return CMD_SUCCESS;
10333 }
10334
10335 static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty, bool uj)
10336 {
10337 struct listnode *sanode;
10338 struct pim_msdp_sa *sa;
10339 char src_str[INET_ADDRSTRLEN];
10340 char grp_str[INET_ADDRSTRLEN];
10341 char rp_str[INET_ADDRSTRLEN];
10342 char timebuf[PIM_MSDP_UPTIME_STRLEN];
10343 char spt_str[8];
10344 char local_str[8];
10345 int64_t now;
10346 json_object *json = NULL;
10347 json_object *json_group = NULL;
10348 json_object *json_row = NULL;
10349
10350 if (uj) {
10351 json = json_object_new_object();
10352 } else {
10353 vty_out(vty,
10354 "Source Group RP Local SPT Uptime\n");
10355 }
10356
10357 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
10358 now = pim_time_monotonic_sec();
10359 pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime);
10360 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
10361 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
10362 if (sa->flags & PIM_MSDP_SAF_PEER) {
10363 pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
10364 if (sa->up) {
10365 strlcpy(spt_str, "yes", sizeof(spt_str));
10366 } else {
10367 strlcpy(spt_str, "no", sizeof(spt_str));
10368 }
10369 } else {
10370 strlcpy(rp_str, "-", sizeof(rp_str));
10371 strlcpy(spt_str, "-", sizeof(spt_str));
10372 }
10373 if (sa->flags & PIM_MSDP_SAF_LOCAL) {
10374 strlcpy(local_str, "yes", sizeof(local_str));
10375 } else {
10376 strlcpy(local_str, "no", sizeof(local_str));
10377 }
10378 if (uj) {
10379 json_object_object_get_ex(json, grp_str, &json_group);
10380
10381 if (!json_group) {
10382 json_group = json_object_new_object();
10383 json_object_object_add(json, grp_str,
10384 json_group);
10385 }
10386
10387 json_row = json_object_new_object();
10388 json_object_string_add(json_row, "source", src_str);
10389 json_object_string_add(json_row, "group", grp_str);
10390 json_object_string_add(json_row, "rp", rp_str);
10391 json_object_string_add(json_row, "local", local_str);
10392 json_object_string_add(json_row, "sptSetup", spt_str);
10393 json_object_string_add(json_row, "upTime", timebuf);
10394 json_object_object_add(json_group, src_str, json_row);
10395 } else {
10396 vty_out(vty, "%-15s %15s %15s %5c %3c %8s\n",
10397 src_str, grp_str, rp_str, local_str[0],
10398 spt_str[0], timebuf);
10399 }
10400 }
10401
10402 if (uj) {
10403 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10404 json, JSON_C_TO_STRING_PRETTY));
10405 json_object_free(json);
10406 }
10407 }
10408
10409 static void ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa,
10410 const char *src_str,
10411 const char *grp_str, struct vty *vty,
10412 bool uj, json_object *json)
10413 {
10414 char rp_str[INET_ADDRSTRLEN];
10415 char peer_str[INET_ADDRSTRLEN];
10416 char timebuf[PIM_MSDP_UPTIME_STRLEN];
10417 char spt_str[8];
10418 char local_str[8];
10419 char statetimer[PIM_MSDP_TIMER_STRLEN];
10420 int64_t now;
10421 json_object *json_group = NULL;
10422 json_object *json_row = NULL;
10423
10424 now = pim_time_monotonic_sec();
10425 pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime);
10426 if (sa->flags & PIM_MSDP_SAF_PEER) {
10427 pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
10428 pim_inet4_dump("<peer?>", sa->peer, peer_str, sizeof(peer_str));
10429 if (sa->up) {
10430 strlcpy(spt_str, "yes", sizeof(spt_str));
10431 } else {
10432 strlcpy(spt_str, "no", sizeof(spt_str));
10433 }
10434 } else {
10435 strlcpy(rp_str, "-", sizeof(rp_str));
10436 strlcpy(peer_str, "-", sizeof(peer_str));
10437 strlcpy(spt_str, "-", sizeof(spt_str));
10438 }
10439 if (sa->flags & PIM_MSDP_SAF_LOCAL) {
10440 strlcpy(local_str, "yes", sizeof(local_str));
10441 } else {
10442 strlcpy(local_str, "no", sizeof(local_str));
10443 }
10444 pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer),
10445 sa->sa_state_timer);
10446 if (uj) {
10447 json_object_object_get_ex(json, grp_str, &json_group);
10448
10449 if (!json_group) {
10450 json_group = json_object_new_object();
10451 json_object_object_add(json, grp_str, json_group);
10452 }
10453
10454 json_row = json_object_new_object();
10455 json_object_string_add(json_row, "source", src_str);
10456 json_object_string_add(json_row, "group", grp_str);
10457 json_object_string_add(json_row, "rp", rp_str);
10458 json_object_string_add(json_row, "local", local_str);
10459 json_object_string_add(json_row, "sptSetup", spt_str);
10460 json_object_string_add(json_row, "upTime", timebuf);
10461 json_object_string_add(json_row, "stateTimer", statetimer);
10462 json_object_object_add(json_group, src_str, json_row);
10463 } else {
10464 vty_out(vty, "SA : %s\n", sa->sg_str);
10465 vty_out(vty, " RP : %s\n", rp_str);
10466 vty_out(vty, " Peer : %s\n", peer_str);
10467 vty_out(vty, " Local : %s\n", local_str);
10468 vty_out(vty, " SPT Setup : %s\n", spt_str);
10469 vty_out(vty, " Uptime : %s\n", timebuf);
10470 vty_out(vty, " State Timer : %s\n", statetimer);
10471 vty_out(vty, "\n");
10472 }
10473 }
10474
10475 static void ip_msdp_show_sa_detail(struct pim_instance *pim, struct vty *vty,
10476 bool uj)
10477 {
10478 struct listnode *sanode;
10479 struct pim_msdp_sa *sa;
10480 char src_str[INET_ADDRSTRLEN];
10481 char grp_str[INET_ADDRSTRLEN];
10482 json_object *json = NULL;
10483
10484 if (uj) {
10485 json = json_object_new_object();
10486 }
10487
10488 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
10489 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
10490 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
10491 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj,
10492 json);
10493 }
10494
10495 if (uj) {
10496 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10497 json, JSON_C_TO_STRING_PRETTY));
10498 json_object_free(json);
10499 }
10500 }
10501
10502 DEFUN (show_ip_msdp_sa_detail,
10503 show_ip_msdp_sa_detail_cmd,
10504 "show ip msdp [vrf NAME] sa detail [json]",
10505 SHOW_STR
10506 IP_STR
10507 MSDP_STR
10508 VRF_CMD_HELP_STR
10509 "MSDP active-source information\n"
10510 "Detailed output\n"
10511 JSON_STR)
10512 {
10513 bool uj = use_json(argc, argv);
10514 int idx = 2;
10515 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10516
10517 if (!vrf)
10518 return CMD_WARNING;
10519
10520 ip_msdp_show_sa_detail(vrf->info, vty, uj);
10521
10522 return CMD_SUCCESS;
10523 }
10524
10525 DEFUN (show_ip_msdp_sa_detail_vrf_all,
10526 show_ip_msdp_sa_detail_vrf_all_cmd,
10527 "show ip msdp vrf all sa detail [json]",
10528 SHOW_STR
10529 IP_STR
10530 MSDP_STR
10531 VRF_CMD_HELP_STR
10532 "MSDP active-source information\n"
10533 "Detailed output\n"
10534 JSON_STR)
10535 {
10536 bool uj = use_json(argc, argv);
10537 struct vrf *vrf;
10538 bool first = true;
10539
10540 if (uj)
10541 vty_out(vty, "{ ");
10542 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
10543 if (uj) {
10544 if (!first)
10545 vty_out(vty, ", ");
10546 vty_out(vty, " \"%s\": ", vrf->name);
10547 first = false;
10548 } else
10549 vty_out(vty, "VRF: %s\n", vrf->name);
10550 ip_msdp_show_sa_detail(vrf->info, vty, uj);
10551 }
10552 if (uj)
10553 vty_out(vty, "}\n");
10554
10555 return CMD_SUCCESS;
10556 }
10557
10558 static void ip_msdp_show_sa_addr(struct pim_instance *pim, struct vty *vty,
10559 const char *addr, bool uj)
10560 {
10561 struct listnode *sanode;
10562 struct pim_msdp_sa *sa;
10563 char src_str[INET_ADDRSTRLEN];
10564 char grp_str[INET_ADDRSTRLEN];
10565 json_object *json = NULL;
10566
10567 if (uj) {
10568 json = json_object_new_object();
10569 }
10570
10571 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
10572 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
10573 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
10574 if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) {
10575 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty,
10576 uj, json);
10577 }
10578 }
10579
10580 if (uj) {
10581 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10582 json, JSON_C_TO_STRING_PRETTY));
10583 json_object_free(json);
10584 }
10585 }
10586
10587 static void ip_msdp_show_sa_sg(struct pim_instance *pim, struct vty *vty,
10588 const char *src, const char *grp, bool uj)
10589 {
10590 struct listnode *sanode;
10591 struct pim_msdp_sa *sa;
10592 char src_str[INET_ADDRSTRLEN];
10593 char grp_str[INET_ADDRSTRLEN];
10594 json_object *json = NULL;
10595
10596 if (uj) {
10597 json = json_object_new_object();
10598 }
10599
10600 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
10601 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
10602 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
10603 if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) {
10604 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty,
10605 uj, json);
10606 }
10607 }
10608
10609 if (uj) {
10610 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10611 json, JSON_C_TO_STRING_PRETTY));
10612 json_object_free(json);
10613 }
10614 }
10615
10616 DEFUN (show_ip_msdp_sa_sg,
10617 show_ip_msdp_sa_sg_cmd,
10618 "show ip msdp [vrf NAME] sa [A.B.C.D [A.B.C.D]] [json]",
10619 SHOW_STR
10620 IP_STR
10621 MSDP_STR
10622 VRF_CMD_HELP_STR
10623 "MSDP active-source information\n"
10624 "source or group ip\n"
10625 "group ip\n"
10626 JSON_STR)
10627 {
10628 bool uj = use_json(argc, argv);
10629 struct vrf *vrf;
10630 int idx = 2;
10631
10632 vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10633
10634 if (!vrf)
10635 return CMD_WARNING;
10636
10637 char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg
10638 : NULL;
10639 char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx)
10640 ? argv[idx]->arg
10641 : NULL;
10642
10643 if (src_ip && grp_ip)
10644 ip_msdp_show_sa_sg(vrf->info, vty, src_ip, grp_ip, uj);
10645 else if (src_ip)
10646 ip_msdp_show_sa_addr(vrf->info, vty, src_ip, uj);
10647 else
10648 ip_msdp_show_sa(vrf->info, vty, uj);
10649
10650 return CMD_SUCCESS;
10651 }
10652
10653 DEFUN (show_ip_msdp_sa_sg_vrf_all,
10654 show_ip_msdp_sa_sg_vrf_all_cmd,
10655 "show ip msdp vrf all sa [A.B.C.D [A.B.C.D]] [json]",
10656 SHOW_STR
10657 IP_STR
10658 MSDP_STR
10659 VRF_CMD_HELP_STR
10660 "MSDP active-source information\n"
10661 "source or group ip\n"
10662 "group ip\n"
10663 JSON_STR)
10664 {
10665 bool uj = use_json(argc, argv);
10666 struct vrf *vrf;
10667 bool first = true;
10668 int idx = 2;
10669
10670 char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg
10671 : NULL;
10672 char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx)
10673 ? argv[idx]->arg
10674 : NULL;
10675
10676 if (uj)
10677 vty_out(vty, "{ ");
10678 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
10679 if (uj) {
10680 if (!first)
10681 vty_out(vty, ", ");
10682 vty_out(vty, " \"%s\": ", vrf->name);
10683 first = false;
10684 } else
10685 vty_out(vty, "VRF: %s\n", vrf->name);
10686
10687 if (src_ip && grp_ip)
10688 ip_msdp_show_sa_sg(vrf->info, vty, src_ip, grp_ip, uj);
10689 else if (src_ip)
10690 ip_msdp_show_sa_addr(vrf->info, vty, src_ip, uj);
10691 else
10692 ip_msdp_show_sa(vrf->info, vty, uj);
10693 }
10694 if (uj)
10695 vty_out(vty, "}\n");
10696
10697 return CMD_SUCCESS;
10698 }
10699
10700 struct pim_sg_cache_walk_data {
10701 struct vty *vty;
10702 json_object *json;
10703 json_object *json_group;
10704 struct in_addr addr;
10705 bool addr_match;
10706 };
10707
10708 static void pim_show_vxlan_sg_entry(struct pim_vxlan_sg *vxlan_sg,
10709 struct pim_sg_cache_walk_data *cwd)
10710 {
10711 struct vty *vty = cwd->vty;
10712 json_object *json = cwd->json;
10713 char src_str[INET_ADDRSTRLEN];
10714 char grp_str[INET_ADDRSTRLEN];
10715 json_object *json_row;
10716 bool installed = (vxlan_sg->up) ? true : false;
10717 const char *iif_name = vxlan_sg->iif?vxlan_sg->iif->name:"-";
10718 const char *oif_name;
10719
10720 if (pim_vxlan_is_orig_mroute(vxlan_sg))
10721 oif_name = vxlan_sg->orig_oif?vxlan_sg->orig_oif->name:"";
10722 else
10723 oif_name = vxlan_sg->term_oif?vxlan_sg->term_oif->name:"";
10724
10725 if (cwd->addr_match && (vxlan_sg->sg.src.s_addr != cwd->addr.s_addr) &&
10726 (vxlan_sg->sg.grp.s_addr != cwd->addr.s_addr)) {
10727 return;
10728 }
10729 pim_inet4_dump("<src?>", vxlan_sg->sg.src, src_str, sizeof(src_str));
10730 pim_inet4_dump("<grp?>", vxlan_sg->sg.grp, grp_str, sizeof(grp_str));
10731 if (json) {
10732 json_object_object_get_ex(json, grp_str, &cwd->json_group);
10733
10734 if (!cwd->json_group) {
10735 cwd->json_group = json_object_new_object();
10736 json_object_object_add(json, grp_str,
10737 cwd->json_group);
10738 }
10739
10740 json_row = json_object_new_object();
10741 json_object_string_add(json_row, "source", src_str);
10742 json_object_string_add(json_row, "group", grp_str);
10743 json_object_string_add(json_row, "input", iif_name);
10744 json_object_string_add(json_row, "output", oif_name);
10745 if (installed)
10746 json_object_boolean_true_add(json_row, "installed");
10747 else
10748 json_object_boolean_false_add(json_row, "installed");
10749 json_object_object_add(cwd->json_group, src_str, json_row);
10750 } else {
10751 vty_out(vty, "%-15s %-15s %-15s %-15s %-5s\n",
10752 src_str, grp_str, iif_name, oif_name,
10753 installed?"I":"");
10754 }
10755 }
10756
10757 static void pim_show_vxlan_sg_hash_entry(struct hash_bucket *backet, void *arg)
10758 {
10759 pim_show_vxlan_sg_entry((struct pim_vxlan_sg *)backet->data,
10760 (struct pim_sg_cache_walk_data *)arg);
10761 }
10762
10763 static void pim_show_vxlan_sg(struct pim_instance *pim,
10764 struct vty *vty, bool uj)
10765 {
10766 json_object *json = NULL;
10767 struct pim_sg_cache_walk_data cwd;
10768
10769 if (uj) {
10770 json = json_object_new_object();
10771 } else {
10772 vty_out(vty, "Codes: I -> installed\n");
10773 vty_out(vty,
10774 "Source Group Input Output Flags\n");
10775 }
10776
10777 memset(&cwd, 0, sizeof(cwd));
10778 cwd.vty = vty;
10779 cwd.json = json;
10780 hash_iterate(pim->vxlan.sg_hash, pim_show_vxlan_sg_hash_entry, &cwd);
10781
10782 if (uj) {
10783 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10784 json, JSON_C_TO_STRING_PRETTY));
10785 json_object_free(json);
10786 }
10787 }
10788
10789 static void pim_show_vxlan_sg_match_addr(struct pim_instance *pim,
10790 struct vty *vty, char *addr_str, bool uj)
10791 {
10792 json_object *json = NULL;
10793 struct pim_sg_cache_walk_data cwd;
10794 int result = 0;
10795
10796 memset(&cwd, 0, sizeof(cwd));
10797 result = inet_pton(AF_INET, addr_str, &cwd.addr);
10798 if (result <= 0) {
10799 vty_out(vty, "Bad address %s: errno=%d: %s\n", addr_str,
10800 errno, safe_strerror(errno));
10801 return;
10802 }
10803
10804 if (uj) {
10805 json = json_object_new_object();
10806 } else {
10807 vty_out(vty, "Codes: I -> installed\n");
10808 vty_out(vty,
10809 "Source Group Input Output Flags\n");
10810 }
10811
10812 cwd.vty = vty;
10813 cwd.json = json;
10814 cwd.addr_match = true;
10815 hash_iterate(pim->vxlan.sg_hash, pim_show_vxlan_sg_hash_entry, &cwd);
10816
10817 if (uj) {
10818 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10819 json, JSON_C_TO_STRING_PRETTY));
10820 json_object_free(json);
10821 }
10822 }
10823
10824 static void pim_show_vxlan_sg_one(struct pim_instance *pim,
10825 struct vty *vty, char *src_str, char *grp_str, bool uj)
10826 {
10827 json_object *json = NULL;
10828 struct prefix_sg sg;
10829 int result = 0;
10830 struct pim_vxlan_sg *vxlan_sg;
10831 const char *iif_name;
10832 bool installed;
10833 const char *oif_name;
10834
10835 result = inet_pton(AF_INET, src_str, &sg.src);
10836 if (result <= 0) {
10837 vty_out(vty, "Bad src address %s: errno=%d: %s\n", src_str,
10838 errno, safe_strerror(errno));
10839 return;
10840 }
10841 result = inet_pton(AF_INET, grp_str, &sg.grp);
10842 if (result <= 0) {
10843 vty_out(vty, "Bad grp address %s: errno=%d: %s\n", grp_str,
10844 errno, safe_strerror(errno));
10845 return;
10846 }
10847
10848 sg.family = AF_INET;
10849 sg.prefixlen = IPV4_MAX_BITLEN;
10850 if (uj)
10851 json = json_object_new_object();
10852
10853 vxlan_sg = pim_vxlan_sg_find(pim, &sg);
10854 if (vxlan_sg) {
10855 installed = (vxlan_sg->up) ? true : false;
10856 iif_name = vxlan_sg->iif?vxlan_sg->iif->name:"-";
10857
10858 if (pim_vxlan_is_orig_mroute(vxlan_sg))
10859 oif_name =
10860 vxlan_sg->orig_oif?vxlan_sg->orig_oif->name:"";
10861 else
10862 oif_name =
10863 vxlan_sg->term_oif?vxlan_sg->term_oif->name:"";
10864
10865 if (uj) {
10866 json_object_string_add(json, "source", src_str);
10867 json_object_string_add(json, "group", grp_str);
10868 json_object_string_add(json, "input", iif_name);
10869 json_object_string_add(json, "output", oif_name);
10870 if (installed)
10871 json_object_boolean_true_add(json, "installed");
10872 else
10873 json_object_boolean_false_add(json,
10874 "installed");
10875 } else {
10876 vty_out(vty, "SG : %s\n", vxlan_sg->sg_str);
10877 vty_out(vty, " Input : %s\n", iif_name);
10878 vty_out(vty, " Output : %s\n", oif_name);
10879 vty_out(vty, " installed : %s\n",
10880 installed?"yes":"no");
10881 }
10882 }
10883
10884 if (uj) {
10885 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10886 json, JSON_C_TO_STRING_PRETTY));
10887 json_object_free(json);
10888 }
10889 }
10890
10891 DEFUN (show_ip_pim_vxlan_sg,
10892 show_ip_pim_vxlan_sg_cmd,
10893 "show ip pim [vrf NAME] vxlan-groups [A.B.C.D [A.B.C.D]] [json]",
10894 SHOW_STR
10895 IP_STR
10896 PIM_STR
10897 VRF_CMD_HELP_STR
10898 "VxLAN BUM groups\n"
10899 "source or group ip\n"
10900 "group ip\n"
10901 JSON_STR)
10902 {
10903 bool uj = use_json(argc, argv);
10904 struct vrf *vrf;
10905 int idx = 2;
10906
10907 vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10908
10909 if (!vrf)
10910 return CMD_WARNING;
10911
10912 char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ?
10913 argv[idx++]->arg:NULL;
10914 char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx) ?
10915 argv[idx]->arg:NULL;
10916
10917 if (src_ip && grp_ip)
10918 pim_show_vxlan_sg_one(vrf->info, vty, src_ip, grp_ip, uj);
10919 else if (src_ip)
10920 pim_show_vxlan_sg_match_addr(vrf->info, vty, src_ip, uj);
10921 else
10922 pim_show_vxlan_sg(vrf->info, vty, uj);
10923
10924 return CMD_SUCCESS;
10925 }
10926
10927 static void pim_show_vxlan_sg_work(struct pim_instance *pim,
10928 struct vty *vty, bool uj)
10929 {
10930 json_object *json = NULL;
10931 struct pim_sg_cache_walk_data cwd;
10932 struct listnode *node;
10933 struct pim_vxlan_sg *vxlan_sg;
10934
10935 if (uj) {
10936 json = json_object_new_object();
10937 } else {
10938 vty_out(vty, "Codes: I -> installed\n");
10939 vty_out(vty,
10940 "Source Group Input Flags\n");
10941 }
10942
10943 memset(&cwd, 0, sizeof(cwd));
10944 cwd.vty = vty;
10945 cwd.json = json;
10946 for (ALL_LIST_ELEMENTS_RO(pim_vxlan_p->work_list, node, vxlan_sg))
10947 pim_show_vxlan_sg_entry(vxlan_sg, &cwd);
10948
10949 if (uj) {
10950 vty_out(vty, "%s\n", json_object_to_json_string_ext(
10951 json, JSON_C_TO_STRING_PRETTY));
10952 json_object_free(json);
10953 }
10954 }
10955
10956 DEFUN_HIDDEN (show_ip_pim_vxlan_sg_work,
10957 show_ip_pim_vxlan_sg_work_cmd,
10958 "show ip pim [vrf NAME] vxlan-work [json]",
10959 SHOW_STR
10960 IP_STR
10961 PIM_STR
10962 VRF_CMD_HELP_STR
10963 "VxLAN work list\n"
10964 JSON_STR)
10965 {
10966 bool uj = use_json(argc, argv);
10967 struct vrf *vrf;
10968 int idx = 2;
10969
10970 vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
10971
10972 if (!vrf)
10973 return CMD_WARNING;
10974
10975 pim_show_vxlan_sg_work(vrf->info, vty, uj);
10976
10977 return CMD_SUCCESS;
10978 }
10979
10980 DEFUN_HIDDEN (no_ip_pim_mlag,
10981 no_ip_pim_mlag_cmd,
10982 "no ip pim mlag",
10983 NO_STR
10984 IP_STR
10985 PIM_STR
10986 "MLAG\n")
10987 {
10988 struct in_addr addr;
10989
10990 addr.s_addr = 0;
10991 pim_vxlan_mlag_update(true/*mlag_enable*/,
10992 false/*peer_state*/, MLAG_ROLE_NONE,
10993 NULL/*peerlink*/, &addr);
10994
10995 return CMD_SUCCESS;
10996 }
10997
10998 DEFUN_HIDDEN (ip_pim_mlag,
10999 ip_pim_mlag_cmd,
11000 "ip pim mlag INTERFACE role [primary|secondary] state [up|down] addr A.B.C.D",
11001 IP_STR
11002 PIM_STR
11003 "MLAG\n"
11004 "peerlink sub interface\n"
11005 "MLAG role\n"
11006 "MLAG role primary\n"
11007 "MLAG role secondary\n"
11008 "peer session state\n"
11009 "peer session state up\n"
11010 "peer session state down\n"
11011 "configure PIP\n"
11012 "unique ip address\n")
11013 {
11014 struct interface *ifp;
11015 const char *peerlink;
11016 uint32_t role;
11017 int idx;
11018 bool peer_state;
11019 int result;
11020 struct in_addr reg_addr;
11021
11022 idx = 3;
11023 peerlink = argv[idx]->arg;
11024 ifp = if_lookup_by_name(peerlink, VRF_DEFAULT);
11025 if (!ifp) {
11026 vty_out(vty, "No such interface name %s\n", peerlink);
11027 return CMD_WARNING;
11028 }
11029
11030 idx += 2;
11031 if (!strcmp(argv[idx]->arg, "primary")) {
11032 role = MLAG_ROLE_PRIMARY;
11033 } else if (!strcmp(argv[idx]->arg, "secondary")) {
11034 role = MLAG_ROLE_SECONDARY;
11035 } else {
11036 vty_out(vty, "unknown MLAG role %s\n", argv[idx]->arg);
11037 return CMD_WARNING;
11038 }
11039
11040 idx += 2;
11041 if (!strcmp(argv[idx]->arg, "up")) {
11042 peer_state = true;
11043 } else if (strcmp(argv[idx]->arg, "down")) {
11044 peer_state = false;
11045 } else {
11046 vty_out(vty, "unknown MLAG state %s\n", argv[idx]->arg);
11047 return CMD_WARNING;
11048 }
11049
11050 idx += 2;
11051 result = inet_pton(AF_INET, argv[idx]->arg, &reg_addr);
11052 if (result <= 0) {
11053 vty_out(vty, "%% Bad reg address %s: errno=%d: %s\n",
11054 argv[idx]->arg,
11055 errno, safe_strerror(errno));
11056 return CMD_WARNING_CONFIG_FAILED;
11057 }
11058 pim_vxlan_mlag_update(true, peer_state, role, ifp, &reg_addr);
11059
11060 return CMD_SUCCESS;
11061 }
11062
11063 void pim_cmd_init(void)
11064 {
11065 install_node(&interface_node); /* INTERFACE_NODE */
11066 if_cmd_init();
11067
11068 install_node(&debug_node);
11069
11070 install_element(ENABLE_NODE, &pim_test_sg_keepalive_cmd);
11071
11072 install_element(CONFIG_NODE, &ip_pim_rp_cmd);
11073 install_element(VRF_NODE, &ip_pim_rp_cmd);
11074 install_element(CONFIG_NODE, &no_ip_pim_rp_cmd);
11075 install_element(VRF_NODE, &no_ip_pim_rp_cmd);
11076 install_element(CONFIG_NODE, &ip_pim_rp_prefix_list_cmd);
11077 install_element(VRF_NODE, &ip_pim_rp_prefix_list_cmd);
11078 install_element(CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd);
11079 install_element(VRF_NODE, &no_ip_pim_rp_prefix_list_cmd);
11080 install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd);
11081 install_element(VRF_NODE, &no_ip_pim_ssm_prefix_list_cmd);
11082 install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
11083 install_element(VRF_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
11084 install_element(CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd);
11085 install_element(VRF_NODE, &ip_pim_ssm_prefix_list_cmd);
11086 install_element(CONFIG_NODE, &ip_pim_register_suppress_cmd);
11087 install_element(VRF_NODE, &ip_pim_register_suppress_cmd);
11088 install_element(CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
11089 install_element(VRF_NODE, &no_ip_pim_register_suppress_cmd);
11090 install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd);
11091 install_element(VRF_NODE, &ip_pim_spt_switchover_infinity_cmd);
11092 install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
11093 install_element(VRF_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
11094 install_element(CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
11095 install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
11096 install_element(CONFIG_NODE,
11097 &no_ip_pim_spt_switchover_infinity_plist_cmd);
11098 install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd);
11099 install_element(CONFIG_NODE, &pim_register_accept_list_cmd);
11100 install_element(VRF_NODE, &pim_register_accept_list_cmd);
11101 install_element(CONFIG_NODE, &ip_pim_joinprune_time_cmd);
11102 install_element(VRF_NODE, &ip_pim_joinprune_time_cmd);
11103 install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
11104 install_element(VRF_NODE, &no_ip_pim_joinprune_time_cmd);
11105 install_element(CONFIG_NODE, &ip_pim_keep_alive_cmd);
11106 install_element(VRF_NODE, &ip_pim_keep_alive_cmd);
11107 install_element(CONFIG_NODE, &ip_pim_rp_keep_alive_cmd);
11108 install_element(VRF_NODE, &ip_pim_rp_keep_alive_cmd);
11109 install_element(CONFIG_NODE, &no_ip_pim_keep_alive_cmd);
11110 install_element(VRF_NODE, &no_ip_pim_keep_alive_cmd);
11111 install_element(CONFIG_NODE, &no_ip_pim_rp_keep_alive_cmd);
11112 install_element(VRF_NODE, &no_ip_pim_rp_keep_alive_cmd);
11113 install_element(CONFIG_NODE, &ip_pim_packets_cmd);
11114 install_element(VRF_NODE, &ip_pim_packets_cmd);
11115 install_element(CONFIG_NODE, &no_ip_pim_packets_cmd);
11116 install_element(VRF_NODE, &no_ip_pim_packets_cmd);
11117 install_element(CONFIG_NODE, &ip_pim_v6_secondary_cmd);
11118 install_element(VRF_NODE, &ip_pim_v6_secondary_cmd);
11119 install_element(CONFIG_NODE, &no_ip_pim_v6_secondary_cmd);
11120 install_element(VRF_NODE, &no_ip_pim_v6_secondary_cmd);
11121 install_element(CONFIG_NODE, &ip_ssmpingd_cmd);
11122 install_element(VRF_NODE, &ip_ssmpingd_cmd);
11123 install_element(CONFIG_NODE, &no_ip_ssmpingd_cmd);
11124 install_element(VRF_NODE, &no_ip_ssmpingd_cmd);
11125 install_element(CONFIG_NODE, &ip_msdp_peer_cmd);
11126 install_element(VRF_NODE, &ip_msdp_peer_cmd);
11127 install_element(CONFIG_NODE, &no_ip_msdp_peer_cmd);
11128 install_element(VRF_NODE, &no_ip_msdp_peer_cmd);
11129 install_element(CONFIG_NODE, &ip_pim_ecmp_cmd);
11130 install_element(VRF_NODE, &ip_pim_ecmp_cmd);
11131 install_element(CONFIG_NODE, &no_ip_pim_ecmp_cmd);
11132 install_element(VRF_NODE, &no_ip_pim_ecmp_cmd);
11133 install_element(CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd);
11134 install_element(VRF_NODE, &ip_pim_ecmp_rebalance_cmd);
11135 install_element(CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd);
11136 install_element(VRF_NODE, &no_ip_pim_ecmp_rebalance_cmd);
11137 install_element(CONFIG_NODE, &ip_pim_mlag_cmd);
11138 install_element(CONFIG_NODE, &no_ip_pim_mlag_cmd);
11139 install_element(CONFIG_NODE, &igmp_group_watermark_cmd);
11140 install_element(VRF_NODE, &igmp_group_watermark_cmd);
11141 install_element(CONFIG_NODE, &no_igmp_group_watermark_cmd);
11142 install_element(VRF_NODE, &no_igmp_group_watermark_cmd);
11143
11144 install_element(INTERFACE_NODE, &interface_ip_igmp_cmd);
11145 install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd);
11146 install_element(INTERFACE_NODE, &interface_ip_igmp_join_cmd);
11147 install_element(INTERFACE_NODE, &interface_no_ip_igmp_join_cmd);
11148 install_element(INTERFACE_NODE, &interface_ip_igmp_version_cmd);
11149 install_element(INTERFACE_NODE, &interface_no_ip_igmp_version_cmd);
11150 install_element(INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd);
11151 install_element(INTERFACE_NODE,
11152 &interface_no_ip_igmp_query_interval_cmd);
11153 install_element(INTERFACE_NODE,
11154 &interface_ip_igmp_query_max_response_time_cmd);
11155 install_element(INTERFACE_NODE,
11156 &interface_no_ip_igmp_query_max_response_time_cmd);
11157 install_element(INTERFACE_NODE,
11158 &interface_ip_igmp_query_max_response_time_dsec_cmd);
11159 install_element(INTERFACE_NODE,
11160 &interface_no_ip_igmp_query_max_response_time_dsec_cmd);
11161 install_element(INTERFACE_NODE,
11162 &interface_ip_igmp_last_member_query_count_cmd);
11163 install_element(INTERFACE_NODE,
11164 &interface_no_ip_igmp_last_member_query_count_cmd);
11165 install_element(INTERFACE_NODE,
11166 &interface_ip_igmp_last_member_query_interval_cmd);
11167 install_element(INTERFACE_NODE,
11168 &interface_no_ip_igmp_last_member_query_interval_cmd);
11169 install_element(INTERFACE_NODE, &interface_ip_pim_activeactive_cmd);
11170 install_element(INTERFACE_NODE, &interface_ip_pim_ssm_cmd);
11171 install_element(INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd);
11172 install_element(INTERFACE_NODE, &interface_ip_pim_sm_cmd);
11173 install_element(INTERFACE_NODE, &interface_no_ip_pim_sm_cmd);
11174 install_element(INTERFACE_NODE, &interface_ip_pim_cmd);
11175 install_element(INTERFACE_NODE, &interface_no_ip_pim_cmd);
11176 install_element(INTERFACE_NODE, &interface_ip_pim_drprio_cmd);
11177 install_element(INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd);
11178 install_element(INTERFACE_NODE, &interface_ip_pim_hello_cmd);
11179 install_element(INTERFACE_NODE, &interface_no_ip_pim_hello_cmd);
11180 install_element(INTERFACE_NODE, &interface_ip_pim_boundary_oil_cmd);
11181 install_element(INTERFACE_NODE, &interface_no_ip_pim_boundary_oil_cmd);
11182 install_element(INTERFACE_NODE, &interface_ip_igmp_query_generate_cmd);
11183
11184 // Static mroutes NEB
11185 install_element(INTERFACE_NODE, &interface_ip_mroute_cmd);
11186 install_element(INTERFACE_NODE, &interface_no_ip_mroute_cmd);
11187
11188 install_element(VIEW_NODE, &show_ip_igmp_interface_cmd);
11189 install_element(VIEW_NODE, &show_ip_igmp_interface_vrf_all_cmd);
11190 install_element(VIEW_NODE, &show_ip_igmp_join_cmd);
11191 install_element(VIEW_NODE, &show_ip_igmp_join_vrf_all_cmd);
11192 install_element(VIEW_NODE, &show_ip_igmp_groups_cmd);
11193 install_element(VIEW_NODE, &show_ip_igmp_groups_vrf_all_cmd);
11194 install_element(VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd);
11195 install_element(VIEW_NODE, &show_ip_igmp_sources_cmd);
11196 install_element(VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd);
11197 install_element(VIEW_NODE, &show_ip_igmp_statistics_cmd);
11198 install_element(VIEW_NODE, &show_ip_pim_assert_cmd);
11199 install_element(VIEW_NODE, &show_ip_pim_assert_internal_cmd);
11200 install_element(VIEW_NODE, &show_ip_pim_assert_metric_cmd);
11201 install_element(VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd);
11202 install_element(VIEW_NODE, &show_ip_pim_interface_traffic_cmd);
11203 install_element(VIEW_NODE, &show_ip_pim_interface_cmd);
11204 install_element(VIEW_NODE, &show_ip_pim_interface_vrf_all_cmd);
11205 install_element(VIEW_NODE, &show_ip_pim_join_cmd);
11206 install_element(VIEW_NODE, &show_ip_pim_join_vrf_all_cmd);
11207 install_element(VIEW_NODE, &show_ip_pim_jp_agg_cmd);
11208 install_element(VIEW_NODE, &show_ip_pim_local_membership_cmd);
11209 install_element(VIEW_NODE, &show_ip_pim_mlag_summary_cmd);
11210 install_element(VIEW_NODE, &show_ip_pim_mlag_up_cmd);
11211 install_element(VIEW_NODE, &show_ip_pim_mlag_up_vrf_all_cmd);
11212 install_element(VIEW_NODE, &show_ip_pim_neighbor_cmd);
11213 install_element(VIEW_NODE, &show_ip_pim_neighbor_vrf_all_cmd);
11214 install_element(VIEW_NODE, &show_ip_pim_rpf_cmd);
11215 install_element(VIEW_NODE, &show_ip_pim_rpf_vrf_all_cmd);
11216 install_element(VIEW_NODE, &show_ip_pim_secondary_cmd);
11217 install_element(VIEW_NODE, &show_ip_pim_state_cmd);
11218 install_element(VIEW_NODE, &show_ip_pim_state_vrf_all_cmd);
11219 install_element(VIEW_NODE, &show_ip_pim_upstream_cmd);
11220 install_element(VIEW_NODE, &show_ip_pim_upstream_vrf_all_cmd);
11221 install_element(VIEW_NODE, &show_ip_pim_channel_cmd);
11222 install_element(VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd);
11223 install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd);
11224 install_element(VIEW_NODE, &show_ip_pim_rp_cmd);
11225 install_element(VIEW_NODE, &show_ip_pim_rp_vrf_all_cmd);
11226 install_element(VIEW_NODE, &show_ip_pim_bsr_cmd);
11227 install_element(VIEW_NODE, &show_ip_multicast_cmd);
11228 install_element(VIEW_NODE, &show_ip_multicast_vrf_all_cmd);
11229 install_element(VIEW_NODE, &show_ip_multicast_count_cmd);
11230 install_element(VIEW_NODE, &show_ip_multicast_count_vrf_all_cmd);
11231 install_element(VIEW_NODE, &show_ip_mroute_cmd);
11232 install_element(VIEW_NODE, &show_ip_mroute_vrf_all_cmd);
11233 install_element(VIEW_NODE, &show_ip_mroute_count_cmd);
11234 install_element(VIEW_NODE, &show_ip_mroute_count_vrf_all_cmd);
11235 install_element(VIEW_NODE, &show_ip_mroute_summary_cmd);
11236 install_element(VIEW_NODE, &show_ip_mroute_summary_vrf_all_cmd);
11237 install_element(VIEW_NODE, &show_ip_rib_cmd);
11238 install_element(VIEW_NODE, &show_ip_ssmpingd_cmd);
11239 install_element(VIEW_NODE, &show_ip_pim_nexthop_cmd);
11240 install_element(VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd);
11241 install_element(VIEW_NODE, &show_ip_pim_bsrp_cmd);
11242 install_element(VIEW_NODE, &show_ip_pim_bsm_db_cmd);
11243 install_element(VIEW_NODE, &show_ip_pim_statistics_cmd);
11244
11245 install_element(ENABLE_NODE, &clear_ip_mroute_count_cmd);
11246 install_element(ENABLE_NODE, &clear_ip_interfaces_cmd);
11247 install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd);
11248 install_element(ENABLE_NODE, &clear_ip_mroute_cmd);
11249 install_element(ENABLE_NODE, &clear_ip_pim_interfaces_cmd);
11250 install_element(ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd);
11251 install_element(ENABLE_NODE, &clear_ip_pim_oil_cmd);
11252 install_element(ENABLE_NODE, &clear_ip_pim_statistics_cmd);
11253
11254 install_element(ENABLE_NODE, &show_debugging_pim_cmd);
11255
11256 install_element(ENABLE_NODE, &debug_igmp_cmd);
11257 install_element(ENABLE_NODE, &no_debug_igmp_cmd);
11258 install_element(ENABLE_NODE, &debug_igmp_events_cmd);
11259 install_element(ENABLE_NODE, &no_debug_igmp_events_cmd);
11260 install_element(ENABLE_NODE, &debug_igmp_packets_cmd);
11261 install_element(ENABLE_NODE, &no_debug_igmp_packets_cmd);
11262 install_element(ENABLE_NODE, &debug_igmp_trace_cmd);
11263 install_element(ENABLE_NODE, &no_debug_igmp_trace_cmd);
11264 install_element(ENABLE_NODE, &debug_mroute_cmd);
11265 install_element(ENABLE_NODE, &debug_mroute_detail_cmd);
11266 install_element(ENABLE_NODE, &no_debug_mroute_cmd);
11267 install_element(ENABLE_NODE, &no_debug_mroute_detail_cmd);
11268 install_element(ENABLE_NODE, &debug_pim_static_cmd);
11269 install_element(ENABLE_NODE, &no_debug_pim_static_cmd);
11270 install_element(ENABLE_NODE, &debug_pim_cmd);
11271 install_element(ENABLE_NODE, &no_debug_pim_cmd);
11272 install_element(ENABLE_NODE, &debug_pim_nht_cmd);
11273 install_element(ENABLE_NODE, &no_debug_pim_nht_cmd);
11274 install_element(ENABLE_NODE, &debug_pim_nht_rp_cmd);
11275 install_element(ENABLE_NODE, &no_debug_pim_nht_rp_cmd);
11276 install_element(ENABLE_NODE, &debug_pim_events_cmd);
11277 install_element(ENABLE_NODE, &no_debug_pim_events_cmd);
11278 install_element(ENABLE_NODE, &debug_pim_packets_cmd);
11279 install_element(ENABLE_NODE, &no_debug_pim_packets_cmd);
11280 install_element(ENABLE_NODE, &debug_pim_packetdump_send_cmd);
11281 install_element(ENABLE_NODE, &no_debug_pim_packetdump_send_cmd);
11282 install_element(ENABLE_NODE, &debug_pim_packetdump_recv_cmd);
11283 install_element(ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd);
11284 install_element(ENABLE_NODE, &debug_pim_trace_cmd);
11285 install_element(ENABLE_NODE, &no_debug_pim_trace_cmd);
11286 install_element(ENABLE_NODE, &debug_pim_trace_detail_cmd);
11287 install_element(ENABLE_NODE, &no_debug_pim_trace_detail_cmd);
11288 install_element(ENABLE_NODE, &debug_ssmpingd_cmd);
11289 install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd);
11290 install_element(ENABLE_NODE, &debug_pim_zebra_cmd);
11291 install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd);
11292 install_element(ENABLE_NODE, &debug_pim_mlag_cmd);
11293 install_element(ENABLE_NODE, &no_debug_pim_mlag_cmd);
11294 install_element(ENABLE_NODE, &debug_pim_vxlan_cmd);
11295 install_element(ENABLE_NODE, &no_debug_pim_vxlan_cmd);
11296 install_element(ENABLE_NODE, &debug_msdp_cmd);
11297 install_element(ENABLE_NODE, &no_debug_msdp_cmd);
11298 install_element(ENABLE_NODE, &debug_msdp_events_cmd);
11299 install_element(ENABLE_NODE, &no_debug_msdp_events_cmd);
11300 install_element(ENABLE_NODE, &debug_msdp_packets_cmd);
11301 install_element(ENABLE_NODE, &no_debug_msdp_packets_cmd);
11302 install_element(ENABLE_NODE, &debug_mtrace_cmd);
11303 install_element(ENABLE_NODE, &no_debug_mtrace_cmd);
11304 install_element(ENABLE_NODE, &debug_bsm_cmd);
11305 install_element(ENABLE_NODE, &no_debug_bsm_cmd);
11306
11307 install_element(CONFIG_NODE, &debug_igmp_cmd);
11308 install_element(CONFIG_NODE, &no_debug_igmp_cmd);
11309 install_element(CONFIG_NODE, &debug_igmp_events_cmd);
11310 install_element(CONFIG_NODE, &no_debug_igmp_events_cmd);
11311 install_element(CONFIG_NODE, &debug_igmp_packets_cmd);
11312 install_element(CONFIG_NODE, &no_debug_igmp_packets_cmd);
11313 install_element(CONFIG_NODE, &debug_igmp_trace_cmd);
11314 install_element(CONFIG_NODE, &no_debug_igmp_trace_cmd);
11315 install_element(CONFIG_NODE, &debug_mroute_cmd);
11316 install_element(CONFIG_NODE, &debug_mroute_detail_cmd);
11317 install_element(CONFIG_NODE, &no_debug_mroute_cmd);
11318 install_element(CONFIG_NODE, &no_debug_mroute_detail_cmd);
11319 install_element(CONFIG_NODE, &debug_pim_static_cmd);
11320 install_element(CONFIG_NODE, &no_debug_pim_static_cmd);
11321 install_element(CONFIG_NODE, &debug_pim_cmd);
11322 install_element(CONFIG_NODE, &no_debug_pim_cmd);
11323 install_element(CONFIG_NODE, &debug_pim_nht_cmd);
11324 install_element(CONFIG_NODE, &no_debug_pim_nht_cmd);
11325 install_element(CONFIG_NODE, &debug_pim_nht_rp_cmd);
11326 install_element(CONFIG_NODE, &no_debug_pim_nht_rp_cmd);
11327 install_element(CONFIG_NODE, &debug_pim_events_cmd);
11328 install_element(CONFIG_NODE, &no_debug_pim_events_cmd);
11329 install_element(CONFIG_NODE, &debug_pim_packets_cmd);
11330 install_element(CONFIG_NODE, &no_debug_pim_packets_cmd);
11331 install_element(CONFIG_NODE, &debug_pim_trace_cmd);
11332 install_element(CONFIG_NODE, &no_debug_pim_trace_cmd);
11333 install_element(CONFIG_NODE, &debug_pim_trace_detail_cmd);
11334 install_element(CONFIG_NODE, &no_debug_pim_trace_detail_cmd);
11335 install_element(CONFIG_NODE, &debug_ssmpingd_cmd);
11336 install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd);
11337 install_element(CONFIG_NODE, &debug_pim_zebra_cmd);
11338 install_element(CONFIG_NODE, &no_debug_pim_zebra_cmd);
11339 install_element(CONFIG_NODE, &debug_pim_mlag_cmd);
11340 install_element(CONFIG_NODE, &no_debug_pim_mlag_cmd);
11341 install_element(CONFIG_NODE, &debug_pim_vxlan_cmd);
11342 install_element(CONFIG_NODE, &no_debug_pim_vxlan_cmd);
11343 install_element(CONFIG_NODE, &debug_msdp_cmd);
11344 install_element(CONFIG_NODE, &no_debug_msdp_cmd);
11345 install_element(CONFIG_NODE, &debug_msdp_events_cmd);
11346 install_element(CONFIG_NODE, &no_debug_msdp_events_cmd);
11347 install_element(CONFIG_NODE, &debug_msdp_packets_cmd);
11348 install_element(CONFIG_NODE, &no_debug_msdp_packets_cmd);
11349 install_element(CONFIG_NODE, &debug_mtrace_cmd);
11350 install_element(CONFIG_NODE, &no_debug_mtrace_cmd);
11351 install_element(CONFIG_NODE, &debug_bsm_cmd);
11352 install_element(CONFIG_NODE, &no_debug_bsm_cmd);
11353
11354 install_element(CONFIG_NODE, &ip_msdp_mesh_group_member_cmd);
11355 install_element(VRF_NODE, &ip_msdp_mesh_group_member_cmd);
11356 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd);
11357 install_element(VRF_NODE, &no_ip_msdp_mesh_group_member_cmd);
11358 install_element(CONFIG_NODE, &ip_msdp_mesh_group_source_cmd);
11359 install_element(VRF_NODE, &ip_msdp_mesh_group_source_cmd);
11360 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd);
11361 install_element(VRF_NODE, &no_ip_msdp_mesh_group_source_cmd);
11362 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_cmd);
11363 install_element(VRF_NODE, &no_ip_msdp_mesh_group_cmd);
11364 install_element(VIEW_NODE, &show_ip_msdp_peer_detail_cmd);
11365 install_element(VIEW_NODE, &show_ip_msdp_peer_detail_vrf_all_cmd);
11366 install_element(VIEW_NODE, &show_ip_msdp_sa_detail_cmd);
11367 install_element(VIEW_NODE, &show_ip_msdp_sa_detail_vrf_all_cmd);
11368 install_element(VIEW_NODE, &show_ip_msdp_sa_sg_cmd);
11369 install_element(VIEW_NODE, &show_ip_msdp_sa_sg_vrf_all_cmd);
11370 install_element(VIEW_NODE, &show_ip_msdp_mesh_group_cmd);
11371 install_element(VIEW_NODE, &show_ip_msdp_mesh_group_vrf_all_cmd);
11372 install_element(VIEW_NODE, &show_ip_pim_ssm_range_cmd);
11373 install_element(VIEW_NODE, &show_ip_pim_group_type_cmd);
11374 install_element(VIEW_NODE, &show_ip_pim_vxlan_sg_cmd);
11375 install_element(VIEW_NODE, &show_ip_pim_vxlan_sg_work_cmd);
11376 install_element(INTERFACE_NODE, &interface_pim_use_source_cmd);
11377 install_element(INTERFACE_NODE, &interface_no_pim_use_source_cmd);
11378 /* Install BSM command */
11379 install_element(INTERFACE_NODE, &ip_pim_bsm_cmd);
11380 install_element(INTERFACE_NODE, &no_ip_pim_bsm_cmd);
11381 install_element(INTERFACE_NODE, &ip_pim_ucast_bsm_cmd);
11382 install_element(INTERFACE_NODE, &no_ip_pim_ucast_bsm_cmd);
11383 /* Install BFD command */
11384 install_element(INTERFACE_NODE, &ip_pim_bfd_cmd);
11385 install_element(INTERFACE_NODE, &ip_pim_bfd_param_cmd);
11386 install_element(INTERFACE_NODE, &no_ip_pim_bfd_cmd);
11387 #if HAVE_BFDD == 0
11388 install_element(INTERFACE_NODE, &no_ip_pim_bfd_param_cmd);
11389 #endif /* !HAVE_BFDD */
11390 }