]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_cmd.c
*: use rb-trees to store interfaces instead of sorted linked-lists
[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 "bfd.h"
64
65 static struct cmd_node pim_global_node = {
66 PIM_NODE, "", 1 /* vtysh ? yes */
67 };
68
69 static struct cmd_node interface_node = {
70 INTERFACE_NODE, "%s(config-if)# ", 1 /* vtysh ? yes */
71 };
72
73 static struct cmd_node debug_node = {DEBUG_NODE, "", 1};
74
75 static struct vrf *pim_cmd_lookup_vrf(struct vty *vty, struct cmd_token *argv[],
76 const int argc, int *idx)
77 {
78 struct vrf *vrf;
79
80 if (argv_find(argv, argc, "NAME", idx))
81 vrf = vrf_lookup_by_name(argv[*idx]->arg);
82 else
83 vrf = vrf_lookup_by_id(VRF_DEFAULT);
84
85 if (!vrf)
86 vty_out(vty, "Specified VRF: %s does not exist\n",
87 argv[*idx]->arg);
88
89 return vrf;
90 }
91
92 static void pim_if_membership_clear(struct interface *ifp)
93 {
94 struct pim_interface *pim_ifp;
95
96 pim_ifp = ifp->info;
97 zassert(pim_ifp);
98
99 if (PIM_IF_TEST_PIM(pim_ifp->options)
100 && PIM_IF_TEST_IGMP(pim_ifp->options)) {
101 return;
102 }
103
104 pim_ifchannel_membership_clear(ifp);
105 }
106
107 /*
108 When PIM is disabled on interface, IGMPv3 local membership
109 information is not injected into PIM interface state.
110
111 The function pim_if_membership_refresh() fetches all IGMPv3 local
112 membership information into PIM. It is intented to be called
113 whenever PIM is enabled on the interface in order to collect missed
114 local membership information.
115 */
116 static void pim_if_membership_refresh(struct interface *ifp)
117 {
118 struct pim_interface *pim_ifp;
119 struct listnode *sock_node;
120 struct igmp_sock *igmp;
121
122 pim_ifp = ifp->info;
123 zassert(pim_ifp);
124
125 if (!PIM_IF_TEST_PIM(pim_ifp->options))
126 return;
127 if (!PIM_IF_TEST_IGMP(pim_ifp->options))
128 return;
129
130 /*
131 First clear off membership from all PIM (S,G) entries on the
132 interface
133 */
134
135 pim_ifchannel_membership_clear(ifp);
136
137 /*
138 Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on
139 the interface
140 */
141
142 /* scan igmp sockets */
143 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
144 struct listnode *grpnode;
145 struct igmp_group *grp;
146
147 /* scan igmp groups */
148 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode,
149 grp)) {
150 struct listnode *srcnode;
151 struct igmp_source *src;
152
153 /* scan group sources */
154 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list,
155 srcnode, src)) {
156
157 if (IGMP_SOURCE_TEST_FORWARDING(
158 src->source_flags)) {
159 struct prefix_sg sg;
160
161 memset(&sg, 0,
162 sizeof(struct prefix_sg));
163 sg.src = src->source_addr;
164 sg.grp = grp->group_addr;
165 pim_ifchannel_local_membership_add(ifp,
166 &sg);
167 }
168
169 } /* scan group sources */
170 } /* scan igmp groups */
171 } /* scan igmp sockets */
172
173 /*
174 Finally delete every PIM (S,G) entry lacking all state info
175 */
176
177 pim_ifchannel_delete_on_noinfo(ifp);
178 }
179
180 static void pim_show_assert_helper(struct vty *vty,
181 struct pim_interface *pim_ifp,
182 struct pim_ifchannel *ch,
183 time_t now)
184 {
185 char ch_src_str[INET_ADDRSTRLEN];
186 char ch_grp_str[INET_ADDRSTRLEN];
187 char winner_str[INET_ADDRSTRLEN];
188 struct in_addr ifaddr;
189 char uptime[10];
190 char timer[10];
191
192 ifaddr = pim_ifp->primary_address;
193
194 pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
195 sizeof(ch_src_str));
196 pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
197 sizeof(ch_grp_str));
198 pim_inet4_dump("<assrt_win?>", ch->ifassert_winner, winner_str,
199 sizeof(winner_str));
200
201 pim_time_uptime(uptime, sizeof(uptime),
202 now - ch->ifassert_creation);
203 pim_time_timer_to_mmss(timer, sizeof(timer),
204 ch->t_ifassert_timer);
205
206 vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n",
207 ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
208 ch_grp_str,
209 pim_ifchannel_ifassert_name(ch->ifassert_state),
210 winner_str, uptime, timer);
211 }
212
213 static void pim_show_assert(struct pim_instance *pim, struct vty *vty)
214 {
215 struct pim_interface *pim_ifp;
216 struct pim_ifchannel *ch;
217 struct interface *ifp;
218 time_t now;
219
220 now = pim_time_monotonic_sec();
221
222 vty_out(vty,
223 "Interface Address Source Group State Winner Uptime Timer\n");
224
225 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
226 pim_ifp = ifp->info;
227 if (!pim_ifp)
228 continue;
229
230 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
231 pim_show_assert_helper(vty, pim_ifp, ch, now);
232 } /* scan interface channels */
233 }
234 }
235
236 static void pim_show_assert_internal_helper(struct vty *vty,
237 struct pim_interface *pim_ifp,
238 struct pim_ifchannel *ch)
239 {
240 char ch_src_str[INET_ADDRSTRLEN];
241 char ch_grp_str[INET_ADDRSTRLEN];
242 struct in_addr ifaddr;
243
244 ifaddr = pim_ifp->primary_address;
245
246 pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
247 sizeof(ch_src_str));
248 pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
249 sizeof(ch_grp_str));
250 vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n",
251 ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
252 ch_grp_str,
253 PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no",
254 pim_macro_ch_could_assert_eval(ch) ? "yes" : "no",
255 PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags)
256 ? "yes"
257 : "no",
258 pim_macro_assert_tracking_desired_eval(ch) ? "yes"
259 : "no");
260 }
261
262 static void pim_show_assert_internal(struct pim_instance *pim, struct vty *vty)
263 {
264 struct pim_interface *pim_ifp;
265 struct pim_ifchannel *ch;
266 struct interface *ifp;
267
268 vty_out(vty,
269 "CA: CouldAssert\n"
270 "ECA: Evaluate CouldAssert\n"
271 "ATD: AssertTrackingDesired\n"
272 "eATD: Evaluate AssertTrackingDesired\n\n");
273
274 vty_out(vty,
275 "Interface Address Source Group CA eCA ATD eATD\n");
276 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
277 pim_ifp = ifp->info;
278 if (!pim_ifp)
279 continue;
280
281 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
282 pim_show_assert_internal_helper(vty, pim_ifp, ch);
283 } /* scan interface channels */
284 }
285 }
286
287 static void pim_show_assert_metric_helper(struct vty *vty,
288 struct pim_interface *pim_ifp,
289 struct pim_ifchannel *ch)
290 {
291 char ch_src_str[INET_ADDRSTRLEN];
292 char ch_grp_str[INET_ADDRSTRLEN];
293 char addr_str[INET_ADDRSTRLEN];
294 struct pim_assert_metric am;
295 struct in_addr ifaddr;
296
297 ifaddr = pim_ifp->primary_address;
298
299 am = pim_macro_spt_assert_metric(&ch->upstream->rpf,
300 pim_ifp->primary_address);
301
302 pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
303 sizeof(ch_src_str));
304 pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
305 sizeof(ch_grp_str));
306 pim_inet4_dump("<addr?>", am.ip_address, addr_str,
307 sizeof(addr_str));
308
309 vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s\n",
310 ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
311 ch_grp_str, am.rpt_bit_flag ? "yes" : "no",
312 am.metric_preference, am.route_metric, addr_str);
313 }
314
315 static void pim_show_assert_metric(struct pim_instance *pim, struct vty *vty)
316 {
317 struct pim_interface *pim_ifp;
318 struct pim_ifchannel *ch;
319 struct interface *ifp;
320
321 vty_out(vty,
322 "Interface Address Source Group RPT Pref Metric Address \n");
323
324 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
325 pim_ifp = ifp->info;
326 if (!pim_ifp)
327 continue;
328
329 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
330 pim_show_assert_metric_helper(vty, pim_ifp, ch);
331 } /* scan interface channels */
332 }
333 }
334
335 static void pim_show_assert_winner_metric_helper(struct vty *vty,
336 struct pim_interface *pim_ifp,
337 struct pim_ifchannel *ch)
338 {
339 char ch_src_str[INET_ADDRSTRLEN];
340 char ch_grp_str[INET_ADDRSTRLEN];
341 char addr_str[INET_ADDRSTRLEN];
342 struct pim_assert_metric *am;
343 struct in_addr ifaddr;
344 char pref_str[5];
345 char metr_str[7];
346
347 ifaddr = pim_ifp->primary_address;
348
349 am = &ch->ifassert_winner_metric;
350
351 pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
352 sizeof(ch_src_str));
353 pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
354 sizeof(ch_grp_str));
355 pim_inet4_dump("<addr?>", am->ip_address, addr_str,
356 sizeof(addr_str));
357
358 if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX)
359 snprintf(pref_str, sizeof(pref_str), "INFI");
360 else
361 snprintf(pref_str, sizeof(pref_str), "%4u",
362 am->metric_preference);
363
364 if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX)
365 snprintf(metr_str, sizeof(metr_str), "INFI");
366 else
367 snprintf(metr_str, sizeof(metr_str), "%6u",
368 am->route_metric);
369
370 vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n",
371 ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
372 ch_grp_str, am->rpt_bit_flag ? "yes" : "no", pref_str,
373 metr_str, addr_str);
374 }
375
376 static void pim_show_assert_winner_metric(struct pim_instance *pim,
377 struct vty *vty)
378 {
379 struct pim_interface *pim_ifp;
380 struct pim_ifchannel *ch;
381 struct interface *ifp;
382
383 vty_out(vty,
384 "Interface Address Source Group RPT Pref Metric Address \n");
385
386 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
387 pim_ifp = ifp->info;
388 if (!pim_ifp)
389 continue;
390
391 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
392 pim_show_assert_winner_metric_helper(vty, pim_ifp, ch);
393 } /* scan interface channels */
394 }
395 }
396
397 static void json_object_pim_ifp_add(struct json_object *json,
398 struct interface *ifp)
399 {
400 struct pim_interface *pim_ifp;
401
402 pim_ifp = ifp->info;
403 json_object_string_add(json, "name", ifp->name);
404 json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down");
405 json_object_string_add(json, "address",
406 inet_ntoa(pim_ifp->primary_address));
407 json_object_int_add(json, "index", ifp->ifindex);
408
409 if (if_is_multicast(ifp))
410 json_object_boolean_true_add(json, "flagMulticast");
411
412 if (if_is_broadcast(ifp))
413 json_object_boolean_true_add(json, "flagBroadcast");
414
415 if (ifp->flags & IFF_ALLMULTI)
416 json_object_boolean_true_add(json, "flagAllMulticast");
417
418 if (ifp->flags & IFF_PROMISC)
419 json_object_boolean_true_add(json, "flagPromiscuous");
420
421 if (PIM_IF_IS_DELETED(ifp))
422 json_object_boolean_true_add(json, "flagDeleted");
423
424 if (pim_if_lan_delay_enabled(ifp))
425 json_object_boolean_true_add(json, "lanDelayEnabled");
426 }
427
428 static void pim_show_membership_helper(struct vty *vty,
429 struct pim_interface *pim_ifp,
430 struct pim_ifchannel *ch,
431 struct json_object *json)
432 {
433 char ch_src_str[INET_ADDRSTRLEN];
434 char ch_grp_str[INET_ADDRSTRLEN];
435 json_object *json_iface = NULL;
436 json_object *json_row = NULL;
437
438 pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
439 sizeof(ch_src_str));
440 pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
441 sizeof(ch_grp_str));
442
443 json_object_object_get_ex(json, ch->interface->name,
444 &json_iface);
445 if (!json_iface) {
446 json_iface = json_object_new_object();
447 json_object_pim_ifp_add(json_iface, ch->interface);
448 json_object_object_add(json, ch->interface->name,
449 json_iface);
450 }
451
452 json_row = json_object_new_object();
453 json_object_string_add(json_row, "source", ch_src_str);
454 json_object_string_add(json_row, "group", ch_grp_str);
455 json_object_string_add(
456 json_row, "localMembership",
457 ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO
458 ? "NOINFO"
459 : "INCLUDE");
460 json_object_object_add(json_iface, ch_grp_str, json_row);
461
462 }
463 static void pim_show_membership(struct pim_instance *pim, struct vty *vty,
464 u_char uj)
465 {
466 struct pim_interface *pim_ifp;
467 struct pim_ifchannel *ch;
468 struct interface *ifp;
469 enum json_type type;
470 json_object *json = NULL;
471 json_object *json_tmp = NULL;
472
473 json = json_object_new_object();
474
475 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
476 pim_ifp = ifp->info;
477 if (!pim_ifp)
478 continue;
479
480 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
481 pim_show_membership_helper(vty, pim_ifp, ch, json);
482 } /* scan interface channels */
483 }
484
485 if (uj) {
486 vty_out(vty, "%s\n", json_object_to_json_string_ext(
487 json, JSON_C_TO_STRING_PRETTY));
488 } else {
489 vty_out(vty,
490 "Interface Address Source Group Membership\n");
491
492 /*
493 * Example of the json data we are traversing
494 *
495 * {
496 * "swp3":{
497 * "name":"swp3",
498 * "state":"up",
499 * "address":"10.1.20.1",
500 * "index":5,
501 * "flagMulticast":true,
502 * "flagBroadcast":true,
503 * "lanDelayEnabled":true,
504 * "226.10.10.10":{
505 * "source":"*",
506 * "group":"226.10.10.10",
507 * "localMembership":"INCLUDE"
508 * }
509 * }
510 * }
511 */
512
513 /* foreach interface */
514 json_object_object_foreach(json, key, val)
515 {
516
517 /* Find all of the keys where the val is an object. In
518 * the example
519 * above the only one is 226.10.10.10
520 */
521 json_object_object_foreach(val, if_field_key,
522 if_field_val)
523 {
524 type = json_object_get_type(if_field_val);
525
526 if (type == json_type_object) {
527 vty_out(vty, "%-9s ", key);
528
529 json_object_object_get_ex(
530 val, "address", &json_tmp);
531 vty_out(vty, "%-15s ",
532 json_object_get_string(
533 json_tmp));
534
535 json_object_object_get_ex(if_field_val,
536 "source",
537 &json_tmp);
538 vty_out(vty, "%-15s ",
539 json_object_get_string(
540 json_tmp));
541
542 /* Group */
543 vty_out(vty, "%-15s ", if_field_key);
544
545 json_object_object_get_ex(
546 if_field_val, "localMembership",
547 &json_tmp);
548 vty_out(vty, "%-10s\n",
549 json_object_get_string(
550 json_tmp));
551 }
552 }
553 }
554 }
555
556 json_object_free(json);
557 }
558
559 static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp,
560 int mloop)
561 {
562 vty_out(vty, "Flags\n");
563 vty_out(vty, "-----\n");
564 vty_out(vty, "All Multicast : %s\n",
565 (ifp->flags & IFF_ALLMULTI) ? "yes" : "no");
566 vty_out(vty, "Broadcast : %s\n",
567 if_is_broadcast(ifp) ? "yes" : "no");
568 vty_out(vty, "Deleted : %s\n",
569 PIM_IF_IS_DELETED(ifp) ? "yes" : "no");
570 vty_out(vty, "Interface Index : %d\n", ifp->ifindex);
571 vty_out(vty, "Multicast : %s\n",
572 if_is_multicast(ifp) ? "yes" : "no");
573 vty_out(vty, "Multicast Loop : %d\n", mloop);
574 vty_out(vty, "Promiscuous : %s\n",
575 (ifp->flags & IFF_PROMISC) ? "yes" : "no");
576 vty_out(vty, "\n");
577 vty_out(vty, "\n");
578 }
579
580 static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
581 u_char uj)
582 {
583 struct interface *ifp;
584 time_t now;
585 json_object *json = NULL;
586 json_object *json_row = NULL;
587
588 now = pim_time_monotonic_sec();
589
590 if (uj)
591 json = json_object_new_object();
592 else
593 vty_out(vty,
594 "Interface State Address V Querier Query Timer Uptime\n");
595
596 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
597 struct pim_interface *pim_ifp;
598 struct listnode *sock_node;
599 struct igmp_sock *igmp;
600
601 pim_ifp = ifp->info;
602
603 if (!pim_ifp)
604 continue;
605
606 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
607 igmp)) {
608 char uptime[10];
609 char query_hhmmss[10];
610
611 pim_time_uptime(uptime, sizeof(uptime),
612 now - igmp->sock_creation);
613 pim_time_timer_to_hhmmss(query_hhmmss,
614 sizeof(query_hhmmss),
615 igmp->t_igmp_query_timer);
616
617 if (uj) {
618 json_row = json_object_new_object();
619 json_object_pim_ifp_add(json_row, ifp);
620 json_object_string_add(json_row, "upTime",
621 uptime);
622 json_object_int_add(json_row, "version",
623 pim_ifp->igmp_version);
624
625 if (igmp->t_igmp_query_timer) {
626 json_object_boolean_true_add(json_row,
627 "querier");
628 json_object_string_add(json_row,
629 "queryTimer",
630 query_hhmmss);
631 }
632
633 json_object_object_add(json, ifp->name,
634 json_row);
635
636 } else {
637 vty_out(vty,
638 "%-9s %5s %15s %d %7s %11s %8s\n",
639 ifp->name,
640 if_is_up(ifp) ? "up" : "down",
641 inet_ntoa(igmp->ifaddr),
642 pim_ifp->igmp_version,
643 igmp->t_igmp_query_timer ? "local"
644 : "other",
645 query_hhmmss, uptime);
646 }
647 }
648 }
649
650 if (uj) {
651 vty_out(vty, "%s\n", json_object_to_json_string_ext(
652 json, JSON_C_TO_STRING_PRETTY));
653 json_object_free(json);
654 }
655 }
656
657 static void igmp_show_interfaces_single(struct pim_instance *pim,
658 struct vty *vty, const char *ifname,
659 u_char uj)
660 {
661 struct igmp_sock *igmp;
662 struct interface *ifp;
663 struct listnode *sock_node;
664 struct pim_interface *pim_ifp;
665 char uptime[10];
666 char query_hhmmss[10];
667 char other_hhmmss[10];
668 int found_ifname = 0;
669 int sqi;
670 int mloop = 0;
671 long gmi_msec; /* Group Membership Interval */
672 long lmqt_msec;
673 long ohpi_msec;
674 long oqpi_msec; /* Other Querier Present Interval */
675 long qri_msec;
676 time_t now;
677
678 json_object *json = NULL;
679 json_object *json_row = NULL;
680
681 if (uj)
682 json = json_object_new_object();
683
684 now = pim_time_monotonic_sec();
685
686 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
687 pim_ifp = ifp->info;
688
689 if (!pim_ifp)
690 continue;
691
692 if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
693 continue;
694
695 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
696 igmp)) {
697 found_ifname = 1;
698 pim_time_uptime(uptime, sizeof(uptime),
699 now - igmp->sock_creation);
700 pim_time_timer_to_hhmmss(query_hhmmss,
701 sizeof(query_hhmmss),
702 igmp->t_igmp_query_timer);
703 pim_time_timer_to_hhmmss(other_hhmmss,
704 sizeof(other_hhmmss),
705 igmp->t_other_querier_timer);
706
707 gmi_msec = PIM_IGMP_GMI_MSEC(
708 igmp->querier_robustness_variable,
709 igmp->querier_query_interval,
710 pim_ifp->igmp_query_max_response_time_dsec);
711
712 sqi = PIM_IGMP_SQI(
713 pim_ifp->igmp_default_query_interval);
714
715 oqpi_msec = PIM_IGMP_OQPI_MSEC(
716 igmp->querier_robustness_variable,
717 igmp->querier_query_interval,
718 pim_ifp->igmp_query_max_response_time_dsec);
719
720 lmqt_msec = PIM_IGMP_LMQT_MSEC(
721 pim_ifp->igmp_query_max_response_time_dsec,
722 igmp->querier_robustness_variable);
723
724 ohpi_msec =
725 PIM_IGMP_OHPI_DSEC(
726 igmp->querier_robustness_variable,
727 igmp->querier_query_interval,
728 pim_ifp->igmp_query_max_response_time_dsec)
729 * 100;
730
731 qri_msec = pim_ifp->igmp_query_max_response_time_dsec
732 * 100;
733 if (pim_ifp->pim_sock_fd >= 0)
734 mloop = pim_socket_mcastloop_get(
735 pim_ifp->pim_sock_fd);
736 else
737 mloop = 0;
738
739 if (uj) {
740 json_row = json_object_new_object();
741 json_object_pim_ifp_add(json_row, ifp);
742 json_object_string_add(json_row, "upTime",
743 uptime);
744 json_object_string_add(json_row, "querier",
745 igmp->t_igmp_query_timer
746 ? "local"
747 : "other");
748 json_object_int_add(json_row, "queryStartCount",
749 igmp->startup_query_count);
750 json_object_string_add(json_row,
751 "queryQueryTimer",
752 query_hhmmss);
753 json_object_string_add(json_row,
754 "queryOtherTimer",
755 other_hhmmss);
756 json_object_int_add(json_row, "version",
757 pim_ifp->igmp_version);
758 json_object_int_add(
759 json_row,
760 "timerGroupMembershipIntervalMsec",
761 gmi_msec);
762 json_object_int_add(json_row,
763 "timerLastMemberQueryMsec",
764 lmqt_msec);
765 json_object_int_add(
766 json_row,
767 "timerOlderHostPresentIntervalMsec",
768 ohpi_msec);
769 json_object_int_add(
770 json_row,
771 "timerOtherQuerierPresentIntervalMsec",
772 oqpi_msec);
773 json_object_int_add(
774 json_row, "timerQueryInterval",
775 igmp->querier_query_interval);
776 json_object_int_add(
777 json_row,
778 "timerQueryResponseIntervalMsec",
779 qri_msec);
780 json_object_int_add(
781 json_row, "timerRobustnessVariable",
782 igmp->querier_robustness_variable);
783 json_object_int_add(json_row,
784 "timerStartupQueryInterval",
785 sqi);
786
787 json_object_object_add(json, ifp->name,
788 json_row);
789
790 } else {
791 vty_out(vty, "Interface : %s\n", ifp->name);
792 vty_out(vty, "State : %s\n",
793 if_is_up(ifp) ? "up" : "down");
794 vty_out(vty, "Address : %s\n",
795 inet_ntoa(pim_ifp->primary_address));
796 vty_out(vty, "Uptime : %s\n", uptime);
797 vty_out(vty, "Version : %d\n",
798 pim_ifp->igmp_version);
799 vty_out(vty, "\n");
800 vty_out(vty, "\n");
801
802 vty_out(vty, "Querier\n");
803 vty_out(vty, "-------\n");
804 vty_out(vty, "Querier : %s\n",
805 igmp->t_igmp_query_timer ? "local"
806 : "other");
807 vty_out(vty, "Start Count : %d\n",
808 igmp->startup_query_count);
809 vty_out(vty, "Query Timer : %s\n",
810 query_hhmmss);
811 vty_out(vty, "Other Timer : %s\n",
812 other_hhmmss);
813 vty_out(vty, "\n");
814 vty_out(vty, "\n");
815
816 vty_out(vty, "Timers\n");
817 vty_out(vty, "------\n");
818 vty_out(vty,
819 "Group Membership Interval : %lis\n",
820 gmi_msec / 1000);
821 vty_out(vty,
822 "Last Member Query Time : %lis\n",
823 lmqt_msec / 1000);
824 vty_out(vty,
825 "Older Host Present Interval : %lis\n",
826 ohpi_msec / 1000);
827 vty_out(vty,
828 "Other Querier Present Interval : %lis\n",
829 oqpi_msec / 1000);
830 vty_out(vty,
831 "Query Interval : %ds\n",
832 igmp->querier_query_interval);
833 vty_out(vty,
834 "Query Response Interval : %lis\n",
835 qri_msec / 1000);
836 vty_out(vty,
837 "Robustness Variable : %d\n",
838 igmp->querier_robustness_variable);
839 vty_out(vty,
840 "Startup Query Interval : %ds\n",
841 sqi);
842 vty_out(vty, "\n");
843 vty_out(vty, "\n");
844
845 pim_print_ifp_flags(vty, ifp, mloop);
846 }
847 }
848 }
849
850 if (uj) {
851 vty_out(vty, "%s\n", json_object_to_json_string_ext(
852 json, JSON_C_TO_STRING_PRETTY));
853 json_object_free(json);
854 } else {
855 if (!found_ifname)
856 vty_out(vty, "%% No such interface\n");
857 }
858 }
859
860 static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty)
861 {
862 struct interface *ifp;
863 time_t now;
864
865 now = pim_time_monotonic_sec();
866
867 vty_out(vty,
868 "Interface Address Source Group Socket Uptime \n");
869
870 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
871 struct pim_interface *pim_ifp;
872 struct listnode *join_node;
873 struct igmp_join *ij;
874 struct in_addr pri_addr;
875 char pri_addr_str[INET_ADDRSTRLEN];
876
877 pim_ifp = ifp->info;
878
879 if (!pim_ifp)
880 continue;
881
882 if (!pim_ifp->igmp_join_list)
883 continue;
884
885 pri_addr = pim_find_primary_addr(ifp);
886 pim_inet4_dump("<pri?>", pri_addr, pri_addr_str,
887 sizeof(pri_addr_str));
888
889 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, join_node,
890 ij)) {
891 char group_str[INET_ADDRSTRLEN];
892 char source_str[INET_ADDRSTRLEN];
893 char uptime[10];
894
895 pim_time_uptime(uptime, sizeof(uptime),
896 now - ij->sock_creation);
897 pim_inet4_dump("<grp?>", ij->group_addr, group_str,
898 sizeof(group_str));
899 pim_inet4_dump("<src?>", ij->source_addr, source_str,
900 sizeof(source_str));
901
902 vty_out(vty, "%-9s %-15s %-15s %-15s %6d %8s\n",
903 ifp->name, pri_addr_str, source_str, group_str,
904 ij->sock_fd, uptime);
905 } /* for (pim_ifp->igmp_join_list) */
906
907 } /* for (iflist) */
908 }
909
910 static void pim_show_interfaces_single(struct pim_instance *pim,
911 struct vty *vty, const char *ifname,
912 u_char uj)
913 {
914 struct in_addr ifaddr;
915 struct interface *ifp;
916 struct listnode *neighnode;
917 struct listnode *upnode;
918 struct pim_interface *pim_ifp;
919 struct pim_neighbor *neigh;
920 struct pim_upstream *up;
921 time_t now;
922 char dr_str[INET_ADDRSTRLEN];
923 char dr_uptime[10];
924 char expire[10];
925 char grp_str[INET_ADDRSTRLEN];
926 char hello_period[10];
927 char hello_timer[10];
928 char neigh_src_str[INET_ADDRSTRLEN];
929 char src_str[INET_ADDRSTRLEN];
930 char stat_uptime[10];
931 char uptime[10];
932 int mloop = 0;
933 int found_ifname = 0;
934 int print_header;
935 json_object *json = NULL;
936 json_object *json_row = NULL;
937 json_object *json_pim_neighbor = NULL;
938 json_object *json_pim_neighbors = NULL;
939 json_object *json_group = NULL;
940 json_object *json_group_source = NULL;
941 json_object *json_fhr_sources = NULL;
942 struct pim_secondary_addr *sec_addr;
943 struct listnode *sec_node;
944
945 now = pim_time_monotonic_sec();
946
947 if (uj)
948 json = json_object_new_object();
949
950 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
951 pim_ifp = ifp->info;
952
953 if (!pim_ifp)
954 continue;
955
956 if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
957 continue;
958
959 found_ifname = 1;
960 ifaddr = pim_ifp->primary_address;
961 pim_inet4_dump("<dr?>", pim_ifp->pim_dr_addr, dr_str,
962 sizeof(dr_str));
963 pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now,
964 pim_ifp->pim_dr_election_last);
965 pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer),
966 pim_ifp->t_pim_hello_timer);
967 pim_time_mmss(hello_period, sizeof(hello_period),
968 pim_ifp->pim_hello_period);
969 pim_time_uptime(stat_uptime, sizeof(stat_uptime),
970 now - pim_ifp->pim_ifstat_start);
971 if (pim_ifp->pim_sock_fd >= 0)
972 mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd);
973 else
974 mloop = 0;
975
976 if (uj) {
977 char pbuf[PREFIX2STR_BUFFER];
978 json_row = json_object_new_object();
979 json_object_pim_ifp_add(json_row, ifp);
980
981 if (pim_ifp->update_source.s_addr != INADDR_ANY) {
982 json_object_string_add(
983 json_row, "useSource",
984 inet_ntoa(pim_ifp->update_source));
985 }
986 if (pim_ifp->sec_addr_list) {
987 json_object *sec_list = NULL;
988
989 sec_list = json_object_new_array();
990 for (ALL_LIST_ELEMENTS_RO(
991 pim_ifp->sec_addr_list, sec_node,
992 sec_addr)) {
993 json_object_array_add(
994 sec_list,
995 json_object_new_string(
996 prefix2str(
997 &sec_addr->addr,
998 pbuf,
999 sizeof(pbuf))));
1000 }
1001 json_object_object_add(json_row,
1002 "secondaryAddressList",
1003 sec_list);
1004 }
1005
1006 // PIM neighbors
1007 if (pim_ifp->pim_neighbor_list->count) {
1008 json_pim_neighbors = json_object_new_object();
1009
1010 for (ALL_LIST_ELEMENTS_RO(
1011 pim_ifp->pim_neighbor_list,
1012 neighnode, neigh)) {
1013 json_pim_neighbor =
1014 json_object_new_object();
1015 pim_inet4_dump("<src?>",
1016 neigh->source_addr,
1017 neigh_src_str,
1018 sizeof(neigh_src_str));
1019 pim_time_uptime(uptime, sizeof(uptime),
1020 now - neigh->creation);
1021 pim_time_timer_to_hhmmss(
1022 expire, sizeof(expire),
1023 neigh->t_expire_timer);
1024
1025 json_object_string_add(
1026 json_pim_neighbor, "address",
1027 neigh_src_str);
1028 json_object_string_add(
1029 json_pim_neighbor, "upTime",
1030 uptime);
1031 json_object_string_add(
1032 json_pim_neighbor, "holdtime",
1033 expire);
1034
1035 json_object_object_add(
1036 json_pim_neighbors,
1037 neigh_src_str,
1038 json_pim_neighbor);
1039 }
1040
1041 json_object_object_add(json_row, "neighbors",
1042 json_pim_neighbors);
1043 }
1044
1045 json_object_string_add(json_row, "drAddress", dr_str);
1046 json_object_int_add(json_row, "drPriority",
1047 pim_ifp->pim_dr_priority);
1048 json_object_string_add(json_row, "drUptime", dr_uptime);
1049 json_object_int_add(json_row, "drElections",
1050 pim_ifp->pim_dr_election_count);
1051 json_object_int_add(json_row, "drChanges",
1052 pim_ifp->pim_dr_election_changes);
1053
1054 // FHR
1055 for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode,
1056 up)) {
1057 if (ifp == up->rpf.source_nexthop.interface) {
1058 if (up->flags
1059 & PIM_UPSTREAM_FLAG_MASK_FHR) {
1060 if (!json_fhr_sources) {
1061 json_fhr_sources =
1062 json_object_new_object();
1063 }
1064
1065 pim_inet4_dump("<src?>",
1066 up->sg.src,
1067 src_str,
1068 sizeof(src_str));
1069 pim_inet4_dump("<grp?>",
1070 up->sg.grp,
1071 grp_str,
1072 sizeof(grp_str));
1073 pim_time_uptime(
1074 uptime, sizeof(uptime),
1075 now - up->state_transition);
1076
1077 /* Does this group live in
1078 * json_fhr_sources? If not
1079 * create it. */
1080 json_object_object_get_ex(
1081 json_fhr_sources,
1082 grp_str, &json_group);
1083
1084 if (!json_group) {
1085 json_group =
1086 json_object_new_object();
1087 json_object_object_add(
1088 json_fhr_sources,
1089 grp_str,
1090 json_group);
1091 }
1092
1093 json_group_source =
1094 json_object_new_object();
1095 json_object_string_add(
1096 json_group_source,
1097 "source", src_str);
1098 json_object_string_add(
1099 json_group_source,
1100 "group", grp_str);
1101 json_object_string_add(
1102 json_group_source,
1103 "upTime", uptime);
1104 json_object_object_add(
1105 json_group, src_str,
1106 json_group_source);
1107 }
1108 }
1109 }
1110
1111 if (json_fhr_sources) {
1112 json_object_object_add(json_row,
1113 "firstHopRouter",
1114 json_fhr_sources);
1115 }
1116
1117 json_object_int_add(json_row, "helloPeriod",
1118 pim_ifp->pim_hello_period);
1119 json_object_string_add(json_row, "helloTimer",
1120 hello_timer);
1121 json_object_string_add(json_row, "helloStatStart",
1122 stat_uptime);
1123 json_object_int_add(json_row, "helloReceived",
1124 pim_ifp->pim_ifstat_hello_recv);
1125 json_object_int_add(json_row, "helloReceivedFailed",
1126 pim_ifp->pim_ifstat_hello_recvfail);
1127 json_object_int_add(json_row, "helloSend",
1128 pim_ifp->pim_ifstat_hello_sent);
1129 json_object_int_add(json_row, "hellosendFailed",
1130 pim_ifp->pim_ifstat_hello_sendfail);
1131 json_object_int_add(json_row, "helloGenerationId",
1132 pim_ifp->pim_generation_id);
1133 json_object_int_add(json_row, "flagMulticastLoop",
1134 mloop);
1135
1136 json_object_int_add(
1137 json_row, "effectivePropagationDelay",
1138 pim_if_effective_propagation_delay_msec(ifp));
1139 json_object_int_add(
1140 json_row, "effectiveOverrideInterval",
1141 pim_if_effective_override_interval_msec(ifp));
1142 json_object_int_add(
1143 json_row, "joinPruneOverrideInterval",
1144 pim_if_jp_override_interval_msec(ifp));
1145
1146 json_object_int_add(
1147 json_row, "propagationDelay",
1148 pim_ifp->pim_propagation_delay_msec);
1149 json_object_int_add(
1150 json_row, "propagationDelayHighest",
1151 pim_ifp->pim_neighbors_highest_propagation_delay_msec);
1152 json_object_int_add(
1153 json_row, "overrideInterval",
1154 pim_ifp->pim_override_interval_msec);
1155 json_object_int_add(
1156 json_row, "overrideIntervalHighest",
1157 pim_ifp->pim_neighbors_highest_override_interval_msec);
1158 json_object_object_add(json, ifp->name, json_row);
1159
1160 } else {
1161 vty_out(vty, "Interface : %s\n", ifp->name);
1162 vty_out(vty, "State : %s\n",
1163 if_is_up(ifp) ? "up" : "down");
1164 if (pim_ifp->update_source.s_addr != INADDR_ANY) {
1165 vty_out(vty, "Use Source : %s\n",
1166 inet_ntoa(pim_ifp->update_source));
1167 }
1168 if (pim_ifp->sec_addr_list) {
1169 char pbuf[PREFIX2STR_BUFFER];
1170 vty_out(vty, "Address : %s (primary)\n",
1171 inet_ntoa(ifaddr));
1172 for (ALL_LIST_ELEMENTS_RO(
1173 pim_ifp->sec_addr_list, sec_node,
1174 sec_addr)) {
1175 vty_out(vty, " %s\n",
1176 prefix2str(&sec_addr->addr,
1177 pbuf, sizeof(pbuf)));
1178 }
1179 } else {
1180 vty_out(vty, "Address : %s\n",
1181 inet_ntoa(ifaddr));
1182 }
1183 vty_out(vty, "\n");
1184
1185 // PIM neighbors
1186 print_header = 1;
1187
1188 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
1189 neighnode, neigh)) {
1190
1191 if (print_header) {
1192 vty_out(vty, "PIM Neighbors\n");
1193 vty_out(vty, "-------------\n");
1194 print_header = 0;
1195 }
1196
1197 pim_inet4_dump("<src?>", neigh->source_addr,
1198 neigh_src_str,
1199 sizeof(neigh_src_str));
1200 pim_time_uptime(uptime, sizeof(uptime),
1201 now - neigh->creation);
1202 pim_time_timer_to_hhmmss(expire, sizeof(expire),
1203 neigh->t_expire_timer);
1204 vty_out(vty,
1205 "%-15s : up for %s, holdtime expires in %s\n",
1206 neigh_src_str, uptime, expire);
1207 }
1208
1209 if (!print_header) {
1210 vty_out(vty, "\n");
1211 vty_out(vty, "\n");
1212 }
1213
1214 vty_out(vty, "Designated Router\n");
1215 vty_out(vty, "-----------------\n");
1216 vty_out(vty, "Address : %s\n", dr_str);
1217 vty_out(vty, "Priority : %d\n",
1218 pim_ifp->pim_dr_priority);
1219 vty_out(vty, "Uptime : %s\n", dr_uptime);
1220 vty_out(vty, "Elections : %d\n",
1221 pim_ifp->pim_dr_election_count);
1222 vty_out(vty, "Changes : %d\n",
1223 pim_ifp->pim_dr_election_changes);
1224 vty_out(vty, "\n");
1225 vty_out(vty, "\n");
1226
1227 // FHR
1228 print_header = 1;
1229 for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode,
1230 up)) {
1231 if (strcmp(ifp->name, up->rpf.source_nexthop
1232 .interface->name)
1233 == 0) {
1234 if (up->flags
1235 & PIM_UPSTREAM_FLAG_MASK_FHR) {
1236
1237 if (print_header) {
1238 vty_out(vty,
1239 "FHR - First Hop Router\n");
1240 vty_out(vty,
1241 "----------------------\n");
1242 print_header = 0;
1243 }
1244
1245 pim_inet4_dump("<src?>",
1246 up->sg.src,
1247 src_str,
1248 sizeof(src_str));
1249 pim_inet4_dump("<grp?>",
1250 up->sg.grp,
1251 grp_str,
1252 sizeof(grp_str));
1253 pim_time_uptime(
1254 uptime, sizeof(uptime),
1255 now - up->state_transition);
1256 vty_out(vty,
1257 "%s : %s is a source, uptime is %s\n",
1258 grp_str, src_str,
1259 uptime);
1260 }
1261 }
1262 }
1263
1264 if (!print_header) {
1265 vty_out(vty, "\n");
1266 vty_out(vty, "\n");
1267 }
1268
1269 vty_out(vty, "Hellos\n");
1270 vty_out(vty, "------\n");
1271 vty_out(vty, "Period : %d\n",
1272 pim_ifp->pim_hello_period);
1273 vty_out(vty, "Timer : %s\n", hello_timer);
1274 vty_out(vty, "StatStart : %s\n", stat_uptime);
1275 vty_out(vty, "Receive : %d\n",
1276 pim_ifp->pim_ifstat_hello_recv);
1277 vty_out(vty, "Receive Failed : %d\n",
1278 pim_ifp->pim_ifstat_hello_recvfail);
1279 vty_out(vty, "Send : %d\n",
1280 pim_ifp->pim_ifstat_hello_sent);
1281 vty_out(vty, "Send Failed : %d\n",
1282 pim_ifp->pim_ifstat_hello_sendfail);
1283 vty_out(vty, "Generation ID : %08x\n",
1284 pim_ifp->pim_generation_id);
1285 vty_out(vty, "\n");
1286 vty_out(vty, "\n");
1287
1288 pim_print_ifp_flags(vty, ifp, mloop);
1289
1290 vty_out(vty, "Join Prune Interval\n");
1291 vty_out(vty, "-------------------\n");
1292 vty_out(vty, "LAN Delay : %s\n",
1293 pim_if_lan_delay_enabled(ifp) ? "yes" : "no");
1294 vty_out(vty, "Effective Propagation Delay : %d msec\n",
1295 pim_if_effective_propagation_delay_msec(ifp));
1296 vty_out(vty, "Effective Override Interval : %d msec\n",
1297 pim_if_effective_override_interval_msec(ifp));
1298 vty_out(vty, "Join Prune Override Interval : %d msec\n",
1299 pim_if_jp_override_interval_msec(ifp));
1300 vty_out(vty, "\n");
1301 vty_out(vty, "\n");
1302
1303 vty_out(vty, "LAN Prune Delay\n");
1304 vty_out(vty, "---------------\n");
1305 vty_out(vty, "Propagation Delay : %d msec\n",
1306 pim_ifp->pim_propagation_delay_msec);
1307 vty_out(vty, "Propagation Delay (Highest) : %d msec\n",
1308 pim_ifp->pim_neighbors_highest_propagation_delay_msec);
1309 vty_out(vty, "Override Interval : %d msec\n",
1310 pim_ifp->pim_override_interval_msec);
1311 vty_out(vty, "Override Interval (Highest) : %d msec\n",
1312 pim_ifp->pim_neighbors_highest_override_interval_msec);
1313 vty_out(vty, "\n");
1314 vty_out(vty, "\n");
1315 }
1316 }
1317
1318 if (uj) {
1319 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1320 json, JSON_C_TO_STRING_PRETTY));
1321 json_object_free(json);
1322 } else {
1323 if (!found_ifname)
1324 vty_out(vty, "%% No such interface\n");
1325 }
1326 }
1327
1328 static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
1329 u_char uj)
1330 {
1331 struct interface *ifp;
1332 struct listnode *upnode;
1333 struct pim_interface *pim_ifp;
1334 struct pim_upstream *up;
1335 int fhr = 0;
1336 int pim_nbrs = 0;
1337 int pim_ifchannels = 0;
1338 json_object *json = NULL;
1339 json_object *json_row = NULL;
1340 json_object *json_tmp;
1341
1342 json = json_object_new_object();
1343
1344 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
1345 pim_ifp = ifp->info;
1346
1347 if (!pim_ifp)
1348 continue;
1349
1350 pim_nbrs = pim_ifp->pim_neighbor_list->count;
1351 pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
1352 fhr = 0;
1353
1354 for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up))
1355 if (ifp == up->rpf.source_nexthop.interface)
1356 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
1357 fhr++;
1358
1359 json_row = json_object_new_object();
1360 json_object_pim_ifp_add(json_row, ifp);
1361 json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
1362 json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
1363 json_object_int_add(json_row, "firstHopRouterCount", fhr);
1364 json_object_string_add(json_row, "pimDesignatedRouter",
1365 inet_ntoa(pim_ifp->pim_dr_addr));
1366
1367 if (pim_ifp->pim_dr_addr.s_addr
1368 == pim_ifp->primary_address.s_addr)
1369 json_object_boolean_true_add(
1370 json_row, "pimDesignatedRouterLocal");
1371
1372 json_object_object_add(json, ifp->name, json_row);
1373 }
1374
1375 if (uj) {
1376 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1377 json, JSON_C_TO_STRING_PRETTY));
1378 } else {
1379 vty_out(vty,
1380 "Interface State Address PIM Nbrs PIM DR FHR IfChannels\n");
1381
1382 json_object_object_foreach(json, key, val)
1383 {
1384 vty_out(vty, "%-9s ", key);
1385
1386 json_object_object_get_ex(val, "state", &json_tmp);
1387 vty_out(vty, "%5s ", json_object_get_string(json_tmp));
1388
1389 json_object_object_get_ex(val, "address", &json_tmp);
1390 vty_out(vty, "%15s ",
1391 json_object_get_string(json_tmp));
1392
1393 json_object_object_get_ex(val, "pimNeighbors",
1394 &json_tmp);
1395 vty_out(vty, "%8d ", json_object_get_int(json_tmp));
1396
1397 if (json_object_object_get_ex(
1398 val, "pimDesignatedRouterLocal",
1399 &json_tmp)) {
1400 vty_out(vty, "%15s ", "local");
1401 } else {
1402 json_object_object_get_ex(
1403 val, "pimDesignatedRouter", &json_tmp);
1404 vty_out(vty, "%15s ",
1405 json_object_get_string(json_tmp));
1406 }
1407
1408 json_object_object_get_ex(val, "firstHopRouter",
1409 &json_tmp);
1410 vty_out(vty, "%3d ", json_object_get_int(json_tmp));
1411
1412 json_object_object_get_ex(val, "pimIfChannels",
1413 &json_tmp);
1414 vty_out(vty, "%9d\n", json_object_get_int(json_tmp));
1415 }
1416 }
1417
1418 json_object_free(json);
1419 }
1420
1421 static void pim_show_interface_traffic(struct pim_instance *pim,
1422 struct vty *vty, u_char uj)
1423 {
1424 struct interface *ifp = NULL;
1425 struct pim_interface *pim_ifp = NULL;
1426 json_object *json = NULL;
1427 json_object *json_row = NULL;
1428
1429 if (uj)
1430 json = json_object_new_object();
1431 else {
1432 vty_out(vty, "\n");
1433 vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n",
1434 "Interface", " HELLO", " JOIN", " PRUNE",
1435 " REGISTER", " REGISTER-STOP", " ASSERT");
1436 vty_out(vty, "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", "",
1437 " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
1438 " Rx/Tx", " Rx/Tx");
1439 vty_out(vty,
1440 "---------------------------------------------------------------------------------------------------------------\n");
1441 }
1442
1443 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
1444 pim_ifp = ifp->info;
1445
1446 if (!pim_ifp)
1447 continue;
1448
1449 if (pim_ifp->pim_sock_fd < 0)
1450 continue;
1451 if (uj) {
1452 json_row = json_object_new_object();
1453 json_object_pim_ifp_add(json_row, ifp);
1454 json_object_int_add(json_row, "helloRx",
1455 pim_ifp->pim_ifstat_hello_recv);
1456 json_object_int_add(json_row, "helloTx",
1457 pim_ifp->pim_ifstat_hello_sent);
1458 json_object_int_add(json_row, "joinRx",
1459 pim_ifp->pim_ifstat_join_recv);
1460 json_object_int_add(json_row, "joinTx",
1461 pim_ifp->pim_ifstat_join_send);
1462 json_object_int_add(json_row, "registerRx",
1463 pim_ifp->pim_ifstat_reg_recv);
1464 json_object_int_add(json_row, "registerTx",
1465 pim_ifp->pim_ifstat_reg_recv);
1466 json_object_int_add(json_row, "registerStopRx",
1467 pim_ifp->pim_ifstat_reg_stop_recv);
1468 json_object_int_add(json_row, "registerStopTx",
1469 pim_ifp->pim_ifstat_reg_stop_send);
1470 json_object_int_add(json_row, "assertRx",
1471 pim_ifp->pim_ifstat_assert_recv);
1472 json_object_int_add(json_row, "assertTx",
1473 pim_ifp->pim_ifstat_assert_send);
1474
1475 json_object_object_add(json, ifp->name, json_row);
1476 } else {
1477 vty_out(vty,
1478 "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n",
1479 ifp->name, pim_ifp->pim_ifstat_hello_recv,
1480 pim_ifp->pim_ifstat_hello_sent,
1481 pim_ifp->pim_ifstat_join_recv,
1482 pim_ifp->pim_ifstat_join_send,
1483 pim_ifp->pim_ifstat_prune_recv,
1484 pim_ifp->pim_ifstat_prune_send,
1485 pim_ifp->pim_ifstat_reg_recv,
1486 pim_ifp->pim_ifstat_reg_send,
1487 pim_ifp->pim_ifstat_reg_stop_recv,
1488 pim_ifp->pim_ifstat_reg_stop_send,
1489 pim_ifp->pim_ifstat_assert_recv,
1490 pim_ifp->pim_ifstat_assert_send);
1491 }
1492 }
1493 if (uj) {
1494 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1495 json, JSON_C_TO_STRING_PRETTY));
1496 json_object_free(json);
1497 }
1498 }
1499
1500 static void pim_show_interface_traffic_single(struct pim_instance *pim,
1501 struct vty *vty,
1502 const char *ifname, u_char uj)
1503 {
1504 struct interface *ifp = NULL;
1505 struct pim_interface *pim_ifp = NULL;
1506 json_object *json = NULL;
1507 json_object *json_row = NULL;
1508 uint8_t found_ifname = 0;
1509
1510 if (uj)
1511 json = json_object_new_object();
1512 else {
1513 vty_out(vty, "\n");
1514 vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n",
1515 "Interface", " HELLO", " JOIN", " PRUNE",
1516 " REGISTER", " REGISTER-STOP", " ASSERT");
1517 vty_out(vty, "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", "",
1518 " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
1519 " Rx/Tx", " Rx/Tx");
1520 vty_out(vty,
1521 "---------------------------------------------------------------------------------------------------------------\n");
1522 }
1523
1524 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
1525 if (strcmp(ifname, ifp->name))
1526 continue;
1527
1528 pim_ifp = ifp->info;
1529
1530 if (!pim_ifp)
1531 continue;
1532
1533 if (pim_ifp->pim_sock_fd < 0)
1534 continue;
1535
1536 found_ifname = 1;
1537 if (uj) {
1538 json_row = json_object_new_object();
1539 json_object_pim_ifp_add(json_row, ifp);
1540 json_object_int_add(json_row, "helloRx",
1541 pim_ifp->pim_ifstat_hello_recv);
1542 json_object_int_add(json_row, "helloTx",
1543 pim_ifp->pim_ifstat_hello_sent);
1544 json_object_int_add(json_row, "joinRx",
1545 pim_ifp->pim_ifstat_join_recv);
1546 json_object_int_add(json_row, "joinTx",
1547 pim_ifp->pim_ifstat_join_send);
1548 json_object_int_add(json_row, "registerRx",
1549 pim_ifp->pim_ifstat_reg_recv);
1550 json_object_int_add(json_row, "registerTx",
1551 pim_ifp->pim_ifstat_reg_recv);
1552 json_object_int_add(json_row, "registerStopRx",
1553 pim_ifp->pim_ifstat_reg_stop_recv);
1554 json_object_int_add(json_row, "registerStopTx",
1555 pim_ifp->pim_ifstat_reg_stop_send);
1556 json_object_int_add(json_row, "assertRx",
1557 pim_ifp->pim_ifstat_assert_recv);
1558 json_object_int_add(json_row, "assertTx",
1559 pim_ifp->pim_ifstat_assert_send);
1560
1561 json_object_object_add(json, ifp->name, json_row);
1562 } else {
1563 vty_out(vty,
1564 "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n",
1565 ifp->name, pim_ifp->pim_ifstat_hello_recv,
1566 pim_ifp->pim_ifstat_hello_sent,
1567 pim_ifp->pim_ifstat_join_recv,
1568 pim_ifp->pim_ifstat_join_send,
1569 pim_ifp->pim_ifstat_prune_recv,
1570 pim_ifp->pim_ifstat_prune_send,
1571 pim_ifp->pim_ifstat_reg_recv,
1572 pim_ifp->pim_ifstat_reg_send,
1573 pim_ifp->pim_ifstat_reg_stop_recv,
1574 pim_ifp->pim_ifstat_reg_stop_send,
1575 pim_ifp->pim_ifstat_assert_recv,
1576 pim_ifp->pim_ifstat_assert_send);
1577 }
1578 }
1579 if (uj) {
1580 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1581 json, JSON_C_TO_STRING_PRETTY));
1582 json_object_free(json);
1583 } else {
1584 if (!found_ifname)
1585 vty_out(vty, "%% No such interface\n");
1586 }
1587 }
1588
1589 static void pim_show_join_helper(struct vty *vty,
1590 struct pim_interface *pim_ifp,
1591 struct pim_ifchannel *ch,
1592 json_object *json,
1593 time_t now,
1594 u_char uj)
1595 {
1596 char ch_src_str[INET_ADDRSTRLEN];
1597 char ch_grp_str[INET_ADDRSTRLEN];
1598 json_object *json_iface = NULL;
1599 json_object *json_row = NULL;
1600 json_object *json_grp = NULL;
1601 struct in_addr ifaddr;
1602 char uptime[10];
1603 char expire[10];
1604 char prune[10];
1605
1606 ifaddr = pim_ifp->primary_address;
1607
1608 pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str,
1609 sizeof(ch_src_str));
1610 pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str,
1611 sizeof(ch_grp_str));
1612
1613 pim_time_uptime_begin(uptime, sizeof(uptime), now,
1614 ch->ifjoin_creation);
1615 pim_time_timer_to_mmss(expire, sizeof(expire),
1616 ch->t_ifjoin_expiry_timer);
1617 pim_time_timer_to_mmss(prune, sizeof(prune),
1618 ch->t_ifjoin_prune_pending_timer);
1619
1620 if (uj) {
1621 json_object_object_get_ex(json, ch->interface->name,
1622 &json_iface);
1623
1624 if (!json_iface) {
1625 json_iface = json_object_new_object();
1626 json_object_pim_ifp_add(json_iface,
1627 ch->interface);
1628 json_object_object_add(
1629 json, ch->interface->name, json_iface);
1630 }
1631
1632 json_row = json_object_new_object();
1633 json_object_string_add(json_row, "source", ch_src_str);
1634 json_object_string_add(json_row, "group", ch_grp_str);
1635 json_object_string_add(json_row, "upTime", uptime);
1636 json_object_string_add(json_row, "expire", expire);
1637 json_object_string_add(json_row, "prune", prune);
1638 json_object_string_add(
1639 json_row, "channelJoinName",
1640 pim_ifchannel_ifjoin_name(ch->ifjoin_state,
1641 ch->flags));
1642 if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
1643 json_object_int_add(json_row, "SGRpt", 1);
1644
1645 json_object_object_get_ex(json_iface, ch_grp_str,
1646 &json_grp);
1647 if (!json_grp) {
1648 json_grp = json_object_new_object();
1649 json_object_object_add(json_grp, ch_src_str,
1650 json_row);
1651 json_object_object_add(json_iface, ch_grp_str,
1652 json_grp);
1653 } else
1654 json_object_object_add(json_grp, ch_src_str,
1655 json_row);
1656 } else {
1657 vty_out(vty,
1658 "%-9s %-15s %-15s %-15s %-10s %8s %-6s %5s\n",
1659 ch->interface->name, inet_ntoa(ifaddr),
1660 ch_src_str, ch_grp_str,
1661 pim_ifchannel_ifjoin_name(ch->ifjoin_state,
1662 ch->flags),
1663 uptime, expire, prune);
1664 }
1665 }
1666
1667 static void pim_show_join(struct pim_instance *pim, struct vty *vty, u_char uj)
1668 {
1669 struct pim_interface *pim_ifp;
1670 struct pim_ifchannel *ch;
1671 struct interface *ifp;
1672 time_t now;
1673 json_object *json = NULL;
1674
1675 now = pim_time_monotonic_sec();
1676
1677 if (uj)
1678 json = json_object_new_object();
1679 else
1680 vty_out(vty,
1681 "Interface Address Source Group State Uptime Expire Prune\n");
1682
1683 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
1684 pim_ifp = ifp->info;
1685 if (!pim_ifp)
1686 continue;
1687
1688 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1689 pim_show_join_helper(vty, pim_ifp, ch, json, now, uj);
1690 } /* scan interface channels */
1691 }
1692
1693 if (uj) {
1694 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1695 json, JSON_C_TO_STRING_PRETTY));
1696 json_object_free(json);
1697 }
1698 }
1699
1700 static void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
1701 const char *neighbor, u_char uj)
1702 {
1703 struct listnode *neighnode;
1704 struct interface *ifp;
1705 struct pim_interface *pim_ifp;
1706 struct pim_neighbor *neigh;
1707 time_t now;
1708 int found_neighbor = 0;
1709 int option_address_list;
1710 int option_dr_priority;
1711 int option_generation_id;
1712 int option_holdtime;
1713 int option_lan_prune_delay;
1714 int option_t_bit;
1715 char uptime[10];
1716 char expire[10];
1717 char neigh_src_str[INET_ADDRSTRLEN];
1718
1719 json_object *json = NULL;
1720 json_object *json_ifp = NULL;
1721 json_object *json_row = NULL;
1722
1723 now = pim_time_monotonic_sec();
1724
1725 if (uj)
1726 json = json_object_new_object();
1727
1728 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
1729 pim_ifp = ifp->info;
1730
1731 if (!pim_ifp)
1732 continue;
1733
1734 if (pim_ifp->pim_sock_fd < 0)
1735 continue;
1736
1737 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
1738 neigh)) {
1739 pim_inet4_dump("<src?>", neigh->source_addr,
1740 neigh_src_str, sizeof(neigh_src_str));
1741
1742 /*
1743 * The user can specify either the interface name or the
1744 * PIM neighbor IP.
1745 * If this pim_ifp matches neither then skip.
1746 */
1747 if (strcmp(neighbor, "detail")
1748 && strcmp(neighbor, ifp->name)
1749 && strcmp(neighbor, neigh_src_str))
1750 continue;
1751
1752 found_neighbor = 1;
1753 pim_time_uptime(uptime, sizeof(uptime),
1754 now - neigh->creation);
1755 pim_time_timer_to_hhmmss(expire, sizeof(expire),
1756 neigh->t_expire_timer);
1757
1758 option_address_list = 0;
1759 option_dr_priority = 0;
1760 option_generation_id = 0;
1761 option_holdtime = 0;
1762 option_lan_prune_delay = 0;
1763 option_t_bit = 0;
1764
1765 if (PIM_OPTION_IS_SET(neigh->hello_options,
1766 PIM_OPTION_MASK_ADDRESS_LIST))
1767 option_address_list = 1;
1768
1769 if (PIM_OPTION_IS_SET(neigh->hello_options,
1770 PIM_OPTION_MASK_DR_PRIORITY))
1771 option_dr_priority = 1;
1772
1773 if (PIM_OPTION_IS_SET(neigh->hello_options,
1774 PIM_OPTION_MASK_GENERATION_ID))
1775 option_generation_id = 1;
1776
1777 if (PIM_OPTION_IS_SET(neigh->hello_options,
1778 PIM_OPTION_MASK_HOLDTIME))
1779 option_holdtime = 1;
1780
1781 if (PIM_OPTION_IS_SET(neigh->hello_options,
1782 PIM_OPTION_MASK_LAN_PRUNE_DELAY))
1783 option_lan_prune_delay = 1;
1784
1785 if (PIM_OPTION_IS_SET(
1786 neigh->hello_options,
1787 PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION))
1788 option_t_bit = 1;
1789
1790 if (uj) {
1791
1792 /* Does this ifp live in json? If not create
1793 * it. */
1794 json_object_object_get_ex(json, ifp->name,
1795 &json_ifp);
1796
1797 if (!json_ifp) {
1798 json_ifp = json_object_new_object();
1799 json_object_pim_ifp_add(json_ifp, ifp);
1800 json_object_object_add(json, ifp->name,
1801 json_ifp);
1802 }
1803
1804 json_row = json_object_new_object();
1805 json_object_string_add(json_row, "interface",
1806 ifp->name);
1807 json_object_string_add(json_row, "address",
1808 neigh_src_str);
1809 json_object_string_add(json_row, "upTime",
1810 uptime);
1811 json_object_string_add(json_row, "holdtime",
1812 expire);
1813 json_object_int_add(json_row, "drPriority",
1814 neigh->dr_priority);
1815 json_object_int_add(json_row, "generationId",
1816 neigh->generation_id);
1817
1818 if (option_address_list)
1819 json_object_boolean_true_add(
1820 json_row,
1821 "helloOptionAddressList");
1822
1823 if (option_dr_priority)
1824 json_object_boolean_true_add(
1825 json_row,
1826 "helloOptionDrPriority");
1827
1828 if (option_generation_id)
1829 json_object_boolean_true_add(
1830 json_row,
1831 "helloOptionGenerationId");
1832
1833 if (option_holdtime)
1834 json_object_boolean_true_add(
1835 json_row,
1836 "helloOptionHoldtime");
1837
1838 if (option_lan_prune_delay)
1839 json_object_boolean_true_add(
1840 json_row,
1841 "helloOptionLanPruneDelay");
1842
1843 if (option_t_bit)
1844 json_object_boolean_true_add(
1845 json_row, "helloOptionTBit");
1846
1847 json_object_object_add(json_ifp, neigh_src_str,
1848 json_row);
1849
1850 } else {
1851 vty_out(vty, "Interface : %s\n", ifp->name);
1852 vty_out(vty, "Neighbor : %s\n", neigh_src_str);
1853 vty_out(vty,
1854 " Uptime : %s\n",
1855 uptime);
1856 vty_out(vty,
1857 " Holdtime : %s\n",
1858 expire);
1859 vty_out(vty,
1860 " DR Priority : %d\n",
1861 neigh->dr_priority);
1862 vty_out(vty,
1863 " Generation ID : %08x\n",
1864 neigh->generation_id);
1865 vty_out(vty,
1866 " Override Interval (msec) : %d\n",
1867 neigh->override_interval_msec);
1868 vty_out(vty,
1869 " Propagation Delay (msec) : %d\n",
1870 neigh->propagation_delay_msec);
1871 vty_out(vty,
1872 " Hello Option - Address List : %s\n",
1873 option_address_list ? "yes" : "no");
1874 vty_out(vty,
1875 " Hello Option - DR Priority : %s\n",
1876 option_dr_priority ? "yes" : "no");
1877 vty_out(vty,
1878 " Hello Option - Generation ID : %s\n",
1879 option_generation_id ? "yes" : "no");
1880 vty_out(vty,
1881 " Hello Option - Holdtime : %s\n",
1882 option_holdtime ? "yes" : "no");
1883 vty_out(vty,
1884 " Hello Option - LAN Prune Delay : %s\n",
1885 option_lan_prune_delay ? "yes" : "no");
1886 vty_out(vty,
1887 " Hello Option - T-bit : %s\n",
1888 option_t_bit ? "yes" : "no");
1889 pim_bfd_show_info(vty, neigh->bfd_info,
1890 json_ifp, uj, 0);
1891 vty_out(vty, "\n");
1892 }
1893 }
1894 }
1895
1896 if (uj) {
1897 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1898 json, JSON_C_TO_STRING_PRETTY));
1899 json_object_free(json);
1900 } else {
1901 {
1902 if (!found_neighbor)
1903 vty_out(vty,
1904 "%% No such interface or neighbor\n");
1905 }
1906 }
1907 }
1908
1909 static void pim_show_state(struct pim_instance *pim, struct vty *vty,
1910 const char *src_or_group, const char *group,
1911 u_char uj)
1912 {
1913 struct channel_oil *c_oil;
1914 struct listnode *node;
1915 json_object *json = NULL;
1916 json_object *json_group = NULL;
1917 json_object *json_ifp_in = NULL;
1918 json_object *json_ifp_out = NULL;
1919 json_object *json_source = NULL;
1920 time_t now;
1921 int first_oif;
1922 now = pim_time_monotonic_sec();
1923
1924 if (uj) {
1925 json = json_object_new_object();
1926 } else {
1927 vty_out(vty,
1928 "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G)");
1929 vty_out(vty,
1930 "\nInstalled Source Group IIF OIL\n");
1931 }
1932
1933 for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
1934 char grp_str[INET_ADDRSTRLEN];
1935 char src_str[INET_ADDRSTRLEN];
1936 char in_ifname[INTERFACE_NAMSIZ + 1];
1937 char out_ifname[INTERFACE_NAMSIZ + 1];
1938 int oif_vif_index;
1939 struct interface *ifp_in;
1940 first_oif = 1;
1941
1942 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str,
1943 sizeof(grp_str));
1944 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str,
1945 sizeof(src_str));
1946 ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent);
1947
1948 if (ifp_in)
1949 strcpy(in_ifname, ifp_in->name);
1950 else
1951 strcpy(in_ifname, "<iif?>");
1952
1953 if (src_or_group) {
1954 if (strcmp(src_or_group, src_str)
1955 && strcmp(src_or_group, grp_str))
1956 continue;
1957
1958 if (group && strcmp(group, grp_str))
1959 continue;
1960 }
1961
1962 if (uj) {
1963
1964 /* Find the group, create it if it doesn't exist */
1965 json_object_object_get_ex(json, grp_str, &json_group);
1966
1967 if (!json_group) {
1968 json_group = json_object_new_object();
1969 json_object_object_add(json, grp_str,
1970 json_group);
1971 }
1972
1973 /* Find the source nested under the group, create it if
1974 * it doesn't exist */
1975 json_object_object_get_ex(json_group, src_str,
1976 &json_source);
1977
1978 if (!json_source) {
1979 json_source = json_object_new_object();
1980 json_object_object_add(json_group, src_str,
1981 json_source);
1982 }
1983
1984 /* Find the inbound interface nested under the source,
1985 * create it if it doesn't exist */
1986 json_object_object_get_ex(json_source, in_ifname,
1987 &json_ifp_in);
1988
1989 if (!json_ifp_in) {
1990 json_ifp_in = json_object_new_object();
1991 json_object_object_add(json_source, in_ifname,
1992 json_ifp_in);
1993 json_object_int_add(json_source, "Installed",
1994 c_oil->installed);
1995 json_object_int_add(json_source, "RefCount",
1996 c_oil->oil_ref_count);
1997 json_object_int_add(json_source, "OilListSize",
1998 c_oil->oil_size);
1999 json_object_int_add(
2000 json_source, "OilRescan",
2001 c_oil->oil_inherited_rescan);
2002 json_object_int_add(json_source, "LastUsed",
2003 c_oil->cc.lastused);
2004 json_object_int_add(json_source, "PacketCount",
2005 c_oil->cc.pktcnt);
2006 json_object_int_add(json_source, "ByteCount",
2007 c_oil->cc.bytecnt);
2008 json_object_int_add(json_source,
2009 "WrongInterface",
2010 c_oil->cc.wrong_if);
2011 }
2012 } else {
2013 vty_out(vty, "%-9d %-15s %-15s %-7s ",
2014 c_oil->installed, src_str, grp_str,
2015 ifp_in->name);
2016 }
2017
2018 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
2019 ++oif_vif_index) {
2020 struct interface *ifp_out;
2021 char oif_uptime[10];
2022 int ttl;
2023
2024 ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
2025 if (ttl < 1)
2026 continue;
2027
2028 ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
2029 pim_time_uptime(
2030 oif_uptime, sizeof(oif_uptime),
2031 now - c_oil->oif_creation[oif_vif_index]);
2032
2033 if (ifp_out)
2034 strcpy(out_ifname, ifp_out->name);
2035 else
2036 strcpy(out_ifname, "<oif?>");
2037
2038 if (uj) {
2039 json_ifp_out = json_object_new_object();
2040 json_object_string_add(json_ifp_out, "source",
2041 src_str);
2042 json_object_string_add(json_ifp_out, "group",
2043 grp_str);
2044 json_object_string_add(json_ifp_out,
2045 "inboundInterface",
2046 in_ifname);
2047 json_object_string_add(json_ifp_out,
2048 "outboundInterface",
2049 out_ifname);
2050 json_object_int_add(json_ifp_out, "installed",
2051 c_oil->installed);
2052
2053 json_object_object_add(json_ifp_in, out_ifname,
2054 json_ifp_out);
2055 } else {
2056 if (first_oif) {
2057 first_oif = 0;
2058 vty_out(vty, "%s(%c%c%c%c)", out_ifname,
2059 (c_oil->oif_flags[oif_vif_index]
2060 & PIM_OIF_FLAG_PROTO_IGMP)
2061 ? 'I'
2062 : ' ',
2063 (c_oil->oif_flags[oif_vif_index]
2064 & PIM_OIF_FLAG_PROTO_PIM)
2065 ? 'J'
2066 : ' ',
2067 (c_oil->oif_flags[oif_vif_index]
2068 & PIM_OIF_FLAG_PROTO_SOURCE)
2069 ? 'S'
2070 : ' ',
2071 (c_oil->oif_flags[oif_vif_index]
2072 & PIM_OIF_FLAG_PROTO_STAR)
2073 ? '*'
2074 : ' ');
2075 } else
2076 vty_out(vty, ", %s(%c%c%c%c)",
2077 out_ifname,
2078 (c_oil->oif_flags[oif_vif_index]
2079 & PIM_OIF_FLAG_PROTO_IGMP)
2080 ? 'I'
2081 : ' ',
2082 (c_oil->oif_flags[oif_vif_index]
2083 & PIM_OIF_FLAG_PROTO_PIM)
2084 ? 'J'
2085 : ' ',
2086 (c_oil->oif_flags[oif_vif_index]
2087 & PIM_OIF_FLAG_PROTO_SOURCE)
2088 ? 'S'
2089 : ' ',
2090 (c_oil->oif_flags[oif_vif_index]
2091 & PIM_OIF_FLAG_PROTO_STAR)
2092 ? '*'
2093 : ' ');
2094 }
2095 }
2096
2097 if (!uj)
2098 vty_out(vty, "\n");
2099 }
2100
2101
2102 if (uj) {
2103 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2104 json, JSON_C_TO_STRING_PRETTY));
2105 json_object_free(json);
2106 } else {
2107 vty_out(vty, "\n");
2108 }
2109 }
2110
2111 static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
2112 u_char uj)
2113 {
2114 struct listnode *neighnode;
2115 struct interface *ifp;
2116 struct pim_interface *pim_ifp;
2117 struct pim_neighbor *neigh;
2118 time_t now;
2119 char uptime[10];
2120 char expire[10];
2121 char neigh_src_str[INET_ADDRSTRLEN];
2122 json_object *json = NULL;
2123 json_object *json_ifp_rows = NULL;
2124 json_object *json_row = NULL;
2125
2126 now = pim_time_monotonic_sec();
2127
2128 if (uj) {
2129 json = json_object_new_object();
2130 } else {
2131 vty_out(vty,
2132 "Interface Neighbor Uptime Holdtime DR Pri\n");
2133 }
2134
2135 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
2136 pim_ifp = ifp->info;
2137
2138 if (!pim_ifp)
2139 continue;
2140
2141 if (pim_ifp->pim_sock_fd < 0)
2142 continue;
2143
2144 if (uj)
2145 json_ifp_rows = json_object_new_object();
2146
2147 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
2148 neigh)) {
2149 pim_inet4_dump("<src?>", neigh->source_addr,
2150 neigh_src_str, sizeof(neigh_src_str));
2151 pim_time_uptime(uptime, sizeof(uptime),
2152 now - neigh->creation);
2153 pim_time_timer_to_hhmmss(expire, sizeof(expire),
2154 neigh->t_expire_timer);
2155
2156 if (uj) {
2157 json_row = json_object_new_object();
2158 json_object_string_add(json_row, "interface",
2159 ifp->name);
2160 json_object_string_add(json_row, "neighbor",
2161 neigh_src_str);
2162 json_object_string_add(json_row, "upTime",
2163 uptime);
2164 json_object_string_add(json_row, "holdTime",
2165 expire);
2166 json_object_int_add(json_row, "holdTimeMax",
2167 neigh->holdtime);
2168 json_object_int_add(json_row, "drPriority",
2169 neigh->dr_priority);
2170 json_object_object_add(json_ifp_rows,
2171 neigh_src_str, json_row);
2172
2173 } else {
2174 vty_out(vty, "%-9s %15s %8s %8s %6d\n",
2175 ifp->name, neigh_src_str, uptime,
2176 expire, neigh->dr_priority);
2177 }
2178 }
2179
2180 if (uj) {
2181 json_object_object_add(json, ifp->name, json_ifp_rows);
2182 json_ifp_rows = NULL;
2183 }
2184 }
2185
2186 if (uj) {
2187 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2188 json, JSON_C_TO_STRING_PRETTY));
2189 json_object_free(json);
2190 }
2191 }
2192
2193 static void pim_show_neighbors_secondary(struct pim_instance *pim,
2194 struct vty *vty)
2195 {
2196 struct interface *ifp;
2197
2198 vty_out(vty,
2199 "Interface Address Neighbor Secondary \n");
2200
2201 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
2202 struct pim_interface *pim_ifp;
2203 struct in_addr ifaddr;
2204 struct listnode *neighnode;
2205 struct pim_neighbor *neigh;
2206
2207 pim_ifp = ifp->info;
2208
2209 if (!pim_ifp)
2210 continue;
2211
2212 if (pim_ifp->pim_sock_fd < 0)
2213 continue;
2214
2215 ifaddr = pim_ifp->primary_address;
2216
2217 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
2218 neigh)) {
2219 char neigh_src_str[INET_ADDRSTRLEN];
2220 struct listnode *prefix_node;
2221 struct prefix *p;
2222
2223 if (!neigh->prefix_list)
2224 continue;
2225
2226 pim_inet4_dump("<src?>", neigh->source_addr,
2227 neigh_src_str, sizeof(neigh_src_str));
2228
2229 for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list,
2230 prefix_node, p)) {
2231 char neigh_sec_str[PREFIX2STR_BUFFER];
2232
2233 prefix2str(p, neigh_sec_str,
2234 sizeof(neigh_sec_str));
2235
2236 vty_out(vty, "%-9s %-15s %-15s %-15s\n",
2237 ifp->name, inet_ntoa(ifaddr),
2238 neigh_src_str, neigh_sec_str);
2239 }
2240 }
2241 }
2242 }
2243
2244 static void json_object_pim_upstream_add(json_object *json,
2245 struct pim_upstream *up)
2246 {
2247 if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
2248 json_object_boolean_true_add(json, "drJoinDesired");
2249
2250 if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
2251 json_object_boolean_true_add(json, "drJoinDesiredUpdated");
2252
2253 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
2254 json_object_boolean_true_add(json, "firstHopRouter");
2255
2256 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
2257 json_object_boolean_true_add(json, "sourceIgmp");
2258
2259 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
2260 json_object_boolean_true_add(json, "sourcePim");
2261
2262 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
2263 json_object_boolean_true_add(json, "sourceStream");
2264
2265 /* XXX: need to print ths flag in the plain text display as well */
2266 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
2267 json_object_boolean_true_add(json, "sourceMsdp");
2268 }
2269
2270 static const char *
2271 pim_upstream_state2brief_str(enum pim_upstream_state join_state,
2272 char *state_str)
2273 {
2274 switch (join_state) {
2275 case PIM_UPSTREAM_NOTJOINED:
2276 strcpy(state_str, "NotJ");
2277 break;
2278 case PIM_UPSTREAM_JOINED:
2279 strcpy(state_str, "J");
2280 break;
2281 default:
2282 strcpy(state_str, "Unk");
2283 }
2284 return state_str;
2285 }
2286
2287 static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state,
2288 char *state_str)
2289 {
2290 switch (reg_state) {
2291 case PIM_REG_NOINFO:
2292 strcpy(state_str, "RegNI");
2293 break;
2294 case PIM_REG_JOIN:
2295 strcpy(state_str, "RegJ");
2296 break;
2297 case PIM_REG_JOIN_PENDING:
2298 case PIM_REG_PRUNE:
2299 strcpy(state_str, "RegP");
2300 break;
2301 default:
2302 strcpy(state_str, "Unk");
2303 }
2304 return state_str;
2305 }
2306
2307 static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
2308 u_char uj)
2309 {
2310 struct listnode *upnode;
2311 struct pim_upstream *up;
2312 time_t now;
2313 json_object *json = NULL;
2314 json_object *json_group = NULL;
2315 json_object *json_row = NULL;
2316
2317 now = pim_time_monotonic_sec();
2318
2319 if (uj)
2320 json = json_object_new_object();
2321 else
2322 vty_out(vty,
2323 "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n");
2324
2325 for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
2326 char src_str[INET_ADDRSTRLEN];
2327 char grp_str[INET_ADDRSTRLEN];
2328 char uptime[10];
2329 char join_timer[10];
2330 char rs_timer[10];
2331 char ka_timer[10];
2332 char msdp_reg_timer[10];
2333 char state_str[PIM_REG_STATE_STR_LEN];
2334
2335 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
2336 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
2337 pim_time_uptime(uptime, sizeof(uptime),
2338 now - up->state_transition);
2339 pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer),
2340 up->t_join_timer);
2341
2342 /*
2343 * If we have a J/P timer for the neighbor display that
2344 */
2345 if (!up->t_join_timer) {
2346 struct pim_neighbor *nbr;
2347
2348 nbr = pim_neighbor_find(
2349 up->rpf.source_nexthop.interface,
2350 up->rpf.rpf_addr.u.prefix4);
2351 if (nbr)
2352 pim_time_timer_to_hhmmss(join_timer,
2353 sizeof(join_timer),
2354 nbr->jp_timer);
2355 }
2356
2357 pim_time_timer_to_hhmmss(rs_timer, sizeof(rs_timer),
2358 up->t_rs_timer);
2359 pim_time_timer_to_hhmmss(ka_timer, sizeof(ka_timer),
2360 up->t_ka_timer);
2361 pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer),
2362 up->t_msdp_reg_timer);
2363
2364 pim_upstream_state2brief_str(up->join_state, state_str);
2365 if (up->reg_state != PIM_REG_NOINFO) {
2366 char tmp_str[PIM_REG_STATE_STR_LEN];
2367
2368 sprintf(state_str + strlen(state_str), ",%s",
2369 pim_reg_state2brief_str(up->reg_state,
2370 tmp_str));
2371 }
2372
2373 if (uj) {
2374 json_object_object_get_ex(json, grp_str, &json_group);
2375
2376 if (!json_group) {
2377 json_group = json_object_new_object();
2378 json_object_object_add(json, grp_str,
2379 json_group);
2380 }
2381
2382 json_row = json_object_new_object();
2383 json_object_pim_upstream_add(json_row, up);
2384 json_object_string_add(
2385 json_row, "inboundInterface",
2386 up->rpf.source_nexthop.interface->name);
2387 json_object_string_add(json_row, "source", src_str);
2388 json_object_string_add(json_row, "group", grp_str);
2389 json_object_string_add(json_row, "state", state_str);
2390 json_object_string_add(
2391 json_row, "joinState",
2392 pim_upstream_state2str(up->join_state));
2393 json_object_string_add(
2394 json_row, "regState",
2395 pim_reg_state2str(up->reg_state, state_str));
2396 json_object_string_add(json_row, "upTime", uptime);
2397 json_object_string_add(json_row, "joinTimer",
2398 join_timer);
2399 json_object_string_add(json_row, "resetTimer",
2400 rs_timer);
2401 json_object_string_add(json_row, "keepaliveTimer",
2402 ka_timer);
2403 json_object_string_add(json_row, "msdpRegTimer",
2404 msdp_reg_timer);
2405 json_object_int_add(json_row, "refCount",
2406 up->ref_count);
2407 json_object_int_add(json_row, "sptBit", up->sptbit);
2408 json_object_object_add(json_group, src_str, json_row);
2409 } else {
2410 vty_out(vty,
2411 "%-10s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n",
2412 up->rpf.source_nexthop.interface->name, src_str,
2413 grp_str, state_str, uptime, join_timer,
2414 rs_timer, ka_timer, up->ref_count);
2415 }
2416 }
2417
2418 if (uj) {
2419 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2420 json, JSON_C_TO_STRING_PRETTY));
2421 json_object_free(json);
2422 }
2423 }
2424
2425 static void pim_show_join_desired_helper(struct pim_instance *pim,
2426 struct vty *vty,
2427 struct pim_interface *pim_ifp,
2428 struct pim_ifchannel *ch,
2429 json_object *json,
2430 u_char uj)
2431 {
2432 struct pim_upstream *up = ch->upstream;
2433 json_object *json_group = NULL;
2434 char src_str[INET_ADDRSTRLEN];
2435 char grp_str[INET_ADDRSTRLEN];
2436 json_object *json_row = NULL;
2437
2438 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
2439 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
2440
2441 if (uj) {
2442 json_object_object_get_ex(json, grp_str, &json_group);
2443
2444 if (!json_group) {
2445 json_group = json_object_new_object();
2446 json_object_object_add(json, grp_str,
2447 json_group);
2448 }
2449
2450 json_row = json_object_new_object();
2451 json_object_pim_upstream_add(json_row, up);
2452 json_object_string_add(json_row, "interface",
2453 ch->interface->name);
2454 json_object_string_add(json_row, "source", src_str);
2455 json_object_string_add(json_row, "group", grp_str);
2456
2457 if (pim_macro_ch_lost_assert(ch))
2458 json_object_boolean_true_add(json_row,
2459 "lostAssert");
2460
2461 if (pim_macro_chisin_joins(ch))
2462 json_object_boolean_true_add(json_row, "joins");
2463
2464 if (pim_macro_chisin_pim_include(ch))
2465 json_object_boolean_true_add(json_row,
2466 "pimInclude");
2467
2468 if (pim_upstream_evaluate_join_desired(pim, up))
2469 json_object_boolean_true_add(
2470 json_row, "evaluateJoinDesired");
2471
2472 json_object_object_add(json_group, src_str, json_row);
2473
2474 } else {
2475 vty_out(vty,
2476 "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n",
2477 ch->interface->name, src_str, grp_str,
2478 pim_macro_ch_lost_assert(ch) ? "yes" : "no",
2479 pim_macro_chisin_joins(ch) ? "yes" : "no",
2480 pim_macro_chisin_pim_include(ch) ? "yes" : "no",
2481 PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(
2482 up->flags)
2483 ? "yes"
2484 : "no",
2485 pim_upstream_evaluate_join_desired(pim, up)
2486 ? "yes"
2487 : "no");
2488 }
2489 }
2490
2491 static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty,
2492 u_char uj)
2493 {
2494 struct pim_interface *pim_ifp;
2495 struct pim_ifchannel *ch;
2496 struct interface *ifp;
2497
2498 json_object *json = NULL;
2499
2500 if (uj)
2501 json = json_object_new_object();
2502 else
2503 vty_out(vty,
2504 "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n");
2505
2506 /* scan per-interface (S,G) state */
2507 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
2508 pim_ifp = ifp->info;
2509 if (!pim_ifp)
2510 continue;
2511
2512
2513 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
2514 /* scan all interfaces */
2515 pim_show_join_desired_helper(pim, vty,
2516 pim_ifp, ch,
2517 json, uj);
2518 }
2519 }
2520
2521 if (uj) {
2522 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2523 json, JSON_C_TO_STRING_PRETTY));
2524 json_object_free(json);
2525 }
2526 }
2527
2528 static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty,
2529 u_char uj)
2530 {
2531 struct listnode *upnode;
2532 struct pim_upstream *up;
2533 json_object *json = NULL;
2534 json_object *json_group = NULL;
2535 json_object *json_row = NULL;
2536
2537 if (uj)
2538 json = json_object_new_object();
2539 else
2540 vty_out(vty,
2541 "Source Group RpfIface RibNextHop RpfAddress \n");
2542
2543 for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
2544 char src_str[INET_ADDRSTRLEN];
2545 char grp_str[INET_ADDRSTRLEN];
2546 char rpf_nexthop_str[PREFIX_STRLEN];
2547 char rpf_addr_str[PREFIX_STRLEN];
2548 struct pim_rpf *rpf;
2549 const char *rpf_ifname;
2550
2551 rpf = &up->rpf;
2552
2553 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
2554 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
2555 pim_addr_dump("<nexthop?>",
2556 &rpf->source_nexthop.mrib_nexthop_addr,
2557 rpf_nexthop_str, sizeof(rpf_nexthop_str));
2558 pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str,
2559 sizeof(rpf_addr_str));
2560
2561 rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
2562
2563 if (uj) {
2564 json_object_object_get_ex(json, grp_str, &json_group);
2565
2566 if (!json_group) {
2567 json_group = json_object_new_object();
2568 json_object_object_add(json, grp_str,
2569 json_group);
2570 }
2571
2572 json_row = json_object_new_object();
2573 json_object_pim_upstream_add(json_row, up);
2574 json_object_string_add(json_row, "source", src_str);
2575 json_object_string_add(json_row, "group", grp_str);
2576 json_object_string_add(json_row, "rpfInterface",
2577 rpf_ifname);
2578 json_object_string_add(json_row, "ribNexthop",
2579 rpf_nexthop_str);
2580 json_object_string_add(json_row, "rpfAddress",
2581 rpf_addr_str);
2582 json_object_object_add(json_group, src_str, json_row);
2583 } else {
2584 vty_out(vty, "%-15s %-15s %-8s %-15s %-15s\n", src_str,
2585 grp_str, rpf_ifname, rpf_nexthop_str,
2586 rpf_addr_str);
2587 }
2588 }
2589
2590 if (uj) {
2591 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2592 json, JSON_C_TO_STRING_PRETTY));
2593 json_object_free(json);
2594 }
2595 }
2596
2597 static void show_rpf_refresh_stats(struct vty *vty, time_t now,
2598 json_object *json)
2599 {
2600 char refresh_uptime[10];
2601
2602 pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now,
2603 qpim_rpf_cache_refresh_last);
2604
2605 if (json) {
2606 json_object_int_add(json, "rpfCacheRefreshDelayMsecs",
2607 qpim_rpf_cache_refresh_delay_msec);
2608 json_object_int_add(
2609 json, "rpfCacheRefreshTimer",
2610 pim_time_timer_remain_msec(qpim_rpf_cache_refresher));
2611 json_object_int_add(json, "rpfCacheRefreshRequests",
2612 qpim_rpf_cache_refresh_requests);
2613 json_object_int_add(json, "rpfCacheRefreshEvents",
2614 qpim_rpf_cache_refresh_events);
2615 json_object_string_add(json, "rpfCacheRefreshLast",
2616 refresh_uptime);
2617 json_object_int_add(json, "nexthopLookups",
2618 qpim_nexthop_lookups);
2619 json_object_int_add(json, "nexthopLookupsAvoided",
2620 nexthop_lookups_avoided);
2621 } else {
2622 vty_out(vty,
2623 "RPF Cache Refresh Delay: %ld msecs\n"
2624 "RPF Cache Refresh Timer: %ld msecs\n"
2625 "RPF Cache Refresh Requests: %lld\n"
2626 "RPF Cache Refresh Events: %lld\n"
2627 "RPF Cache Refresh Last: %s\n"
2628 "Nexthop Lookups: %lld\n"
2629 "Nexthop Lookups Avoided: %lld\n",
2630 qpim_rpf_cache_refresh_delay_msec,
2631 pim_time_timer_remain_msec(qpim_rpf_cache_refresher),
2632 (long long)qpim_rpf_cache_refresh_requests,
2633 (long long)qpim_rpf_cache_refresh_events,
2634 refresh_uptime, (long long)qpim_nexthop_lookups,
2635 (long long)nexthop_lookups_avoided);
2636 }
2637 }
2638
2639 static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
2640 time_t now)
2641 {
2642 char uptime_scan_oil[10];
2643 char uptime_mroute_add[10];
2644 char uptime_mroute_del[10];
2645
2646 pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now,
2647 qpim_scan_oil_last);
2648 pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now,
2649 pim->mroute_add_last);
2650 pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now,
2651 pim->mroute_del_last);
2652
2653 vty_out(vty,
2654 "Scan OIL - Last: %s Events: %lld\n"
2655 "MFC Add - Last: %s Events: %lld\n"
2656 "MFC Del - Last: %s Events: %lld\n",
2657 uptime_scan_oil, (long long)qpim_scan_oil_events,
2658 uptime_mroute_add, (long long)pim->mroute_add_events,
2659 uptime_mroute_del, (long long)pim->mroute_del_events);
2660 }
2661
2662 static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, u_char uj)
2663 {
2664 struct listnode *up_node;
2665 struct pim_upstream *up;
2666 time_t now = pim_time_monotonic_sec();
2667 json_object *json = NULL;
2668 json_object *json_group = NULL;
2669 json_object *json_row = NULL;
2670
2671 if (uj) {
2672 json = json_object_new_object();
2673 show_rpf_refresh_stats(vty, now, json);
2674 } else {
2675 show_rpf_refresh_stats(vty, now, json);
2676 vty_out(vty, "\n");
2677 vty_out(vty,
2678 "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n");
2679 }
2680
2681 for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, up_node, up)) {
2682 char src_str[INET_ADDRSTRLEN];
2683 char grp_str[INET_ADDRSTRLEN];
2684 char rpf_addr_str[PREFIX_STRLEN];
2685 char rib_nexthop_str[PREFIX_STRLEN];
2686 const char *rpf_ifname;
2687 struct pim_rpf *rpf = &up->rpf;
2688
2689 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
2690 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
2691 pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str,
2692 sizeof(rpf_addr_str));
2693 pim_addr_dump("<nexthop?>",
2694 &rpf->source_nexthop.mrib_nexthop_addr,
2695 rib_nexthop_str, sizeof(rib_nexthop_str));
2696
2697 rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
2698
2699 if (uj) {
2700 json_object_object_get_ex(json, grp_str, &json_group);
2701
2702 if (!json_group) {
2703 json_group = json_object_new_object();
2704 json_object_object_add(json, grp_str,
2705 json_group);
2706 }
2707
2708 json_row = json_object_new_object();
2709 json_object_string_add(json_row, "source", src_str);
2710 json_object_string_add(json_row, "group", grp_str);
2711 json_object_string_add(json_row, "rpfInterface",
2712 rpf_ifname);
2713 json_object_string_add(json_row, "rpfAddress",
2714 rpf_addr_str);
2715 json_object_string_add(json_row, "ribNexthop",
2716 rib_nexthop_str);
2717 json_object_int_add(
2718 json_row, "routeMetric",
2719 rpf->source_nexthop.mrib_route_metric);
2720 json_object_int_add(
2721 json_row, "routePreference",
2722 rpf->source_nexthop.mrib_metric_preference);
2723 json_object_object_add(json_group, src_str, json_row);
2724
2725 } else {
2726 vty_out(vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d\n",
2727 src_str, grp_str, rpf_ifname, rpf_addr_str,
2728 rib_nexthop_str,
2729 rpf->source_nexthop.mrib_route_metric,
2730 rpf->source_nexthop.mrib_metric_preference);
2731 }
2732 }
2733
2734 if (uj) {
2735 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2736 json, JSON_C_TO_STRING_PRETTY));
2737 json_object_free(json);
2738 }
2739 }
2740
2741 struct pnc_cache_walk_data {
2742 struct vty *vty;
2743 struct pim_instance *pim;
2744 };
2745
2746 static int pim_print_pnc_cache_walkcb(struct hash_backet *backet, void *arg)
2747 {
2748 struct pim_nexthop_cache *pnc = backet->data;
2749 struct pnc_cache_walk_data *cwd = arg;
2750 struct vty *vty = cwd->vty;
2751 struct pim_instance *pim = cwd->pim;
2752 struct nexthop *nh_node = NULL;
2753 ifindex_t first_ifindex;
2754 struct interface *ifp = NULL;
2755
2756 if (!pnc)
2757 return CMD_SUCCESS;
2758
2759 for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
2760 first_ifindex = nh_node->ifindex;
2761 ifp = if_lookup_by_index(first_ifindex, pim->vrf_id);
2762
2763 vty_out(vty, "%-15s ", inet_ntoa(pnc->rpf.rpf_addr.u.prefix4));
2764 vty_out(vty, "%-14s ", ifp ? ifp->name : "NULL");
2765 vty_out(vty, "%s ", inet_ntoa(nh_node->gate.ipv4));
2766 vty_out(vty, "\n");
2767 }
2768 return CMD_SUCCESS;
2769 }
2770
2771 static void pim_show_nexthop(struct pim_instance *pim, struct vty *vty)
2772 {
2773 struct pnc_cache_walk_data cwd;
2774
2775 cwd.vty = vty;
2776 cwd.pim = pim;
2777 vty_out(vty, "Number of registered addresses: %lu\n",
2778 pim->rpf_hash->count);
2779 vty_out(vty, "Address Interface Nexthop\n");
2780 vty_out(vty, "-------------------------------------------\n");
2781
2782 hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd);
2783 }
2784
2785 static void igmp_show_groups(struct pim_instance *pim, struct vty *vty,
2786 u_char uj)
2787 {
2788 struct interface *ifp;
2789 time_t now;
2790 json_object *json = NULL;
2791 json_object *json_iface = NULL;
2792 json_object *json_row = NULL;
2793
2794 now = pim_time_monotonic_sec();
2795
2796 if (uj)
2797 json = json_object_new_object();
2798 else
2799 vty_out(vty,
2800 "Interface Address Group Mode Timer Srcs V Uptime \n");
2801
2802 /* scan interfaces */
2803 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
2804 struct pim_interface *pim_ifp = ifp->info;
2805 struct listnode *sock_node;
2806 struct igmp_sock *igmp;
2807
2808 if (!pim_ifp)
2809 continue;
2810
2811 /* scan igmp sockets */
2812 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
2813 igmp)) {
2814 char ifaddr_str[INET_ADDRSTRLEN];
2815 struct listnode *grpnode;
2816 struct igmp_group *grp;
2817
2818 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
2819 sizeof(ifaddr_str));
2820
2821 /* scan igmp groups */
2822 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
2823 grpnode, grp)) {
2824 char group_str[INET_ADDRSTRLEN];
2825 char hhmmss[10];
2826 char uptime[10];
2827
2828 pim_inet4_dump("<group?>", grp->group_addr,
2829 group_str, sizeof(group_str));
2830 pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss),
2831 grp->t_group_timer);
2832 pim_time_uptime(uptime, sizeof(uptime),
2833 now - grp->group_creation);
2834
2835 if (uj) {
2836 json_object_object_get_ex(
2837 json, ifp->name, &json_iface);
2838
2839 if (!json_iface) {
2840 json_iface =
2841 json_object_new_object();
2842 json_object_pim_ifp_add(
2843 json_iface, ifp);
2844 json_object_object_add(
2845 json, ifp->name,
2846 json_iface);
2847 }
2848
2849 json_row = json_object_new_object();
2850 json_object_string_add(
2851 json_row, "source", ifaddr_str);
2852 json_object_string_add(
2853 json_row, "group", group_str);
2854
2855 if (grp->igmp_version == 3)
2856 json_object_string_add(
2857 json_row, "mode",
2858 grp->group_filtermode_isexcl
2859 ? "EXCLUDE"
2860 : "INCLUDE");
2861
2862 json_object_string_add(json_row,
2863 "timer", hhmmss);
2864 json_object_int_add(
2865 json_row, "sourcesCount",
2866 grp->group_source_list
2867 ? listcount(
2868 grp->group_source_list)
2869 : 0);
2870 json_object_int_add(json_row, "version",
2871 grp->igmp_version);
2872 json_object_string_add(
2873 json_row, "uptime", uptime);
2874 json_object_object_add(json_iface,
2875 group_str,
2876 json_row);
2877
2878 } else {
2879 vty_out(vty,
2880 "%-9s %-15s %-15s %4s %8s %4d %d %8s\n",
2881 ifp->name, ifaddr_str,
2882 group_str,
2883 grp->igmp_version == 3
2884 ? (grp->group_filtermode_isexcl
2885 ? "EXCL"
2886 : "INCL")
2887 : "----",
2888 hhmmss,
2889 grp->group_source_list
2890 ? listcount(
2891 grp->group_source_list)
2892 : 0,
2893 grp->igmp_version, uptime);
2894 }
2895 } /* scan igmp groups */
2896 } /* scan igmp sockets */
2897 } /* scan interfaces */
2898
2899 if (uj) {
2900 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2901 json, JSON_C_TO_STRING_PRETTY));
2902 json_object_free(json);
2903 }
2904 }
2905
2906 static void igmp_show_group_retransmission(struct pim_instance *pim,
2907 struct vty *vty)
2908 {
2909 struct interface *ifp;
2910
2911 vty_out(vty,
2912 "Interface Address Group RetTimer Counter RetSrcs\n");
2913
2914 /* scan interfaces */
2915 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
2916 struct pim_interface *pim_ifp = ifp->info;
2917 struct listnode *sock_node;
2918 struct igmp_sock *igmp;
2919
2920 if (!pim_ifp)
2921 continue;
2922
2923 /* scan igmp sockets */
2924 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
2925 igmp)) {
2926 char ifaddr_str[INET_ADDRSTRLEN];
2927 struct listnode *grpnode;
2928 struct igmp_group *grp;
2929
2930 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
2931 sizeof(ifaddr_str));
2932
2933 /* scan igmp groups */
2934 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
2935 grpnode, grp)) {
2936 char group_str[INET_ADDRSTRLEN];
2937 char grp_retr_mmss[10];
2938 struct listnode *src_node;
2939 struct igmp_source *src;
2940 int grp_retr_sources = 0;
2941
2942 pim_inet4_dump("<group?>", grp->group_addr,
2943 group_str, sizeof(group_str));
2944 pim_time_timer_to_mmss(
2945 grp_retr_mmss, sizeof(grp_retr_mmss),
2946 grp->t_group_query_retransmit_timer);
2947
2948
2949 /* count group sources with retransmission state
2950 */
2951 for (ALL_LIST_ELEMENTS_RO(
2952 grp->group_source_list, src_node,
2953 src)) {
2954 if (src->source_query_retransmit_count
2955 > 0) {
2956 ++grp_retr_sources;
2957 }
2958 }
2959
2960 vty_out(vty, "%-9s %-15s %-15s %-8s %7d %7d\n",
2961 ifp->name, ifaddr_str, group_str,
2962 grp_retr_mmss,
2963 grp->group_specific_query_retransmit_count,
2964 grp_retr_sources);
2965
2966 } /* scan igmp groups */
2967 } /* scan igmp sockets */
2968 } /* scan interfaces */
2969 }
2970
2971 static void igmp_show_sources(struct pim_instance *pim, struct vty *vty)
2972 {
2973 struct interface *ifp;
2974 time_t now;
2975
2976 now = pim_time_monotonic_sec();
2977
2978 vty_out(vty,
2979 "Interface Address Group Source Timer Fwd Uptime \n");
2980
2981 /* scan interfaces */
2982 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
2983 struct pim_interface *pim_ifp = ifp->info;
2984 struct listnode *sock_node;
2985 struct igmp_sock *igmp;
2986
2987 if (!pim_ifp)
2988 continue;
2989
2990 /* scan igmp sockets */
2991 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
2992 igmp)) {
2993 char ifaddr_str[INET_ADDRSTRLEN];
2994 struct listnode *grpnode;
2995 struct igmp_group *grp;
2996
2997 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
2998 sizeof(ifaddr_str));
2999
3000 /* scan igmp groups */
3001 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
3002 grpnode, grp)) {
3003 char group_str[INET_ADDRSTRLEN];
3004 struct listnode *srcnode;
3005 struct igmp_source *src;
3006
3007 pim_inet4_dump("<group?>", grp->group_addr,
3008 group_str, sizeof(group_str));
3009
3010 /* scan group sources */
3011 for (ALL_LIST_ELEMENTS_RO(
3012 grp->group_source_list, srcnode,
3013 src)) {
3014 char source_str[INET_ADDRSTRLEN];
3015 char mmss[10];
3016 char uptime[10];
3017
3018 pim_inet4_dump(
3019 "<source?>", src->source_addr,
3020 source_str, sizeof(source_str));
3021
3022 pim_time_timer_to_mmss(
3023 mmss, sizeof(mmss),
3024 src->t_source_timer);
3025
3026 pim_time_uptime(
3027 uptime, sizeof(uptime),
3028 now - src->source_creation);
3029
3030 vty_out(vty,
3031 "%-9s %-15s %-15s %-15s %5s %3s %8s\n",
3032 ifp->name, ifaddr_str,
3033 group_str, source_str, mmss,
3034 IGMP_SOURCE_TEST_FORWARDING(
3035 src->source_flags)
3036 ? "Y"
3037 : "N",
3038 uptime);
3039
3040 } /* scan group sources */
3041 } /* scan igmp groups */
3042 } /* scan igmp sockets */
3043 } /* scan interfaces */
3044 }
3045
3046 static void igmp_show_source_retransmission(struct pim_instance *pim,
3047 struct vty *vty)
3048 {
3049 struct interface *ifp;
3050
3051 vty_out(vty,
3052 "Interface Address Group Source Counter\n");
3053
3054 /* scan interfaces */
3055 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
3056 struct pim_interface *pim_ifp = ifp->info;
3057 struct listnode *sock_node;
3058 struct igmp_sock *igmp;
3059
3060 if (!pim_ifp)
3061 continue;
3062
3063 /* scan igmp sockets */
3064 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
3065 igmp)) {
3066 char ifaddr_str[INET_ADDRSTRLEN];
3067 struct listnode *grpnode;
3068 struct igmp_group *grp;
3069
3070 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
3071 sizeof(ifaddr_str));
3072
3073 /* scan igmp groups */
3074 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
3075 grpnode, grp)) {
3076 char group_str[INET_ADDRSTRLEN];
3077 struct listnode *srcnode;
3078 struct igmp_source *src;
3079
3080 pim_inet4_dump("<group?>", grp->group_addr,
3081 group_str, sizeof(group_str));
3082
3083 /* scan group sources */
3084 for (ALL_LIST_ELEMENTS_RO(
3085 grp->group_source_list, srcnode,
3086 src)) {
3087 char source_str[INET_ADDRSTRLEN];
3088
3089 pim_inet4_dump(
3090 "<source?>", src->source_addr,
3091 source_str, sizeof(source_str));
3092
3093 vty_out(vty,
3094 "%-9s %-15s %-15s %-15s %7d\n",
3095 ifp->name, ifaddr_str,
3096 group_str, source_str,
3097 src->source_query_retransmit_count);
3098
3099 } /* scan group sources */
3100 } /* scan igmp groups */
3101 } /* scan igmp sockets */
3102 } /* scan interfaces */
3103 }
3104
3105 static void clear_igmp_interfaces(struct pim_instance *pim)
3106 {
3107 struct interface *ifp;
3108
3109 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name)
3110 pim_if_addr_del_all_igmp(ifp);
3111
3112 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name)
3113 pim_if_addr_add_all(ifp);
3114 }
3115
3116 static void clear_pim_interfaces(struct pim_instance *pim)
3117 {
3118 struct interface *ifp;
3119
3120 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
3121 if (ifp->info) {
3122 pim_neighbor_delete_all(ifp, "interface cleared");
3123 }
3124 }
3125 }
3126
3127 static void clear_interfaces(struct pim_instance *pim)
3128 {
3129 clear_igmp_interfaces(pim);
3130 clear_pim_interfaces(pim);
3131 }
3132
3133 #define PIM_GET_PIM_INTERFACE(pim_ifp, ifp) \
3134 pim_ifp = ifp->info; \
3135 if (!pim_ifp) { \
3136 vty_out(vty, \
3137 "%% Enable PIM and/or IGMP on this interface first\n"); \
3138 return CMD_WARNING_CONFIG_FAILED; \
3139 }
3140
3141 DEFUN (clear_ip_interfaces,
3142 clear_ip_interfaces_cmd,
3143 "clear ip interfaces [vrf NAME]",
3144 CLEAR_STR
3145 IP_STR
3146 "Reset interfaces\n"
3147 VRF_CMD_HELP_STR)
3148 {
3149 int idx = 2;
3150 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3151
3152 if (!vrf)
3153 return CMD_WARNING;
3154
3155 clear_interfaces(vrf->info);
3156
3157 return CMD_SUCCESS;
3158 }
3159
3160 DEFUN (clear_ip_igmp_interfaces,
3161 clear_ip_igmp_interfaces_cmd,
3162 "clear ip igmp [vrf NAME] interfaces",
3163 CLEAR_STR
3164 IP_STR
3165 CLEAR_IP_IGMP_STR
3166 VRF_CMD_HELP_STR
3167 "Reset IGMP interfaces\n")
3168 {
3169 int idx = 2;
3170 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3171
3172 if (!vrf)
3173 return CMD_WARNING;
3174
3175 clear_igmp_interfaces(vrf->info);
3176
3177 return CMD_SUCCESS;
3178 }
3179
3180 static void mroute_add_all(struct pim_instance *pim)
3181 {
3182 struct listnode *node;
3183 struct channel_oil *c_oil;
3184
3185 for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
3186 if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) {
3187 /* just log warning */
3188 char source_str[INET_ADDRSTRLEN];
3189 char group_str[INET_ADDRSTRLEN];
3190 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
3191 source_str, sizeof(source_str));
3192 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
3193 group_str, sizeof(group_str));
3194 zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC",
3195 __FILE__, __PRETTY_FUNCTION__, source_str,
3196 group_str);
3197 }
3198 }
3199 }
3200
3201 static void mroute_del_all(struct pim_instance *pim)
3202 {
3203 struct listnode *node;
3204 struct channel_oil *c_oil;
3205
3206 for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
3207 if (pim_mroute_del(c_oil, __PRETTY_FUNCTION__)) {
3208 /* just log warning */
3209 char source_str[INET_ADDRSTRLEN];
3210 char group_str[INET_ADDRSTRLEN];
3211 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin,
3212 source_str, sizeof(source_str));
3213 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp,
3214 group_str, sizeof(group_str));
3215 zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC",
3216 __FILE__, __PRETTY_FUNCTION__, source_str,
3217 group_str);
3218 }
3219 }
3220 }
3221
3222 DEFUN (clear_ip_mroute,
3223 clear_ip_mroute_cmd,
3224 "clear ip mroute [vrf NAME]",
3225 CLEAR_STR
3226 IP_STR
3227 "Reset multicast routes\n"
3228 VRF_CMD_HELP_STR)
3229 {
3230 int idx = 2;
3231 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3232
3233 if (!vrf)
3234 return CMD_WARNING;
3235
3236 mroute_del_all(vrf->info);
3237 mroute_add_all(vrf->info);
3238
3239 return CMD_SUCCESS;
3240 }
3241
3242 DEFUN (clear_ip_pim_interfaces,
3243 clear_ip_pim_interfaces_cmd,
3244 "clear ip pim [vrf NAME] interfaces",
3245 CLEAR_STR
3246 IP_STR
3247 CLEAR_IP_PIM_STR
3248 VRF_CMD_HELP_STR
3249 "Reset PIM interfaces\n")
3250 {
3251 int idx = 2;
3252 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3253
3254 if (!vrf)
3255 return CMD_WARNING;
3256
3257 clear_pim_interfaces(vrf->info);
3258
3259 return CMD_SUCCESS;
3260 }
3261
3262 DEFUN (clear_ip_pim_interface_traffic,
3263 clear_ip_pim_interface_traffic_cmd,
3264 "clear ip pim [vrf NAME] interface traffic",
3265 "Reset functions\n"
3266 "IP information\n"
3267 "PIM clear commands\n"
3268 VRF_CMD_HELP_STR
3269 "Reset PIM interfaces\n"
3270 "Reset Protocol Packet counters\n")
3271 {
3272 int idx = 2;
3273 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3274 struct interface *ifp = NULL;
3275 struct pim_interface *pim_ifp = NULL;
3276
3277 if (!vrf)
3278 return CMD_WARNING;
3279
3280 RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name) {
3281 pim_ifp = ifp->info;
3282
3283 if (!pim_ifp)
3284 continue;
3285
3286 pim_ifp->pim_ifstat_hello_recv = 0;
3287 pim_ifp->pim_ifstat_hello_sent = 0;
3288 pim_ifp->pim_ifstat_join_recv = 0;
3289 pim_ifp->pim_ifstat_join_send = 0;
3290 pim_ifp->pim_ifstat_prune_recv = 0;
3291 pim_ifp->pim_ifstat_prune_send = 0;
3292 pim_ifp->pim_ifstat_reg_recv = 0;
3293 pim_ifp->pim_ifstat_reg_send = 0;
3294 pim_ifp->pim_ifstat_reg_stop_recv = 0;
3295 pim_ifp->pim_ifstat_reg_stop_send = 0;
3296 pim_ifp->pim_ifstat_assert_recv = 0;
3297 pim_ifp->pim_ifstat_assert_send = 0;
3298 }
3299
3300 return CMD_SUCCESS;
3301 }
3302
3303 DEFUN (clear_ip_pim_oil,
3304 clear_ip_pim_oil_cmd,
3305 "clear ip pim [vrf NAME] oil",
3306 CLEAR_STR
3307 IP_STR
3308 CLEAR_IP_PIM_STR
3309 VRF_CMD_HELP_STR
3310 "Rescan PIM OIL (output interface list)\n")
3311 {
3312 int idx = 2;
3313 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3314
3315 if (!vrf)
3316 return CMD_WARNING;
3317
3318 pim_scan_oil(vrf->info);
3319
3320 return CMD_SUCCESS;
3321 }
3322
3323 DEFUN (show_ip_igmp_interface,
3324 show_ip_igmp_interface_cmd,
3325 "show ip igmp [vrf NAME] interface [detail|WORD] [json]",
3326 SHOW_STR
3327 IP_STR
3328 IGMP_STR
3329 VRF_CMD_HELP_STR
3330 "IGMP interface information\n"
3331 "Detailed output\n"
3332 "interface name\n"
3333 JSON_STR)
3334 {
3335 int idx = 2;
3336 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3337 u_char uj = use_json(argc, argv);
3338
3339 if (!vrf)
3340 return CMD_WARNING;
3341
3342 if (argv_find(argv, argc, "detail", &idx)
3343 || argv_find(argv, argc, "WORD", &idx))
3344 igmp_show_interfaces_single(vrf->info, vty, argv[idx]->arg, uj);
3345 else
3346 igmp_show_interfaces(vrf->info, vty, uj);
3347
3348 return CMD_SUCCESS;
3349 }
3350
3351 DEFUN (show_ip_igmp_interface_vrf_all,
3352 show_ip_igmp_interface_vrf_all_cmd,
3353 "show ip igmp vrf all interface [detail|WORD] [json]",
3354 SHOW_STR
3355 IP_STR
3356 IGMP_STR
3357 VRF_CMD_HELP_STR
3358 "IGMP interface information\n"
3359 "Detailed output\n"
3360 "interface name\n"
3361 JSON_STR)
3362 {
3363 int idx = 2;
3364 u_char uj = use_json(argc, argv);
3365 struct vrf *vrf;
3366 bool first = true;
3367
3368 if (uj)
3369 vty_out(vty, "{ ");
3370 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3371 if (uj) {
3372 if (!first)
3373 vty_out(vty, ", ");
3374 vty_out(vty, " \"%s\": ", vrf->name);
3375 first = false;
3376 } else
3377 vty_out(vty, "VRF: %s\n", vrf->name);
3378 if (argv_find(argv, argc, "detail", &idx)
3379 || argv_find(argv, argc, "WORD", &idx))
3380 igmp_show_interfaces_single(vrf->info, vty,
3381 argv[idx]->arg, uj);
3382 else
3383 igmp_show_interfaces(vrf->info, vty, uj);
3384 }
3385 if (uj)
3386 vty_out(vty, "}\n");
3387
3388 return CMD_SUCCESS;
3389 }
3390
3391 DEFUN (show_ip_igmp_join,
3392 show_ip_igmp_join_cmd,
3393 "show ip igmp [vrf NAME] join",
3394 SHOW_STR
3395 IP_STR
3396 IGMP_STR
3397 VRF_CMD_HELP_STR
3398 "IGMP static join information\n")
3399 {
3400 int idx = 2;
3401 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3402
3403 if (!vrf)
3404 return CMD_WARNING;
3405
3406 igmp_show_interface_join(vrf->info, vty);
3407
3408 return CMD_SUCCESS;
3409 }
3410
3411 DEFUN (show_ip_igmp_join_vrf_all,
3412 show_ip_igmp_join_vrf_all_cmd,
3413 "show ip igmp vrf all join",
3414 SHOW_STR
3415 IP_STR
3416 IGMP_STR
3417 VRF_CMD_HELP_STR
3418 "IGMP static join information\n")
3419 {
3420 u_char uj = use_json(argc, argv);
3421 struct vrf *vrf;
3422 bool first = true;
3423
3424 if (uj)
3425 vty_out(vty, "{ ");
3426 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3427 if (uj) {
3428 if (!first)
3429 vty_out(vty, ", ");
3430 vty_out(vty, " \"%s\": ", vrf->name);
3431 first = false;
3432 } else
3433 vty_out(vty, "VRF: %s\n", vrf->name);
3434 igmp_show_interface_join(vrf->info, vty);
3435 }
3436 if (uj)
3437 vty_out(vty, "}\n");
3438
3439 return CMD_SUCCESS;
3440 }
3441
3442 DEFUN (show_ip_igmp_groups,
3443 show_ip_igmp_groups_cmd,
3444 "show ip igmp [vrf NAME] groups [json]",
3445 SHOW_STR
3446 IP_STR
3447 IGMP_STR
3448 VRF_CMD_HELP_STR
3449 IGMP_GROUP_STR
3450 JSON_STR)
3451 {
3452 int idx = 2;
3453 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3454 u_char uj = use_json(argc, argv);
3455
3456 if (!vrf)
3457 return CMD_WARNING;
3458
3459 igmp_show_groups(vrf->info, vty, uj);
3460
3461 return CMD_SUCCESS;
3462 }
3463
3464 DEFUN (show_ip_igmp_groups_vrf_all,
3465 show_ip_igmp_groups_vrf_all_cmd,
3466 "show ip igmp vrf all groups [json]",
3467 SHOW_STR
3468 IP_STR
3469 IGMP_STR
3470 VRF_CMD_HELP_STR
3471 IGMP_GROUP_STR
3472 JSON_STR)
3473 {
3474 u_char uj = use_json(argc, argv);
3475 struct vrf *vrf;
3476 bool first = true;
3477
3478 if (uj)
3479 vty_out(vty, "{ ");
3480 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3481 if (uj) {
3482 if (!first)
3483 vty_out(vty, ", ");
3484 vty_out(vty, " \"%s\": ", vrf->name);
3485 first = false;
3486 } else
3487 vty_out(vty, "VRF: %s\n", vrf->name);
3488 igmp_show_groups(vrf->info, vty, uj);
3489 }
3490 if (uj)
3491 vty_out(vty, "}\n");
3492
3493 return CMD_SUCCESS;
3494 }
3495
3496 DEFUN (show_ip_igmp_groups_retransmissions,
3497 show_ip_igmp_groups_retransmissions_cmd,
3498 "show ip igmp [vrf NAME] groups retransmissions",
3499 SHOW_STR
3500 IP_STR
3501 IGMP_STR
3502 VRF_CMD_HELP_STR
3503 IGMP_GROUP_STR
3504 "IGMP group retransmissions\n")
3505 {
3506 int idx = 2;
3507 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3508
3509 if (!vrf)
3510 return CMD_WARNING;
3511
3512 igmp_show_group_retransmission(vrf->info, vty);
3513
3514 return CMD_SUCCESS;
3515 }
3516
3517 DEFUN (show_ip_igmp_sources,
3518 show_ip_igmp_sources_cmd,
3519 "show ip igmp [vrf NAME] sources",
3520 SHOW_STR
3521 IP_STR
3522 IGMP_STR
3523 VRF_CMD_HELP_STR
3524 IGMP_SOURCE_STR)
3525 {
3526 int idx = 2;
3527 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3528
3529 if (!vrf)
3530 return CMD_WARNING;
3531
3532 igmp_show_sources(vrf->info, vty);
3533
3534 return CMD_SUCCESS;
3535 }
3536
3537 DEFUN (show_ip_igmp_sources_retransmissions,
3538 show_ip_igmp_sources_retransmissions_cmd,
3539 "show ip igmp [vrf NAME] sources retransmissions",
3540 SHOW_STR
3541 IP_STR
3542 IGMP_STR
3543 VRF_CMD_HELP_STR
3544 IGMP_SOURCE_STR
3545 "IGMP source retransmissions\n")
3546 {
3547 int idx = 2;
3548 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3549
3550 if (!vrf)
3551 return CMD_WARNING;
3552
3553 igmp_show_source_retransmission(vrf->info, vty);
3554
3555 return CMD_SUCCESS;
3556 }
3557
3558 DEFUN (show_ip_pim_assert,
3559 show_ip_pim_assert_cmd,
3560 "show ip pim [vrf NAME] assert",
3561 SHOW_STR
3562 IP_STR
3563 PIM_STR
3564 VRF_CMD_HELP_STR
3565 "PIM interface assert\n")
3566 {
3567 int idx = 2;
3568 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3569
3570 if (!vrf)
3571 return CMD_WARNING;
3572
3573 pim_show_assert(vrf->info, vty);
3574
3575 return CMD_SUCCESS;
3576 }
3577
3578 DEFUN (show_ip_pim_assert_internal,
3579 show_ip_pim_assert_internal_cmd,
3580 "show ip pim [vrf NAME] assert-internal",
3581 SHOW_STR
3582 IP_STR
3583 PIM_STR
3584 VRF_CMD_HELP_STR
3585 "PIM interface internal assert state\n")
3586 {
3587 int idx = 2;
3588 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3589
3590 if (!vrf)
3591 return CMD_WARNING;
3592
3593 pim_show_assert_internal(vrf->info, vty);
3594
3595 return CMD_SUCCESS;
3596 }
3597
3598 DEFUN (show_ip_pim_assert_metric,
3599 show_ip_pim_assert_metric_cmd,
3600 "show ip pim [vrf NAME] assert-metric",
3601 SHOW_STR
3602 IP_STR
3603 PIM_STR
3604 VRF_CMD_HELP_STR
3605 "PIM interface assert metric\n")
3606 {
3607 int idx = 2;
3608 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3609
3610 if (!vrf)
3611 return CMD_WARNING;
3612
3613 pim_show_assert_metric(vrf->info, vty);
3614
3615 return CMD_SUCCESS;
3616 }
3617
3618 DEFUN (show_ip_pim_assert_winner_metric,
3619 show_ip_pim_assert_winner_metric_cmd,
3620 "show ip pim [vrf NAME] assert-winner-metric",
3621 SHOW_STR
3622 IP_STR
3623 PIM_STR
3624 VRF_CMD_HELP_STR
3625 "PIM interface assert winner metric\n")
3626 {
3627 int idx = 2;
3628 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3629
3630 if (!vrf)
3631 return CMD_WARNING;
3632
3633 pim_show_assert_winner_metric(vrf->info, vty);
3634
3635 return CMD_SUCCESS;
3636 }
3637
3638 DEFUN (show_ip_pim_interface,
3639 show_ip_pim_interface_cmd,
3640 "show ip pim [vrf NAME] interface [detail|WORD] [json]",
3641 SHOW_STR
3642 IP_STR
3643 PIM_STR
3644 VRF_CMD_HELP_STR
3645 "PIM interface information\n"
3646 "Detailed output\n"
3647 "interface name\n"
3648 JSON_STR)
3649 {
3650 int idx = 2;
3651 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3652 u_char uj = use_json(argc, argv);
3653
3654 if (!vrf)
3655 return CMD_WARNING;
3656
3657 if (argv_find(argv, argc, "WORD", &idx)
3658 || argv_find(argv, argc, "detail", &idx))
3659 pim_show_interfaces_single(vrf->info, vty, argv[idx]->arg, uj);
3660 else
3661 pim_show_interfaces(vrf->info, vty, uj);
3662
3663 return CMD_SUCCESS;
3664 }
3665
3666 DEFUN (show_ip_pim_interface_vrf_all,
3667 show_ip_pim_interface_vrf_all_cmd,
3668 "show ip pim vrf all interface [detail|WORD] [json]",
3669 SHOW_STR
3670 IP_STR
3671 PIM_STR
3672 VRF_CMD_HELP_STR
3673 "PIM interface information\n"
3674 "Detailed output\n"
3675 "interface name\n"
3676 JSON_STR)
3677 {
3678 int idx = 6;
3679 u_char uj = use_json(argc, argv);
3680 struct vrf *vrf;
3681 bool first = true;
3682
3683 if (uj)
3684 vty_out(vty, "{ ");
3685 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3686 if (uj) {
3687 if (!first)
3688 vty_out(vty, ", ");
3689 vty_out(vty, " \"%s\": ", vrf->name);
3690 first = false;
3691 } else
3692 vty_out(vty, "VRF: %s\n", vrf->name);
3693 if (argv_find(argv, argc, "WORD", &idx)
3694 || argv_find(argv, argc, "detail", &idx))
3695 pim_show_interfaces_single(vrf->info, vty,
3696 argv[idx]->arg, uj);
3697 else
3698 pim_show_interfaces(vrf->info, vty, uj);
3699 }
3700 if (uj)
3701 vty_out(vty, "}\n");
3702
3703 return CMD_SUCCESS;
3704 }
3705
3706 DEFUN (show_ip_pim_join,
3707 show_ip_pim_join_cmd,
3708 "show ip pim [vrf NAME] join [json]",
3709 SHOW_STR
3710 IP_STR
3711 PIM_STR
3712 VRF_CMD_HELP_STR
3713 "PIM interface join information\n"
3714 JSON_STR)
3715 {
3716 int idx = 2;
3717 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3718 u_char uj = use_json(argc, argv);
3719
3720 if (!vrf)
3721 return CMD_WARNING;
3722
3723 pim_show_join(vrf->info, vty, uj);
3724
3725 return CMD_SUCCESS;
3726 }
3727
3728 DEFUN (show_ip_pim_join_vrf_all,
3729 show_ip_pim_join_vrf_all_cmd,
3730 "show ip pim vrf all join [json]",
3731 SHOW_STR
3732 IP_STR
3733 PIM_STR
3734 VRF_CMD_HELP_STR
3735 "PIM interface join information\n"
3736 JSON_STR)
3737 {
3738 u_char uj = use_json(argc, argv);
3739 struct vrf *vrf;
3740 bool first = true;
3741
3742 if (uj)
3743 vty_out(vty, "{ ");
3744 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3745 if (uj) {
3746 if (!first)
3747 vty_out(vty, ", ");
3748 vty_out(vty, " \"%s\": ", vrf->name);
3749 first = false;
3750 } else
3751 vty_out(vty, "VRF: %s\n", vrf->name);
3752 pim_show_join(vrf->info, vty, uj);
3753 }
3754 if (uj)
3755 vty_out(vty, "}\n");
3756
3757 return CMD_WARNING;
3758 }
3759
3760 DEFUN (show_ip_pim_local_membership,
3761 show_ip_pim_local_membership_cmd,
3762 "show ip pim [vrf NAME] local-membership [json]",
3763 SHOW_STR
3764 IP_STR
3765 PIM_STR
3766 VRF_CMD_HELP_STR
3767 "PIM interface local-membership\n"
3768 JSON_STR)
3769 {
3770 int idx = 2;
3771 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3772 u_char uj = use_json(argc, argv);
3773
3774 if (!vrf)
3775 return CMD_WARNING;
3776
3777 pim_show_membership(vrf->info, vty, uj);
3778
3779 return CMD_SUCCESS;
3780 }
3781
3782 DEFUN (show_ip_pim_neighbor,
3783 show_ip_pim_neighbor_cmd,
3784 "show ip pim [vrf NAME] neighbor [detail|WORD] [json]",
3785 SHOW_STR
3786 IP_STR
3787 PIM_STR
3788 VRF_CMD_HELP_STR
3789 "PIM neighbor information\n"
3790 "Detailed output\n"
3791 "Name of interface or neighbor\n"
3792 JSON_STR)
3793 {
3794 int idx = 2;
3795 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3796 u_char uj = use_json(argc, argv);
3797
3798 if (!vrf)
3799 return CMD_WARNING;
3800
3801 if (argv_find(argv, argc, "detail", &idx)
3802 || argv_find(argv, argc, "WORD", &idx))
3803 pim_show_neighbors_single(vrf->info, vty, argv[idx]->arg, uj);
3804 else
3805 pim_show_neighbors(vrf->info, vty, uj);
3806
3807 return CMD_SUCCESS;
3808 }
3809
3810 DEFUN (show_ip_pim_neighbor_vrf_all,
3811 show_ip_pim_neighbor_vrf_all_cmd,
3812 "show ip pim vrf all neighbor [detail|WORD] [json]",
3813 SHOW_STR
3814 IP_STR
3815 PIM_STR
3816 VRF_CMD_HELP_STR
3817 "PIM neighbor information\n"
3818 "Detailed output\n"
3819 "Name of interface or neighbor\n"
3820 JSON_STR)
3821 {
3822 int idx = 2;
3823 u_char uj = use_json(argc, argv);
3824 struct vrf *vrf;
3825 bool first = true;
3826
3827 if (uj)
3828 vty_out(vty, "{ ");
3829 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3830 if (uj) {
3831 if (!first)
3832 vty_out(vty, ", ");
3833 vty_out(vty, " \"%s\": ", vrf->name);
3834 first = false;
3835 } else
3836 vty_out(vty, "VRF: %s\n", vrf->name);
3837 if (argv_find(argv, argc, "detail", &idx)
3838 || argv_find(argv, argc, "WORD", &idx))
3839 pim_show_neighbors_single(vrf->info, vty,
3840 argv[idx]->arg, uj);
3841 else
3842 pim_show_neighbors(vrf->info, vty, uj);
3843 }
3844 if (uj)
3845 vty_out(vty, "}\n");
3846
3847 return CMD_SUCCESS;
3848 }
3849
3850 DEFUN (show_ip_pim_secondary,
3851 show_ip_pim_secondary_cmd,
3852 "show ip pim [vrf NAME] secondary",
3853 SHOW_STR
3854 IP_STR
3855 PIM_STR
3856 VRF_CMD_HELP_STR
3857 "PIM neighbor addresses\n")
3858 {
3859 int idx = 2;
3860 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3861
3862 if (!vrf)
3863 return CMD_WARNING;
3864
3865 pim_show_neighbors_secondary(vrf->info, vty);
3866
3867 return CMD_SUCCESS;
3868 }
3869
3870 DEFUN (show_ip_pim_state,
3871 show_ip_pim_state_cmd,
3872 "show ip pim [vrf NAME] state [A.B.C.D [A.B.C.D]] [json]",
3873 SHOW_STR
3874 IP_STR
3875 PIM_STR
3876 VRF_CMD_HELP_STR
3877 "PIM state information\n"
3878 "Unicast or Multicast address\n"
3879 "Multicast address\n"
3880 JSON_STR)
3881 {
3882 const char *src_or_group = NULL;
3883 const char *group = NULL;
3884 int idx = 2;
3885 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3886 u_char uj = use_json(argc, argv);
3887
3888 if (!vrf)
3889 return CMD_WARNING;
3890
3891 if (uj)
3892 argc--;
3893
3894 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
3895 src_or_group = argv[idx]->arg;
3896 if (idx + 1 < argc)
3897 group = argv[idx + 1]->arg;
3898 }
3899
3900 pim_show_state(vrf->info, vty, src_or_group, group, uj);
3901
3902 return CMD_SUCCESS;
3903 }
3904
3905 DEFUN (show_ip_pim_state_vrf_all,
3906 show_ip_pim_state_vrf_all_cmd,
3907 "show ip pim vrf all state [A.B.C.D [A.B.C.D]] [json]",
3908 SHOW_STR
3909 IP_STR
3910 PIM_STR
3911 VRF_CMD_HELP_STR
3912 "PIM state information\n"
3913 "Unicast or Multicast address\n"
3914 "Multicast address\n"
3915 JSON_STR)
3916 {
3917 const char *src_or_group = NULL;
3918 const char *group = NULL;
3919 int idx = 2;
3920 u_char uj = use_json(argc, argv);
3921 struct vrf *vrf;
3922 bool first = true;
3923
3924 if (uj) {
3925 vty_out(vty, "{ ");
3926 argc--;
3927 }
3928
3929 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
3930 src_or_group = argv[idx]->arg;
3931 if (idx + 1 < argc)
3932 group = argv[idx + 1]->arg;
3933 }
3934
3935 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3936 if (uj) {
3937 if (!first)
3938 vty_out(vty, ", ");
3939 vty_out(vty, " \"%s\": ", vrf->name);
3940 first = false;
3941 } else
3942 vty_out(vty, "VRF: %s\n", vrf->name);
3943 pim_show_state(vrf->info, vty, src_or_group, group, uj);
3944 }
3945 if (uj)
3946 vty_out(vty, "}\n");
3947
3948 return CMD_SUCCESS;
3949 }
3950
3951 DEFUN (show_ip_pim_upstream,
3952 show_ip_pim_upstream_cmd,
3953 "show ip pim [vrf NAME] upstream [json]",
3954 SHOW_STR
3955 IP_STR
3956 PIM_STR
3957 VRF_CMD_HELP_STR
3958 "PIM upstream information\n"
3959 JSON_STR)
3960 {
3961 int idx = 2;
3962 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
3963 u_char uj = use_json(argc, argv);
3964
3965 if (!vrf)
3966 return CMD_WARNING;
3967
3968 pim_show_upstream(vrf->info, vty, uj);
3969
3970 return CMD_SUCCESS;
3971 }
3972
3973 DEFUN (show_ip_pim_upstream_vrf_all,
3974 show_ip_pim_upstream_vrf_all_cmd,
3975 "show ip pim vrf all upstream [json]",
3976 SHOW_STR
3977 IP_STR
3978 PIM_STR
3979 VRF_CMD_HELP_STR
3980 "PIM upstream information\n"
3981 JSON_STR)
3982 {
3983 u_char uj = use_json(argc, argv);
3984 struct vrf *vrf;
3985 bool first = true;
3986
3987 if (uj)
3988 vty_out(vty, "{ ");
3989 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3990 if (uj) {
3991 if (!first)
3992 vty_out(vty, ", ");
3993 vty_out(vty, " \"%s\": ", vrf->name);
3994 first = false;
3995 } else
3996 vty_out(vty, "VRF: %s\n", vrf->name);
3997 pim_show_upstream(vrf->info, vty, uj);
3998 }
3999
4000 return CMD_SUCCESS;
4001 }
4002
4003 DEFUN (show_ip_pim_upstream_join_desired,
4004 show_ip_pim_upstream_join_desired_cmd,
4005 "show ip pim [vrf NAME] upstream-join-desired [json]",
4006 SHOW_STR
4007 IP_STR
4008 PIM_STR
4009 VRF_CMD_HELP_STR
4010 "PIM upstream join-desired\n"
4011 JSON_STR)
4012 {
4013 int idx = 2;
4014 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4015 u_char uj = use_json(argc, argv);
4016
4017 if (!vrf)
4018 return CMD_WARNING;
4019
4020 pim_show_join_desired(vrf->info, vty, uj);
4021
4022 return CMD_SUCCESS;
4023 }
4024
4025 DEFUN (show_ip_pim_upstream_rpf,
4026 show_ip_pim_upstream_rpf_cmd,
4027 "show ip pim [vrf NAME] upstream-rpf [json]",
4028 SHOW_STR
4029 IP_STR
4030 PIM_STR
4031 VRF_CMD_HELP_STR
4032 "PIM upstream source rpf\n"
4033 JSON_STR)
4034 {
4035 int idx = 2;
4036 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4037 u_char uj = use_json(argc, argv);
4038
4039 if (!vrf)
4040 return CMD_WARNING;
4041
4042 pim_show_upstream_rpf(vrf->info, vty, uj);
4043
4044 return CMD_SUCCESS;
4045 }
4046
4047 DEFUN (show_ip_pim_rp,
4048 show_ip_pim_rp_cmd,
4049 "show ip pim [vrf NAME] rp-info [json]",
4050 SHOW_STR
4051 IP_STR
4052 PIM_STR
4053 VRF_CMD_HELP_STR
4054 "PIM RP information\n"
4055 JSON_STR)
4056 {
4057 int idx = 2;
4058 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4059 u_char uj = use_json(argc, argv);
4060
4061 if (!vrf)
4062 return CMD_WARNING;
4063
4064 pim_rp_show_information(vrf->info, vty, uj);
4065
4066 return CMD_SUCCESS;
4067 }
4068
4069 DEFUN (show_ip_pim_rp_vrf_all,
4070 show_ip_pim_rp_vrf_all_cmd,
4071 "show ip pim vrf all rp-info [json]",
4072 SHOW_STR
4073 IP_STR
4074 PIM_STR
4075 VRF_CMD_HELP_STR
4076 "PIM RP information\n"
4077 JSON_STR)
4078 {
4079 u_char uj = use_json(argc, argv);
4080 struct vrf *vrf;
4081 bool first = true;
4082
4083 if (uj)
4084 vty_out(vty, "{ ");
4085 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4086 if (uj) {
4087 if (!first)
4088 vty_out(vty, ", ");
4089 vty_out(vty, " \"%s\": ", vrf->name);
4090 first = false;
4091 } else
4092 vty_out(vty, "VRF: %s\n", vrf->name);
4093 pim_rp_show_information(vrf->info, vty, uj);
4094 }
4095 if (uj)
4096 vty_out(vty, "}\n");
4097
4098 return CMD_SUCCESS;
4099 }
4100
4101 DEFUN (show_ip_pim_rpf,
4102 show_ip_pim_rpf_cmd,
4103 "show ip pim [vrf NAME] rpf [json]",
4104 SHOW_STR
4105 IP_STR
4106 PIM_STR
4107 VRF_CMD_HELP_STR
4108 "PIM cached source rpf information\n"
4109 JSON_STR)
4110 {
4111 int idx = 2;
4112 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4113 u_char uj = use_json(argc, argv);
4114
4115 if (!vrf)
4116 return CMD_WARNING;
4117
4118 pim_show_rpf(vrf->info, vty, uj);
4119
4120 return CMD_SUCCESS;
4121 }
4122
4123 DEFUN (show_ip_pim_rpf_vrf_all,
4124 show_ip_pim_rpf_vrf_all_cmd,
4125 "show ip pim vrf all rpf [json]",
4126 SHOW_STR
4127 IP_STR
4128 PIM_STR
4129 VRF_CMD_HELP_STR
4130 "PIM cached source rpf information\n"
4131 JSON_STR)
4132 {
4133 u_char uj = use_json(argc, argv);
4134 struct vrf *vrf;
4135 bool first = true;
4136
4137 if (uj)
4138 vty_out(vty, "{ ");
4139 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4140 if (uj) {
4141 if (!first)
4142 vty_out(vty, ", ");
4143 vty_out(vty, " \"%s\": ", vrf->name);
4144 first = false;
4145 } else
4146 vty_out(vty, "VRF: %s\n", vrf->name);
4147 pim_show_rpf(vrf->info, vty, uj);
4148 }
4149 if (uj)
4150 vty_out(vty, "}\n");
4151
4152 return CMD_SUCCESS;
4153 }
4154
4155 DEFUN (show_ip_pim_nexthop,
4156 show_ip_pim_nexthop_cmd,
4157 "show ip pim [vrf NAME] nexthop",
4158 SHOW_STR
4159 IP_STR
4160 PIM_STR
4161 VRF_CMD_HELP_STR
4162 "PIM cached nexthop rpf information\n")
4163 {
4164 int idx = 2;
4165 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4166
4167 if (!vrf)
4168 return CMD_WARNING;
4169
4170 pim_show_nexthop(vrf->info, vty);
4171
4172 return CMD_SUCCESS;
4173 }
4174
4175 DEFUN (show_ip_pim_nexthop_lookup,
4176 show_ip_pim_nexthop_lookup_cmd,
4177 "show ip pim [vrf NAME] nexthop-lookup A.B.C.D A.B.C.D",
4178 SHOW_STR
4179 IP_STR
4180 PIM_STR
4181 VRF_CMD_HELP_STR
4182 "PIM cached nexthop rpf lookup\n"
4183 "Source/RP address\n"
4184 "Multicast Group address\n")
4185 {
4186 struct pim_nexthop_cache pnc;
4187 struct prefix nht_p;
4188 int result = 0;
4189 struct in_addr src_addr, grp_addr;
4190 struct in_addr vif_source;
4191 const char *addr_str, *addr_str1;
4192 struct prefix grp;
4193 struct pim_nexthop nexthop;
4194 char nexthop_addr_str[PREFIX_STRLEN];
4195 char grp_str[PREFIX_STRLEN];
4196 int idx = 2;
4197 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4198
4199 if (!vrf)
4200 return CMD_WARNING;
4201
4202 argv_find(argv, argc, "A.B.C.D", &idx);
4203 addr_str = argv[idx]->arg;
4204 result = inet_pton(AF_INET, addr_str, &src_addr);
4205 if (result <= 0) {
4206 vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str,
4207 errno, safe_strerror(errno));
4208 return CMD_WARNING;
4209 }
4210
4211 if (pim_is_group_224_4(src_addr)) {
4212 vty_out(vty,
4213 "Invalid argument. Expected Valid Source Address.\n");
4214 return CMD_WARNING;
4215 }
4216
4217 addr_str1 = argv[idx + 1]->arg;
4218 result = inet_pton(AF_INET, addr_str1, &grp_addr);
4219 if (result <= 0) {
4220 vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str,
4221 errno, safe_strerror(errno));
4222 return CMD_WARNING;
4223 }
4224
4225 if (!pim_is_group_224_4(grp_addr)) {
4226 vty_out(vty,
4227 "Invalid argument. Expected Valid Multicast Group Address.\n");
4228 return CMD_WARNING;
4229 }
4230
4231 if (!pim_rp_set_upstream_addr(vrf->info, &vif_source, src_addr,
4232 grp_addr))
4233 return CMD_SUCCESS;
4234
4235 memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
4236 nht_p.family = AF_INET;
4237 nht_p.prefixlen = IPV4_MAX_BITLEN;
4238 nht_p.u.prefix4 = vif_source;
4239 grp.family = AF_INET;
4240 grp.prefixlen = IPV4_MAX_BITLEN;
4241 grp.u.prefix4 = grp_addr;
4242 memset(&nexthop, 0, sizeof(nexthop));
4243
4244 if (pim_find_or_track_nexthop(vrf->info, &nht_p, NULL, NULL, &pnc))
4245 pim_ecmp_nexthop_search(vrf->info, &pnc, &nexthop, &nht_p, &grp,
4246 0);
4247 else
4248 pim_ecmp_nexthop_lookup(vrf->info, &nexthop, vif_source, &nht_p,
4249 &grp, 0);
4250
4251 pim_addr_dump("<grp?>", &grp, grp_str, sizeof(grp_str));
4252 pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr,
4253 nexthop_addr_str, sizeof(nexthop_addr_str));
4254 vty_out(vty, "Group %s --- Nexthop %s Interface %s \n", grp_str,
4255 nexthop_addr_str, nexthop.interface->name);
4256
4257 return CMD_SUCCESS;
4258 }
4259
4260 DEFUN (show_ip_pim_interface_traffic,
4261 show_ip_pim_interface_traffic_cmd,
4262 "show ip pim [vrf NAME] interface traffic [WORD] [json]",
4263 SHOW_STR
4264 IP_STR
4265 PIM_STR
4266 VRF_CMD_HELP_STR
4267 "PIM interface information\n"
4268 "Protocol Packet counters\n"
4269 "Interface name\n"
4270 JSON_STR)
4271 {
4272 int idx = 2;
4273 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4274 u_char uj = use_json(argc, argv);
4275
4276 if (!vrf)
4277 return CMD_WARNING;
4278
4279 if (argv_find(argv, argc, "WORD", &idx))
4280 pim_show_interface_traffic_single(vrf->info, vty,
4281 argv[idx]->arg, uj);
4282 else
4283 pim_show_interface_traffic(vrf->info, vty, uj);
4284
4285 return CMD_SUCCESS;
4286 }
4287
4288 static void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty)
4289 {
4290 struct interface *ifp;
4291
4292 vty_out(vty, "\n");
4293
4294 vty_out(vty,
4295 "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut\n");
4296
4297 RB_FOREACH (ifp, if_name_head, &pim->vrf->ifaces_by_name) {
4298 struct pim_interface *pim_ifp;
4299 struct in_addr ifaddr;
4300 struct sioc_vif_req vreq;
4301
4302 pim_ifp = ifp->info;
4303
4304 if (!pim_ifp)
4305 continue;
4306
4307 memset(&vreq, 0, sizeof(vreq));
4308 vreq.vifi = pim_ifp->mroute_vif_index;
4309
4310 if (ioctl(pim->mroute_socket, SIOCGETVIFCNT, &vreq)) {
4311 zlog_warn(
4312 "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
4313 (unsigned long)SIOCGETVIFCNT, ifp->name,
4314 pim_ifp->mroute_vif_index, errno,
4315 safe_strerror(errno));
4316 }
4317
4318 ifaddr = pim_ifp->primary_address;
4319
4320 vty_out(vty, "%-12s %-15s %3d %3d %7lu %7lu %10lu %10lu\n",
4321 ifp->name, inet_ntoa(ifaddr), ifp->ifindex,
4322 pim_ifp->mroute_vif_index, (unsigned long)vreq.icount,
4323 (unsigned long)vreq.ocount, (unsigned long)vreq.ibytes,
4324 (unsigned long)vreq.obytes);
4325 }
4326 }
4327
4328 static void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim,
4329 struct vty *vty)
4330 {
4331 struct vrf *vrf = pim->vrf;
4332 time_t now = pim_time_monotonic_sec();
4333 char uptime[10];
4334
4335 pim = vrf->info;
4336
4337 vty_out(vty, "Mroute socket descriptor:");
4338
4339 vty_out(vty, " %d(%s)\n", pim->mroute_socket, vrf->name);
4340
4341 pim_time_uptime(uptime, sizeof(uptime),
4342 now - pim->mroute_socket_creation);
4343 vty_out(vty, "Mroute socket uptime: %s\n", uptime);
4344
4345 vty_out(vty, "\n");
4346
4347 pim_zebra_zclient_update(vty);
4348 pim_zlookup_show_ip_multicast(vty);
4349
4350 vty_out(vty, "\n");
4351 vty_out(vty, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS);
4352
4353 vty_out(vty, "\n");
4354 vty_out(vty, "Upstream Join Timer: %d secs\n", qpim_t_periodic);
4355 vty_out(vty, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME);
4356 vty_out(vty, "PIM ECMP: %s\n", qpim_ecmp_enable ? "Enable" : "Disable");
4357 vty_out(vty, "PIM ECMP Rebalance: %s\n",
4358 qpim_ecmp_rebalance_enable ? "Enable" : "Disable");
4359
4360 vty_out(vty, "\n");
4361
4362 show_rpf_refresh_stats(vty, now, NULL);
4363
4364 vty_out(vty, "\n");
4365
4366 show_scan_oil_stats(pim, vty, now);
4367
4368 show_multicast_interfaces(pim, vty);
4369 }
4370
4371 DEFUN (show_ip_multicast,
4372 show_ip_multicast_cmd,
4373 "show ip multicast [vrf NAME]",
4374 SHOW_STR
4375 IP_STR
4376 VRF_CMD_HELP_STR
4377 "Multicast global information\n")
4378 {
4379 int idx = 2;
4380 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4381
4382 if (!vrf)
4383 return CMD_WARNING;
4384
4385 pim_cmd_show_ip_multicast_helper(vrf->info, vty);
4386
4387 return CMD_SUCCESS;
4388 }
4389
4390 DEFUN (show_ip_multicast_vrf_all,
4391 show_ip_multicast_vrf_all_cmd,
4392 "show ip multicast vrf all",
4393 SHOW_STR
4394 IP_STR
4395 VRF_CMD_HELP_STR
4396 "Multicast global information\n")
4397 {
4398 u_char uj = use_json(argc, argv);
4399 struct vrf *vrf;
4400 bool first = true;
4401
4402 if (uj)
4403 vty_out(vty, "{ ");
4404 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4405 if (uj) {
4406 if (!first)
4407 vty_out(vty, ", ");
4408 vty_out(vty, " \"%s\": ", vrf->name);
4409 first = false;
4410 } else
4411 vty_out(vty, "VRF: %s\n", vrf->name);
4412 pim_cmd_show_ip_multicast_helper(vrf->info, vty);
4413 }
4414 if (uj)
4415 vty_out(vty, "}\n");
4416
4417 return CMD_SUCCESS;
4418 }
4419
4420 static void show_mroute(struct pim_instance *pim, struct vty *vty,
4421 bool fill, u_char uj)
4422 {
4423 struct listnode *node;
4424 struct channel_oil *c_oil;
4425 struct static_route *s_route;
4426 time_t now;
4427 json_object *json = NULL;
4428 json_object *json_group = NULL;
4429 json_object *json_source = NULL;
4430 json_object *json_oil = NULL;
4431 json_object *json_ifp_out = NULL;
4432 int found_oif = 0;
4433 int first = 1;
4434 char grp_str[INET_ADDRSTRLEN];
4435 char src_str[INET_ADDRSTRLEN];
4436 char in_ifname[INTERFACE_NAMSIZ + 1];
4437 char out_ifname[INTERFACE_NAMSIZ + 1];
4438 int oif_vif_index;
4439 struct interface *ifp_in;
4440 char proto[100];
4441
4442 if (uj) {
4443 json = json_object_new_object();
4444 } else {
4445 vty_out(vty,
4446 "Source Group Proto Input Output TTL Uptime\n");
4447 }
4448
4449 now = pim_time_monotonic_sec();
4450
4451 /* print list of PIM and IGMP routes */
4452 for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
4453 found_oif = 0;
4454 first = 1;
4455 if (!c_oil->installed && !uj)
4456 continue;
4457
4458 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str,
4459 sizeof(grp_str));
4460 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str,
4461 sizeof(src_str));
4462 ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent);
4463
4464 if (ifp_in)
4465 strcpy(in_ifname, ifp_in->name);
4466 else
4467 strcpy(in_ifname, "<iif?>");
4468
4469 if (uj) {
4470
4471 /* Find the group, create it if it doesn't exist */
4472 json_object_object_get_ex(json, grp_str, &json_group);
4473
4474 if (!json_group) {
4475 json_group = json_object_new_object();
4476 json_object_object_add(json, grp_str,
4477 json_group);
4478 }
4479
4480 /* Find the source nested under the group, create it if
4481 * it doesn't exist */
4482 json_object_object_get_ex(json_group, src_str,
4483 &json_source);
4484
4485 if (!json_source) {
4486 json_source = json_object_new_object();
4487 json_object_object_add(json_group, src_str,
4488 json_source);
4489 }
4490
4491 /* Find the inbound interface nested under the source,
4492 * create it if it doesn't exist */
4493 json_object_int_add(json_source, "installed",
4494 c_oil->installed);
4495 json_object_int_add(json_source, "refCount",
4496 c_oil->oil_ref_count);
4497 json_object_int_add(json_source, "oilSize",
4498 c_oil->oil_size);
4499 json_object_int_add(json_source, "OilInheritedRescan",
4500 c_oil->oil_inherited_rescan);
4501 json_object_string_add(json_source, "iif", in_ifname);
4502 json_oil = NULL;
4503 }
4504
4505 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
4506 ++oif_vif_index) {
4507 struct interface *ifp_out;
4508 char oif_uptime[10];
4509 int ttl;
4510
4511 ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
4512 if (ttl < 1)
4513 continue;
4514
4515 ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
4516 pim_time_uptime(
4517 oif_uptime, sizeof(oif_uptime),
4518 now - c_oil->oif_creation[oif_vif_index]);
4519 found_oif = 1;
4520
4521 if (ifp_out)
4522 strcpy(out_ifname, ifp_out->name);
4523 else
4524 strcpy(out_ifname, "<oif?>");
4525
4526 if (uj) {
4527 json_ifp_out = json_object_new_object();
4528 json_object_string_add(json_ifp_out, "source",
4529 src_str);
4530 json_object_string_add(json_ifp_out, "group",
4531 grp_str);
4532
4533 if (c_oil->oif_flags[oif_vif_index]
4534 & PIM_OIF_FLAG_PROTO_PIM)
4535 json_object_boolean_true_add(
4536 json_ifp_out, "protocolPim");
4537
4538 if (c_oil->oif_flags[oif_vif_index]
4539 & PIM_OIF_FLAG_PROTO_IGMP)
4540 json_object_boolean_true_add(
4541 json_ifp_out, "protocolIgmp");
4542
4543 if (c_oil->oif_flags[oif_vif_index]
4544 & PIM_OIF_FLAG_PROTO_SOURCE)
4545 json_object_boolean_true_add(
4546 json_ifp_out, "protocolSource");
4547
4548 if (c_oil->oif_flags[oif_vif_index]
4549 & PIM_OIF_FLAG_PROTO_STAR)
4550 json_object_boolean_true_add(
4551 json_ifp_out,
4552 "protocolInherited");
4553
4554 json_object_string_add(json_ifp_out,
4555 "inboundInterface",
4556 in_ifname);
4557 json_object_int_add(json_ifp_out, "iVifI",
4558 c_oil->oil.mfcc_parent);
4559 json_object_string_add(json_ifp_out,
4560 "outboundInterface",
4561 out_ifname);
4562 json_object_int_add(json_ifp_out, "oVifI",
4563 oif_vif_index);
4564 json_object_int_add(json_ifp_out, "ttl", ttl);
4565 json_object_string_add(json_ifp_out, "upTime",
4566 oif_uptime);
4567 if (!json_oil) {
4568 json_oil = json_object_new_object();
4569 json_object_object_add(json_source,
4570 "oil", json_oil);
4571 }
4572 json_object_object_add(json_oil, out_ifname,
4573 json_ifp_out);
4574 } else {
4575 if (c_oil->oif_flags[oif_vif_index]
4576 & PIM_OIF_FLAG_PROTO_PIM) {
4577 strcpy(proto, "PIM");
4578 }
4579
4580 if (c_oil->oif_flags[oif_vif_index]
4581 & PIM_OIF_FLAG_PROTO_IGMP) {
4582 strcpy(proto, "IGMP");
4583 }
4584
4585 if (c_oil->oif_flags[oif_vif_index]
4586 & PIM_OIF_FLAG_PROTO_SOURCE) {
4587 strcpy(proto, "SRC");
4588 }
4589
4590 if (c_oil->oif_flags[oif_vif_index]
4591 & PIM_OIF_FLAG_PROTO_STAR) {
4592 strcpy(proto, "STAR");
4593 }
4594
4595 vty_out(vty,
4596 "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n",
4597 src_str, grp_str, proto, in_ifname,
4598 out_ifname, ttl, oif_uptime);
4599
4600 if (first) {
4601 src_str[0] = '\0';
4602 grp_str[0] = '\0';
4603 in_ifname[0] = '\0';
4604 first = 0;
4605 }
4606 }
4607 }
4608
4609 if (!uj && !found_oif) {
4610 vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n",
4611 src_str, grp_str, "none", in_ifname, "none", 0,
4612 "--:--:--");
4613 }
4614 }
4615
4616 /* Print list of static routes */
4617 for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
4618 first = 1;
4619
4620 if (!s_route->c_oil.installed)
4621 continue;
4622
4623 pim_inet4_dump("<group?>", s_route->group, grp_str,
4624 sizeof(grp_str));
4625 pim_inet4_dump("<source?>", s_route->source, src_str,
4626 sizeof(src_str));
4627 ifp_in = pim_if_find_by_vif_index(pim, s_route->iif);
4628 found_oif = 0;
4629
4630 if (ifp_in)
4631 strcpy(in_ifname, ifp_in->name);
4632 else
4633 strcpy(in_ifname, "<iif?>");
4634
4635 if (uj) {
4636
4637 /* Find the group, create it if it doesn't exist */
4638 json_object_object_get_ex(json, grp_str, &json_group);
4639
4640 if (!json_group) {
4641 json_group = json_object_new_object();
4642 json_object_object_add(json, grp_str,
4643 json_group);
4644 }
4645
4646 /* Find the source nested under the group, create it if
4647 * it doesn't exist */
4648 json_object_object_get_ex(json_group, src_str,
4649 &json_source);
4650
4651 if (!json_source) {
4652 json_source = json_object_new_object();
4653 json_object_object_add(json_group, src_str,
4654 json_source);
4655 }
4656
4657 json_object_string_add(json_source, "iif", in_ifname);
4658 json_oil = NULL;
4659 } else {
4660 strcpy(proto, "STATIC");
4661 }
4662
4663 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
4664 ++oif_vif_index) {
4665 struct interface *ifp_out;
4666 char oif_uptime[10];
4667 int ttl;
4668
4669 ttl = s_route->oif_ttls[oif_vif_index];
4670 if (ttl < 1)
4671 continue;
4672
4673 ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
4674 pim_time_uptime(oif_uptime, sizeof(oif_uptime),
4675 now -
4676 s_route->c_oil.oif_creation[oif_vif_index]);
4677 found_oif = 1;
4678
4679 if (ifp_out)
4680 strcpy(out_ifname, ifp_out->name);
4681 else
4682 strcpy(out_ifname, "<oif?>");
4683
4684 if (uj) {
4685 json_ifp_out = json_object_new_object();
4686 json_object_string_add(json_ifp_out, "source",
4687 src_str);
4688 json_object_string_add(json_ifp_out, "group",
4689 grp_str);
4690 json_object_boolean_true_add(json_ifp_out,
4691 "protocolStatic");
4692 json_object_string_add(json_ifp_out,
4693 "inboundInterface",
4694 in_ifname);
4695 json_object_int_add(
4696 json_ifp_out, "iVifI",
4697 s_route->c_oil.oil.mfcc_parent);
4698 json_object_string_add(json_ifp_out,
4699 "outboundInterface",
4700 out_ifname);
4701 json_object_int_add(json_ifp_out, "oVifI",
4702 oif_vif_index);
4703 json_object_int_add(json_ifp_out, "ttl", ttl);
4704 json_object_string_add(json_ifp_out, "upTime",
4705 oif_uptime);
4706 if (!json_oil) {
4707 json_oil = json_object_new_object();
4708 json_object_object_add(json_source,
4709 "oil", json_oil);
4710 }
4711 json_object_object_add(json_oil, out_ifname,
4712 json_ifp_out);
4713 } else {
4714 vty_out(vty,
4715 "%-15s %-15s %-6s %-10s %-10s %-3d %8s %s\n",
4716 src_str, grp_str, proto, in_ifname,
4717 out_ifname, ttl, oif_uptime,
4718 pim->vrf->name);
4719 if (first && !fill) {
4720 src_str[0] = '\0';
4721 grp_str[0] = '\0';
4722 in_ifname[0] = '\0';
4723 first = 0;
4724 }
4725 }
4726 }
4727
4728 if (!uj && !found_oif) {
4729 vty_out(vty,
4730 "%-15s %-15s %-6s %-10s %-10s %-3d %8s %s\n",
4731 src_str, grp_str, proto, in_ifname, "none", 0,
4732 "--:--:--", pim->vrf->name);
4733 }
4734 }
4735
4736 if (uj) {
4737 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4738 json, JSON_C_TO_STRING_PRETTY));
4739 json_object_free(json);
4740 }
4741 }
4742
4743 DEFUN (show_ip_mroute,
4744 show_ip_mroute_cmd,
4745 "show ip mroute [vrf NAME] [fill] [json]",
4746 SHOW_STR
4747 IP_STR
4748 MROUTE_STR
4749 VRF_CMD_HELP_STR
4750 "Fill in Assumed data\n"
4751 JSON_STR)
4752 {
4753 u_char uj = use_json(argc, argv);
4754 bool fill = false;
4755 int idx = 2;
4756 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4757
4758 if (!vrf)
4759 return CMD_WARNING;
4760
4761 if (argv_find(argv, argc, "fill", &idx))
4762 fill = true;
4763
4764 show_mroute(vrf->info, vty, fill, uj);
4765 return CMD_SUCCESS;
4766 }
4767
4768 DEFUN (show_ip_mroute_vrf_all,
4769 show_ip_mroute_vrf_all_cmd,
4770 "show ip mroute vrf all [fill] [json]",
4771 SHOW_STR
4772 IP_STR
4773 MROUTE_STR
4774 VRF_CMD_HELP_STR
4775 "Fill in Assumed data\n"
4776 JSON_STR)
4777 {
4778 u_char uj = use_json(argc, argv);
4779 int idx = 4;
4780 struct vrf *vrf;
4781 bool first = true;
4782 bool fill = false;
4783
4784 if (argv_find(argv, argc, "fill", &idx))
4785 fill = true;
4786
4787 if (uj)
4788 vty_out(vty, "{ ");
4789 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4790 if (uj) {
4791 if (!first)
4792 vty_out(vty, ", ");
4793 vty_out(vty, " \"%s\": ", vrf->name);
4794 first = false;
4795 } else
4796 vty_out(vty, "VRF: %s\n", vrf->name);
4797 show_mroute(vrf->info, vty, fill, uj);
4798 }
4799 if (uj)
4800 vty_out(vty, "}\n");
4801
4802 return CMD_SUCCESS;
4803 }
4804
4805 static void show_mroute_count(struct pim_instance *pim, struct vty *vty)
4806 {
4807 struct listnode *node;
4808 struct channel_oil *c_oil;
4809 struct static_route *s_route;
4810
4811 vty_out(vty, "\n");
4812
4813 vty_out(vty,
4814 "Source Group LastUsed Packets Bytes WrongIf \n");
4815
4816 /* Print PIM and IGMP route counts */
4817 for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
4818 char group_str[INET_ADDRSTRLEN];
4819 char source_str[INET_ADDRSTRLEN];
4820
4821 if (!c_oil->installed)
4822 continue;
4823
4824 pim_mroute_update_counters(c_oil);
4825
4826 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str,
4827 sizeof(group_str));
4828 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str,
4829 sizeof(source_str));
4830
4831 vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n",
4832 source_str, group_str, c_oil->cc.lastused / 100,
4833 c_oil->cc.pktcnt, c_oil->cc.bytecnt,
4834 c_oil->cc.wrong_if);
4835 }
4836
4837 for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
4838 char group_str[INET_ADDRSTRLEN];
4839 char source_str[INET_ADDRSTRLEN];
4840
4841 if (!s_route->c_oil.installed)
4842 continue;
4843
4844 pim_mroute_update_counters(&s_route->c_oil);
4845
4846 pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp,
4847 group_str, sizeof(group_str));
4848 pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin,
4849 source_str, sizeof(source_str));
4850
4851 vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n",
4852 source_str, group_str, s_route->c_oil.cc.lastused,
4853 s_route->c_oil.cc.pktcnt, s_route->c_oil.cc.bytecnt,
4854 s_route->c_oil.cc.wrong_if);
4855 }
4856 }
4857
4858 DEFUN (show_ip_mroute_count,
4859 show_ip_mroute_count_cmd,
4860 "show ip mroute [vrf NAME] count",
4861 SHOW_STR
4862 IP_STR
4863 MROUTE_STR
4864 VRF_CMD_HELP_STR
4865 "Route and packet count data\n")
4866 {
4867 int idx = 2;
4868 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4869
4870 if (!vrf)
4871 return CMD_WARNING;
4872
4873 show_mroute_count(vrf->info, vty);
4874 return CMD_SUCCESS;
4875 }
4876
4877 DEFUN (show_ip_mroute_count_vrf_all,
4878 show_ip_mroute_count_vrf_all_cmd,
4879 "show ip mroute vrf all count",
4880 SHOW_STR
4881 IP_STR
4882 MROUTE_STR
4883 VRF_CMD_HELP_STR
4884 "Route and packet count data\n")
4885 {
4886 u_char uj = use_json(argc, argv);
4887 struct vrf *vrf;
4888 bool first = true;
4889
4890 if (uj)
4891 vty_out(vty, "{ ");
4892 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4893 if (uj) {
4894 if (!first)
4895 vty_out(vty, ", ");
4896 vty_out(vty, " \"%s\": ", vrf->name);
4897 first = false;
4898 } else
4899 vty_out(vty, "VRF: %s\n", vrf->name);
4900 show_mroute_count(vrf->info, vty);
4901 }
4902 if (uj)
4903 vty_out(vty, "}\n");
4904
4905 return CMD_SUCCESS;
4906 }
4907
4908 DEFUN (show_ip_rib,
4909 show_ip_rib_cmd,
4910 "show ip rib [vrf NAME] A.B.C.D",
4911 SHOW_STR
4912 IP_STR
4913 RIB_STR
4914 VRF_CMD_HELP_STR
4915 "Unicast address\n")
4916 {
4917 int idx = 2;
4918 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
4919 struct in_addr addr;
4920 const char *addr_str;
4921 struct pim_nexthop nexthop;
4922 char nexthop_addr_str[PREFIX_STRLEN];
4923 int result;
4924
4925 if (!vrf)
4926 return CMD_WARNING;
4927
4928 memset(&nexthop, 0, sizeof(nexthop));
4929 argv_find(argv, argc, "A.B.C.D", &idx);
4930 addr_str = argv[idx]->arg;
4931 result = inet_pton(AF_INET, addr_str, &addr);
4932 if (result <= 0) {
4933 vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str,
4934 errno, safe_strerror(errno));
4935 return CMD_WARNING;
4936 }
4937
4938 if (pim_nexthop_lookup(vrf->info, &nexthop, addr, 0)) {
4939 vty_out(vty,
4940 "Failure querying RIB nexthop for unicast address %s\n",
4941 addr_str);
4942 return CMD_WARNING;
4943 }
4944
4945 vty_out(vty,
4946 "Address NextHop Interface Metric Preference\n");
4947
4948 pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr,
4949 nexthop_addr_str, sizeof(nexthop_addr_str));
4950
4951 vty_out(vty, "%-15s %-15s %-9s %6d %10d\n", addr_str, nexthop_addr_str,
4952 nexthop.interface ? nexthop.interface->name : "<ifname?>",
4953 nexthop.mrib_route_metric, nexthop.mrib_metric_preference);
4954
4955 return CMD_SUCCESS;
4956 }
4957
4958 static void show_ssmpingd(struct pim_instance *pim, struct vty *vty)
4959 {
4960 struct listnode *node;
4961 struct ssmpingd_sock *ss;
4962 time_t now;
4963
4964 vty_out(vty,
4965 "Source Socket Address Port Uptime Requests\n");
4966
4967 if (!pim->ssmpingd_list)
4968 return;
4969
4970 now = pim_time_monotonic_sec();
4971
4972 for (ALL_LIST_ELEMENTS_RO(pim->ssmpingd_list, node, ss)) {
4973 char source_str[INET_ADDRSTRLEN];
4974 char ss_uptime[10];
4975 struct sockaddr_in bind_addr;
4976 socklen_t len = sizeof(bind_addr);
4977 char bind_addr_str[INET_ADDRSTRLEN];
4978
4979 pim_inet4_dump("<src?>", ss->source_addr, source_str,
4980 sizeof(source_str));
4981
4982 if (pim_socket_getsockname(
4983 ss->sock_fd, (struct sockaddr *)&bind_addr, &len)) {
4984 vty_out(vty,
4985 "%% Failure reading socket name for ssmpingd source %s on fd=%d\n",
4986 source_str, ss->sock_fd);
4987 }
4988
4989 pim_inet4_dump("<addr?>", bind_addr.sin_addr, bind_addr_str,
4990 sizeof(bind_addr_str));
4991 pim_time_uptime(ss_uptime, sizeof(ss_uptime),
4992 now - ss->creation);
4993
4994 vty_out(vty, "%-15s %6d %-15s %5d %8s %8lld\n", source_str,
4995 ss->sock_fd, bind_addr_str, ntohs(bind_addr.sin_port),
4996 ss_uptime, (long long)ss->requests);
4997 }
4998 }
4999
5000 DEFUN (show_ip_ssmpingd,
5001 show_ip_ssmpingd_cmd,
5002 "show ip ssmpingd [vrf NAME]",
5003 SHOW_STR
5004 IP_STR
5005 SHOW_SSMPINGD_STR
5006 VRF_CMD_HELP_STR)
5007 {
5008 int idx = 2;
5009 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5010
5011 if (!vrf)
5012 return CMD_WARNING;
5013
5014 show_ssmpingd(vrf->info, vty);
5015 return CMD_SUCCESS;
5016 }
5017
5018 static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty,
5019 const char *rp, const char *group,
5020 const char *plist)
5021 {
5022 int result;
5023
5024 result = pim_rp_new(pim, rp, group, plist);
5025
5026 if (result == PIM_MALLOC_FAIL) {
5027 vty_out(vty, "%% Out of memory\n");
5028 return CMD_WARNING_CONFIG_FAILED;
5029 }
5030
5031 if (result == PIM_GROUP_BAD_ADDRESS) {
5032 vty_out(vty, "%% Bad group address specified: %s\n", group);
5033 return CMD_WARNING_CONFIG_FAILED;
5034 }
5035
5036 if (result == PIM_RP_BAD_ADDRESS) {
5037 vty_out(vty, "%% Bad RP address specified: %s\n", rp);
5038 return CMD_WARNING_CONFIG_FAILED;
5039 }
5040
5041 if (result == PIM_RP_NO_PATH) {
5042 vty_out(vty, "%% No Path to RP address specified: %s\n", rp);
5043 return CMD_WARNING;
5044 }
5045
5046 if (result == PIM_GROUP_OVERLAP) {
5047 vty_out(vty, "%% Group range specified cannot exact match another\n");
5048 return CMD_WARNING_CONFIG_FAILED;
5049 }
5050
5051 if (result == PIM_GROUP_PFXLIST_OVERLAP) {
5052 vty_out(vty,
5053 "%% This group is already covered by a RP prefix-list\n");
5054 return CMD_WARNING_CONFIG_FAILED;
5055 }
5056
5057 if (result == PIM_RP_PFXLIST_IN_USE) {
5058 vty_out(vty,
5059 "%% The same prefix-list cannot be applied to multiple RPs\n");
5060 return CMD_WARNING_CONFIG_FAILED;
5061 }
5062
5063 return CMD_SUCCESS;
5064 }
5065
5066 static int pim_cmd_spt_switchover(struct pim_instance *pim,
5067 enum pim_spt_switchover spt,
5068 const char *plist)
5069 {
5070 pim->spt.switchover = spt;
5071
5072 switch (pim->spt.switchover) {
5073 case PIM_SPT_IMMEDIATE:
5074 if (pim->spt.plist)
5075 XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
5076
5077 pim_upstream_add_lhr_star_pimreg(pim);
5078 break;
5079 case PIM_SPT_INFINITY:
5080 pim_upstream_remove_lhr_star_pimreg(pim, plist);
5081
5082 if (pim->spt.plist)
5083 XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
5084
5085 if (plist)
5086 pim->spt.plist =
5087 XSTRDUP(MTYPE_PIM_SPT_PLIST_NAME, plist);
5088 break;
5089 }
5090
5091 return CMD_SUCCESS;
5092 }
5093
5094 DEFUN (ip_pim_spt_switchover_infinity,
5095 ip_pim_spt_switchover_infinity_cmd,
5096 "ip pim spt-switchover infinity-and-beyond",
5097 IP_STR
5098 PIM_STR
5099 "SPT-Switchover\n"
5100 "Never switch to SPT Tree\n")
5101 {
5102 PIM_DECLVAR_CONTEXT(vrf, pim);
5103 return pim_cmd_spt_switchover(pim, PIM_SPT_INFINITY, NULL);
5104 }
5105
5106 DEFUN (ip_pim_spt_switchover_infinity_plist,
5107 ip_pim_spt_switchover_infinity_plist_cmd,
5108 "ip pim spt-switchover infinity-and-beyond prefix-list WORD",
5109 IP_STR
5110 PIM_STR
5111 "SPT-Switchover\n"
5112 "Never switch to SPT Tree\n"
5113 "Prefix-List to control which groups to switch\n"
5114 "Prefix-List name\n")
5115 {
5116 PIM_DECLVAR_CONTEXT(vrf, pim);
5117 return pim_cmd_spt_switchover(pim, PIM_SPT_INFINITY, argv[5]->arg);
5118 }
5119
5120 DEFUN (no_ip_pim_spt_switchover_infinity,
5121 no_ip_pim_spt_switchover_infinity_cmd,
5122 "no ip pim spt-switchover infinity-and-beyond",
5123 NO_STR
5124 IP_STR
5125 PIM_STR
5126 "SPT_Switchover\n"
5127 "Never switch to SPT Tree\n")
5128 {
5129 PIM_DECLVAR_CONTEXT(vrf, pim);
5130 return pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL);
5131 }
5132
5133 DEFUN (no_ip_pim_spt_switchover_infinity_plist,
5134 no_ip_pim_spt_switchover_infinity_plist_cmd,
5135 "no ip pim spt-switchover infinity-and-beyond prefix-list WORD",
5136 NO_STR
5137 IP_STR
5138 PIM_STR
5139 "SPT_Switchover\n"
5140 "Never switch to SPT Tree\n"
5141 "Prefix-List to control which groups to switch\n"
5142 "Prefix-List name\n")
5143 {
5144 PIM_DECLVAR_CONTEXT(vrf, pim);
5145 return pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL);
5146 }
5147
5148 DEFUN (ip_pim_joinprune_time,
5149 ip_pim_joinprune_time_cmd,
5150 "ip pim join-prune-interval (60-600)",
5151 IP_STR
5152 "pim multicast routing\n"
5153 "Join Prune Send Interval\n"
5154 "Seconds\n")
5155 {
5156 PIM_DECLVAR_CONTEXT(vrf, pim);
5157 qpim_t_periodic = atoi(argv[3]->arg);
5158 return CMD_SUCCESS;
5159 }
5160
5161 DEFUN (no_ip_pim_joinprune_time,
5162 no_ip_pim_joinprune_time_cmd,
5163 "no ip pim join-prune-interval (60-600)",
5164 NO_STR
5165 IP_STR
5166 "pim multicast routing\n"
5167 "Join Prune Send Interval\n"
5168 "Seconds\n")
5169 {
5170 PIM_DECLVAR_CONTEXT(vrf, pim);
5171 qpim_t_periodic = PIM_DEFAULT_T_PERIODIC;
5172 return CMD_SUCCESS;
5173 }
5174
5175 DEFUN (ip_pim_register_suppress,
5176 ip_pim_register_suppress_cmd,
5177 "ip pim register-suppress-time (5-60000)",
5178 IP_STR
5179 "pim multicast routing\n"
5180 "Register Suppress Timer\n"
5181 "Seconds\n")
5182 {
5183 PIM_DECLVAR_CONTEXT(vrf, pim);
5184 qpim_register_suppress_time = atoi(argv[3]->arg);
5185 return CMD_SUCCESS;
5186 }
5187
5188 DEFUN (no_ip_pim_register_suppress,
5189 no_ip_pim_register_suppress_cmd,
5190 "no ip pim register-suppress-time (5-60000)",
5191 NO_STR
5192 IP_STR
5193 "pim multicast routing\n"
5194 "Register Suppress Timer\n"
5195 "Seconds\n")
5196 {
5197 PIM_DECLVAR_CONTEXT(vrf, pim);
5198 qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT;
5199 return CMD_SUCCESS;
5200 }
5201
5202 DEFUN (ip_pim_rp_keep_alive,
5203 ip_pim_rp_keep_alive_cmd,
5204 "ip pim rp keep-alive-timer (31-60000)",
5205 IP_STR
5206 "pim multicast routing\n"
5207 "Rendevous Point\n"
5208 "Keep alive Timer\n"
5209 "Seconds\n")
5210 {
5211 PIM_DECLVAR_CONTEXT(vrf, pim);
5212 pim->rp_keep_alive_time = atoi(argv[4]->arg);
5213 return CMD_SUCCESS;
5214 }
5215
5216 DEFUN (no_ip_pim_rp_keep_alive,
5217 no_ip_pim_rp_keep_alive_cmd,
5218 "no ip pim rp keep-alive-timer (31-60000)",
5219 NO_STR
5220 IP_STR
5221 "pim multicast routing\n"
5222 "Rendevous Point\n"
5223 "Keep alive Timer\n"
5224 "Seconds\n")
5225 {
5226 PIM_DECLVAR_CONTEXT(vrf, pim);
5227 pim->rp_keep_alive_time = PIM_KEEPALIVE_PERIOD;
5228 return CMD_SUCCESS;
5229 }
5230
5231 DEFUN (ip_pim_keep_alive,
5232 ip_pim_keep_alive_cmd,
5233 "ip pim keep-alive-timer (31-60000)",
5234 IP_STR
5235 "pim multicast routing\n"
5236 "Keep alive Timer\n"
5237 "Seconds\n")
5238 {
5239 PIM_DECLVAR_CONTEXT(vrf, pim);
5240 pim->keep_alive_time = atoi(argv[3]->arg);
5241 return CMD_SUCCESS;
5242 }
5243
5244 DEFUN (no_ip_pim_keep_alive,
5245 no_ip_pim_keep_alive_cmd,
5246 "no ip pim keep-alive-timer (31-60000)",
5247 NO_STR
5248 IP_STR
5249 "pim multicast routing\n"
5250 "Keep alive Timer\n"
5251 "Seconds\n")
5252 {
5253 PIM_DECLVAR_CONTEXT(vrf, pim);
5254 pim->keep_alive_time = PIM_KEEPALIVE_PERIOD;
5255 return CMD_SUCCESS;
5256 }
5257
5258 DEFUN (ip_pim_packets,
5259 ip_pim_packets_cmd,
5260 "ip pim packets (1-100)",
5261 IP_STR
5262 "pim multicast routing\n"
5263 "packets to process at one time per fd\n"
5264 "Number of packets\n")
5265 {
5266 PIM_DECLVAR_CONTEXT(vrf, pim);
5267 qpim_packet_process = atoi(argv[3]->arg);
5268 return CMD_SUCCESS;
5269 }
5270
5271 DEFUN (no_ip_pim_packets,
5272 no_ip_pim_packets_cmd,
5273 "no ip pim packets (1-100)",
5274 NO_STR
5275 IP_STR
5276 "pim multicast routing\n"
5277 "packets to process at one time per fd\n"
5278 "Number of packets\n")
5279 {
5280 PIM_DECLVAR_CONTEXT(vrf, pim);
5281 qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS;
5282 return CMD_SUCCESS;
5283 }
5284
5285 DEFUN (ip_pim_v6_secondary,
5286 ip_pim_v6_secondary_cmd,
5287 "ip pim send-v6-secondary",
5288 IP_STR
5289 "pim multicast routing\n"
5290 "Send v6 secondary addresses\n")
5291 {
5292 PIM_DECLVAR_CONTEXT(vrf, pim);
5293 pim->send_v6_secondary = 1;
5294
5295 return CMD_SUCCESS;
5296 }
5297
5298 DEFUN (no_ip_pim_v6_secondary,
5299 no_ip_pim_v6_secondary_cmd,
5300 "no ip pim send-v6-secondary",
5301 NO_STR
5302 IP_STR
5303 "pim multicast routing\n"
5304 "Send v6 secondary addresses\n")
5305 {
5306 PIM_DECLVAR_CONTEXT(vrf, pim);
5307 pim->send_v6_secondary = 0;
5308
5309 return CMD_SUCCESS;
5310 }
5311
5312 DEFUN (ip_pim_rp,
5313 ip_pim_rp_cmd,
5314 "ip pim rp A.B.C.D [A.B.C.D/M]",
5315 IP_STR
5316 "pim multicast routing\n"
5317 "Rendevous Point\n"
5318 "ip address of RP\n"
5319 "Group Address range to cover\n")
5320 {
5321 PIM_DECLVAR_CONTEXT(vrf, pim);
5322 int idx_ipv4 = 3;
5323
5324 if (argc == (idx_ipv4 + 1))
5325 return pim_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg, NULL,
5326 NULL);
5327 else
5328 return pim_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg,
5329 argv[idx_ipv4 + 1]->arg, NULL);
5330 }
5331
5332 DEFUN (ip_pim_rp_prefix_list,
5333 ip_pim_rp_prefix_list_cmd,
5334 "ip pim rp A.B.C.D prefix-list WORD",
5335 IP_STR
5336 "pim multicast routing\n"
5337 "Rendevous Point\n"
5338 "ip address of RP\n"
5339 "group prefix-list filter\n"
5340 "Name of a prefix-list\n")
5341 {
5342 PIM_DECLVAR_CONTEXT(vrf, pim);
5343 return pim_rp_cmd_worker(pim, vty, argv[3]->arg, NULL, argv[5]->arg);
5344 }
5345
5346 static int pim_no_rp_cmd_worker(struct pim_instance *pim, struct vty *vty,
5347 const char *rp, const char *group,
5348 const char *plist)
5349 {
5350 int result = pim_rp_del(pim, rp, group, plist);
5351
5352 if (result == PIM_GROUP_BAD_ADDRESS) {
5353 vty_out(vty, "%% Bad group address specified: %s\n", group);
5354 return CMD_WARNING_CONFIG_FAILED;
5355 }
5356
5357 if (result == PIM_RP_BAD_ADDRESS) {
5358 vty_out(vty, "%% Bad RP address specified: %s\n", rp);
5359 return CMD_WARNING_CONFIG_FAILED;
5360 }
5361
5362 if (result == PIM_RP_NOT_FOUND) {
5363 vty_out(vty, "%% Unable to find specified RP\n");
5364 return CMD_WARNING_CONFIG_FAILED;
5365 }
5366
5367 return CMD_SUCCESS;
5368 }
5369
5370 DEFUN (no_ip_pim_rp,
5371 no_ip_pim_rp_cmd,
5372 "no ip pim rp A.B.C.D [A.B.C.D/M]",
5373 NO_STR
5374 IP_STR
5375 "pim multicast routing\n"
5376 "Rendevous Point\n"
5377 "ip address of RP\n"
5378 "Group Address range to cover\n")
5379 {
5380 PIM_DECLVAR_CONTEXT(vrf, pim);
5381 int idx_ipv4 = 4, idx_group = 0;
5382
5383 if (argv_find(argv, argc, "A.B.C.D/M", &idx_group))
5384 return pim_no_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg,
5385 argv[idx_group]->arg, NULL);
5386 else
5387 return pim_no_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg, NULL,
5388 NULL);
5389 }
5390
5391 DEFUN (no_ip_pim_rp_prefix_list,
5392 no_ip_pim_rp_prefix_list_cmd,
5393 "no ip pim rp A.B.C.D prefix-list WORD",
5394 NO_STR
5395 IP_STR
5396 "pim multicast routing\n"
5397 "Rendevous Point\n"
5398 "ip address of RP\n"
5399 "group prefix-list filter\n"
5400 "Name of a prefix-list\n")
5401 {
5402 PIM_DECLVAR_CONTEXT(vrf, pim);
5403 return pim_no_rp_cmd_worker(pim, vty, argv[4]->arg, NULL, argv[6]->arg);
5404 }
5405
5406 static int pim_ssm_cmd_worker(struct pim_instance *pim, struct vty *vty,
5407 const char *plist)
5408 {
5409 int result = pim_ssm_range_set(pim, pim->vrf_id, plist);
5410
5411 if (result == PIM_SSM_ERR_NONE)
5412 return CMD_SUCCESS;
5413
5414 switch (result) {
5415 case PIM_SSM_ERR_NO_VRF:
5416 vty_out(vty, "%% VRF doesn't exist\n");
5417 break;
5418 case PIM_SSM_ERR_DUP:
5419 vty_out(vty, "%% duplicate config\n");
5420 break;
5421 default:
5422 vty_out(vty, "%% ssm range config failed\n");
5423 }
5424
5425 return CMD_WARNING_CONFIG_FAILED;
5426 }
5427
5428 DEFUN (ip_pim_ssm_prefix_list,
5429 ip_pim_ssm_prefix_list_cmd,
5430 "ip pim ssm prefix-list WORD",
5431 IP_STR
5432 "pim multicast routing\n"
5433 "Source Specific Multicast\n"
5434 "group range prefix-list filter\n"
5435 "Name of a prefix-list\n")
5436 {
5437 PIM_DECLVAR_CONTEXT(vrf, pim);
5438 return pim_ssm_cmd_worker(pim, vty, argv[4]->arg);
5439 }
5440
5441 DEFUN (no_ip_pim_ssm_prefix_list,
5442 no_ip_pim_ssm_prefix_list_cmd,
5443 "no ip pim ssm prefix-list",
5444 NO_STR
5445 IP_STR
5446 "pim multicast routing\n"
5447 "Source Specific Multicast\n"
5448 "group range prefix-list filter\n")
5449 {
5450 PIM_DECLVAR_CONTEXT(vrf, pim);
5451 return pim_ssm_cmd_worker(pim, vty, NULL);
5452 }
5453
5454 DEFUN (no_ip_pim_ssm_prefix_list_name,
5455 no_ip_pim_ssm_prefix_list_name_cmd,
5456 "no ip pim ssm prefix-list WORD",
5457 NO_STR
5458 IP_STR
5459 "pim multicast routing\n"
5460 "Source Specific Multicast\n"
5461 "group range prefix-list filter\n"
5462 "Name of a prefix-list\n")
5463 {
5464 PIM_DECLVAR_CONTEXT(vrf, pim);
5465 struct pim_ssm *ssm = pim->ssm_info;
5466
5467 if (ssm->plist_name && !strcmp(ssm->plist_name, argv[5]->arg))
5468 return pim_ssm_cmd_worker(pim, vty, NULL);
5469
5470 vty_out(vty, "%% pim ssm prefix-list %s doesn't exist\n", argv[5]->arg);
5471
5472 return CMD_WARNING_CONFIG_FAILED;
5473 }
5474
5475 static void ip_pim_ssm_show_group_range(struct pim_instance *pim,
5476 struct vty *vty, u_char uj)
5477 {
5478 struct pim_ssm *ssm = pim->ssm_info;
5479 const char *range_str =
5480 ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
5481
5482 if (uj) {
5483 json_object *json;
5484 json = json_object_new_object();
5485 json_object_string_add(json, "ssmGroups", range_str);
5486 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5487 json, JSON_C_TO_STRING_PRETTY));
5488 json_object_free(json);
5489 } else
5490 vty_out(vty, "SSM group range : %s\n", range_str);
5491 }
5492
5493 DEFUN (show_ip_pim_ssm_range,
5494 show_ip_pim_ssm_range_cmd,
5495 "show ip pim [vrf NAME] group-type [json]",
5496 SHOW_STR
5497 IP_STR
5498 PIM_STR
5499 VRF_CMD_HELP_STR
5500 "PIM group type\n"
5501 JSON_STR)
5502 {
5503 int idx = 2;
5504 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5505 u_char uj = use_json(argc, argv);
5506
5507 if (!vrf)
5508 return CMD_WARNING;
5509
5510 ip_pim_ssm_show_group_range(vrf->info, vty, uj);
5511
5512 return CMD_SUCCESS;
5513 }
5514
5515 static void ip_pim_ssm_show_group_type(struct pim_instance *pim,
5516 struct vty *vty, u_char uj,
5517 const char *group)
5518 {
5519 struct in_addr group_addr;
5520 const char *type_str;
5521 int result;
5522
5523 result = inet_pton(AF_INET, group, &group_addr);
5524 if (result <= 0)
5525 type_str = "invalid";
5526 else {
5527 if (pim_is_group_224_4(group_addr))
5528 type_str =
5529 pim_is_grp_ssm(pim, group_addr) ? "SSM" : "ASM";
5530 else
5531 type_str = "not-multicast";
5532 }
5533
5534 if (uj) {
5535 json_object *json;
5536 json = json_object_new_object();
5537 json_object_string_add(json, "groupType", type_str);
5538 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5539 json, JSON_C_TO_STRING_PRETTY));
5540 json_object_free(json);
5541 } else
5542 vty_out(vty, "Group type : %s\n", type_str);
5543 }
5544
5545 DEFUN (show_ip_pim_group_type,
5546 show_ip_pim_group_type_cmd,
5547 "show ip pim [vrf NAME] group-type A.B.C.D [json]",
5548 SHOW_STR
5549 IP_STR
5550 PIM_STR
5551 VRF_CMD_HELP_STR
5552 "multicast group type\n"
5553 "group address\n"
5554 JSON_STR)
5555 {
5556 int idx = 2;
5557 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
5558 u_char uj = use_json(argc, argv);
5559
5560 if (!vrf)
5561 return CMD_WARNING;
5562
5563 argv_find(argv, argc, "A.B.C.D", &idx);
5564 ip_pim_ssm_show_group_type(vrf->info, vty, uj, argv[idx]->arg);
5565
5566 return CMD_SUCCESS;
5567 }
5568
5569 DEFUN_HIDDEN (ip_multicast_routing,
5570 ip_multicast_routing_cmd,
5571 "ip multicast-routing",
5572 IP_STR
5573 "Enable IP multicast forwarding\n")
5574 {
5575 return CMD_SUCCESS;
5576 }
5577
5578 DEFUN_HIDDEN (no_ip_multicast_routing,
5579 no_ip_multicast_routing_cmd,
5580 "no ip multicast-routing",
5581 NO_STR
5582 IP_STR
5583 "Enable IP multicast forwarding\n")
5584 {
5585 vty_out(vty,
5586 "Command is Disabled and will be removed in a future version\n");
5587 return CMD_SUCCESS;
5588 }
5589
5590 DEFUN (ip_ssmpingd,
5591 ip_ssmpingd_cmd,
5592 "ip ssmpingd [A.B.C.D]",
5593 IP_STR
5594 CONF_SSMPINGD_STR
5595 "Source address\n")
5596 {
5597 PIM_DECLVAR_CONTEXT(vrf, pim);
5598 int idx_ipv4 = 2;
5599 int result;
5600 struct in_addr source_addr;
5601 const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0";
5602
5603 result = inet_pton(AF_INET, source_str, &source_addr);
5604 if (result <= 0) {
5605 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n",
5606 source_str, errno, safe_strerror(errno));
5607 return CMD_WARNING_CONFIG_FAILED;
5608 }
5609
5610 result = pim_ssmpingd_start(pim, source_addr);
5611 if (result) {
5612 vty_out(vty, "%% Failure starting ssmpingd for source %s: %d\n",
5613 source_str, result);
5614 return CMD_WARNING_CONFIG_FAILED;
5615 }
5616
5617 return CMD_SUCCESS;
5618 }
5619
5620 DEFUN (no_ip_ssmpingd,
5621 no_ip_ssmpingd_cmd,
5622 "no ip ssmpingd [A.B.C.D]",
5623 NO_STR
5624 IP_STR
5625 CONF_SSMPINGD_STR
5626 "Source address\n")
5627 {
5628 PIM_DECLVAR_CONTEXT(vrf, pim);
5629 int idx_ipv4 = 3;
5630 int result;
5631 struct in_addr source_addr;
5632 const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0";
5633
5634 result = inet_pton(AF_INET, source_str, &source_addr);
5635 if (result <= 0) {
5636 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n",
5637 source_str, errno, safe_strerror(errno));
5638 return CMD_WARNING_CONFIG_FAILED;
5639 }
5640
5641 result = pim_ssmpingd_stop(pim, source_addr);
5642 if (result) {
5643 vty_out(vty, "%% Failure stopping ssmpingd for source %s: %d\n",
5644 source_str, result);
5645 return CMD_WARNING_CONFIG_FAILED;
5646 }
5647
5648 return CMD_SUCCESS;
5649 }
5650
5651 DEFUN (ip_pim_ecmp,
5652 ip_pim_ecmp_cmd,
5653 "ip pim ecmp",
5654 IP_STR
5655 "pim multicast routing\n"
5656 "Enable PIM ECMP \n")
5657 {
5658 PIM_DECLVAR_CONTEXT(vrf, pim);
5659 qpim_ecmp_enable = 1;
5660
5661 return CMD_SUCCESS;
5662 }
5663
5664 DEFUN (no_ip_pim_ecmp,
5665 no_ip_pim_ecmp_cmd,
5666 "no ip pim ecmp",
5667 NO_STR
5668 IP_STR
5669 "pim multicast routing\n"
5670 "Disable PIM ECMP \n")
5671 {
5672 PIM_DECLVAR_CONTEXT(vrf, pim);
5673 qpim_ecmp_enable = 0;
5674
5675 return CMD_SUCCESS;
5676 }
5677
5678 DEFUN (ip_pim_ecmp_rebalance,
5679 ip_pim_ecmp_rebalance_cmd,
5680 "ip pim ecmp rebalance",
5681 IP_STR
5682 "pim multicast routing\n"
5683 "Enable PIM ECMP \n"
5684 "Enable PIM ECMP Rebalance\n")
5685 {
5686 PIM_DECLVAR_CONTEXT(vrf, pim);
5687 qpim_ecmp_enable = 1;
5688 qpim_ecmp_rebalance_enable = 1;
5689
5690 return CMD_SUCCESS;
5691 }
5692
5693 DEFUN (no_ip_pim_ecmp_rebalance,
5694 no_ip_pim_ecmp_rebalance_cmd,
5695 "no ip pim ecmp rebalance",
5696 NO_STR
5697 IP_STR
5698 "pim multicast routing\n"
5699 "Disable PIM ECMP \n"
5700 "Disable PIM ECMP Rebalance\n")
5701 {
5702 PIM_DECLVAR_CONTEXT(vrf, pim);
5703 qpim_ecmp_rebalance_enable = 0;
5704
5705 return CMD_SUCCESS;
5706 }
5707
5708 static int pim_cmd_igmp_start(struct vty *vty, struct interface *ifp)
5709 {
5710 struct pim_interface *pim_ifp;
5711 uint8_t need_startup = 0;
5712
5713 pim_ifp = ifp->info;
5714
5715 if (!pim_ifp) {
5716 pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */);
5717 if (!pim_ifp) {
5718 vty_out(vty, "Could not enable IGMP on interface %s\n",
5719 ifp->name);
5720 return CMD_WARNING_CONFIG_FAILED;
5721 }
5722 need_startup = 1;
5723 } else {
5724 if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
5725 PIM_IF_DO_IGMP(pim_ifp->options);
5726 need_startup = 1;
5727 }
5728 }
5729
5730 /* 'ip igmp' executed multiple times, with need_startup
5731 avoid multiple if add all and membership refresh */
5732 if (need_startup) {
5733 pim_if_addr_add_all(ifp);
5734 pim_if_membership_refresh(ifp);
5735 }
5736
5737 return CMD_SUCCESS;
5738 }
5739
5740 DEFUN (interface_ip_igmp,
5741 interface_ip_igmp_cmd,
5742 "ip igmp",
5743 IP_STR
5744 IFACE_IGMP_STR)
5745 {
5746 VTY_DECLVAR_CONTEXT(interface, ifp);
5747
5748 return pim_cmd_igmp_start(vty, ifp);
5749 }
5750
5751 DEFUN (interface_no_ip_igmp,
5752 interface_no_ip_igmp_cmd,
5753 "no ip igmp",
5754 NO_STR
5755 IP_STR
5756 IFACE_IGMP_STR)
5757 {
5758 VTY_DECLVAR_CONTEXT(interface, ifp);
5759 struct pim_interface *pim_ifp = ifp->info;
5760
5761 if (!pim_ifp)
5762 return CMD_SUCCESS;
5763
5764 PIM_IF_DONT_IGMP(pim_ifp->options);
5765
5766 pim_if_membership_clear(ifp);
5767
5768 pim_if_addr_del_all_igmp(ifp);
5769
5770 if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
5771 pim_if_delete(ifp);
5772 }
5773
5774 return CMD_SUCCESS;
5775 }
5776
5777 DEFUN (interface_ip_igmp_join,
5778 interface_ip_igmp_join_cmd,
5779 "ip igmp join A.B.C.D A.B.C.D",
5780 IP_STR
5781 IFACE_IGMP_STR
5782 "IGMP join multicast group\n"
5783 "Multicast group address\n"
5784 "Source address\n")
5785 {
5786 VTY_DECLVAR_CONTEXT(interface, ifp);
5787 int idx_ipv4 = 3;
5788 int idx_ipv4_2 = 4;
5789 const char *group_str;
5790 const char *source_str;
5791 struct in_addr group_addr;
5792 struct in_addr source_addr;
5793 int result;
5794
5795 /* Group address */
5796 group_str = argv[idx_ipv4]->arg;
5797 result = inet_pton(AF_INET, group_str, &group_addr);
5798 if (result <= 0) {
5799 vty_out(vty, "Bad group address %s: errno=%d: %s\n", group_str,
5800 errno, safe_strerror(errno));
5801 return CMD_WARNING_CONFIG_FAILED;
5802 }
5803
5804 /* Source address */
5805 source_str = argv[idx_ipv4_2]->arg;
5806 result = inet_pton(AF_INET, source_str, &source_addr);
5807 if (result <= 0) {
5808 vty_out(vty, "Bad source address %s: errno=%d: %s\n",
5809 source_str, errno, safe_strerror(errno));
5810 return CMD_WARNING_CONFIG_FAILED;
5811 }
5812
5813 CMD_FERR_RETURN(pim_if_igmp_join_add(ifp, group_addr, source_addr),
5814 "Failure joining IGMP group: $ERR");
5815
5816 return CMD_SUCCESS;
5817 }
5818
5819 DEFUN (interface_no_ip_igmp_join,
5820 interface_no_ip_igmp_join_cmd,
5821 "no ip igmp join A.B.C.D A.B.C.D",
5822 NO_STR
5823 IP_STR
5824 IFACE_IGMP_STR
5825 "IGMP join multicast group\n"
5826 "Multicast group address\n"
5827 "Source address\n")
5828 {
5829 VTY_DECLVAR_CONTEXT(interface, ifp);
5830 int idx_ipv4 = 4;
5831 int idx_ipv4_2 = 5;
5832 const char *group_str;
5833 const char *source_str;
5834 struct in_addr group_addr;
5835 struct in_addr source_addr;
5836 int result;
5837
5838 /* Group address */
5839 group_str = argv[idx_ipv4]->arg;
5840 result = inet_pton(AF_INET, group_str, &group_addr);
5841 if (result <= 0) {
5842 vty_out(vty, "Bad group address %s: errno=%d: %s\n", group_str,
5843 errno, safe_strerror(errno));
5844 return CMD_WARNING_CONFIG_FAILED;
5845 }
5846
5847 /* Source address */
5848 source_str = argv[idx_ipv4_2]->arg;
5849 result = inet_pton(AF_INET, source_str, &source_addr);
5850 if (result <= 0) {
5851 vty_out(vty, "Bad source address %s: errno=%d: %s\n",
5852 source_str, errno, safe_strerror(errno));
5853 return CMD_WARNING_CONFIG_FAILED;
5854 }
5855
5856 result = pim_if_igmp_join_del(ifp, group_addr, source_addr);
5857 if (result) {
5858 vty_out(vty,
5859 "%% Failure leaving IGMP group %s source %s on interface %s: %d\n",
5860 group_str, source_str, ifp->name, result);
5861 return CMD_WARNING_CONFIG_FAILED;
5862 }
5863
5864 return CMD_SUCCESS;
5865 }
5866
5867 /*
5868 CLI reconfiguration affects the interface level (struct pim_interface).
5869 This function propagates the reconfiguration to every active socket
5870 for that interface.
5871 */
5872 static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp)
5873 {
5874 struct interface *ifp;
5875 struct pim_interface *pim_ifp;
5876
5877 zassert(igmp);
5878
5879 /* other querier present? */
5880
5881 if (igmp->t_other_querier_timer)
5882 return;
5883
5884 /* this is the querier */
5885
5886 zassert(igmp->interface);
5887 zassert(igmp->interface->info);
5888
5889 ifp = igmp->interface;
5890 pim_ifp = ifp->info;
5891
5892 if (PIM_DEBUG_IGMP_TRACE) {
5893 char ifaddr_str[INET_ADDRSTRLEN];
5894 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
5895 sizeof(ifaddr_str));
5896 zlog_debug("%s: Querier %s on %s reconfig query_interval=%d",
5897 __PRETTY_FUNCTION__, ifaddr_str, ifp->name,
5898 pim_ifp->igmp_default_query_interval);
5899 }
5900
5901 /*
5902 igmp_startup_mode_on() will reset QQI:
5903
5904 igmp->querier_query_interval = pim_ifp->igmp_default_query_interval;
5905 */
5906 igmp_startup_mode_on(igmp);
5907 }
5908
5909 static void igmp_sock_query_reschedule(struct igmp_sock *igmp)
5910 {
5911 if (igmp->t_igmp_query_timer) {
5912 /* other querier present */
5913 zassert(igmp->t_igmp_query_timer);
5914 zassert(!igmp->t_other_querier_timer);
5915
5916 pim_igmp_general_query_off(igmp);
5917 pim_igmp_general_query_on(igmp);
5918
5919 zassert(igmp->t_igmp_query_timer);
5920 zassert(!igmp->t_other_querier_timer);
5921 } else {
5922 /* this is the querier */
5923
5924 zassert(!igmp->t_igmp_query_timer);
5925 zassert(igmp->t_other_querier_timer);
5926
5927 pim_igmp_other_querier_timer_off(igmp);
5928 pim_igmp_other_querier_timer_on(igmp);
5929
5930 zassert(!igmp->t_igmp_query_timer);
5931 zassert(igmp->t_other_querier_timer);
5932 }
5933 }
5934
5935 static void change_query_interval(struct pim_interface *pim_ifp,
5936 int query_interval)
5937 {
5938 struct listnode *sock_node;
5939 struct igmp_sock *igmp;
5940
5941 pim_ifp->igmp_default_query_interval = query_interval;
5942
5943 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
5944 igmp_sock_query_interval_reconfig(igmp);
5945 igmp_sock_query_reschedule(igmp);
5946 }
5947 }
5948
5949 static void change_query_max_response_time(struct pim_interface *pim_ifp,
5950 int query_max_response_time_dsec)
5951 {
5952 struct listnode *sock_node;
5953 struct igmp_sock *igmp;
5954
5955 pim_ifp->igmp_query_max_response_time_dsec =
5956 query_max_response_time_dsec;
5957
5958 /*
5959 Below we modify socket/group/source timers in order to quickly
5960 reflect the change. Otherwise, those timers would eventually catch
5961 up.
5962 */
5963
5964 /* scan all sockets */
5965 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
5966 struct listnode *grp_node;
5967 struct igmp_group *grp;
5968
5969 /* reschedule socket general query */
5970 igmp_sock_query_reschedule(igmp);
5971
5972 /* scan socket groups */
5973 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node,
5974 grp)) {
5975 struct listnode *src_node;
5976 struct igmp_source *src;
5977
5978 /* reset group timers for groups in EXCLUDE mode */
5979 if (grp->group_filtermode_isexcl) {
5980 igmp_group_reset_gmi(grp);
5981 }
5982
5983 /* scan group sources */
5984 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list,
5985 src_node, src)) {
5986
5987 /* reset source timers for sources with running
5988 * timers */
5989 if (src->t_source_timer) {
5990 igmp_source_reset_gmi(igmp, grp, src);
5991 }
5992 }
5993 }
5994 }
5995 }
5996
5997 #define IGMP_QUERY_INTERVAL_MIN (1)
5998 #define IGMP_QUERY_INTERVAL_MAX (1800)
5999
6000 DEFUN (interface_ip_igmp_query_interval,
6001 interface_ip_igmp_query_interval_cmd,
6002 "ip igmp query-interval (1-1800)",
6003 IP_STR
6004 IFACE_IGMP_STR
6005 IFACE_IGMP_QUERY_INTERVAL_STR
6006 "Query interval in seconds\n")
6007 {
6008 VTY_DECLVAR_CONTEXT(interface, ifp);
6009 struct pim_interface *pim_ifp = ifp->info;
6010 int query_interval;
6011 int query_interval_dsec;
6012 int ret;
6013
6014 if (!pim_ifp) {
6015 ret = pim_cmd_igmp_start(vty, ifp);
6016 if (ret != CMD_SUCCESS)
6017 return ret;
6018 pim_ifp = ifp->info;
6019 }
6020
6021 query_interval = atoi(argv[3]->arg);
6022 query_interval_dsec = 10 * query_interval;
6023
6024 /*
6025 It seems we don't need to check bounds since command.c does it
6026 already, but we verify them anyway for extra safety.
6027 */
6028 if (query_interval < IGMP_QUERY_INTERVAL_MIN) {
6029 vty_out(vty,
6030 "General query interval %d lower than minimum %d\n",
6031 query_interval, IGMP_QUERY_INTERVAL_MIN);
6032 return CMD_WARNING_CONFIG_FAILED;
6033 }
6034 if (query_interval > IGMP_QUERY_INTERVAL_MAX) {
6035 vty_out(vty,
6036 "General query interval %d higher than maximum %d\n",
6037 query_interval, IGMP_QUERY_INTERVAL_MAX);
6038 return CMD_WARNING_CONFIG_FAILED;
6039 }
6040
6041 if (query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) {
6042 vty_out(vty,
6043 "Can't set general query interval %d dsec <= query max response time %d dsec.\n",
6044 query_interval_dsec,
6045 pim_ifp->igmp_query_max_response_time_dsec);
6046 return CMD_WARNING_CONFIG_FAILED;
6047 }
6048
6049 change_query_interval(pim_ifp, query_interval);
6050
6051 return CMD_SUCCESS;
6052 }
6053
6054 DEFUN (interface_no_ip_igmp_query_interval,
6055 interface_no_ip_igmp_query_interval_cmd,
6056 "no ip igmp query-interval",
6057 NO_STR
6058 IP_STR
6059 IFACE_IGMP_STR
6060 IFACE_IGMP_QUERY_INTERVAL_STR)
6061 {
6062 VTY_DECLVAR_CONTEXT(interface, ifp);
6063 struct pim_interface *pim_ifp = ifp->info;
6064 int default_query_interval_dsec;
6065
6066 if (!pim_ifp)
6067 return CMD_SUCCESS;
6068
6069 default_query_interval_dsec = IGMP_GENERAL_QUERY_INTERVAL * 10;
6070
6071 if (default_query_interval_dsec
6072 <= pim_ifp->igmp_query_max_response_time_dsec) {
6073 vty_out(vty,
6074 "Can't set default general query interval %d dsec <= query max response time %d dsec.\n",
6075 default_query_interval_dsec,
6076 pim_ifp->igmp_query_max_response_time_dsec);
6077 return CMD_WARNING_CONFIG_FAILED;
6078 }
6079
6080 change_query_interval(pim_ifp, IGMP_GENERAL_QUERY_INTERVAL);
6081
6082 return CMD_SUCCESS;
6083 }
6084
6085 DEFUN (interface_ip_igmp_version,
6086 interface_ip_igmp_version_cmd,
6087 "ip igmp version (2-3)",
6088 IP_STR
6089 IFACE_IGMP_STR
6090 "IGMP version\n"
6091 "IGMP version number\n")
6092 {
6093 VTY_DECLVAR_CONTEXT(interface, ifp);
6094 struct pim_interface *pim_ifp = ifp->info;
6095 int igmp_version, old_version = 0;
6096 int ret;
6097
6098 if (!pim_ifp) {
6099 ret = pim_cmd_igmp_start(vty, ifp);
6100 if (ret != CMD_SUCCESS)
6101 return ret;
6102 pim_ifp = ifp->info;
6103 }
6104
6105 igmp_version = atoi(argv[3]->arg);
6106 old_version = pim_ifp->igmp_version;
6107 pim_ifp->igmp_version = igmp_version;
6108
6109 // Check if IGMP is Enabled otherwise, enable on interface
6110 if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
6111 PIM_IF_DO_IGMP(pim_ifp->options);
6112 pim_if_addr_add_all(ifp);
6113 pim_if_membership_refresh(ifp);
6114 old_version = igmp_version; // avoid refreshing membership
6115 // again.
6116 }
6117 /* Current and new version is different refresh existing
6118 membership. Going from 3 -> 2 or 2 -> 3. */
6119 if (old_version != igmp_version)
6120 pim_if_membership_refresh(ifp);
6121
6122 return CMD_SUCCESS;
6123 }
6124
6125 DEFUN (interface_no_ip_igmp_version,
6126 interface_no_ip_igmp_version_cmd,
6127 "no ip igmp version (2-3)",
6128 NO_STR
6129 IP_STR
6130 IFACE_IGMP_STR
6131 "IGMP version\n"
6132 "IGMP version number\n")
6133 {
6134 VTY_DECLVAR_CONTEXT(interface, ifp);
6135 struct pim_interface *pim_ifp = ifp->info;
6136
6137 if (!pim_ifp)
6138 return CMD_SUCCESS;
6139
6140 pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
6141
6142 return CMD_SUCCESS;
6143 }
6144
6145 #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10)
6146 #define IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC (250)
6147
6148 DEFUN (interface_ip_igmp_query_max_response_time,
6149 interface_ip_igmp_query_max_response_time_cmd,
6150 "ip igmp query-max-response-time (10-250)",
6151 IP_STR
6152 IFACE_IGMP_STR
6153 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
6154 "Query response value in deci-seconds\n")
6155 {
6156 VTY_DECLVAR_CONTEXT(interface, ifp);
6157 struct pim_interface *pim_ifp = ifp->info;
6158 int query_max_response_time;
6159 int ret;
6160
6161 if (!pim_ifp) {
6162 ret = pim_cmd_igmp_start(vty, ifp);
6163 if (ret != CMD_SUCCESS)
6164 return ret;
6165 pim_ifp = ifp->info;
6166 }
6167
6168 query_max_response_time = atoi(argv[3]->arg);
6169
6170 if (query_max_response_time
6171 >= pim_ifp->igmp_default_query_interval * 10) {
6172 vty_out(vty,
6173 "Can't set query max response time %d sec >= general query interval %d sec\n",
6174 query_max_response_time,
6175 pim_ifp->igmp_default_query_interval);
6176 return CMD_WARNING_CONFIG_FAILED;
6177 }
6178
6179 change_query_max_response_time(pim_ifp, query_max_response_time);
6180
6181 return CMD_SUCCESS;
6182 }
6183
6184 DEFUN (interface_no_ip_igmp_query_max_response_time,
6185 interface_no_ip_igmp_query_max_response_time_cmd,
6186 "no ip igmp query-max-response-time (10-250)",
6187 NO_STR
6188 IP_STR
6189 IFACE_IGMP_STR
6190 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
6191 "Time for response in deci-seconds\n")
6192 {
6193 VTY_DECLVAR_CONTEXT(interface, ifp);
6194 struct pim_interface *pim_ifp = ifp->info;
6195
6196 if (!pim_ifp)
6197 return CMD_SUCCESS;
6198
6199 change_query_max_response_time(pim_ifp,
6200 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
6201
6202 return CMD_SUCCESS;
6203 }
6204
6205 #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10)
6206 #define IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC (250)
6207
6208 DEFUN_HIDDEN (interface_ip_igmp_query_max_response_time_dsec,
6209 interface_ip_igmp_query_max_response_time_dsec_cmd,
6210 "ip igmp query-max-response-time-dsec (10-250)",
6211 IP_STR
6212 IFACE_IGMP_STR
6213 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR
6214 "Query response value in deciseconds\n")
6215 {
6216 VTY_DECLVAR_CONTEXT(interface, ifp);
6217 struct pim_interface *pim_ifp = ifp->info;
6218 int query_max_response_time_dsec;
6219 int default_query_interval_dsec;
6220 int ret;
6221
6222 if (!pim_ifp) {
6223 ret = pim_cmd_igmp_start(vty, ifp);
6224 if (ret != CMD_SUCCESS)
6225 return ret;
6226 pim_ifp = ifp->info;
6227 }
6228
6229 query_max_response_time_dsec = atoi(argv[4]->arg);
6230
6231 default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
6232
6233 if (query_max_response_time_dsec >= default_query_interval_dsec) {
6234 vty_out(vty,
6235 "Can't set query max response time %d dsec >= general query interval %d dsec\n",
6236 query_max_response_time_dsec,
6237 default_query_interval_dsec);
6238 return CMD_WARNING_CONFIG_FAILED;
6239 }
6240
6241 change_query_max_response_time(pim_ifp, query_max_response_time_dsec);
6242
6243 return CMD_SUCCESS;
6244 }
6245
6246 DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec,
6247 interface_no_ip_igmp_query_max_response_time_dsec_cmd,
6248 "no ip igmp query-max-response-time-dsec",
6249 NO_STR
6250 IP_STR
6251 IFACE_IGMP_STR
6252 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR)
6253 {
6254 VTY_DECLVAR_CONTEXT(interface, ifp);
6255 struct pim_interface *pim_ifp = ifp->info;
6256
6257 if (!pim_ifp)
6258 return CMD_SUCCESS;
6259
6260 change_query_max_response_time(pim_ifp,
6261 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
6262
6263 return CMD_SUCCESS;
6264 }
6265
6266 DEFUN (interface_ip_pim_drprio,
6267 interface_ip_pim_drprio_cmd,
6268 "ip pim drpriority (1-4294967295)",
6269 IP_STR
6270 PIM_STR
6271 "Set the Designated Router Election Priority\n"
6272 "Value of the new DR Priority\n")
6273 {
6274 VTY_DECLVAR_CONTEXT(interface, ifp);
6275 int idx_number = 3;
6276 struct pim_interface *pim_ifp = ifp->info;
6277 uint32_t old_dr_prio;
6278
6279 if (!pim_ifp) {
6280 vty_out(vty, "Please enable PIM on interface, first\n");
6281 return CMD_WARNING_CONFIG_FAILED;
6282 }
6283
6284 old_dr_prio = pim_ifp->pim_dr_priority;
6285
6286 pim_ifp->pim_dr_priority = strtol(argv[idx_number]->arg, NULL, 10);
6287
6288 if (old_dr_prio != pim_ifp->pim_dr_priority) {
6289 if (pim_if_dr_election(ifp))
6290 pim_hello_restart_now(ifp);
6291 }
6292
6293 return CMD_SUCCESS;
6294 }
6295
6296 DEFUN (interface_no_ip_pim_drprio,
6297 interface_no_ip_pim_drprio_cmd,
6298 "no ip pim drpriority [(1-4294967295)]",
6299 NO_STR
6300 IP_STR
6301 PIM_STR
6302 "Revert the Designated Router Priority to default\n"
6303 "Old Value of the Priority\n")
6304 {
6305 VTY_DECLVAR_CONTEXT(interface, ifp);
6306 struct pim_interface *pim_ifp = ifp->info;
6307
6308 if (!pim_ifp) {
6309 vty_out(vty, "Pim not enabled on this interface\n");
6310 return CMD_WARNING_CONFIG_FAILED;
6311 }
6312
6313 if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) {
6314 pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY;
6315 if (pim_if_dr_election(ifp))
6316 pim_hello_restart_now(ifp);
6317 }
6318
6319 return CMD_SUCCESS;
6320 }
6321
6322 static int pim_cmd_interface_add(struct interface *ifp)
6323 {
6324 struct pim_interface *pim_ifp = ifp->info;
6325
6326 if (!pim_ifp) {
6327 pim_ifp = pim_if_new(ifp, 0 /* igmp=false */, 1 /* pim=true */);
6328 if (!pim_ifp) {
6329 return 0;
6330 }
6331 } else {
6332 PIM_IF_DO_PIM(pim_ifp->options);
6333 }
6334
6335 pim_if_addr_add_all(ifp);
6336 pim_if_membership_refresh(ifp);
6337 return 1;
6338 }
6339
6340 DEFUN_HIDDEN (interface_ip_pim_ssm,
6341 interface_ip_pim_ssm_cmd,
6342 "ip pim ssm",
6343 IP_STR
6344 PIM_STR
6345 IFACE_PIM_STR)
6346 {
6347 VTY_DECLVAR_CONTEXT(interface, ifp);
6348
6349 if (!pim_cmd_interface_add(ifp)) {
6350 vty_out(vty, "Could not enable PIM SM on interface\n");
6351 return CMD_WARNING_CONFIG_FAILED;
6352 }
6353
6354 vty_out(vty,
6355 "WARN: Enabled PIM SM on interface; configure PIM SSM "
6356 "range if needed\n");
6357 return CMD_SUCCESS;
6358 }
6359
6360 DEFUN (interface_ip_pim_sm,
6361 interface_ip_pim_sm_cmd,
6362 "ip pim sm",
6363 IP_STR
6364 PIM_STR
6365 IFACE_PIM_SM_STR)
6366 {
6367 struct pim_interface *pim_ifp;
6368
6369 VTY_DECLVAR_CONTEXT(interface, ifp);
6370 if (!pim_cmd_interface_add(ifp)) {
6371 vty_out(vty, "Could not enable PIM SM on interface\n");
6372 return CMD_WARNING_CONFIG_FAILED;
6373 }
6374
6375 pim_ifp = ifp->info;
6376
6377 pim_if_create_pimreg(pim_ifp->pim);
6378
6379 return CMD_SUCCESS;
6380 }
6381
6382 static int pim_cmd_interface_delete(struct interface *ifp)
6383 {
6384 struct pim_interface *pim_ifp = ifp->info;
6385
6386 if (!pim_ifp)
6387 return 1;
6388
6389 PIM_IF_DONT_PIM(pim_ifp->options);
6390
6391 pim_if_membership_clear(ifp);
6392
6393 /*
6394 pim_sock_delete() removes all neighbors from
6395 pim_ifp->pim_neighbor_list.
6396 */
6397 pim_sock_delete(ifp, "pim unconfigured on interface");
6398
6399 if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
6400 pim_if_addr_del_all(ifp);
6401 pim_if_delete(ifp);
6402 }
6403
6404 return 1;
6405 }
6406
6407 DEFUN_HIDDEN (interface_no_ip_pim_ssm,
6408 interface_no_ip_pim_ssm_cmd,
6409 "no ip pim ssm",
6410 NO_STR
6411 IP_STR
6412 PIM_STR
6413 IFACE_PIM_STR)
6414 {
6415 VTY_DECLVAR_CONTEXT(interface, ifp);
6416 if (!pim_cmd_interface_delete(ifp)) {
6417 vty_out(vty, "Unable to delete interface information\n");
6418 return CMD_WARNING_CONFIG_FAILED;
6419 }
6420
6421 return CMD_SUCCESS;
6422 }
6423
6424 DEFUN (interface_no_ip_pim_sm,
6425 interface_no_ip_pim_sm_cmd,
6426 "no ip pim sm",
6427 NO_STR
6428 IP_STR
6429 PIM_STR
6430 IFACE_PIM_SM_STR)
6431 {
6432 VTY_DECLVAR_CONTEXT(interface, ifp);
6433 if (!pim_cmd_interface_delete(ifp)) {
6434 vty_out(vty, "Unable to delete interface information\n");
6435 return CMD_WARNING_CONFIG_FAILED;
6436 }
6437
6438 return CMD_SUCCESS;
6439 }
6440
6441 /* boundaries */
6442 DEFUN(interface_ip_pim_boundary_oil,
6443 interface_ip_pim_boundary_oil_cmd,
6444 "ip multicast boundary oil WORD",
6445 IP_STR
6446 "Generic multicast configuration options\n"
6447 "Define multicast boundary\n"
6448 "Filter OIL by group using prefix list\n"
6449 "Prefix list to filter OIL with\n")
6450 {
6451 VTY_DECLVAR_CONTEXT(interface, iif);
6452 struct pim_interface *pim_ifp;
6453 int idx = 0;
6454
6455 argv_find(argv, argc, "WORD", &idx);
6456
6457 PIM_GET_PIM_INTERFACE(pim_ifp, iif);
6458
6459 if (pim_ifp->boundary_oil_plist)
6460 XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
6461
6462 pim_ifp->boundary_oil_plist =
6463 XSTRDUP(MTYPE_PIM_INTERFACE, argv[idx]->arg);
6464
6465 /* Interface will be pruned from OIL on next Join */
6466 return CMD_SUCCESS;
6467 }
6468
6469 DEFUN(interface_no_ip_pim_boundary_oil,
6470 interface_no_ip_pim_boundary_oil_cmd,
6471 "no ip multicast boundary oil [WORD]",
6472 NO_STR
6473 IP_STR
6474 "Generic multicast configuration options\n"
6475 "Define multicast boundary\n"
6476 "Filter OIL by group using prefix list\n"
6477 "Prefix list to filter OIL with\n")
6478 {
6479 VTY_DECLVAR_CONTEXT(interface, iif);
6480 struct pim_interface *pim_ifp;
6481 int idx;
6482
6483 argv_find(argv, argc, "WORD", &idx);
6484
6485 PIM_GET_PIM_INTERFACE(pim_ifp, iif);
6486
6487 if (pim_ifp->boundary_oil_plist)
6488 XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
6489
6490 return CMD_SUCCESS;
6491 }
6492
6493 DEFUN (interface_ip_mroute,
6494 interface_ip_mroute_cmd,
6495 "ip mroute INTERFACE A.B.C.D",
6496 IP_STR
6497 "Add multicast route\n"
6498 "Outgoing interface name\n"
6499 "Group address\n")
6500 {
6501 VTY_DECLVAR_CONTEXT(interface, iif);
6502 struct pim_interface *pim_ifp;
6503 struct pim_instance *pim;
6504 int idx_interface = 2;
6505 int idx_ipv4 = 3;
6506 struct interface *oif;
6507 const char *oifname;
6508 const char *grp_str;
6509 struct in_addr grp_addr;
6510 struct in_addr src_addr;
6511 int result;
6512
6513 PIM_GET_PIM_INTERFACE(pim_ifp, iif);
6514 pim = pim_ifp->pim;
6515
6516 oifname = argv[idx_interface]->arg;
6517 oif = if_lookup_by_name(oifname, pim->vrf_id);
6518 if (!oif) {
6519 vty_out(vty, "No such interface name %s\n", oifname);
6520 return CMD_WARNING;
6521 }
6522
6523 grp_str = argv[idx_ipv4]->arg;
6524 result = inet_pton(AF_INET, grp_str, &grp_addr);
6525 if (result <= 0) {
6526 vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
6527 errno, safe_strerror(errno));
6528 return CMD_WARNING;
6529 }
6530
6531 src_addr.s_addr = INADDR_ANY;
6532
6533 if (pim_static_add(pim, iif, oif, grp_addr, src_addr)) {
6534 vty_out(vty, "Failed to add route\n");
6535 return CMD_WARNING;
6536 }
6537
6538 return CMD_SUCCESS;
6539 }
6540
6541 DEFUN (interface_ip_mroute_source,
6542 interface_ip_mroute_source_cmd,
6543 "ip mroute INTERFACE A.B.C.D A.B.C.D",
6544 IP_STR
6545 "Add multicast route\n"
6546 "Outgoing interface name\n"
6547 "Group address\n"
6548 "Source address\n")
6549 {
6550 VTY_DECLVAR_CONTEXT(interface, iif);
6551 struct pim_interface *pim_ifp;
6552 struct pim_instance *pim;
6553 int idx_interface = 2;
6554 int idx_ipv4 = 3;
6555 int idx_ipv4_2 = 4;
6556 struct interface *oif;
6557 const char *oifname;
6558 const char *grp_str;
6559 struct in_addr grp_addr;
6560 const char *src_str;
6561 struct in_addr src_addr;
6562 int result;
6563
6564 PIM_GET_PIM_INTERFACE(pim_ifp, iif);
6565 pim = pim_ifp->pim;
6566
6567 oifname = argv[idx_interface]->arg;
6568 oif = if_lookup_by_name(oifname, pim->vrf_id);
6569 if (!oif) {
6570 vty_out(vty, "No such interface name %s\n", oifname);
6571 return CMD_WARNING;
6572 }
6573
6574 grp_str = argv[idx_ipv4]->arg;
6575 result = inet_pton(AF_INET, grp_str, &grp_addr);
6576 if (result <= 0) {
6577 vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
6578 errno, safe_strerror(errno));
6579 return CMD_WARNING;
6580 }
6581
6582 src_str = argv[idx_ipv4_2]->arg;
6583 result = inet_pton(AF_INET, src_str, &src_addr);
6584 if (result <= 0) {
6585 vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str,
6586 errno, safe_strerror(errno));
6587 return CMD_WARNING;
6588 }
6589
6590 if (pim_static_add(pim, iif, oif, grp_addr, src_addr)) {
6591 vty_out(vty, "Failed to add route\n");
6592 return CMD_WARNING;
6593 }
6594
6595 return CMD_SUCCESS;
6596 }
6597
6598 DEFUN (interface_no_ip_mroute,
6599 interface_no_ip_mroute_cmd,
6600 "no ip mroute INTERFACE A.B.C.D",
6601 NO_STR
6602 IP_STR
6603 "Add multicast route\n"
6604 "Outgoing interface name\n"
6605 "Group Address\n")
6606 {
6607 VTY_DECLVAR_CONTEXT(interface, iif);
6608 struct pim_interface *pim_ifp;
6609 struct pim_instance *pim;
6610 int idx_interface = 3;
6611 int idx_ipv4 = 4;
6612 struct interface *oif;
6613 const char *oifname;
6614 const char *grp_str;
6615 struct in_addr grp_addr;
6616 struct in_addr src_addr;
6617 int result;
6618
6619 PIM_GET_PIM_INTERFACE(pim_ifp, iif);
6620 pim = pim_ifp->pim;
6621
6622 oifname = argv[idx_interface]->arg;
6623 oif = if_lookup_by_name(oifname, pim->vrf_id);
6624 if (!oif) {
6625 vty_out(vty, "No such interface name %s\n", oifname);
6626 return CMD_WARNING;
6627 }
6628
6629 grp_str = argv[idx_ipv4]->arg;
6630 result = inet_pton(AF_INET, grp_str, &grp_addr);
6631 if (result <= 0) {
6632 vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
6633 errno, safe_strerror(errno));
6634 return CMD_WARNING;
6635 }
6636
6637 src_addr.s_addr = INADDR_ANY;
6638
6639 if (pim_static_del(pim, iif, oif, grp_addr, src_addr)) {
6640 vty_out(vty, "Failed to remove route\n");
6641 return CMD_WARNING;
6642 }
6643
6644 return CMD_SUCCESS;
6645 }
6646
6647 DEFUN (interface_no_ip_mroute_source,
6648 interface_no_ip_mroute_source_cmd,
6649 "no ip mroute INTERFACE A.B.C.D A.B.C.D",
6650 NO_STR
6651 IP_STR
6652 "Add multicast route\n"
6653 "Outgoing interface name\n"
6654 "Group Address\n"
6655 "Source Address\n")
6656 {
6657 VTY_DECLVAR_CONTEXT(interface, iif);
6658 struct pim_interface *pim_ifp;
6659 struct pim_instance *pim;
6660 int idx_interface = 3;
6661 int idx_ipv4 = 4;
6662 int idx_ipv4_2 = 5;
6663 struct interface *oif;
6664 const char *oifname;
6665 const char *grp_str;
6666 struct in_addr grp_addr;
6667 const char *src_str;
6668 struct in_addr src_addr;
6669 int result;
6670
6671 PIM_GET_PIM_INTERFACE(pim_ifp, iif);
6672 pim = pim_ifp->pim;
6673
6674 oifname = argv[idx_interface]->arg;
6675 oif = if_lookup_by_name(oifname, pim->vrf_id);
6676 if (!oif) {
6677 vty_out(vty, "No such interface name %s\n", oifname);
6678 return CMD_WARNING;
6679 }
6680
6681 grp_str = argv[idx_ipv4]->arg;
6682 result = inet_pton(AF_INET, grp_str, &grp_addr);
6683 if (result <= 0) {
6684 vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
6685 errno, safe_strerror(errno));
6686 return CMD_WARNING;
6687 }
6688
6689 src_str = argv[idx_ipv4_2]->arg;
6690 result = inet_pton(AF_INET, src_str, &src_addr);
6691 if (result <= 0) {
6692 vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str,
6693 errno, safe_strerror(errno));
6694 return CMD_WARNING;
6695 }
6696
6697 if (pim_static_del(pim, iif, oif, grp_addr, src_addr)) {
6698 vty_out(vty, "Failed to remove route\n");
6699 return CMD_WARNING;
6700 }
6701
6702 return CMD_SUCCESS;
6703 }
6704
6705 DEFUN (interface_ip_pim_hello,
6706 interface_ip_pim_hello_cmd,
6707 "ip pim hello (1-180) [(1-180)]",
6708 IP_STR
6709 PIM_STR
6710 IFACE_PIM_HELLO_STR
6711 IFACE_PIM_HELLO_TIME_STR
6712 IFACE_PIM_HELLO_HOLD_STR)
6713 {
6714 VTY_DECLVAR_CONTEXT(interface, ifp);
6715 int idx_time = 3;
6716 int idx_hold = 4;
6717 struct pim_interface *pim_ifp = ifp->info;
6718
6719 if (!pim_ifp) {
6720 if (!pim_cmd_interface_add(ifp)) {
6721 vty_out(vty, "Could not enable PIM SM on interface\n");
6722 return CMD_WARNING_CONFIG_FAILED;
6723 }
6724 }
6725
6726 pim_ifp = ifp->info;
6727 pim_ifp->pim_hello_period = strtol(argv[idx_time]->arg, NULL, 10);
6728
6729 if (argc == idx_hold + 1)
6730 pim_ifp->pim_default_holdtime =
6731 strtol(argv[idx_hold]->arg, NULL, 10);
6732
6733 return CMD_SUCCESS;
6734 }
6735
6736 DEFUN (interface_no_ip_pim_hello,
6737 interface_no_ip_pim_hello_cmd,
6738 "no ip pim hello [(1-180) (1-180)]",
6739 NO_STR
6740 IP_STR
6741 PIM_STR
6742 IFACE_PIM_HELLO_STR
6743 IFACE_PIM_HELLO_TIME_STR
6744 IFACE_PIM_HELLO_HOLD_STR)
6745 {
6746 VTY_DECLVAR_CONTEXT(interface, ifp);
6747 struct pim_interface *pim_ifp = ifp->info;
6748
6749 if (!pim_ifp) {
6750 vty_out(vty, "Pim not enabled on this interface\n");
6751 return CMD_WARNING_CONFIG_FAILED;
6752 }
6753
6754 pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD;
6755 pim_ifp->pim_default_holdtime = -1;
6756
6757 return CMD_SUCCESS;
6758 }
6759
6760 DEFUN (debug_igmp,
6761 debug_igmp_cmd,
6762 "debug igmp",
6763 DEBUG_STR
6764 DEBUG_IGMP_STR)
6765 {
6766 PIM_DO_DEBUG_IGMP_EVENTS;
6767 PIM_DO_DEBUG_IGMP_PACKETS;
6768 PIM_DO_DEBUG_IGMP_TRACE;
6769 return CMD_SUCCESS;
6770 }
6771
6772 DEFUN (no_debug_igmp,
6773 no_debug_igmp_cmd,
6774 "no debug igmp",
6775 NO_STR
6776 DEBUG_STR
6777 DEBUG_IGMP_STR)
6778 {
6779 PIM_DONT_DEBUG_IGMP_EVENTS;
6780 PIM_DONT_DEBUG_IGMP_PACKETS;
6781 PIM_DONT_DEBUG_IGMP_TRACE;
6782 return CMD_SUCCESS;
6783 }
6784
6785
6786 DEFUN (debug_igmp_events,
6787 debug_igmp_events_cmd,
6788 "debug igmp events",
6789 DEBUG_STR
6790 DEBUG_IGMP_STR
6791 DEBUG_IGMP_EVENTS_STR)
6792 {
6793 PIM_DO_DEBUG_IGMP_EVENTS;
6794 return CMD_SUCCESS;
6795 }
6796
6797 DEFUN (no_debug_igmp_events,
6798 no_debug_igmp_events_cmd,
6799 "no debug igmp events",
6800 NO_STR
6801 DEBUG_STR
6802 DEBUG_IGMP_STR
6803 DEBUG_IGMP_EVENTS_STR)
6804 {
6805 PIM_DONT_DEBUG_IGMP_EVENTS;
6806 return CMD_SUCCESS;
6807 }
6808
6809
6810 DEFUN (debug_igmp_packets,
6811 debug_igmp_packets_cmd,
6812 "debug igmp packets",
6813 DEBUG_STR
6814 DEBUG_IGMP_STR
6815 DEBUG_IGMP_PACKETS_STR)
6816 {
6817 PIM_DO_DEBUG_IGMP_PACKETS;
6818 return CMD_SUCCESS;
6819 }
6820
6821 DEFUN (no_debug_igmp_packets,
6822 no_debug_igmp_packets_cmd,
6823 "no debug igmp packets",
6824 NO_STR
6825 DEBUG_STR
6826 DEBUG_IGMP_STR
6827 DEBUG_IGMP_PACKETS_STR)
6828 {
6829 PIM_DONT_DEBUG_IGMP_PACKETS;
6830 return CMD_SUCCESS;
6831 }
6832
6833
6834 DEFUN (debug_igmp_trace,
6835 debug_igmp_trace_cmd,
6836 "debug igmp trace",
6837 DEBUG_STR
6838 DEBUG_IGMP_STR
6839 DEBUG_IGMP_TRACE_STR)
6840 {
6841 PIM_DO_DEBUG_IGMP_TRACE;
6842 return CMD_SUCCESS;
6843 }
6844
6845 DEFUN (no_debug_igmp_trace,
6846 no_debug_igmp_trace_cmd,
6847 "no debug igmp trace",
6848 NO_STR
6849 DEBUG_STR
6850 DEBUG_IGMP_STR
6851 DEBUG_IGMP_TRACE_STR)
6852 {
6853 PIM_DONT_DEBUG_IGMP_TRACE;
6854 return CMD_SUCCESS;
6855 }
6856
6857
6858 DEFUN (debug_mroute,
6859 debug_mroute_cmd,
6860 "debug mroute",
6861 DEBUG_STR
6862 DEBUG_MROUTE_STR)
6863 {
6864 PIM_DO_DEBUG_MROUTE;
6865 return CMD_SUCCESS;
6866 }
6867
6868 DEFUN (debug_mroute_detail,
6869 debug_mroute_detail_cmd,
6870 "debug mroute detail",
6871 DEBUG_STR
6872 DEBUG_MROUTE_STR
6873 "detailed\n")
6874 {
6875 PIM_DO_DEBUG_MROUTE_DETAIL;
6876 return CMD_SUCCESS;
6877 }
6878
6879 DEFUN (no_debug_mroute,
6880 no_debug_mroute_cmd,
6881 "no debug mroute",
6882 NO_STR
6883 DEBUG_STR
6884 DEBUG_MROUTE_STR)
6885 {
6886 PIM_DONT_DEBUG_MROUTE;
6887 return CMD_SUCCESS;
6888 }
6889
6890 DEFUN (no_debug_mroute_detail,
6891 no_debug_mroute_detail_cmd,
6892 "no debug mroute detail",
6893 NO_STR
6894 DEBUG_STR
6895 DEBUG_MROUTE_STR
6896 "detailed\n")
6897 {
6898 PIM_DONT_DEBUG_MROUTE_DETAIL;
6899 return CMD_SUCCESS;
6900 }
6901
6902 DEFUN (debug_static,
6903 debug_static_cmd,
6904 "debug static",
6905 DEBUG_STR
6906 DEBUG_STATIC_STR)
6907 {
6908 PIM_DO_DEBUG_STATIC;
6909 return CMD_SUCCESS;
6910 }
6911
6912 DEFUN (no_debug_static,
6913 no_debug_static_cmd,
6914 "no debug static",
6915 NO_STR
6916 DEBUG_STR
6917 DEBUG_STATIC_STR)
6918 {
6919 PIM_DONT_DEBUG_STATIC;
6920 return CMD_SUCCESS;
6921 }
6922
6923
6924 DEFUN (debug_pim,
6925 debug_pim_cmd,
6926 "debug pim",
6927 DEBUG_STR
6928 DEBUG_PIM_STR)
6929 {
6930 PIM_DO_DEBUG_PIM_EVENTS;
6931 PIM_DO_DEBUG_PIM_PACKETS;
6932 PIM_DO_DEBUG_PIM_TRACE;
6933 PIM_DO_DEBUG_MSDP_EVENTS;
6934 PIM_DO_DEBUG_MSDP_PACKETS;
6935 return CMD_SUCCESS;
6936 }
6937
6938 DEFUN (no_debug_pim,
6939 no_debug_pim_cmd,
6940 "no debug pim",
6941 NO_STR
6942 DEBUG_STR
6943 DEBUG_PIM_STR)
6944 {
6945 PIM_DONT_DEBUG_PIM_EVENTS;
6946 PIM_DONT_DEBUG_PIM_PACKETS;
6947 PIM_DONT_DEBUG_PIM_TRACE;
6948 PIM_DONT_DEBUG_MSDP_EVENTS;
6949 PIM_DONT_DEBUG_MSDP_PACKETS;
6950
6951 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
6952 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
6953
6954 return CMD_SUCCESS;
6955 }
6956
6957 DEFUN (debug_pim_nht,
6958 debug_pim_nht_cmd,
6959 "debug pim nht",
6960 DEBUG_STR
6961 DEBUG_PIM_STR
6962 "Nexthop Tracking\n")
6963 {
6964 PIM_DO_DEBUG_PIM_NHT;
6965 return CMD_SUCCESS;
6966 }
6967
6968 DEFUN (no_debug_pim_nht,
6969 no_debug_pim_nht_cmd,
6970 "no debug pim nht",
6971 NO_STR
6972 DEBUG_STR
6973 DEBUG_PIM_STR
6974 "Nexthop Tracking\n")
6975 {
6976 PIM_DONT_DEBUG_PIM_NHT;
6977 return CMD_SUCCESS;
6978 }
6979
6980 DEFUN (debug_pim_nht_rp,
6981 debug_pim_nht_rp_cmd,
6982 "debug pim nht rp",
6983 DEBUG_STR
6984 DEBUG_PIM_STR
6985 "Nexthop Tracking\n"
6986 "RP Nexthop Tracking\n")
6987 {
6988 PIM_DO_DEBUG_PIM_NHT_RP;
6989 return CMD_SUCCESS;
6990 }
6991
6992 DEFUN (no_debug_pim_nht_rp,
6993 no_debug_pim_nht_rp_cmd,
6994 "no debug pim nht rp",
6995 NO_STR
6996 DEBUG_STR
6997 DEBUG_PIM_STR
6998 "Nexthop Tracking\n"
6999 "RP Nexthop Tracking\n")
7000 {
7001 PIM_DONT_DEBUG_PIM_NHT_RP;
7002 return CMD_SUCCESS;
7003 }
7004
7005 DEFUN (debug_pim_events,
7006 debug_pim_events_cmd,
7007 "debug pim events",
7008 DEBUG_STR
7009 DEBUG_PIM_STR
7010 DEBUG_PIM_EVENTS_STR)
7011 {
7012 PIM_DO_DEBUG_PIM_EVENTS;
7013 return CMD_SUCCESS;
7014 }
7015
7016 DEFUN (no_debug_pim_events,
7017 no_debug_pim_events_cmd,
7018 "no debug pim events",
7019 NO_STR
7020 DEBUG_STR
7021 DEBUG_PIM_STR
7022 DEBUG_PIM_EVENTS_STR)
7023 {
7024 PIM_DONT_DEBUG_PIM_EVENTS;
7025 return CMD_SUCCESS;
7026 }
7027
7028 DEFUN (debug_pim_packets,
7029 debug_pim_packets_cmd,
7030 "debug pim packets [<hello|joins|register>]",
7031 DEBUG_STR
7032 DEBUG_PIM_STR
7033 DEBUG_PIM_PACKETS_STR
7034 DEBUG_PIM_HELLO_PACKETS_STR
7035 DEBUG_PIM_J_P_PACKETS_STR
7036 DEBUG_PIM_PIM_REG_PACKETS_STR)
7037 {
7038 int idx = 0;
7039 if (argv_find(argv, argc, "hello", &idx)) {
7040 PIM_DO_DEBUG_PIM_HELLO;
7041 vty_out(vty, "PIM Hello debugging is on\n");
7042 } else if (argv_find(argv, argc, "joins", &idx)) {
7043 PIM_DO_DEBUG_PIM_J_P;
7044 vty_out(vty, "PIM Join/Prune debugging is on\n");
7045 } else if (argv_find(argv, argc, "register", &idx)) {
7046 PIM_DO_DEBUG_PIM_REG;
7047 vty_out(vty, "PIM Register debugging is on\n");
7048 } else {
7049 PIM_DO_DEBUG_PIM_PACKETS;
7050 vty_out(vty, "PIM Packet debugging is on \n");
7051 }
7052 return CMD_SUCCESS;
7053 }
7054
7055 DEFUN (no_debug_pim_packets,
7056 no_debug_pim_packets_cmd,
7057 "no debug pim packets [<hello|joins|register>]",
7058 NO_STR
7059 DEBUG_STR
7060 DEBUG_PIM_STR
7061 DEBUG_PIM_PACKETS_STR
7062 DEBUG_PIM_HELLO_PACKETS_STR
7063 DEBUG_PIM_J_P_PACKETS_STR
7064 DEBUG_PIM_PIM_REG_PACKETS_STR)
7065 {
7066 int idx = 0;
7067 if (argv_find(argv, argc, "hello", &idx)) {
7068 PIM_DONT_DEBUG_PIM_HELLO;
7069 vty_out(vty, "PIM Hello debugging is off \n");
7070 } else if (argv_find(argv, argc, "joins", &idx)) {
7071 PIM_DONT_DEBUG_PIM_J_P;
7072 vty_out(vty, "PIM Join/Prune debugging is off \n");
7073 } else if (argv_find(argv, argc, "register", &idx)) {
7074 PIM_DONT_DEBUG_PIM_REG;
7075 vty_out(vty, "PIM Register debugging is off\n");
7076 } else
7077 PIM_DONT_DEBUG_PIM_PACKETS;
7078
7079 return CMD_SUCCESS;
7080 }
7081
7082
7083 DEFUN (debug_pim_packetdump_send,
7084 debug_pim_packetdump_send_cmd,
7085 "debug pim packet-dump send",
7086 DEBUG_STR
7087 DEBUG_PIM_STR
7088 DEBUG_PIM_PACKETDUMP_STR
7089 DEBUG_PIM_PACKETDUMP_SEND_STR)
7090 {
7091 PIM_DO_DEBUG_PIM_PACKETDUMP_SEND;
7092 return CMD_SUCCESS;
7093 }
7094
7095 DEFUN (no_debug_pim_packetdump_send,
7096 no_debug_pim_packetdump_send_cmd,
7097 "no debug pim packet-dump send",
7098 NO_STR
7099 DEBUG_STR
7100 DEBUG_PIM_STR
7101 DEBUG_PIM_PACKETDUMP_STR
7102 DEBUG_PIM_PACKETDUMP_SEND_STR)
7103 {
7104 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
7105 return CMD_SUCCESS;
7106 }
7107
7108 DEFUN (debug_pim_packetdump_recv,
7109 debug_pim_packetdump_recv_cmd,
7110 "debug pim packet-dump receive",
7111 DEBUG_STR
7112 DEBUG_PIM_STR
7113 DEBUG_PIM_PACKETDUMP_STR
7114 DEBUG_PIM_PACKETDUMP_RECV_STR)
7115 {
7116 PIM_DO_DEBUG_PIM_PACKETDUMP_RECV;
7117 return CMD_SUCCESS;
7118 }
7119
7120 DEFUN (no_debug_pim_packetdump_recv,
7121 no_debug_pim_packetdump_recv_cmd,
7122 "no debug pim packet-dump receive",
7123 NO_STR
7124 DEBUG_STR
7125 DEBUG_PIM_STR
7126 DEBUG_PIM_PACKETDUMP_STR
7127 DEBUG_PIM_PACKETDUMP_RECV_STR)
7128 {
7129 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
7130 return CMD_SUCCESS;
7131 }
7132
7133 DEFUN (debug_pim_trace,
7134 debug_pim_trace_cmd,
7135 "debug pim trace",
7136 DEBUG_STR
7137 DEBUG_PIM_STR
7138 DEBUG_PIM_TRACE_STR)
7139 {
7140 PIM_DO_DEBUG_PIM_TRACE;
7141 return CMD_SUCCESS;
7142 }
7143
7144 DEFUN (debug_pim_trace_detail,
7145 debug_pim_trace_detail_cmd,
7146 "debug pim trace detail",
7147 DEBUG_STR
7148 DEBUG_PIM_STR
7149 DEBUG_PIM_TRACE_STR
7150 "Detailed Information\n")
7151 {
7152 PIM_DO_DEBUG_PIM_TRACE_DETAIL;
7153 return CMD_SUCCESS;
7154 }
7155
7156 DEFUN (no_debug_pim_trace,
7157 no_debug_pim_trace_cmd,
7158 "no debug pim trace",
7159 NO_STR
7160 DEBUG_STR
7161 DEBUG_PIM_STR
7162 DEBUG_PIM_TRACE_STR)
7163 {
7164 PIM_DONT_DEBUG_PIM_TRACE;
7165 return CMD_SUCCESS;
7166 }
7167
7168 DEFUN (no_debug_pim_trace_detail,
7169 no_debug_pim_trace_detail_cmd,
7170 "no debug pim trace detail",
7171 NO_STR
7172 DEBUG_STR
7173 DEBUG_PIM_STR
7174 DEBUG_PIM_TRACE_STR
7175 "Detailed Information\n")
7176 {
7177 PIM_DONT_DEBUG_PIM_TRACE_DETAIL;
7178 return CMD_SUCCESS;
7179 }
7180
7181 DEFUN (debug_ssmpingd,
7182 debug_ssmpingd_cmd,
7183 "debug ssmpingd",
7184 DEBUG_STR
7185 DEBUG_SSMPINGD_STR)
7186 {
7187 PIM_DO_DEBUG_SSMPINGD;
7188 return CMD_SUCCESS;
7189 }
7190
7191 DEFUN (no_debug_ssmpingd,
7192 no_debug_ssmpingd_cmd,
7193 "no debug ssmpingd",
7194 NO_STR
7195 DEBUG_STR
7196 DEBUG_SSMPINGD_STR)
7197 {
7198 PIM_DONT_DEBUG_SSMPINGD;
7199 return CMD_SUCCESS;
7200 }
7201
7202 DEFUN (debug_pim_zebra,
7203 debug_pim_zebra_cmd,
7204 "debug pim zebra",
7205 DEBUG_STR
7206 DEBUG_PIM_STR
7207 DEBUG_PIM_ZEBRA_STR)
7208 {
7209 PIM_DO_DEBUG_ZEBRA;
7210 return CMD_SUCCESS;
7211 }
7212
7213 DEFUN (no_debug_pim_zebra,
7214 no_debug_pim_zebra_cmd,
7215 "no debug pim zebra",
7216 NO_STR
7217 DEBUG_STR
7218 DEBUG_PIM_STR
7219 DEBUG_PIM_ZEBRA_STR)
7220 {
7221 PIM_DONT_DEBUG_ZEBRA;
7222 return CMD_SUCCESS;
7223 }
7224
7225 DEFUN (debug_msdp,
7226 debug_msdp_cmd,
7227 "debug msdp",
7228 DEBUG_STR
7229 DEBUG_MSDP_STR)
7230 {
7231 PIM_DO_DEBUG_MSDP_EVENTS;
7232 PIM_DO_DEBUG_MSDP_PACKETS;
7233 return CMD_SUCCESS;
7234 }
7235
7236 DEFUN (no_debug_msdp,
7237 no_debug_msdp_cmd,
7238 "no debug msdp",
7239 NO_STR
7240 DEBUG_STR
7241 DEBUG_MSDP_STR)
7242 {
7243 PIM_DONT_DEBUG_MSDP_EVENTS;
7244 PIM_DONT_DEBUG_MSDP_PACKETS;
7245 return CMD_SUCCESS;
7246 }
7247
7248 ALIAS(no_debug_msdp, undebug_msdp_cmd, "undebug msdp",
7249 UNDEBUG_STR DEBUG_MSDP_STR)
7250
7251 DEFUN (debug_msdp_events,
7252 debug_msdp_events_cmd,
7253 "debug msdp events",
7254 DEBUG_STR
7255 DEBUG_MSDP_STR
7256 DEBUG_MSDP_EVENTS_STR)
7257 {
7258 PIM_DO_DEBUG_MSDP_EVENTS;
7259 return CMD_SUCCESS;
7260 }
7261
7262 DEFUN (no_debug_msdp_events,
7263 no_debug_msdp_events_cmd,
7264 "no debug msdp events",
7265 NO_STR
7266 DEBUG_STR
7267 DEBUG_MSDP_STR
7268 DEBUG_MSDP_EVENTS_STR)
7269 {
7270 PIM_DONT_DEBUG_MSDP_EVENTS;
7271 return CMD_SUCCESS;
7272 }
7273
7274 ALIAS(no_debug_msdp_events, undebug_msdp_events_cmd, "undebug msdp events",
7275 UNDEBUG_STR DEBUG_MSDP_STR DEBUG_MSDP_EVENTS_STR)
7276
7277 DEFUN (debug_msdp_packets,
7278 debug_msdp_packets_cmd,
7279 "debug msdp packets",
7280 DEBUG_STR
7281 DEBUG_MSDP_STR
7282 DEBUG_MSDP_PACKETS_STR)
7283 {
7284 PIM_DO_DEBUG_MSDP_PACKETS;
7285 return CMD_SUCCESS;
7286 }
7287
7288 DEFUN (no_debug_msdp_packets,
7289 no_debug_msdp_packets_cmd,
7290 "no debug msdp packets",
7291 NO_STR
7292 DEBUG_STR
7293 DEBUG_MSDP_STR
7294 DEBUG_MSDP_PACKETS_STR)
7295 {
7296 PIM_DONT_DEBUG_MSDP_PACKETS;
7297 return CMD_SUCCESS;
7298 }
7299
7300 ALIAS(no_debug_msdp_packets, undebug_msdp_packets_cmd, "undebug msdp packets",
7301 UNDEBUG_STR DEBUG_MSDP_STR DEBUG_MSDP_PACKETS_STR)
7302
7303 DEFUN_NOSH (show_debugging_pim,
7304 show_debugging_pim_cmd,
7305 "show debugging [pim]",
7306 SHOW_STR
7307 DEBUG_STR
7308 PIM_STR)
7309 {
7310 vty_out(vty, "PIM debugging status\n");
7311
7312 pim_debug_config_write(vty);
7313
7314 return CMD_SUCCESS;
7315 }
7316
7317 static int interface_pim_use_src_cmd_worker(struct vty *vty, const char *source)
7318 {
7319 int result;
7320 struct in_addr source_addr;
7321 VTY_DECLVAR_CONTEXT(interface, ifp);
7322
7323 result = inet_pton(AF_INET, source, &source_addr);
7324 if (result <= 0) {
7325 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", source,
7326 errno, safe_strerror(errno));
7327 return CMD_WARNING_CONFIG_FAILED;
7328 }
7329
7330 result = pim_update_source_set(ifp, source_addr);
7331 switch (result) {
7332 case PIM_SUCCESS:
7333 break;
7334 case PIM_IFACE_NOT_FOUND:
7335 vty_out(vty, "Pim not enabled on this interface\n");
7336 break;
7337 case PIM_UPDATE_SOURCE_DUP:
7338 vty_out(vty, "%% Source already set to %s\n", source);
7339 break;
7340 default:
7341 vty_out(vty, "%% Source set failed\n");
7342 }
7343
7344 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
7345 }
7346
7347 DEFUN (interface_pim_use_source,
7348 interface_pim_use_source_cmd,
7349 "ip pim use-source A.B.C.D",
7350 IP_STR
7351 "pim multicast routing\n"
7352 "Configure primary IP address\n"
7353 "source ip address\n")
7354 {
7355 return interface_pim_use_src_cmd_worker(vty, argv[3]->arg);
7356 }
7357
7358 DEFUN (interface_no_pim_use_source,
7359 interface_no_pim_use_source_cmd,
7360 "no ip pim use-source [A.B.C.D]",
7361 NO_STR
7362 IP_STR
7363 "pim multicast routing\n"
7364 "Delete source IP address\n"
7365 "source ip address\n")
7366 {
7367 return interface_pim_use_src_cmd_worker(vty, "0.0.0.0");
7368 }
7369
7370 DEFUN (ip_pim_bfd,
7371 ip_pim_bfd_cmd,
7372 "ip pim bfd",
7373 IP_STR
7374 PIM_STR
7375 "Enables BFD support\n")
7376 {
7377 VTY_DECLVAR_CONTEXT(interface, ifp);
7378 struct pim_interface *pim_ifp = ifp->info;
7379 struct bfd_info *bfd_info = NULL;
7380
7381 if (!pim_ifp) {
7382 if (!pim_cmd_interface_add(ifp)) {
7383 vty_out(vty, "Could not enable PIM SM on interface\n");
7384 return CMD_WARNING;
7385 }
7386 }
7387 pim_ifp = ifp->info;
7388
7389 bfd_info = pim_ifp->bfd_info;
7390
7391 if (!bfd_info || !CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG))
7392 pim_bfd_if_param_set(ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
7393 BFD_DEF_DETECT_MULT, 1);
7394
7395 return CMD_SUCCESS;
7396 }
7397
7398 DEFUN (no_ip_pim_bfd,
7399 no_ip_pim_bfd_cmd,
7400 "no ip pim bfd",
7401 NO_STR
7402 IP_STR
7403 PIM_STR
7404 "Disables BFD support\n")
7405 {
7406 VTY_DECLVAR_CONTEXT(interface, ifp);
7407 struct pim_interface *pim_ifp = ifp->info;
7408
7409 if (!pim_ifp) {
7410 vty_out(vty, "Pim not enabled on this interface\n");
7411 return CMD_WARNING;
7412 }
7413
7414 if (pim_ifp->bfd_info) {
7415 pim_bfd_reg_dereg_all_nbr(ifp, ZEBRA_BFD_DEST_DEREGISTER);
7416 bfd_info_free(&(pim_ifp->bfd_info));
7417 }
7418
7419 return CMD_SUCCESS;
7420 }
7421
7422 DEFUN (ip_pim_bfd_param,
7423 ip_pim_bfd_param_cmd,
7424 "ip pim bfd (2-255) (50-60000) (50-60000)",
7425 IP_STR
7426 PIM_STR
7427 "Enables BFD support\n"
7428 "Detect Multiplier\n"
7429 "Required min receive interval\n"
7430 "Desired min transmit interval\n")
7431 {
7432 VTY_DECLVAR_CONTEXT(interface, ifp);
7433 int idx_number = 3;
7434 int idx_number_2 = 4;
7435 int idx_number_3 = 5;
7436 u_int32_t rx_val;
7437 u_int32_t tx_val;
7438 u_int8_t dm_val;
7439 int ret;
7440 struct pim_interface *pim_ifp = ifp->info;
7441
7442 if (!pim_ifp) {
7443 if (!pim_cmd_interface_add(ifp)) {
7444 vty_out(vty, "Could not enable PIM SM on interface\n");
7445 return CMD_WARNING;
7446 }
7447 }
7448
7449 if ((ret = bfd_validate_param(
7450 vty, argv[idx_number]->arg, argv[idx_number_2]->arg,
7451 argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val))
7452 != CMD_SUCCESS)
7453 return ret;
7454
7455 pim_bfd_if_param_set(ifp, rx_val, tx_val, dm_val, 0);
7456
7457 return CMD_SUCCESS;
7458 }
7459
7460 ALIAS(no_ip_pim_bfd, no_ip_pim_bfd_param_cmd,
7461 "no ip pim bfd (2-255) (50-60000) (50-60000)", NO_STR IP_STR PIM_STR
7462 "Enables BFD support\n"
7463 "Detect Multiplier\n"
7464 "Required min receive interval\n"
7465 "Desired min transmit interval\n")
7466
7467 static int ip_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty,
7468 const char *peer, const char *local)
7469 {
7470 enum pim_msdp_err result;
7471 struct in_addr peer_addr;
7472 struct in_addr local_addr;
7473
7474 result = inet_pton(AF_INET, peer, &peer_addr);
7475 if (result <= 0) {
7476 vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer,
7477 errno, safe_strerror(errno));
7478 return CMD_WARNING_CONFIG_FAILED;
7479 }
7480
7481 result = inet_pton(AF_INET, local, &local_addr);
7482 if (result <= 0) {
7483 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", local,
7484 errno, safe_strerror(errno));
7485 return CMD_WARNING_CONFIG_FAILED;
7486 }
7487
7488 result = pim_msdp_peer_add(pim, peer_addr, local_addr, "default",
7489 NULL /* mp_p */);
7490 switch (result) {
7491 case PIM_MSDP_ERR_NONE:
7492 break;
7493 case PIM_MSDP_ERR_OOM:
7494 vty_out(vty, "%% Out of memory\n");
7495 break;
7496 case PIM_MSDP_ERR_PEER_EXISTS:
7497 vty_out(vty, "%% Peer exists\n");
7498 break;
7499 case PIM_MSDP_ERR_MAX_MESH_GROUPS:
7500 vty_out(vty, "%% Only one mesh-group allowed currently\n");
7501 break;
7502 default:
7503 vty_out(vty, "%% peer add failed\n");
7504 }
7505
7506 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
7507 }
7508
7509 DEFUN_HIDDEN (ip_msdp_peer,
7510 ip_msdp_peer_cmd,
7511 "ip msdp peer A.B.C.D source A.B.C.D",
7512 IP_STR
7513 CFG_MSDP_STR
7514 "Configure MSDP peer\n"
7515 "peer ip address\n"
7516 "Source address for TCP connection\n"
7517 "local ip address\n")
7518 {
7519 PIM_DECLVAR_CONTEXT(vrf, pim);
7520 return ip_msdp_peer_cmd_worker(pim, vty, argv[3]->arg, argv[5]->arg);
7521 }
7522
7523 static int ip_no_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty,
7524 const char *peer)
7525 {
7526 enum pim_msdp_err result;
7527 struct in_addr peer_addr;
7528
7529 result = inet_pton(AF_INET, peer, &peer_addr);
7530 if (result <= 0) {
7531 vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer,
7532 errno, safe_strerror(errno));
7533 return CMD_WARNING_CONFIG_FAILED;
7534 }
7535
7536 result = pim_msdp_peer_del(pim, peer_addr);
7537 switch (result) {
7538 case PIM_MSDP_ERR_NONE:
7539 break;
7540 case PIM_MSDP_ERR_NO_PEER:
7541 vty_out(vty, "%% Peer does not exist\n");
7542 break;
7543 default:
7544 vty_out(vty, "%% peer del failed\n");
7545 }
7546
7547 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
7548 }
7549
7550 DEFUN_HIDDEN (no_ip_msdp_peer,
7551 no_ip_msdp_peer_cmd,
7552 "no ip msdp peer A.B.C.D",
7553 NO_STR
7554 IP_STR
7555 CFG_MSDP_STR
7556 "Delete MSDP peer\n"
7557 "peer ip address\n")
7558 {
7559 PIM_DECLVAR_CONTEXT(vrf, pim);
7560 return ip_no_msdp_peer_cmd_worker(pim, vty, argv[4]->arg);
7561 }
7562
7563 static int ip_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim,
7564 struct vty *vty, const char *mg,
7565 const char *mbr)
7566 {
7567 enum pim_msdp_err result;
7568 struct in_addr mbr_ip;
7569
7570 result = inet_pton(AF_INET, mbr, &mbr_ip);
7571 if (result <= 0) {
7572 vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr,
7573 errno, safe_strerror(errno));
7574 return CMD_WARNING_CONFIG_FAILED;
7575 }
7576
7577 result = pim_msdp_mg_mbr_add(pim, mg, mbr_ip);
7578 switch (result) {
7579 case PIM_MSDP_ERR_NONE:
7580 break;
7581 case PIM_MSDP_ERR_OOM:
7582 vty_out(vty, "%% Out of memory\n");
7583 break;
7584 case PIM_MSDP_ERR_MG_MBR_EXISTS:
7585 vty_out(vty, "%% mesh-group member exists\n");
7586 break;
7587 case PIM_MSDP_ERR_MAX_MESH_GROUPS:
7588 vty_out(vty, "%% Only one mesh-group allowed currently\n");
7589 break;
7590 default:
7591 vty_out(vty, "%% member add failed\n");
7592 }
7593
7594 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
7595 }
7596
7597 DEFUN (ip_msdp_mesh_group_member,
7598 ip_msdp_mesh_group_member_cmd,
7599 "ip msdp mesh-group WORD member A.B.C.D",
7600 IP_STR
7601 CFG_MSDP_STR
7602 "Configure MSDP mesh-group\n"
7603 "mesh group name\n"
7604 "mesh group member\n"
7605 "peer ip address\n")
7606 {
7607 PIM_DECLVAR_CONTEXT(vrf, pim);
7608 return ip_msdp_mesh_group_member_cmd_worker(pim, vty, argv[3]->arg,
7609 argv[5]->arg);
7610 }
7611
7612 static int ip_no_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim,
7613 struct vty *vty,
7614 const char *mg,
7615 const char *mbr)
7616 {
7617 enum pim_msdp_err result;
7618 struct in_addr mbr_ip;
7619
7620 result = inet_pton(AF_INET, mbr, &mbr_ip);
7621 if (result <= 0) {
7622 vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr,
7623 errno, safe_strerror(errno));
7624 return CMD_WARNING_CONFIG_FAILED;
7625 }
7626
7627 result = pim_msdp_mg_mbr_del(pim, mg, mbr_ip);
7628 switch (result) {
7629 case PIM_MSDP_ERR_NONE:
7630 break;
7631 case PIM_MSDP_ERR_NO_MG:
7632 vty_out(vty, "%% mesh-group does not exist\n");
7633 break;
7634 case PIM_MSDP_ERR_NO_MG_MBR:
7635 vty_out(vty, "%% mesh-group member does not exist\n");
7636 break;
7637 default:
7638 vty_out(vty, "%% mesh-group member del failed\n");
7639 }
7640
7641 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
7642 }
7643 DEFUN (no_ip_msdp_mesh_group_member,
7644 no_ip_msdp_mesh_group_member_cmd,
7645 "no ip msdp mesh-group WORD member A.B.C.D",
7646 NO_STR
7647 IP_STR
7648 CFG_MSDP_STR
7649 "Delete MSDP mesh-group member\n"
7650 "mesh group name\n"
7651 "mesh group member\n"
7652 "peer ip address\n")
7653 {
7654 PIM_DECLVAR_CONTEXT(vrf, pim);
7655 return ip_no_msdp_mesh_group_member_cmd_worker(pim, vty, argv[4]->arg,
7656 argv[6]->arg);
7657 }
7658
7659 static int ip_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim,
7660 struct vty *vty, const char *mg,
7661 const char *src)
7662 {
7663 enum pim_msdp_err result;
7664 struct in_addr src_ip;
7665
7666 result = inet_pton(AF_INET, src, &src_ip);
7667 if (result <= 0) {
7668 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", src,
7669 errno, safe_strerror(errno));
7670 return CMD_WARNING_CONFIG_FAILED;
7671 }
7672
7673 result = pim_msdp_mg_src_add(pim, mg, src_ip);
7674 switch (result) {
7675 case PIM_MSDP_ERR_NONE:
7676 break;
7677 case PIM_MSDP_ERR_OOM:
7678 vty_out(vty, "%% Out of memory\n");
7679 break;
7680 case PIM_MSDP_ERR_MAX_MESH_GROUPS:
7681 vty_out(vty, "%% Only one mesh-group allowed currently\n");
7682 break;
7683 default:
7684 vty_out(vty, "%% source add failed\n");
7685 }
7686
7687 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
7688 }
7689
7690
7691 DEFUN (ip_msdp_mesh_group_source,
7692 ip_msdp_mesh_group_source_cmd,
7693 "ip msdp mesh-group WORD source A.B.C.D",
7694 IP_STR
7695 CFG_MSDP_STR
7696 "Configure MSDP mesh-group\n"
7697 "mesh group name\n"
7698 "mesh group local address\n"
7699 "source ip address for the TCP connection\n")
7700 {
7701 PIM_DECLVAR_CONTEXT(vrf, pim);
7702 return ip_msdp_mesh_group_source_cmd_worker(pim, vty, argv[3]->arg,
7703 argv[5]->arg);
7704 }
7705
7706 static int ip_no_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim,
7707 struct vty *vty,
7708 const char *mg)
7709 {
7710 enum pim_msdp_err result;
7711
7712 result = pim_msdp_mg_src_del(pim, mg);
7713 switch (result) {
7714 case PIM_MSDP_ERR_NONE:
7715 break;
7716 case PIM_MSDP_ERR_NO_MG:
7717 vty_out(vty, "%% mesh-group does not exist\n");
7718 break;
7719 default:
7720 vty_out(vty, "%% mesh-group source del failed\n");
7721 }
7722
7723 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
7724 }
7725
7726 static int ip_no_msdp_mesh_group_cmd_worker(struct pim_instance *pim,
7727 struct vty *vty, const char *mg)
7728 {
7729 enum pim_msdp_err result;
7730
7731 result = pim_msdp_mg_del(pim, mg);
7732 switch (result) {
7733 case PIM_MSDP_ERR_NONE:
7734 break;
7735 case PIM_MSDP_ERR_NO_MG:
7736 vty_out(vty, "%% mesh-group does not exist\n");
7737 break;
7738 default:
7739 vty_out(vty, "%% mesh-group source del failed\n");
7740 }
7741
7742 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
7743 }
7744
7745 DEFUN (no_ip_msdp_mesh_group_source,
7746 no_ip_msdp_mesh_group_source_cmd,
7747 "no ip msdp mesh-group WORD source [A.B.C.D]",
7748 NO_STR
7749 IP_STR
7750 CFG_MSDP_STR
7751 "Delete MSDP mesh-group source\n"
7752 "mesh group name\n"
7753 "mesh group source\n"
7754 "mesh group local address\n")
7755 {
7756 PIM_DECLVAR_CONTEXT(vrf, pim);
7757 if (argc == 7)
7758 return ip_no_msdp_mesh_group_cmd_worker(pim, vty, argv[6]->arg);
7759 else
7760 return ip_no_msdp_mesh_group_source_cmd_worker(pim, vty,
7761 argv[4]->arg);
7762 }
7763
7764 static void print_empty_json_obj(struct vty *vty)
7765 {
7766 json_object *json;
7767 json = json_object_new_object();
7768 vty_out(vty, "%s\n",
7769 json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
7770 json_object_free(json);
7771 }
7772
7773 static void ip_msdp_show_mesh_group(struct pim_instance *pim, struct vty *vty,
7774 u_char uj)
7775 {
7776 struct listnode *mbrnode;
7777 struct pim_msdp_mg_mbr *mbr;
7778 struct pim_msdp_mg *mg = pim->msdp.mg;
7779 char mbr_str[INET_ADDRSTRLEN];
7780 char src_str[INET_ADDRSTRLEN];
7781 char state_str[PIM_MSDP_STATE_STRLEN];
7782 enum pim_msdp_peer_state state;
7783 json_object *json = NULL;
7784 json_object *json_mg_row = NULL;
7785 json_object *json_members = NULL;
7786 json_object *json_row = NULL;
7787
7788 if (!mg) {
7789 if (uj)
7790 print_empty_json_obj(vty);
7791 return;
7792 }
7793
7794 pim_inet4_dump("<source?>", mg->src_ip, src_str, sizeof(src_str));
7795 if (uj) {
7796 json = json_object_new_object();
7797 /* currently there is only one mesh group but we should still
7798 * make
7799 * it a dict with mg-name as key */
7800 json_mg_row = json_object_new_object();
7801 json_object_string_add(json_mg_row, "name",
7802 mg->mesh_group_name);
7803 json_object_string_add(json_mg_row, "source", src_str);
7804 } else {
7805 vty_out(vty, "Mesh group : %s\n", mg->mesh_group_name);
7806 vty_out(vty, " Source : %s\n", src_str);
7807 vty_out(vty, " Member State\n");
7808 }
7809
7810 for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) {
7811 pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str));
7812 if (mbr->mp) {
7813 state = mbr->mp->state;
7814 } else {
7815 state = PIM_MSDP_DISABLED;
7816 }
7817 pim_msdp_state_dump(state, state_str, sizeof(state_str));
7818 if (uj) {
7819 json_row = json_object_new_object();
7820 json_object_string_add(json_row, "member", mbr_str);
7821 json_object_string_add(json_row, "state", state_str);
7822 if (!json_members) {
7823 json_members = json_object_new_object();
7824 json_object_object_add(json_mg_row, "members",
7825 json_members);
7826 }
7827 json_object_object_add(json_members, mbr_str, json_row);
7828 } else {
7829 vty_out(vty, " %-15s %11s\n", mbr_str, state_str);
7830 }
7831 }
7832
7833 if (uj) {
7834 json_object_object_add(json, mg->mesh_group_name, json_mg_row);
7835 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7836 json, JSON_C_TO_STRING_PRETTY));
7837 json_object_free(json);
7838 }
7839 }
7840
7841 DEFUN (show_ip_msdp_mesh_group,
7842 show_ip_msdp_mesh_group_cmd,
7843 "show ip msdp [vrf NAME] mesh-group [json]",
7844 SHOW_STR
7845 IP_STR
7846 MSDP_STR
7847 VRF_CMD_HELP_STR
7848 "MSDP mesh-group information\n"
7849 JSON_STR)
7850 {
7851 u_char uj = use_json(argc, argv);
7852 int idx = 2;
7853 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
7854
7855 if (!vrf)
7856 return CMD_WARNING;
7857
7858 ip_msdp_show_mesh_group(vrf->info, vty, uj);
7859
7860 return CMD_SUCCESS;
7861 }
7862
7863 DEFUN (show_ip_msdp_mesh_group_vrf_all,
7864 show_ip_msdp_mesh_group_vrf_all_cmd,
7865 "show ip msdp vrf all mesh-group [json]",
7866 SHOW_STR
7867 IP_STR
7868 MSDP_STR
7869 VRF_CMD_HELP_STR
7870 "MSDP mesh-group information\n"
7871 JSON_STR)
7872 {
7873 u_char uj = use_json(argc, argv);
7874 struct vrf *vrf;
7875 bool first = true;
7876
7877 if (uj)
7878 vty_out(vty, "{ ");
7879 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
7880 if (uj) {
7881 if (!first)
7882 vty_out(vty, ", ");
7883 vty_out(vty, " \"%s\": ", vrf->name);
7884 first = false;
7885 } else
7886 vty_out(vty, "VRF: %s\n", vrf->name);
7887 ip_msdp_show_mesh_group(vrf->info, vty, uj);
7888 }
7889 if (uj)
7890 vty_out(vty, "}\n");
7891
7892 return CMD_SUCCESS;
7893 }
7894
7895 static void ip_msdp_show_peers(struct pim_instance *pim, struct vty *vty,
7896 u_char uj)
7897 {
7898 struct listnode *mpnode;
7899 struct pim_msdp_peer *mp;
7900 char peer_str[INET_ADDRSTRLEN];
7901 char local_str[INET_ADDRSTRLEN];
7902 char state_str[PIM_MSDP_STATE_STRLEN];
7903 char timebuf[PIM_MSDP_UPTIME_STRLEN];
7904 int64_t now;
7905 json_object *json = NULL;
7906 json_object *json_row = NULL;
7907
7908
7909 if (uj) {
7910 json = json_object_new_object();
7911 } else {
7912 vty_out(vty,
7913 "Peer Local State Uptime SaCnt\n");
7914 }
7915
7916 for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, mpnode, mp)) {
7917 if (mp->state == PIM_MSDP_ESTABLISHED) {
7918 now = pim_time_monotonic_sec();
7919 pim_time_uptime(timebuf, sizeof(timebuf),
7920 now - mp->uptime);
7921 } else {
7922 strcpy(timebuf, "-");
7923 }
7924 pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
7925 pim_inet4_dump("<local?>", mp->local, local_str,
7926 sizeof(local_str));
7927 pim_msdp_state_dump(mp->state, state_str, sizeof(state_str));
7928 if (uj) {
7929 json_row = json_object_new_object();
7930 json_object_string_add(json_row, "peer", peer_str);
7931 json_object_string_add(json_row, "local", local_str);
7932 json_object_string_add(json_row, "state", state_str);
7933 json_object_string_add(json_row, "upTime", timebuf);
7934 json_object_int_add(json_row, "saCount", mp->sa_cnt);
7935 json_object_object_add(json, peer_str, json_row);
7936 } else {
7937 vty_out(vty, "%-15s %15s %11s %8s %6d\n", peer_str,
7938 local_str, state_str, timebuf, mp->sa_cnt);
7939 }
7940 }
7941
7942 if (uj) {
7943 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7944 json, JSON_C_TO_STRING_PRETTY));
7945 json_object_free(json);
7946 }
7947 }
7948
7949 static void ip_msdp_show_peers_detail(struct pim_instance *pim, struct vty *vty,
7950 const char *peer, u_char uj)
7951 {
7952 struct listnode *mpnode;
7953 struct pim_msdp_peer *mp;
7954 char peer_str[INET_ADDRSTRLEN];
7955 char local_str[INET_ADDRSTRLEN];
7956 char state_str[PIM_MSDP_STATE_STRLEN];
7957 char timebuf[PIM_MSDP_UPTIME_STRLEN];
7958 char katimer[PIM_MSDP_TIMER_STRLEN];
7959 char crtimer[PIM_MSDP_TIMER_STRLEN];
7960 char holdtimer[PIM_MSDP_TIMER_STRLEN];
7961 int64_t now;
7962 json_object *json = NULL;
7963 json_object *json_row = NULL;
7964
7965 if (uj) {
7966 json = json_object_new_object();
7967 }
7968
7969 for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, mpnode, mp)) {
7970 pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
7971 if (strcmp(peer, "detail") && strcmp(peer, peer_str))
7972 continue;
7973
7974 if (mp->state == PIM_MSDP_ESTABLISHED) {
7975 now = pim_time_monotonic_sec();
7976 pim_time_uptime(timebuf, sizeof(timebuf),
7977 now - mp->uptime);
7978 } else {
7979 strcpy(timebuf, "-");
7980 }
7981 pim_inet4_dump("<local?>", mp->local, local_str,
7982 sizeof(local_str));
7983 pim_msdp_state_dump(mp->state, state_str, sizeof(state_str));
7984 pim_time_timer_to_hhmmss(katimer, sizeof(katimer),
7985 mp->ka_timer);
7986 pim_time_timer_to_hhmmss(crtimer, sizeof(crtimer),
7987 mp->cr_timer);
7988 pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer),
7989 mp->hold_timer);
7990
7991 if (uj) {
7992 json_row = json_object_new_object();
7993 json_object_string_add(json_row, "peer", peer_str);
7994 json_object_string_add(json_row, "local", local_str);
7995 json_object_string_add(json_row, "meshGroupName",
7996 mp->mesh_group_name);
7997 json_object_string_add(json_row, "state", state_str);
7998 json_object_string_add(json_row, "upTime", timebuf);
7999 json_object_string_add(json_row, "keepAliveTimer",
8000 katimer);
8001 json_object_string_add(json_row, "connRetryTimer",
8002 crtimer);
8003 json_object_string_add(json_row, "holdTimer",
8004 holdtimer);
8005 json_object_string_add(json_row, "lastReset",
8006 mp->last_reset);
8007 json_object_int_add(json_row, "connAttempts",
8008 mp->conn_attempts);
8009 json_object_int_add(json_row, "establishedChanges",
8010 mp->est_flaps);
8011 json_object_int_add(json_row, "saCount", mp->sa_cnt);
8012 json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt);
8013 json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt);
8014 json_object_int_add(json_row, "saSent", mp->sa_tx_cnt);
8015 json_object_int_add(json_row, "saRcvd", mp->sa_rx_cnt);
8016 json_object_object_add(json, peer_str, json_row);
8017 } else {
8018 vty_out(vty, "Peer : %s\n", peer_str);
8019 vty_out(vty, " Local : %s\n", local_str);
8020 vty_out(vty, " Mesh Group : %s\n",
8021 mp->mesh_group_name);
8022 vty_out(vty, " State : %s\n", state_str);
8023 vty_out(vty, " Uptime : %s\n", timebuf);
8024
8025 vty_out(vty, " Keepalive Timer : %s\n", katimer);
8026 vty_out(vty, " Conn Retry Timer : %s\n", crtimer);
8027 vty_out(vty, " Hold Timer : %s\n", holdtimer);
8028 vty_out(vty, " Last Reset : %s\n",
8029 mp->last_reset);
8030 vty_out(vty, " Conn Attempts : %d\n",
8031 mp->conn_attempts);
8032 vty_out(vty, " Established Changes : %d\n",
8033 mp->est_flaps);
8034 vty_out(vty, " SA Count : %d\n",
8035 mp->sa_cnt);
8036 vty_out(vty, " Statistics :\n");
8037 vty_out(vty,
8038 " Sent Rcvd\n");
8039 vty_out(vty, " Keepalives : %10d %10d\n",
8040 mp->ka_tx_cnt, mp->ka_rx_cnt);
8041 vty_out(vty, " SAs : %10d %10d\n",
8042 mp->sa_tx_cnt, mp->sa_rx_cnt);
8043 vty_out(vty, "\n");
8044 }
8045 }
8046
8047 if (uj) {
8048 vty_out(vty, "%s\n", json_object_to_json_string_ext(
8049 json, JSON_C_TO_STRING_PRETTY));
8050 json_object_free(json);
8051 }
8052 }
8053
8054 DEFUN (show_ip_msdp_peer_detail,
8055 show_ip_msdp_peer_detail_cmd,
8056 "show ip msdp [vrf NAME] peer [detail|A.B.C.D] [json]",
8057 SHOW_STR
8058 IP_STR
8059 MSDP_STR
8060 VRF_CMD_HELP_STR
8061 "MSDP peer information\n"
8062 "Detailed output\n"
8063 "peer ip address\n"
8064 JSON_STR)
8065 {
8066 u_char uj = use_json(argc, argv);
8067 int idx = 2;
8068 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
8069
8070 if (!vrf)
8071 return CMD_WARNING;
8072
8073 char *arg = NULL;
8074
8075 if (argv_find(argv, argc, "detail", &idx))
8076 arg = argv[idx]->text;
8077 else if (argv_find(argv, argc, "A.B.C.D", &idx))
8078 arg = argv[idx]->arg;
8079
8080 if (arg)
8081 ip_msdp_show_peers_detail(vrf->info, vty, argv[idx]->arg, uj);
8082 else
8083 ip_msdp_show_peers(vrf->info, vty, uj);
8084
8085 return CMD_SUCCESS;
8086 }
8087
8088 DEFUN (show_ip_msdp_peer_detail_vrf_all,
8089 show_ip_msdp_peer_detail_vrf_all_cmd,
8090 "show ip msdp vrf all peer [detail|A.B.C.D] [json]",
8091 SHOW_STR
8092 IP_STR
8093 MSDP_STR
8094 VRF_CMD_HELP_STR
8095 "MSDP peer information\n"
8096 "Detailed output\n"
8097 "peer ip address\n"
8098 JSON_STR)
8099 {
8100 int idx = 2;
8101 u_char uj = use_json(argc, argv);
8102 struct vrf *vrf;
8103 bool first = true;
8104
8105 if (uj)
8106 vty_out(vty, "{ ");
8107 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
8108 if (uj) {
8109 if (!first)
8110 vty_out(vty, ", ");
8111 vty_out(vty, " \"%s\": ", vrf->name);
8112 first = false;
8113 } else
8114 vty_out(vty, "VRF: %s\n", vrf->name);
8115 if (argv_find(argv, argc, "detail", &idx)
8116 || argv_find(argv, argc, "A.B.C.D", &idx))
8117 ip_msdp_show_peers_detail(vrf->info, vty,
8118 argv[idx]->arg, uj);
8119 else
8120 ip_msdp_show_peers(vrf->info, vty, uj);
8121 }
8122 if (uj)
8123 vty_out(vty, "}\n");
8124
8125 return CMD_SUCCESS;
8126 }
8127
8128 static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty,
8129 u_char uj)
8130 {
8131 struct listnode *sanode;
8132 struct pim_msdp_sa *sa;
8133 char src_str[INET_ADDRSTRLEN];
8134 char grp_str[INET_ADDRSTRLEN];
8135 char rp_str[INET_ADDRSTRLEN];
8136 char timebuf[PIM_MSDP_UPTIME_STRLEN];
8137 char spt_str[8];
8138 char local_str[8];
8139 int64_t now;
8140 json_object *json = NULL;
8141 json_object *json_group = NULL;
8142 json_object *json_row = NULL;
8143
8144 if (uj) {
8145 json = json_object_new_object();
8146 } else {
8147 vty_out(vty,
8148 "Source Group RP Local SPT Uptime\n");
8149 }
8150
8151 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
8152 now = pim_time_monotonic_sec();
8153 pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime);
8154 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
8155 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
8156 if (sa->flags & PIM_MSDP_SAF_PEER) {
8157 pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
8158 if (sa->up) {
8159 strcpy(spt_str, "yes");
8160 } else {
8161 strcpy(spt_str, "no");
8162 }
8163 } else {
8164 strcpy(rp_str, "-");
8165 strcpy(spt_str, "-");
8166 }
8167 if (sa->flags & PIM_MSDP_SAF_LOCAL) {
8168 strcpy(local_str, "yes");
8169 } else {
8170 strcpy(local_str, "no");
8171 }
8172 if (uj) {
8173 json_object_object_get_ex(json, grp_str, &json_group);
8174
8175 if (!json_group) {
8176 json_group = json_object_new_object();
8177 json_object_object_add(json, grp_str,
8178 json_group);
8179 }
8180
8181 json_row = json_object_new_object();
8182 json_object_string_add(json_row, "source", src_str);
8183 json_object_string_add(json_row, "group", grp_str);
8184 json_object_string_add(json_row, "rp", rp_str);
8185 json_object_string_add(json_row, "local", local_str);
8186 json_object_string_add(json_row, "sptSetup", spt_str);
8187 json_object_string_add(json_row, "upTime", timebuf);
8188 json_object_object_add(json_group, src_str, json_row);
8189 } else {
8190 vty_out(vty, "%-15s %15s %15s %5c %3c %8s\n",
8191 src_str, grp_str, rp_str, local_str[0],
8192 spt_str[0], timebuf);
8193 }
8194 }
8195
8196 if (uj) {
8197 vty_out(vty, "%s\n", json_object_to_json_string_ext(
8198 json, JSON_C_TO_STRING_PRETTY));
8199 json_object_free(json);
8200 }
8201 }
8202
8203 static void ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa,
8204 const char *src_str,
8205 const char *grp_str, struct vty *vty,
8206 u_char uj, json_object *json)
8207 {
8208 char rp_str[INET_ADDRSTRLEN];
8209 char peer_str[INET_ADDRSTRLEN];
8210 char timebuf[PIM_MSDP_UPTIME_STRLEN];
8211 char spt_str[8];
8212 char local_str[8];
8213 char statetimer[PIM_MSDP_TIMER_STRLEN];
8214 int64_t now;
8215 json_object *json_group = NULL;
8216 json_object *json_row = NULL;
8217
8218 now = pim_time_monotonic_sec();
8219 pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime);
8220 if (sa->flags & PIM_MSDP_SAF_PEER) {
8221 pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
8222 pim_inet4_dump("<peer?>", sa->peer, peer_str, sizeof(peer_str));
8223 if (sa->up) {
8224 strcpy(spt_str, "yes");
8225 } else {
8226 strcpy(spt_str, "no");
8227 }
8228 } else {
8229 strcpy(rp_str, "-");
8230 strcpy(peer_str, "-");
8231 strcpy(spt_str, "-");
8232 }
8233 if (sa->flags & PIM_MSDP_SAF_LOCAL) {
8234 strcpy(local_str, "yes");
8235 } else {
8236 strcpy(local_str, "no");
8237 }
8238 pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer),
8239 sa->sa_state_timer);
8240 if (uj) {
8241 json_object_object_get_ex(json, grp_str, &json_group);
8242
8243 if (!json_group) {
8244 json_group = json_object_new_object();
8245 json_object_object_add(json, grp_str, json_group);
8246 }
8247
8248 json_row = json_object_new_object();
8249 json_object_string_add(json_row, "source", src_str);
8250 json_object_string_add(json_row, "group", grp_str);
8251 json_object_string_add(json_row, "rp", rp_str);
8252 json_object_string_add(json_row, "local", local_str);
8253 json_object_string_add(json_row, "sptSetup", spt_str);
8254 json_object_string_add(json_row, "upTime", timebuf);
8255 json_object_string_add(json_row, "stateTimer", statetimer);
8256 json_object_object_add(json_group, src_str, json_row);
8257 } else {
8258 vty_out(vty, "SA : %s\n", sa->sg_str);
8259 vty_out(vty, " RP : %s\n", rp_str);
8260 vty_out(vty, " Peer : %s\n", peer_str);
8261 vty_out(vty, " Local : %s\n", local_str);
8262 vty_out(vty, " SPT Setup : %s\n", spt_str);
8263 vty_out(vty, " Uptime : %s\n", timebuf);
8264 vty_out(vty, " State Timer : %s\n", statetimer);
8265 vty_out(vty, "\n");
8266 }
8267 }
8268
8269 static void ip_msdp_show_sa_detail(struct pim_instance *pim, struct vty *vty,
8270 u_char uj)
8271 {
8272 struct listnode *sanode;
8273 struct pim_msdp_sa *sa;
8274 char src_str[INET_ADDRSTRLEN];
8275 char grp_str[INET_ADDRSTRLEN];
8276 json_object *json = NULL;
8277
8278 if (uj) {
8279 json = json_object_new_object();
8280 }
8281
8282 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
8283 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
8284 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
8285 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj,
8286 json);
8287 }
8288
8289 if (uj) {
8290 vty_out(vty, "%s\n", json_object_to_json_string_ext(
8291 json, JSON_C_TO_STRING_PRETTY));
8292 json_object_free(json);
8293 }
8294 }
8295
8296 DEFUN (show_ip_msdp_sa_detail,
8297 show_ip_msdp_sa_detail_cmd,
8298 "show ip msdp [vrf NAME] sa detail [json]",
8299 SHOW_STR
8300 IP_STR
8301 MSDP_STR
8302 VRF_CMD_HELP_STR
8303 "MSDP active-source information\n"
8304 "Detailed output\n"
8305 JSON_STR)
8306 {
8307 u_char uj = use_json(argc, argv);
8308 int idx = 2;
8309 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
8310
8311 if (!vrf)
8312 return CMD_WARNING;
8313
8314 ip_msdp_show_sa_detail(vrf->info, vty, uj);
8315
8316 return CMD_SUCCESS;
8317 }
8318
8319 DEFUN (show_ip_msdp_sa_detail_vrf_all,
8320 show_ip_msdp_sa_detail_vrf_all_cmd,
8321 "show ip msdp vrf all sa detail [json]",
8322 SHOW_STR
8323 IP_STR
8324 MSDP_STR
8325 VRF_CMD_HELP_STR
8326 "MSDP active-source information\n"
8327 "Detailed output\n"
8328 JSON_STR)
8329 {
8330 u_char uj = use_json(argc, argv);
8331 struct vrf *vrf;
8332 bool first = true;
8333
8334 if (uj)
8335 vty_out(vty, "{ ");
8336 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
8337 if (uj) {
8338 if (!first)
8339 vty_out(vty, ", ");
8340 vty_out(vty, " \"%s\": ", vrf->name);
8341 first = false;
8342 } else
8343 vty_out(vty, "VRF: %s\n", vrf->name);
8344 ip_msdp_show_sa_detail(vrf->info, vty, uj);
8345 }
8346 if (uj)
8347 vty_out(vty, "}\n");
8348
8349 return CMD_SUCCESS;
8350 }
8351
8352 static void ip_msdp_show_sa_addr(struct pim_instance *pim, struct vty *vty,
8353 const char *addr, u_char uj)
8354 {
8355 struct listnode *sanode;
8356 struct pim_msdp_sa *sa;
8357 char src_str[INET_ADDRSTRLEN];
8358 char grp_str[INET_ADDRSTRLEN];
8359 json_object *json = NULL;
8360
8361 if (uj) {
8362 json = json_object_new_object();
8363 }
8364
8365 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
8366 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
8367 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
8368 if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) {
8369 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty,
8370 uj, json);
8371 }
8372 }
8373
8374 if (uj) {
8375 vty_out(vty, "%s\n", json_object_to_json_string_ext(
8376 json, JSON_C_TO_STRING_PRETTY));
8377 json_object_free(json);
8378 }
8379 }
8380
8381 static void ip_msdp_show_sa_sg(struct pim_instance *pim, struct vty *vty,
8382 const char *src, const char *grp, u_char uj)
8383 {
8384 struct listnode *sanode;
8385 struct pim_msdp_sa *sa;
8386 char src_str[INET_ADDRSTRLEN];
8387 char grp_str[INET_ADDRSTRLEN];
8388 json_object *json = NULL;
8389
8390 if (uj) {
8391 json = json_object_new_object();
8392 }
8393
8394 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
8395 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
8396 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
8397 if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) {
8398 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty,
8399 uj, json);
8400 }
8401 }
8402
8403 if (uj) {
8404 vty_out(vty, "%s\n", json_object_to_json_string_ext(
8405 json, JSON_C_TO_STRING_PRETTY));
8406 json_object_free(json);
8407 }
8408 }
8409
8410 DEFUN (show_ip_msdp_sa_sg,
8411 show_ip_msdp_sa_sg_cmd,
8412 "show ip msdp [vrf NAME] sa [A.B.C.D [A.B.C.D]] [json]",
8413 SHOW_STR
8414 IP_STR
8415 MSDP_STR
8416 VRF_CMD_HELP_STR
8417 "MSDP active-source information\n"
8418 "source or group ip\n"
8419 "group ip\n"
8420 JSON_STR)
8421 {
8422 u_char uj = use_json(argc, argv);
8423 struct vrf *vrf;
8424 int idx = 2;
8425
8426 vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
8427
8428 if (!vrf)
8429 return CMD_WARNING;
8430
8431 char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg
8432 : NULL;
8433 char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx)
8434 ? argv[idx]->arg
8435 : NULL;
8436
8437 if (src_ip && grp_ip)
8438 ip_msdp_show_sa_sg(vrf->info, vty, src_ip, grp_ip, uj);
8439 else if (src_ip)
8440 ip_msdp_show_sa_addr(vrf->info, vty, src_ip, uj);
8441 else
8442 ip_msdp_show_sa(vrf->info, vty, uj);
8443
8444 return CMD_SUCCESS;
8445 }
8446
8447 DEFUN (show_ip_msdp_sa_sg_vrf_all,
8448 show_ip_msdp_sa_sg_vrf_all_cmd,
8449 "show ip msdp vrf all sa [A.B.C.D [A.B.C.D]] [json]",
8450 SHOW_STR
8451 IP_STR
8452 MSDP_STR
8453 VRF_CMD_HELP_STR
8454 "MSDP active-source information\n"
8455 "source or group ip\n"
8456 "group ip\n"
8457 JSON_STR)
8458 {
8459 u_char uj = use_json(argc, argv);
8460 struct vrf *vrf;
8461 bool first = true;
8462 int idx = 2;
8463
8464 char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg
8465 : NULL;
8466 char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx)
8467 ? argv[idx]->arg
8468 : NULL;
8469
8470 if (uj)
8471 vty_out(vty, "{ ");
8472 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
8473 if (uj) {
8474 if (!first)
8475 vty_out(vty, ", ");
8476 vty_out(vty, " \"%s\": ", vrf->name);
8477 first = false;
8478 } else
8479 vty_out(vty, "VRF: %s\n", vrf->name);
8480
8481 if (src_ip && grp_ip)
8482 ip_msdp_show_sa_sg(vrf->info, vty, src_ip, grp_ip, uj);
8483 else if (src_ip)
8484 ip_msdp_show_sa_addr(vrf->info, vty, src_ip, uj);
8485 else
8486 ip_msdp_show_sa(vrf->info, vty, uj);
8487 }
8488 if (uj)
8489 vty_out(vty, "}\n");
8490
8491 return CMD_SUCCESS;
8492 }
8493
8494
8495 void pim_cmd_init(void)
8496 {
8497 install_node(&pim_global_node, pim_global_config_write); /* PIM_NODE */
8498 install_node(&interface_node,
8499 pim_interface_config_write); /* INTERFACE_NODE */
8500 if_cmd_init();
8501
8502 install_node(&debug_node, pim_debug_config_write);
8503
8504 install_element(CONFIG_NODE, &ip_multicast_routing_cmd);
8505 install_element(CONFIG_NODE, &no_ip_multicast_routing_cmd);
8506 install_element(CONFIG_NODE, &ip_pim_rp_cmd);
8507 install_element(VRF_NODE, &ip_pim_rp_cmd);
8508 install_element(CONFIG_NODE, &no_ip_pim_rp_cmd);
8509 install_element(VRF_NODE, &no_ip_pim_rp_cmd);
8510 install_element(CONFIG_NODE, &ip_pim_rp_prefix_list_cmd);
8511 install_element(VRF_NODE, &ip_pim_rp_prefix_list_cmd);
8512 install_element(CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd);
8513 install_element(VRF_NODE, &no_ip_pim_rp_prefix_list_cmd);
8514 install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd);
8515 install_element(VRF_NODE, &no_ip_pim_ssm_prefix_list_cmd);
8516 install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
8517 install_element(VRF_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
8518 install_element(CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd);
8519 install_element(VRF_NODE, &ip_pim_ssm_prefix_list_cmd);
8520 install_element(CONFIG_NODE, &ip_pim_register_suppress_cmd);
8521 install_element(VRF_NODE, &ip_pim_register_suppress_cmd);
8522 install_element(CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
8523 install_element(VRF_NODE, &no_ip_pim_register_suppress_cmd);
8524 install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd);
8525 install_element(VRF_NODE, &ip_pim_spt_switchover_infinity_cmd);
8526 install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
8527 install_element(VRF_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
8528 install_element(CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
8529 install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
8530 install_element(CONFIG_NODE,
8531 &no_ip_pim_spt_switchover_infinity_plist_cmd);
8532 install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd);
8533 install_element(CONFIG_NODE, &ip_pim_joinprune_time_cmd);
8534 install_element(VRF_NODE, &ip_pim_joinprune_time_cmd);
8535 install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
8536 install_element(VRF_NODE, &no_ip_pim_joinprune_time_cmd);
8537 install_element(CONFIG_NODE, &ip_pim_keep_alive_cmd);
8538 install_element(VRF_NODE, &ip_pim_keep_alive_cmd);
8539 install_element(CONFIG_NODE, &ip_pim_rp_keep_alive_cmd);
8540 install_element(VRF_NODE, &ip_pim_rp_keep_alive_cmd);
8541 install_element(CONFIG_NODE, &no_ip_pim_keep_alive_cmd);
8542 install_element(VRF_NODE, &no_ip_pim_keep_alive_cmd);
8543 install_element(CONFIG_NODE, &no_ip_pim_rp_keep_alive_cmd);
8544 install_element(VRF_NODE, &no_ip_pim_rp_keep_alive_cmd);
8545 install_element(CONFIG_NODE, &ip_pim_packets_cmd);
8546 install_element(VRF_NODE, &ip_pim_packets_cmd);
8547 install_element(CONFIG_NODE, &no_ip_pim_packets_cmd);
8548 install_element(VRF_NODE, &no_ip_pim_packets_cmd);
8549 install_element(CONFIG_NODE, &ip_pim_v6_secondary_cmd);
8550 install_element(VRF_NODE, &ip_pim_v6_secondary_cmd);
8551 install_element(CONFIG_NODE, &no_ip_pim_v6_secondary_cmd);
8552 install_element(VRF_NODE, &no_ip_pim_v6_secondary_cmd);
8553 install_element(CONFIG_NODE, &ip_ssmpingd_cmd);
8554 install_element(VRF_NODE, &ip_ssmpingd_cmd);
8555 install_element(CONFIG_NODE, &no_ip_ssmpingd_cmd);
8556 install_element(VRF_NODE, &no_ip_ssmpingd_cmd);
8557 install_element(CONFIG_NODE, &ip_msdp_peer_cmd);
8558 install_element(VRF_NODE, &ip_msdp_peer_cmd);
8559 install_element(CONFIG_NODE, &no_ip_msdp_peer_cmd);
8560 install_element(VRF_NODE, &no_ip_msdp_peer_cmd);
8561 install_element(CONFIG_NODE, &ip_pim_ecmp_cmd);
8562 install_element(VRF_NODE, &ip_pim_ecmp_cmd);
8563 install_element(CONFIG_NODE, &no_ip_pim_ecmp_cmd);
8564 install_element(VRF_NODE, &no_ip_pim_ecmp_cmd);
8565 install_element(CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd);
8566 install_element(VRF_NODE, &ip_pim_ecmp_rebalance_cmd);
8567 install_element(CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd);
8568 install_element(VRF_NODE, &no_ip_pim_ecmp_rebalance_cmd);
8569
8570 install_element(INTERFACE_NODE, &interface_ip_igmp_cmd);
8571 install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd);
8572 install_element(INTERFACE_NODE, &interface_ip_igmp_join_cmd);
8573 install_element(INTERFACE_NODE, &interface_no_ip_igmp_join_cmd);
8574 install_element(INTERFACE_NODE, &interface_ip_igmp_version_cmd);
8575 install_element(INTERFACE_NODE, &interface_no_ip_igmp_version_cmd);
8576 install_element(INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd);
8577 install_element(INTERFACE_NODE,
8578 &interface_no_ip_igmp_query_interval_cmd);
8579 install_element(INTERFACE_NODE,
8580 &interface_ip_igmp_query_max_response_time_cmd);
8581 install_element(INTERFACE_NODE,
8582 &interface_no_ip_igmp_query_max_response_time_cmd);
8583 install_element(INTERFACE_NODE,
8584 &interface_ip_igmp_query_max_response_time_dsec_cmd);
8585 install_element(INTERFACE_NODE,
8586 &interface_no_ip_igmp_query_max_response_time_dsec_cmd);
8587 install_element(INTERFACE_NODE, &interface_ip_pim_ssm_cmd);
8588 install_element(INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd);
8589 install_element(INTERFACE_NODE, &interface_ip_pim_sm_cmd);
8590 install_element(INTERFACE_NODE, &interface_no_ip_pim_sm_cmd);
8591 install_element(INTERFACE_NODE, &interface_ip_pim_drprio_cmd);
8592 install_element(INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd);
8593 install_element(INTERFACE_NODE, &interface_ip_pim_hello_cmd);
8594 install_element(INTERFACE_NODE, &interface_no_ip_pim_hello_cmd);
8595 install_element(INTERFACE_NODE, &interface_ip_pim_boundary_oil_cmd);
8596 install_element(INTERFACE_NODE, &interface_no_ip_pim_boundary_oil_cmd);
8597
8598 // Static mroutes NEB
8599 install_element(INTERFACE_NODE, &interface_ip_mroute_cmd);
8600 install_element(INTERFACE_NODE, &interface_ip_mroute_source_cmd);
8601 install_element(INTERFACE_NODE, &interface_no_ip_mroute_cmd);
8602 install_element(INTERFACE_NODE, &interface_no_ip_mroute_source_cmd);
8603
8604 install_element(VIEW_NODE, &show_ip_igmp_interface_cmd);
8605 install_element(VIEW_NODE, &show_ip_igmp_interface_vrf_all_cmd);
8606 install_element(VIEW_NODE, &show_ip_igmp_join_cmd);
8607 install_element(VIEW_NODE, &show_ip_igmp_join_vrf_all_cmd);
8608 install_element(VIEW_NODE, &show_ip_igmp_groups_cmd);
8609 install_element(VIEW_NODE, &show_ip_igmp_groups_vrf_all_cmd);
8610 install_element(VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd);
8611 install_element(VIEW_NODE, &show_ip_igmp_sources_cmd);
8612 install_element(VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd);
8613 install_element(VIEW_NODE, &show_ip_pim_assert_cmd);
8614 install_element(VIEW_NODE, &show_ip_pim_assert_internal_cmd);
8615 install_element(VIEW_NODE, &show_ip_pim_assert_metric_cmd);
8616 install_element(VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd);
8617 install_element(VIEW_NODE, &show_ip_pim_interface_traffic_cmd);
8618 install_element(VIEW_NODE, &show_ip_pim_interface_cmd);
8619 install_element(VIEW_NODE, &show_ip_pim_interface_vrf_all_cmd);
8620 install_element(VIEW_NODE, &show_ip_pim_join_cmd);
8621 install_element(VIEW_NODE, &show_ip_pim_join_vrf_all_cmd);
8622 install_element(VIEW_NODE, &show_ip_pim_local_membership_cmd);
8623 install_element(VIEW_NODE, &show_ip_pim_neighbor_cmd);
8624 install_element(VIEW_NODE, &show_ip_pim_neighbor_vrf_all_cmd);
8625 install_element(VIEW_NODE, &show_ip_pim_rpf_cmd);
8626 install_element(VIEW_NODE, &show_ip_pim_rpf_vrf_all_cmd);
8627 install_element(VIEW_NODE, &show_ip_pim_secondary_cmd);
8628 install_element(VIEW_NODE, &show_ip_pim_state_cmd);
8629 install_element(VIEW_NODE, &show_ip_pim_state_vrf_all_cmd);
8630 install_element(VIEW_NODE, &show_ip_pim_upstream_cmd);
8631 install_element(VIEW_NODE, &show_ip_pim_upstream_vrf_all_cmd);
8632 install_element(VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd);
8633 install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd);
8634 install_element(VIEW_NODE, &show_ip_pim_rp_cmd);
8635 install_element(VIEW_NODE, &show_ip_pim_rp_vrf_all_cmd);
8636 install_element(VIEW_NODE, &show_ip_multicast_cmd);
8637 install_element(VIEW_NODE, &show_ip_multicast_vrf_all_cmd);
8638 install_element(VIEW_NODE, &show_ip_mroute_cmd);
8639 install_element(VIEW_NODE, &show_ip_mroute_vrf_all_cmd);
8640 install_element(VIEW_NODE, &show_ip_mroute_count_cmd);
8641 install_element(VIEW_NODE, &show_ip_mroute_count_vrf_all_cmd);
8642 install_element(VIEW_NODE, &show_ip_rib_cmd);
8643 install_element(VIEW_NODE, &show_ip_ssmpingd_cmd);
8644 install_element(VIEW_NODE, &show_debugging_pim_cmd);
8645 install_element(VIEW_NODE, &show_ip_pim_nexthop_cmd);
8646 install_element(VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd);
8647
8648 install_element(ENABLE_NODE, &clear_ip_interfaces_cmd);
8649 install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd);
8650 install_element(ENABLE_NODE, &clear_ip_mroute_cmd);
8651 install_element(ENABLE_NODE, &clear_ip_pim_interfaces_cmd);
8652 install_element(ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd);
8653 install_element(ENABLE_NODE, &clear_ip_pim_oil_cmd);
8654
8655 install_element(ENABLE_NODE, &debug_igmp_cmd);
8656 install_element(ENABLE_NODE, &no_debug_igmp_cmd);
8657 install_element(ENABLE_NODE, &debug_igmp_events_cmd);
8658 install_element(ENABLE_NODE, &no_debug_igmp_events_cmd);
8659 install_element(ENABLE_NODE, &debug_igmp_packets_cmd);
8660 install_element(ENABLE_NODE, &no_debug_igmp_packets_cmd);
8661 install_element(ENABLE_NODE, &debug_igmp_trace_cmd);
8662 install_element(ENABLE_NODE, &no_debug_igmp_trace_cmd);
8663 install_element(ENABLE_NODE, &debug_mroute_cmd);
8664 install_element(ENABLE_NODE, &debug_mroute_detail_cmd);
8665 install_element(ENABLE_NODE, &no_debug_mroute_cmd);
8666 install_element(ENABLE_NODE, &no_debug_mroute_detail_cmd);
8667 install_element(ENABLE_NODE, &debug_static_cmd);
8668 install_element(ENABLE_NODE, &no_debug_static_cmd);
8669 install_element(ENABLE_NODE, &debug_pim_cmd);
8670 install_element(ENABLE_NODE, &no_debug_pim_cmd);
8671 install_element(ENABLE_NODE, &debug_pim_nht_cmd);
8672 install_element(ENABLE_NODE, &no_debug_pim_nht_cmd);
8673 install_element(ENABLE_NODE, &debug_pim_nht_rp_cmd);
8674 install_element(ENABLE_NODE, &no_debug_pim_nht_rp_cmd);
8675 install_element(ENABLE_NODE, &debug_pim_events_cmd);
8676 install_element(ENABLE_NODE, &no_debug_pim_events_cmd);
8677 install_element(ENABLE_NODE, &debug_pim_packets_cmd);
8678 install_element(ENABLE_NODE, &no_debug_pim_packets_cmd);
8679 install_element(ENABLE_NODE, &debug_pim_packetdump_send_cmd);
8680 install_element(ENABLE_NODE, &no_debug_pim_packetdump_send_cmd);
8681 install_element(ENABLE_NODE, &debug_pim_packetdump_recv_cmd);
8682 install_element(ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd);
8683 install_element(ENABLE_NODE, &debug_pim_trace_cmd);
8684 install_element(ENABLE_NODE, &no_debug_pim_trace_cmd);
8685 install_element(ENABLE_NODE, &debug_pim_trace_detail_cmd);
8686 install_element(ENABLE_NODE, &no_debug_pim_trace_detail_cmd);
8687 install_element(ENABLE_NODE, &debug_ssmpingd_cmd);
8688 install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd);
8689 install_element(ENABLE_NODE, &debug_pim_zebra_cmd);
8690 install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd);
8691 install_element(ENABLE_NODE, &debug_msdp_cmd);
8692 install_element(ENABLE_NODE, &no_debug_msdp_cmd);
8693 install_element(ENABLE_NODE, &undebug_msdp_cmd);
8694 install_element(ENABLE_NODE, &debug_msdp_events_cmd);
8695 install_element(ENABLE_NODE, &no_debug_msdp_events_cmd);
8696 install_element(ENABLE_NODE, &undebug_msdp_events_cmd);
8697 install_element(ENABLE_NODE, &debug_msdp_packets_cmd);
8698 install_element(ENABLE_NODE, &no_debug_msdp_packets_cmd);
8699 install_element(ENABLE_NODE, &undebug_msdp_packets_cmd);
8700
8701 install_element(CONFIG_NODE, &debug_igmp_cmd);
8702 install_element(CONFIG_NODE, &no_debug_igmp_cmd);
8703 install_element(CONFIG_NODE, &debug_igmp_events_cmd);
8704 install_element(CONFIG_NODE, &no_debug_igmp_events_cmd);
8705 install_element(CONFIG_NODE, &debug_igmp_packets_cmd);
8706 install_element(CONFIG_NODE, &no_debug_igmp_packets_cmd);
8707 install_element(CONFIG_NODE, &debug_igmp_trace_cmd);
8708 install_element(CONFIG_NODE, &no_debug_igmp_trace_cmd);
8709 install_element(CONFIG_NODE, &debug_mroute_cmd);
8710 install_element(CONFIG_NODE, &debug_mroute_detail_cmd);
8711 install_element(CONFIG_NODE, &no_debug_mroute_cmd);
8712 install_element(CONFIG_NODE, &no_debug_mroute_detail_cmd);
8713 install_element(CONFIG_NODE, &debug_static_cmd);
8714 install_element(CONFIG_NODE, &no_debug_static_cmd);
8715 install_element(CONFIG_NODE, &debug_pim_cmd);
8716 install_element(CONFIG_NODE, &no_debug_pim_cmd);
8717 install_element(CONFIG_NODE, &debug_pim_nht_cmd);
8718 install_element(CONFIG_NODE, &no_debug_pim_nht_cmd);
8719 install_element(CONFIG_NODE, &debug_pim_nht_rp_cmd);
8720 install_element(CONFIG_NODE, &no_debug_pim_nht_rp_cmd);
8721 install_element(CONFIG_NODE, &debug_pim_events_cmd);
8722 install_element(CONFIG_NODE, &no_debug_pim_events_cmd);
8723 install_element(CONFIG_NODE, &debug_pim_packets_cmd);
8724 install_element(CONFIG_NODE, &no_debug_pim_packets_cmd);
8725 install_element(CONFIG_NODE, &debug_pim_trace_cmd);
8726 install_element(CONFIG_NODE, &no_debug_pim_trace_cmd);
8727 install_element(CONFIG_NODE, &debug_pim_trace_detail_cmd);
8728 install_element(CONFIG_NODE, &no_debug_pim_trace_detail_cmd);
8729 install_element(CONFIG_NODE, &debug_ssmpingd_cmd);
8730 install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd);
8731 install_element(CONFIG_NODE, &debug_pim_zebra_cmd);
8732 install_element(CONFIG_NODE, &no_debug_pim_zebra_cmd);
8733 install_element(CONFIG_NODE, &debug_msdp_cmd);
8734 install_element(CONFIG_NODE, &no_debug_msdp_cmd);
8735 install_element(CONFIG_NODE, &undebug_msdp_cmd);
8736 install_element(CONFIG_NODE, &debug_msdp_events_cmd);
8737 install_element(CONFIG_NODE, &no_debug_msdp_events_cmd);
8738 install_element(CONFIG_NODE, &undebug_msdp_events_cmd);
8739 install_element(CONFIG_NODE, &debug_msdp_packets_cmd);
8740 install_element(CONFIG_NODE, &no_debug_msdp_packets_cmd);
8741 install_element(CONFIG_NODE, &undebug_msdp_packets_cmd);
8742
8743 install_element(CONFIG_NODE, &ip_msdp_mesh_group_member_cmd);
8744 install_element(VRF_NODE, &ip_msdp_mesh_group_member_cmd);
8745 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd);
8746 install_element(VRF_NODE, &no_ip_msdp_mesh_group_member_cmd);
8747 install_element(CONFIG_NODE, &ip_msdp_mesh_group_source_cmd);
8748 install_element(VRF_NODE, &ip_msdp_mesh_group_source_cmd);
8749 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd);
8750 install_element(VRF_NODE, &no_ip_msdp_mesh_group_source_cmd);
8751 install_element(VIEW_NODE, &show_ip_msdp_peer_detail_cmd);
8752 install_element(VIEW_NODE, &show_ip_msdp_peer_detail_vrf_all_cmd);
8753 install_element(VIEW_NODE, &show_ip_msdp_sa_detail_cmd);
8754 install_element(VIEW_NODE, &show_ip_msdp_sa_detail_vrf_all_cmd);
8755 install_element(VIEW_NODE, &show_ip_msdp_sa_sg_cmd);
8756 install_element(VIEW_NODE, &show_ip_msdp_sa_sg_vrf_all_cmd);
8757 install_element(VIEW_NODE, &show_ip_msdp_mesh_group_cmd);
8758 install_element(VIEW_NODE, &show_ip_msdp_mesh_group_vrf_all_cmd);
8759 install_element(VIEW_NODE, &show_ip_pim_ssm_range_cmd);
8760 install_element(VIEW_NODE, &show_ip_pim_group_type_cmd);
8761 install_element(INTERFACE_NODE, &interface_pim_use_source_cmd);
8762 install_element(INTERFACE_NODE, &interface_no_pim_use_source_cmd);
8763 /* Install BFD command */
8764 install_element(INTERFACE_NODE, &ip_pim_bfd_cmd);
8765 install_element(INTERFACE_NODE, &ip_pim_bfd_param_cmd);
8766 install_element(INTERFACE_NODE, &no_ip_pim_bfd_cmd);
8767 install_element(INTERFACE_NODE, &no_ip_pim_bfd_param_cmd);
8768 }