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