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