]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_cmd.c
pimd: Convert channel_oil_hash and list into 'struct pim_instance *'
[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 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 (!qpim_ssmpingd_list)
4225 return;
4226
4227 now = pim_time_monotonic_sec();
4228
4229 for (ALL_LIST_ELEMENTS_RO(qpim_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(vty);
4265 return CMD_SUCCESS;
4266 }
4267
4268 static int pim_rp_cmd_worker(struct vty *vty, const char *rp, const char *group,
4269 const char *plist)
4270 {
4271 int result;
4272
4273 result = pim_rp_new(pimg, rp, group, plist);
4274
4275 if (result == PIM_MALLOC_FAIL) {
4276 vty_out(vty, "%% Out of memory\n");
4277 return CMD_WARNING_CONFIG_FAILED;
4278 }
4279
4280 if (result == PIM_GROUP_BAD_ADDRESS) {
4281 vty_out(vty, "%% Bad group address specified: %s\n", group);
4282 return CMD_WARNING_CONFIG_FAILED;
4283 }
4284
4285 if (result == PIM_RP_BAD_ADDRESS) {
4286 vty_out(vty, "%% Bad RP address specified: %s\n", rp);
4287 return CMD_WARNING_CONFIG_FAILED;
4288 }
4289
4290 if (result == PIM_RP_NO_PATH) {
4291 vty_out(vty, "%% No Path to RP address specified: %s\n", rp);
4292 return CMD_WARNING_CONFIG_FAILED;
4293 }
4294
4295 if (result == PIM_GROUP_OVERLAP) {
4296 vty_out(vty, "%% Group range specified cannot overlap\n");
4297 return CMD_WARNING_CONFIG_FAILED;
4298 }
4299
4300 if (result == PIM_GROUP_PFXLIST_OVERLAP) {
4301 vty_out(vty,
4302 "%% This group is already covered by a RP prefix-list\n");
4303 return CMD_WARNING_CONFIG_FAILED;
4304 }
4305
4306 if (result == PIM_RP_PFXLIST_IN_USE) {
4307 vty_out(vty,
4308 "%% The same prefix-list cannot be applied to multiple RPs\n");
4309 return CMD_WARNING_CONFIG_FAILED;
4310 }
4311
4312 return CMD_SUCCESS;
4313 }
4314
4315 static int pim_cmd_spt_switchover(enum pim_spt_switchover spt,
4316 const char *plist)
4317 {
4318 pimg->spt.switchover = spt;
4319
4320 switch (pimg->spt.switchover) {
4321 case PIM_SPT_IMMEDIATE:
4322 if (pimg->spt.plist)
4323 XFREE(MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist);
4324
4325 pim_upstream_add_lhr_star_pimreg(pimg);
4326 break;
4327 case PIM_SPT_INFINITY:
4328 pim_upstream_remove_lhr_star_pimreg(pimg, plist);
4329
4330 if (pimg->spt.plist)
4331 XFREE(MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist);
4332
4333 if (plist)
4334 pimg->spt.plist =
4335 XSTRDUP(MTYPE_PIM_SPT_PLIST_NAME, plist);
4336 break;
4337 }
4338
4339 return CMD_SUCCESS;
4340 }
4341
4342 DEFUN (ip_pim_spt_switchover_infinity,
4343 ip_pim_spt_switchover_infinity_cmd,
4344 "ip pim spt-switchover infinity-and-beyond",
4345 IP_STR
4346 PIM_STR
4347 "SPT-Switchover\n"
4348 "Never switch to SPT Tree\n")
4349 {
4350 return pim_cmd_spt_switchover(PIM_SPT_INFINITY, NULL);
4351 }
4352
4353 DEFUN (ip_pim_spt_switchover_infinity_plist,
4354 ip_pim_spt_switchover_infinity_plist_cmd,
4355 "ip pim spt-switchover infinity-and-beyond prefix-list WORD",
4356 IP_STR
4357 PIM_STR
4358 "SPT-Switchover\n"
4359 "Never switch to SPT Tree\n"
4360 "Prefix-List to control which groups to switch\n"
4361 "Prefix-List name\n")
4362 {
4363 return pim_cmd_spt_switchover(PIM_SPT_INFINITY, argv[5]->arg);
4364 }
4365
4366 DEFUN (no_ip_pim_spt_switchover_infinity,
4367 no_ip_pim_spt_switchover_infinity_cmd,
4368 "no ip pim spt-switchover infinity-and-beyond",
4369 NO_STR
4370 IP_STR
4371 PIM_STR
4372 "SPT_Switchover\n"
4373 "Never switch to SPT Tree\n")
4374 {
4375 return pim_cmd_spt_switchover(PIM_SPT_IMMEDIATE, NULL);
4376 }
4377
4378 DEFUN (no_ip_pim_spt_switchover_infinity_plist,
4379 no_ip_pim_spt_switchover_infinity_plist_cmd,
4380 "no ip pim spt-switchover infinity-and-beyond prefix-list WORD",
4381 NO_STR
4382 IP_STR
4383 PIM_STR
4384 "SPT_Switchover\n"
4385 "Never switch to SPT Tree\n"
4386 "Prefix-List to control which groups to switch\n"
4387 "Prefix-List name\n")
4388 {
4389 return pim_cmd_spt_switchover(PIM_SPT_IMMEDIATE, NULL);
4390 }
4391
4392 DEFUN (ip_pim_joinprune_time,
4393 ip_pim_joinprune_time_cmd,
4394 "ip pim join-prune-interval (60-600)",
4395 IP_STR
4396 "pim multicast routing\n"
4397 "Join Prune Send Interval\n"
4398 "Seconds\n")
4399 {
4400 qpim_t_periodic = atoi(argv[3]->arg);
4401 return CMD_SUCCESS;
4402 }
4403
4404 DEFUN (no_ip_pim_joinprune_time,
4405 no_ip_pim_joinprune_time_cmd,
4406 "no ip pim join-prune-interval (60-600)",
4407 NO_STR
4408 IP_STR
4409 "pim multicast routing\n"
4410 "Join Prune Send Interval\n"
4411 "Seconds\n")
4412 {
4413 qpim_t_periodic = PIM_DEFAULT_T_PERIODIC;
4414 return CMD_SUCCESS;
4415 }
4416
4417 DEFUN (ip_pim_register_suppress,
4418 ip_pim_register_suppress_cmd,
4419 "ip pim register-suppress-time (5-60000)",
4420 IP_STR
4421 "pim multicast routing\n"
4422 "Register Suppress Timer\n"
4423 "Seconds\n")
4424 {
4425 qpim_register_suppress_time = atoi(argv[3]->arg);
4426 return CMD_SUCCESS;
4427 }
4428
4429 DEFUN (no_ip_pim_register_suppress,
4430 no_ip_pim_register_suppress_cmd,
4431 "no ip pim register-suppress-time (5-60000)",
4432 NO_STR
4433 IP_STR
4434 "pim multicast routing\n"
4435 "Register Suppress Timer\n"
4436 "Seconds\n")
4437 {
4438 qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT;
4439 return CMD_SUCCESS;
4440 }
4441
4442 DEFUN (ip_pim_keep_alive,
4443 ip_pim_keep_alive_cmd,
4444 "ip pim keep-alive-timer (31-60000)",
4445 IP_STR
4446 "pim multicast routing\n"
4447 "Keep alive Timer\n"
4448 "Seconds\n")
4449 {
4450 qpim_keep_alive_time = atoi(argv[3]->arg);
4451 return CMD_SUCCESS;
4452 }
4453
4454 DEFUN (no_ip_pim_keep_alive,
4455 no_ip_pim_keep_alive_cmd,
4456 "no ip pim keep-alive-timer (31-60000)",
4457 NO_STR
4458 IP_STR
4459 "pim multicast routing\n"
4460 "Keep alive Timer\n"
4461 "Seconds\n")
4462 {
4463 qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD;
4464 return CMD_SUCCESS;
4465 }
4466
4467 DEFUN (ip_pim_packets,
4468 ip_pim_packets_cmd,
4469 "ip pim packets (1-100)",
4470 IP_STR
4471 "pim multicast routing\n"
4472 "packets to process at one time per fd\n"
4473 "Number of packets\n")
4474 {
4475 qpim_packet_process = atoi(argv[3]->arg);
4476 return CMD_SUCCESS;
4477 }
4478
4479 DEFUN (no_ip_pim_packets,
4480 no_ip_pim_packets_cmd,
4481 "no ip pim packets (1-100)",
4482 NO_STR
4483 IP_STR
4484 "pim multicast routing\n"
4485 "packets to process at one time per fd\n"
4486 "Number of packets\n")
4487 {
4488 qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS;
4489 return CMD_SUCCESS;
4490 }
4491
4492 DEFUN (ip_pim_v6_secondary,
4493 ip_pim_v6_secondary_cmd,
4494 "ip pim send-v6-secondary",
4495 IP_STR
4496 "pim multicast routing\n"
4497 "Send v6 secondary addresses\n")
4498 {
4499 pimg->send_v6_secondary = 1;
4500
4501 return CMD_SUCCESS;
4502 }
4503
4504 DEFUN (no_ip_pim_v6_secondary,
4505 no_ip_pim_v6_secondary_cmd,
4506 "no ip pim send-v6-secondary",
4507 NO_STR
4508 IP_STR
4509 "pim multicast routing\n"
4510 "Send v6 secondary addresses\n")
4511 {
4512 pimg->send_v6_secondary = 0;
4513
4514 return CMD_SUCCESS;
4515 }
4516
4517 DEFUN (ip_pim_rp,
4518 ip_pim_rp_cmd,
4519 "ip pim rp A.B.C.D [A.B.C.D/M]",
4520 IP_STR
4521 "pim multicast routing\n"
4522 "Rendevous Point\n"
4523 "ip address of RP\n"
4524 "Group Address range to cover\n")
4525 {
4526 int idx_ipv4 = 3;
4527
4528 if (argc == (idx_ipv4 + 1))
4529 return pim_rp_cmd_worker(vty, argv[idx_ipv4]->arg, NULL, NULL);
4530 else
4531 return pim_rp_cmd_worker(vty, argv[idx_ipv4]->arg,
4532 argv[idx_ipv4 + 1]->arg, NULL);
4533 }
4534
4535 DEFUN (ip_pim_rp_prefix_list,
4536 ip_pim_rp_prefix_list_cmd,
4537 "ip pim rp A.B.C.D prefix-list WORD",
4538 IP_STR
4539 "pim multicast routing\n"
4540 "Rendevous Point\n"
4541 "ip address of RP\n"
4542 "group prefix-list filter\n"
4543 "Name of a prefix-list\n")
4544 {
4545 return pim_rp_cmd_worker(vty, argv[3]->arg, NULL, argv[5]->arg);
4546 }
4547
4548 static int pim_no_rp_cmd_worker(struct vty *vty, const char *rp,
4549 const char *group, const char *plist)
4550 {
4551 int result = pim_rp_del(pimg, rp, group, plist);
4552
4553 if (result == PIM_GROUP_BAD_ADDRESS) {
4554 vty_out(vty, "%% Bad group address specified: %s\n", group);
4555 return CMD_WARNING_CONFIG_FAILED;
4556 }
4557
4558 if (result == PIM_RP_BAD_ADDRESS) {
4559 vty_out(vty, "%% Bad RP address specified: %s\n", rp);
4560 return CMD_WARNING_CONFIG_FAILED;
4561 }
4562
4563 if (result == PIM_RP_NOT_FOUND) {
4564 vty_out(vty, "%% Unable to find specified RP\n");
4565 return CMD_WARNING_CONFIG_FAILED;
4566 }
4567
4568 return CMD_SUCCESS;
4569 }
4570
4571 DEFUN (no_ip_pim_rp,
4572 no_ip_pim_rp_cmd,
4573 "no ip pim rp A.B.C.D [A.B.C.D/M]",
4574 NO_STR
4575 IP_STR
4576 "pim multicast routing\n"
4577 "Rendevous Point\n"
4578 "ip address of RP\n"
4579 "Group Address range to cover\n")
4580 {
4581 int idx_ipv4 = 4, idx_group = 0;
4582
4583 if (argv_find(argv, argc, "A.B.C.D/M", &idx_group))
4584 return pim_no_rp_cmd_worker(vty, argv[idx_ipv4]->arg,
4585 argv[idx_group]->arg, NULL);
4586 else
4587 return pim_no_rp_cmd_worker(vty, argv[idx_ipv4]->arg, NULL,
4588 NULL);
4589 }
4590
4591 DEFUN (no_ip_pim_rp_prefix_list,
4592 no_ip_pim_rp_prefix_list_cmd,
4593 "no ip pim rp A.B.C.D prefix-list WORD",
4594 NO_STR
4595 IP_STR
4596 "pim multicast routing\n"
4597 "Rendevous Point\n"
4598 "ip address of RP\n"
4599 "group prefix-list filter\n"
4600 "Name of a prefix-list\n")
4601 {
4602 return pim_no_rp_cmd_worker(vty, argv[4]->arg, NULL, argv[6]->arg);
4603 }
4604
4605 static int pim_ssm_cmd_worker(struct vty *vty, const char *plist)
4606 {
4607 int result = pim_ssm_range_set(pimg->vrf_id, plist);
4608
4609 if (result == PIM_SSM_ERR_NONE)
4610 return CMD_SUCCESS;
4611
4612 switch (result) {
4613 case PIM_SSM_ERR_NO_VRF:
4614 vty_out(vty, "%% VRF doesn't exist\n");
4615 break;
4616 case PIM_SSM_ERR_DUP:
4617 vty_out(vty, "%% duplicate config\n");
4618 break;
4619 default:
4620 vty_out(vty, "%% ssm range config failed\n");
4621 }
4622
4623 return CMD_WARNING_CONFIG_FAILED;
4624 }
4625
4626 DEFUN (ip_pim_ssm_prefix_list,
4627 ip_pim_ssm_prefix_list_cmd,
4628 "ip pim ssm prefix-list WORD",
4629 IP_STR
4630 "pim multicast routing\n"
4631 "Source Specific Multicast\n"
4632 "group range prefix-list filter\n"
4633 "Name of a prefix-list\n")
4634 {
4635 return pim_ssm_cmd_worker(vty, argv[0]->arg);
4636 }
4637
4638 DEFUN (no_ip_pim_ssm_prefix_list,
4639 no_ip_pim_ssm_prefix_list_cmd,
4640 "no ip pim ssm prefix-list",
4641 NO_STR
4642 IP_STR
4643 "pim multicast routing\n"
4644 "Source Specific Multicast\n"
4645 "group range prefix-list filter\n")
4646 {
4647 return pim_ssm_cmd_worker(vty, NULL);
4648 }
4649
4650 DEFUN (no_ip_pim_ssm_prefix_list_name,
4651 no_ip_pim_ssm_prefix_list_name_cmd,
4652 "no ip pim ssm prefix-list WORD",
4653 NO_STR
4654 IP_STR
4655 "pim multicast routing\n"
4656 "Source Specific Multicast\n"
4657 "group range prefix-list filter\n"
4658 "Name of a prefix-list\n")
4659 {
4660 struct pim_ssm *ssm = pimg->ssm_info;
4661
4662 if (ssm->plist_name && !strcmp(ssm->plist_name, argv[0]->arg))
4663 return pim_ssm_cmd_worker(vty, NULL);
4664
4665 vty_out(vty, "%% pim ssm prefix-list %s doesn't exist\n", argv[0]->arg);
4666
4667 return CMD_WARNING_CONFIG_FAILED;
4668 }
4669
4670 static void ip_pim_ssm_show_group_range(struct vty *vty, u_char uj)
4671 {
4672 struct pim_ssm *ssm = pimg->ssm_info;
4673 const char *range_str =
4674 ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
4675
4676 if (uj) {
4677 json_object *json;
4678 json = json_object_new_object();
4679 json_object_string_add(json, "ssmGroups", range_str);
4680 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4681 json, JSON_C_TO_STRING_PRETTY));
4682 json_object_free(json);
4683 } else
4684 vty_out(vty, "SSM group range : %s\n", range_str);
4685 }
4686
4687 DEFUN (show_ip_pim_ssm_range,
4688 show_ip_pim_ssm_range_cmd,
4689 "show ip pim group-type [json]",
4690 SHOW_STR
4691 IP_STR
4692 PIM_STR
4693 "PIM group type\n"
4694 "JavaScript Object Notation\n")
4695 {
4696 u_char uj = use_json(argc, argv);
4697 ip_pim_ssm_show_group_range(vty, uj);
4698
4699 return CMD_SUCCESS;
4700 }
4701
4702 static void ip_pim_ssm_show_group_type(struct vty *vty, u_char uj,
4703 const char *group)
4704 {
4705 struct in_addr group_addr;
4706 const char *type_str;
4707 int result;
4708
4709 result = inet_pton(AF_INET, group, &group_addr);
4710 if (result <= 0)
4711 type_str = "invalid";
4712 else {
4713 if (pim_is_group_224_4(group_addr))
4714 type_str = pim_is_grp_ssm(group_addr) ? "SSM" : "ASM";
4715 else
4716 type_str = "not-multicast";
4717 }
4718
4719 if (uj) {
4720 json_object *json;
4721 json = json_object_new_object();
4722 json_object_string_add(json, "groupType", type_str);
4723 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4724 json, JSON_C_TO_STRING_PRETTY));
4725 json_object_free(json);
4726 } else
4727 vty_out(vty, "Group type : %s\n", type_str);
4728 }
4729
4730 DEFUN (show_ip_pim_group_type,
4731 show_ip_pim_group_type_cmd,
4732 "show ip pim group-type A.B.C.D [json]",
4733 SHOW_STR
4734 IP_STR
4735 PIM_STR
4736 "multicast group type\n"
4737 "group address\n"
4738 "JavaScript Object Notation\n")
4739 {
4740 u_char uj = use_json(argc, argv);
4741 ip_pim_ssm_show_group_type(vty, uj, argv[0]->arg);
4742
4743 return CMD_SUCCESS;
4744 }
4745
4746 DEFUN_HIDDEN (ip_multicast_routing,
4747 ip_multicast_routing_cmd,
4748 "ip multicast-routing",
4749 IP_STR
4750 "Enable IP multicast forwarding\n")
4751 {
4752 return CMD_SUCCESS;
4753 }
4754
4755 DEFUN_HIDDEN (no_ip_multicast_routing,
4756 no_ip_multicast_routing_cmd,
4757 "no ip multicast-routing",
4758 NO_STR
4759 IP_STR
4760 "Enable IP multicast forwarding\n")
4761 {
4762 vty_out(vty,
4763 "Command is Disabled and will be removed in a future version\n");
4764 return CMD_SUCCESS;
4765 }
4766
4767 DEFUN (ip_ssmpingd,
4768 ip_ssmpingd_cmd,
4769 "ip ssmpingd [A.B.C.D]",
4770 IP_STR
4771 CONF_SSMPINGD_STR
4772 "Source address\n")
4773 {
4774 int idx_ipv4 = 2;
4775 int result;
4776 struct in_addr source_addr;
4777 const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0";
4778
4779 result = inet_pton(AF_INET, source_str, &source_addr);
4780 if (result <= 0) {
4781 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n",
4782 source_str, errno, safe_strerror(errno));
4783 return CMD_WARNING_CONFIG_FAILED;
4784 }
4785
4786 result = pim_ssmpingd_start(source_addr);
4787 if (result) {
4788 vty_out(vty, "%% Failure starting ssmpingd for source %s: %d\n",
4789 source_str, result);
4790 return CMD_WARNING_CONFIG_FAILED;
4791 }
4792
4793 return CMD_SUCCESS;
4794 }
4795
4796 DEFUN (no_ip_ssmpingd,
4797 no_ip_ssmpingd_cmd,
4798 "no ip ssmpingd [A.B.C.D]",
4799 NO_STR
4800 IP_STR
4801 CONF_SSMPINGD_STR
4802 "Source address\n")
4803 {
4804 int idx_ipv4 = 3;
4805 int result;
4806 struct in_addr source_addr;
4807 const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0";
4808
4809 result = inet_pton(AF_INET, source_str, &source_addr);
4810 if (result <= 0) {
4811 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n",
4812 source_str, errno, safe_strerror(errno));
4813 return CMD_WARNING_CONFIG_FAILED;
4814 }
4815
4816 result = pim_ssmpingd_stop(source_addr);
4817 if (result) {
4818 vty_out(vty, "%% Failure stopping ssmpingd for source %s: %d\n",
4819 source_str, result);
4820 return CMD_WARNING_CONFIG_FAILED;
4821 }
4822
4823 return CMD_SUCCESS;
4824 }
4825
4826 DEFUN (ip_pim_ecmp,
4827 ip_pim_ecmp_cmd,
4828 "ip pim ecmp",
4829 IP_STR
4830 "pim multicast routing\n"
4831 "Enable PIM ECMP \n")
4832 {
4833 qpim_ecmp_enable = 1;
4834
4835 return CMD_SUCCESS;
4836 }
4837
4838 DEFUN (no_ip_pim_ecmp,
4839 no_ip_pim_ecmp_cmd,
4840 "no ip pim ecmp",
4841 NO_STR
4842 IP_STR
4843 "pim multicast routing\n"
4844 "Disable PIM ECMP \n")
4845 {
4846 qpim_ecmp_enable = 0;
4847
4848 return CMD_SUCCESS;
4849 }
4850
4851 DEFUN (ip_pim_ecmp_rebalance,
4852 ip_pim_ecmp_rebalance_cmd,
4853 "ip pim ecmp rebalance",
4854 IP_STR
4855 "pim multicast routing\n"
4856 "Enable PIM ECMP \n"
4857 "Enable PIM ECMP Rebalance\n")
4858 {
4859 qpim_ecmp_enable = 1;
4860 qpim_ecmp_rebalance_enable = 1;
4861
4862 return CMD_SUCCESS;
4863 }
4864
4865 DEFUN (no_ip_pim_ecmp_rebalance,
4866 no_ip_pim_ecmp_rebalance_cmd,
4867 "no ip pim ecmp rebalance",
4868 NO_STR
4869 IP_STR
4870 "pim multicast routing\n"
4871 "Disable PIM ECMP \n"
4872 "Disable PIM ECMP Rebalance\n")
4873 {
4874 qpim_ecmp_rebalance_enable = 0;
4875
4876 return CMD_SUCCESS;
4877 }
4878
4879 static int pim_cmd_igmp_start(struct vty *vty, struct interface *ifp)
4880 {
4881 struct pim_interface *pim_ifp;
4882 uint8_t need_startup = 0;
4883
4884 pim_ifp = ifp->info;
4885
4886 if (!pim_ifp) {
4887 pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */);
4888 if (!pim_ifp) {
4889 vty_out(vty, "Could not enable IGMP on interface %s\n",
4890 ifp->name);
4891 return CMD_WARNING_CONFIG_FAILED;
4892 }
4893 need_startup = 1;
4894 } else {
4895 if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
4896 PIM_IF_DO_IGMP(pim_ifp->options);
4897 need_startup = 1;
4898 }
4899 }
4900
4901 /* 'ip igmp' executed multiple times, with need_startup
4902 avoid multiple if add all and membership refresh */
4903 if (need_startup) {
4904 pim_if_addr_add_all(ifp);
4905 pim_if_membership_refresh(ifp);
4906 }
4907
4908 return CMD_SUCCESS;
4909 }
4910
4911 DEFUN (interface_ip_igmp,
4912 interface_ip_igmp_cmd,
4913 "ip igmp",
4914 IP_STR
4915 IFACE_IGMP_STR)
4916 {
4917 VTY_DECLVAR_CONTEXT(interface, ifp);
4918
4919 return pim_cmd_igmp_start(vty, ifp);
4920 }
4921
4922 DEFUN (interface_no_ip_igmp,
4923 interface_no_ip_igmp_cmd,
4924 "no ip igmp",
4925 NO_STR
4926 IP_STR
4927 IFACE_IGMP_STR)
4928 {
4929 VTY_DECLVAR_CONTEXT(interface, ifp);
4930 struct pim_interface *pim_ifp = ifp->info;
4931
4932 if (!pim_ifp)
4933 return CMD_SUCCESS;
4934
4935 PIM_IF_DONT_IGMP(pim_ifp->options);
4936
4937 pim_if_membership_clear(ifp);
4938
4939 pim_if_addr_del_all_igmp(ifp);
4940
4941 if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
4942 pim_if_delete(ifp);
4943 }
4944
4945 return CMD_SUCCESS;
4946 }
4947
4948 DEFUN (interface_ip_igmp_join,
4949 interface_ip_igmp_join_cmd,
4950 "ip igmp join A.B.C.D A.B.C.D",
4951 IP_STR
4952 IFACE_IGMP_STR
4953 "IGMP join multicast group\n"
4954 "Multicast group address\n"
4955 "Source address\n")
4956 {
4957 VTY_DECLVAR_CONTEXT(interface, ifp);
4958 int idx_ipv4 = 3;
4959 int idx_ipv4_2 = 4;
4960 const char *group_str;
4961 const char *source_str;
4962 struct in_addr group_addr;
4963 struct in_addr source_addr;
4964 int result;
4965
4966 /* Group address */
4967 group_str = argv[idx_ipv4]->arg;
4968 result = inet_pton(AF_INET, group_str, &group_addr);
4969 if (result <= 0) {
4970 vty_out(vty, "Bad group address %s: errno=%d: %s\n", group_str,
4971 errno, safe_strerror(errno));
4972 return CMD_WARNING_CONFIG_FAILED;
4973 }
4974
4975 /* Source address */
4976 source_str = argv[idx_ipv4_2]->arg;
4977 result = inet_pton(AF_INET, source_str, &source_addr);
4978 if (result <= 0) {
4979 vty_out(vty, "Bad source address %s: errno=%d: %s\n",
4980 source_str, errno, safe_strerror(errno));
4981 return CMD_WARNING_CONFIG_FAILED;
4982 }
4983
4984 result = pim_if_igmp_join_add(ifp, group_addr, source_addr);
4985 if (result) {
4986 vty_out(vty,
4987 "%% Failure joining IGMP group %s source %s on interface %s: %d\n",
4988 group_str, source_str, ifp->name, result);
4989 return CMD_WARNING_CONFIG_FAILED;
4990 }
4991
4992 return CMD_SUCCESS;
4993 }
4994
4995 DEFUN (interface_no_ip_igmp_join,
4996 interface_no_ip_igmp_join_cmd,
4997 "no ip igmp join A.B.C.D A.B.C.D",
4998 NO_STR
4999 IP_STR
5000 IFACE_IGMP_STR
5001 "IGMP join multicast group\n"
5002 "Multicast group address\n"
5003 "Source address\n")
5004 {
5005 VTY_DECLVAR_CONTEXT(interface, ifp);
5006 int idx_ipv4 = 4;
5007 int idx_ipv4_2 = 5;
5008 const char *group_str;
5009 const char *source_str;
5010 struct in_addr group_addr;
5011 struct in_addr source_addr;
5012 int result;
5013
5014 /* Group address */
5015 group_str = argv[idx_ipv4]->arg;
5016 result = inet_pton(AF_INET, group_str, &group_addr);
5017 if (result <= 0) {
5018 vty_out(vty, "Bad group address %s: errno=%d: %s\n", group_str,
5019 errno, safe_strerror(errno));
5020 return CMD_WARNING_CONFIG_FAILED;
5021 }
5022
5023 /* Source address */
5024 source_str = argv[idx_ipv4_2]->arg;
5025 result = inet_pton(AF_INET, source_str, &source_addr);
5026 if (result <= 0) {
5027 vty_out(vty, "Bad source address %s: errno=%d: %s\n",
5028 source_str, errno, safe_strerror(errno));
5029 return CMD_WARNING_CONFIG_FAILED;
5030 }
5031
5032 result = pim_if_igmp_join_del(ifp, group_addr, source_addr);
5033 if (result) {
5034 vty_out(vty,
5035 "%% Failure leaving IGMP group %s source %s on interface %s: %d\n",
5036 group_str, source_str, ifp->name, result);
5037 return CMD_WARNING_CONFIG_FAILED;
5038 }
5039
5040 return CMD_SUCCESS;
5041 }
5042
5043 /*
5044 CLI reconfiguration affects the interface level (struct pim_interface).
5045 This function propagates the reconfiguration to every active socket
5046 for that interface.
5047 */
5048 static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp)
5049 {
5050 struct interface *ifp;
5051 struct pim_interface *pim_ifp;
5052
5053 zassert(igmp);
5054
5055 /* other querier present? */
5056
5057 if (igmp->t_other_querier_timer)
5058 return;
5059
5060 /* this is the querier */
5061
5062 zassert(igmp->interface);
5063 zassert(igmp->interface->info);
5064
5065 ifp = igmp->interface;
5066 pim_ifp = ifp->info;
5067
5068 if (PIM_DEBUG_IGMP_TRACE) {
5069 char ifaddr_str[INET_ADDRSTRLEN];
5070 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
5071 sizeof(ifaddr_str));
5072 zlog_debug("%s: Querier %s on %s reconfig query_interval=%d",
5073 __PRETTY_FUNCTION__, ifaddr_str, ifp->name,
5074 pim_ifp->igmp_default_query_interval);
5075 }
5076
5077 /*
5078 igmp_startup_mode_on() will reset QQI:
5079
5080 igmp->querier_query_interval = pim_ifp->igmp_default_query_interval;
5081 */
5082 igmp_startup_mode_on(igmp);
5083 }
5084
5085 static void igmp_sock_query_reschedule(struct igmp_sock *igmp)
5086 {
5087 if (igmp->t_igmp_query_timer) {
5088 /* other querier present */
5089 zassert(igmp->t_igmp_query_timer);
5090 zassert(!igmp->t_other_querier_timer);
5091
5092 pim_igmp_general_query_off(igmp);
5093 pim_igmp_general_query_on(igmp);
5094
5095 zassert(igmp->t_igmp_query_timer);
5096 zassert(!igmp->t_other_querier_timer);
5097 } else {
5098 /* this is the querier */
5099
5100 zassert(!igmp->t_igmp_query_timer);
5101 zassert(igmp->t_other_querier_timer);
5102
5103 pim_igmp_other_querier_timer_off(igmp);
5104 pim_igmp_other_querier_timer_on(igmp);
5105
5106 zassert(!igmp->t_igmp_query_timer);
5107 zassert(igmp->t_other_querier_timer);
5108 }
5109 }
5110
5111 static void change_query_interval(struct pim_interface *pim_ifp,
5112 int query_interval)
5113 {
5114 struct listnode *sock_node;
5115 struct igmp_sock *igmp;
5116
5117 pim_ifp->igmp_default_query_interval = query_interval;
5118
5119 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
5120 igmp_sock_query_interval_reconfig(igmp);
5121 igmp_sock_query_reschedule(igmp);
5122 }
5123 }
5124
5125 static void change_query_max_response_time(struct pim_interface *pim_ifp,
5126 int query_max_response_time_dsec)
5127 {
5128 struct listnode *sock_node;
5129 struct igmp_sock *igmp;
5130
5131 pim_ifp->igmp_query_max_response_time_dsec =
5132 query_max_response_time_dsec;
5133
5134 /*
5135 Below we modify socket/group/source timers in order to quickly
5136 reflect the change. Otherwise, those timers would eventually catch
5137 up.
5138 */
5139
5140 /* scan all sockets */
5141 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
5142 struct listnode *grp_node;
5143 struct igmp_group *grp;
5144
5145 /* reschedule socket general query */
5146 igmp_sock_query_reschedule(igmp);
5147
5148 /* scan socket groups */
5149 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node,
5150 grp)) {
5151 struct listnode *src_node;
5152 struct igmp_source *src;
5153
5154 /* reset group timers for groups in EXCLUDE mode */
5155 if (grp->group_filtermode_isexcl) {
5156 igmp_group_reset_gmi(grp);
5157 }
5158
5159 /* scan group sources */
5160 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list,
5161 src_node, src)) {
5162
5163 /* reset source timers for sources with running
5164 * timers */
5165 if (src->t_source_timer) {
5166 igmp_source_reset_gmi(igmp, grp, src);
5167 }
5168 }
5169 }
5170 }
5171 }
5172
5173 #define IGMP_QUERY_INTERVAL_MIN (1)
5174 #define IGMP_QUERY_INTERVAL_MAX (1800)
5175
5176 DEFUN (interface_ip_igmp_query_interval,
5177 interface_ip_igmp_query_interval_cmd,
5178 "ip igmp query-interval (1-1800)",
5179 IP_STR
5180 IFACE_IGMP_STR
5181 IFACE_IGMP_QUERY_INTERVAL_STR
5182 "Query interval in seconds\n")
5183 {
5184 VTY_DECLVAR_CONTEXT(interface, ifp);
5185 struct pim_interface *pim_ifp = ifp->info;
5186 int query_interval;
5187 int query_interval_dsec;
5188 int ret;
5189
5190 if (!pim_ifp) {
5191 ret = pim_cmd_igmp_start(vty, ifp);
5192 if (ret != CMD_SUCCESS)
5193 return ret;
5194 pim_ifp = ifp->info;
5195 }
5196
5197 query_interval = atoi(argv[3]->arg);
5198 query_interval_dsec = 10 * query_interval;
5199
5200 /*
5201 It seems we don't need to check bounds since command.c does it
5202 already, but we verify them anyway for extra safety.
5203 */
5204 if (query_interval < IGMP_QUERY_INTERVAL_MIN) {
5205 vty_out(vty,
5206 "General query interval %d lower than minimum %d\n",
5207 query_interval, IGMP_QUERY_INTERVAL_MIN);
5208 return CMD_WARNING_CONFIG_FAILED;
5209 }
5210 if (query_interval > IGMP_QUERY_INTERVAL_MAX) {
5211 vty_out(vty,
5212 "General query interval %d higher than maximum %d\n",
5213 query_interval, IGMP_QUERY_INTERVAL_MAX);
5214 return CMD_WARNING_CONFIG_FAILED;
5215 }
5216
5217 if (query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) {
5218 vty_out(vty,
5219 "Can't set general query interval %d dsec <= query max response time %d dsec.\n",
5220 query_interval_dsec,
5221 pim_ifp->igmp_query_max_response_time_dsec);
5222 return CMD_WARNING_CONFIG_FAILED;
5223 }
5224
5225 change_query_interval(pim_ifp, query_interval);
5226
5227 return CMD_SUCCESS;
5228 }
5229
5230 DEFUN (interface_no_ip_igmp_query_interval,
5231 interface_no_ip_igmp_query_interval_cmd,
5232 "no ip igmp query-interval",
5233 NO_STR
5234 IP_STR
5235 IFACE_IGMP_STR
5236 IFACE_IGMP_QUERY_INTERVAL_STR)
5237 {
5238 VTY_DECLVAR_CONTEXT(interface, ifp);
5239 struct pim_interface *pim_ifp = ifp->info;
5240 int default_query_interval_dsec;
5241
5242 if (!pim_ifp)
5243 return CMD_SUCCESS;
5244
5245 default_query_interval_dsec = IGMP_GENERAL_QUERY_INTERVAL * 10;
5246
5247 if (default_query_interval_dsec
5248 <= pim_ifp->igmp_query_max_response_time_dsec) {
5249 vty_out(vty,
5250 "Can't set default general query interval %d dsec <= query max response time %d dsec.\n",
5251 default_query_interval_dsec,
5252 pim_ifp->igmp_query_max_response_time_dsec);
5253 return CMD_WARNING_CONFIG_FAILED;
5254 }
5255
5256 change_query_interval(pim_ifp, IGMP_GENERAL_QUERY_INTERVAL);
5257
5258 return CMD_SUCCESS;
5259 }
5260
5261 DEFUN (interface_ip_igmp_version,
5262 interface_ip_igmp_version_cmd,
5263 "ip igmp version (2-3)",
5264 IP_STR
5265 IFACE_IGMP_STR
5266 "IGMP version\n"
5267 "IGMP version number\n")
5268 {
5269 VTY_DECLVAR_CONTEXT(interface, ifp);
5270 struct pim_interface *pim_ifp = ifp->info;
5271 int igmp_version, old_version = 0;
5272 int ret;
5273
5274 if (!pim_ifp) {
5275 ret = pim_cmd_igmp_start(vty, ifp);
5276 if (ret != CMD_SUCCESS)
5277 return ret;
5278 pim_ifp = ifp->info;
5279 }
5280
5281 igmp_version = atoi(argv[3]->arg);
5282 old_version = pim_ifp->igmp_version;
5283 pim_ifp->igmp_version = igmp_version;
5284
5285 // Check if IGMP is Enabled otherwise, enable on interface
5286 if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
5287 PIM_IF_DO_IGMP(pim_ifp->options);
5288 pim_if_addr_add_all(ifp);
5289 pim_if_membership_refresh(ifp);
5290 old_version = igmp_version; // avoid refreshing membership
5291 // again.
5292 }
5293 /* Current and new version is different refresh existing
5294 membership. Going from 3 -> 2 or 2 -> 3. */
5295 if (old_version != igmp_version)
5296 pim_if_membership_refresh(ifp);
5297
5298 return CMD_SUCCESS;
5299 }
5300
5301 DEFUN (interface_no_ip_igmp_version,
5302 interface_no_ip_igmp_version_cmd,
5303 "no ip igmp version (2-3)",
5304 NO_STR
5305 IP_STR
5306 IFACE_IGMP_STR
5307 "IGMP version\n"
5308 "IGMP version number\n")
5309 {
5310 VTY_DECLVAR_CONTEXT(interface, ifp);
5311 struct pim_interface *pim_ifp = ifp->info;
5312
5313 if (!pim_ifp)
5314 return CMD_SUCCESS;
5315
5316 pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
5317
5318 return CMD_SUCCESS;
5319 }
5320
5321 #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10)
5322 #define IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC (250)
5323
5324 DEFUN (interface_ip_igmp_query_max_response_time,
5325 interface_ip_igmp_query_max_response_time_cmd,
5326 "ip igmp query-max-response-time (10-250)",
5327 IP_STR
5328 IFACE_IGMP_STR
5329 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
5330 "Query response value in deci-seconds\n")
5331 {
5332 VTY_DECLVAR_CONTEXT(interface, ifp);
5333 struct pim_interface *pim_ifp = ifp->info;
5334 int query_max_response_time;
5335 int ret;
5336
5337 if (!pim_ifp) {
5338 ret = pim_cmd_igmp_start(vty, ifp);
5339 if (ret != CMD_SUCCESS)
5340 return ret;
5341 pim_ifp = ifp->info;
5342 }
5343
5344 query_max_response_time = atoi(argv[3]->arg);
5345
5346 if (query_max_response_time
5347 >= pim_ifp->igmp_default_query_interval * 10) {
5348 vty_out(vty,
5349 "Can't set query max response time %d sec >= general query interval %d sec\n",
5350 query_max_response_time,
5351 pim_ifp->igmp_default_query_interval);
5352 return CMD_WARNING_CONFIG_FAILED;
5353 }
5354
5355 change_query_max_response_time(pim_ifp, query_max_response_time);
5356
5357 return CMD_SUCCESS;
5358 }
5359
5360 DEFUN (interface_no_ip_igmp_query_max_response_time,
5361 interface_no_ip_igmp_query_max_response_time_cmd,
5362 "no ip igmp query-max-response-time (10-250)",
5363 NO_STR
5364 IP_STR
5365 IFACE_IGMP_STR
5366 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
5367 "Time for response in deci-seconds\n")
5368 {
5369 VTY_DECLVAR_CONTEXT(interface, ifp);
5370 struct pim_interface *pim_ifp = ifp->info;
5371
5372 if (!pim_ifp)
5373 return CMD_SUCCESS;
5374
5375 change_query_max_response_time(pim_ifp,
5376 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
5377
5378 return CMD_SUCCESS;
5379 }
5380
5381 #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10)
5382 #define IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC (250)
5383
5384 DEFUN_HIDDEN (interface_ip_igmp_query_max_response_time_dsec,
5385 interface_ip_igmp_query_max_response_time_dsec_cmd,
5386 "ip igmp query-max-response-time-dsec (10-250)",
5387 IP_STR
5388 IFACE_IGMP_STR
5389 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR
5390 "Query response value in deciseconds\n")
5391 {
5392 VTY_DECLVAR_CONTEXT(interface, ifp);
5393 struct pim_interface *pim_ifp = ifp->info;
5394 int query_max_response_time_dsec;
5395 int default_query_interval_dsec;
5396 int ret;
5397
5398 if (!pim_ifp) {
5399 ret = pim_cmd_igmp_start(vty, ifp);
5400 if (ret != CMD_SUCCESS)
5401 return ret;
5402 pim_ifp = ifp->info;
5403 }
5404
5405 query_max_response_time_dsec = atoi(argv[4]->arg);
5406
5407 default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
5408
5409 if (query_max_response_time_dsec >= default_query_interval_dsec) {
5410 vty_out(vty,
5411 "Can't set query max response time %d dsec >= general query interval %d dsec\n",
5412 query_max_response_time_dsec,
5413 default_query_interval_dsec);
5414 return CMD_WARNING_CONFIG_FAILED;
5415 }
5416
5417 change_query_max_response_time(pim_ifp, query_max_response_time_dsec);
5418
5419 return CMD_SUCCESS;
5420 }
5421
5422 DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec,
5423 interface_no_ip_igmp_query_max_response_time_dsec_cmd,
5424 "no ip igmp query-max-response-time-dsec",
5425 NO_STR
5426 IP_STR
5427 IFACE_IGMP_STR
5428 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR)
5429 {
5430 VTY_DECLVAR_CONTEXT(interface, ifp);
5431 struct pim_interface *pim_ifp = ifp->info;
5432
5433 if (!pim_ifp)
5434 return CMD_SUCCESS;
5435
5436 change_query_max_response_time(pim_ifp,
5437 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
5438
5439 return CMD_SUCCESS;
5440 }
5441
5442 DEFUN (interface_ip_pim_drprio,
5443 interface_ip_pim_drprio_cmd,
5444 "ip pim drpriority (1-4294967295)",
5445 IP_STR
5446 PIM_STR
5447 "Set the Designated Router Election Priority\n"
5448 "Value of the new DR Priority\n")
5449 {
5450 VTY_DECLVAR_CONTEXT(interface, ifp);
5451 int idx_number = 3;
5452 struct pim_interface *pim_ifp = ifp->info;
5453 uint32_t old_dr_prio;
5454
5455 if (!pim_ifp) {
5456 vty_out(vty, "Please enable PIM on interface, first\n");
5457 return CMD_WARNING_CONFIG_FAILED;
5458 }
5459
5460 old_dr_prio = pim_ifp->pim_dr_priority;
5461
5462 pim_ifp->pim_dr_priority = strtol(argv[idx_number]->arg, NULL, 10);
5463
5464 if (old_dr_prio != pim_ifp->pim_dr_priority) {
5465 if (pim_if_dr_election(ifp))
5466 pim_hello_restart_now(ifp);
5467 }
5468
5469 return CMD_SUCCESS;
5470 }
5471
5472 DEFUN (interface_no_ip_pim_drprio,
5473 interface_no_ip_pim_drprio_cmd,
5474 "no ip pim drpriority [(1-4294967295)]",
5475 NO_STR
5476 IP_STR
5477 PIM_STR
5478 "Revert the Designated Router Priority to default\n"
5479 "Old Value of the Priority\n")
5480 {
5481 VTY_DECLVAR_CONTEXT(interface, ifp);
5482 struct pim_interface *pim_ifp = ifp->info;
5483
5484 if (!pim_ifp) {
5485 vty_out(vty, "Pim not enabled on this interface\n");
5486 return CMD_WARNING_CONFIG_FAILED;
5487 }
5488
5489 if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) {
5490 pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY;
5491 if (pim_if_dr_election(ifp))
5492 pim_hello_restart_now(ifp);
5493 }
5494
5495 return CMD_SUCCESS;
5496 }
5497
5498 static int pim_cmd_interface_add(struct interface *ifp)
5499 {
5500 struct pim_interface *pim_ifp = ifp->info;
5501
5502 if (!pim_ifp) {
5503 pim_ifp = pim_if_new(ifp, 0 /* igmp=false */, 1 /* pim=true */);
5504 if (!pim_ifp) {
5505 return 0;
5506 }
5507 } else {
5508 PIM_IF_DO_PIM(pim_ifp->options);
5509 }
5510
5511 pim_if_addr_add_all(ifp);
5512 pim_if_membership_refresh(ifp);
5513 return 1;
5514 }
5515
5516 DEFUN_HIDDEN (interface_ip_pim_ssm,
5517 interface_ip_pim_ssm_cmd,
5518 "ip pim ssm",
5519 IP_STR
5520 PIM_STR
5521 IFACE_PIM_STR)
5522 {
5523 VTY_DECLVAR_CONTEXT(interface, ifp);
5524
5525 if (!pim_cmd_interface_add(ifp)) {
5526 vty_out(vty, "Could not enable PIM SM on interface\n");
5527 return CMD_WARNING_CONFIG_FAILED;
5528 }
5529
5530 vty_out(vty,
5531 "WARN: Enabled PIM SM on interface; configure PIM SSM "
5532 "range if needed\n");
5533 return CMD_SUCCESS;
5534 }
5535
5536 DEFUN (interface_ip_pim_sm,
5537 interface_ip_pim_sm_cmd,
5538 "ip pim sm",
5539 IP_STR
5540 PIM_STR
5541 IFACE_PIM_SM_STR)
5542 {
5543 struct pim_interface *pim_ifp;
5544
5545 VTY_DECLVAR_CONTEXT(interface, ifp);
5546 if (!pim_cmd_interface_add(ifp)) {
5547 vty_out(vty, "Could not enable PIM SM on interface\n");
5548 return CMD_WARNING_CONFIG_FAILED;
5549 }
5550
5551 pim_ifp = ifp->info;
5552
5553 pim_if_create_pimreg(pim_ifp->pim);
5554
5555 return CMD_SUCCESS;
5556 }
5557
5558 static int pim_cmd_interface_delete(struct interface *ifp)
5559 {
5560 struct pim_interface *pim_ifp = ifp->info;
5561
5562 if (!pim_ifp)
5563 return 1;
5564
5565 PIM_IF_DONT_PIM(pim_ifp->options);
5566
5567 pim_if_membership_clear(ifp);
5568
5569 /*
5570 pim_sock_delete() removes all neighbors from
5571 pim_ifp->pim_neighbor_list.
5572 */
5573 pim_sock_delete(ifp, "pim unconfigured on interface");
5574
5575 if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
5576 pim_if_addr_del_all(ifp);
5577 pim_if_delete(ifp);
5578 }
5579
5580 return 1;
5581 }
5582
5583 DEFUN_HIDDEN (interface_no_ip_pim_ssm,
5584 interface_no_ip_pim_ssm_cmd,
5585 "no ip pim ssm",
5586 NO_STR
5587 IP_STR
5588 PIM_STR
5589 IFACE_PIM_STR)
5590 {
5591 VTY_DECLVAR_CONTEXT(interface, ifp);
5592 if (!pim_cmd_interface_delete(ifp)) {
5593 vty_out(vty, "Unable to delete interface information\n");
5594 return CMD_WARNING_CONFIG_FAILED;
5595 }
5596
5597 return CMD_SUCCESS;
5598 }
5599
5600 DEFUN (interface_no_ip_pim_sm,
5601 interface_no_ip_pim_sm_cmd,
5602 "no ip pim sm",
5603 NO_STR
5604 IP_STR
5605 PIM_STR
5606 IFACE_PIM_SM_STR)
5607 {
5608 VTY_DECLVAR_CONTEXT(interface, ifp);
5609 if (!pim_cmd_interface_delete(ifp)) {
5610 vty_out(vty, "Unable to delete interface information\n");
5611 return CMD_WARNING_CONFIG_FAILED;
5612 }
5613
5614 return CMD_SUCCESS;
5615 }
5616
5617 DEFUN (interface_ip_mroute,
5618 interface_ip_mroute_cmd,
5619 "ip mroute INTERFACE A.B.C.D",
5620 IP_STR
5621 "Add multicast route\n"
5622 "Outgoing interface name\n"
5623 "Group address\n")
5624 {
5625 VTY_DECLVAR_CONTEXT(interface, iif);
5626 struct pim_interface *pim_ifp;
5627 struct pim_instance *pim;
5628 int idx_interface = 2;
5629 int idx_ipv4 = 3;
5630 struct interface *oif;
5631 const char *oifname;
5632 const char *grp_str;
5633 struct in_addr grp_addr;
5634 struct in_addr src_addr;
5635 int result;
5636
5637 pim_ifp = iif->info;
5638 pim = pim_ifp->pim;
5639
5640 oifname = argv[idx_interface]->arg;
5641 oif = if_lookup_by_name(oifname, pim->vrf_id);
5642 if (!oif) {
5643 vty_out(vty, "No such interface name %s\n", oifname);
5644 return CMD_WARNING;
5645 }
5646
5647 grp_str = argv[idx_ipv4]->arg;
5648 result = inet_pton(AF_INET, grp_str, &grp_addr);
5649 if (result <= 0) {
5650 vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
5651 errno, safe_strerror(errno));
5652 return CMD_WARNING;
5653 }
5654
5655 src_addr.s_addr = INADDR_ANY;
5656
5657 if (pim_static_add(pim, iif, oif, grp_addr, src_addr)) {
5658 vty_out(vty, "Failed to add route\n");
5659 return CMD_WARNING;
5660 }
5661
5662 return CMD_SUCCESS;
5663 }
5664
5665 DEFUN (interface_ip_mroute_source,
5666 interface_ip_mroute_source_cmd,
5667 "ip mroute INTERFACE A.B.C.D A.B.C.D",
5668 IP_STR
5669 "Add multicast route\n"
5670 "Outgoing interface name\n"
5671 "Group address\n"
5672 "Source address\n")
5673 {
5674 VTY_DECLVAR_CONTEXT(interface, iif);
5675 struct pim_interface *pim_ifp;
5676 struct pim_instance *pim;
5677 int idx_interface = 2;
5678 int idx_ipv4 = 3;
5679 int idx_ipv4_2 = 4;
5680 struct interface *oif;
5681 const char *oifname;
5682 const char *grp_str;
5683 struct in_addr grp_addr;
5684 const char *src_str;
5685 struct in_addr src_addr;
5686 int result;
5687
5688 pim_ifp = iif->info;
5689 pim = pim_ifp->pim;
5690
5691 oifname = argv[idx_interface]->arg;
5692 oif = if_lookup_by_name(oifname, pim->vrf_id);
5693 if (!oif) {
5694 vty_out(vty, "No such interface name %s\n", oifname);
5695 return CMD_WARNING;
5696 }
5697
5698 grp_str = argv[idx_ipv4]->arg;
5699 result = inet_pton(AF_INET, grp_str, &grp_addr);
5700 if (result <= 0) {
5701 vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
5702 errno, safe_strerror(errno));
5703 return CMD_WARNING;
5704 }
5705
5706 src_str = argv[idx_ipv4_2]->arg;
5707 result = inet_pton(AF_INET, src_str, &src_addr);
5708 if (result <= 0) {
5709 vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str,
5710 errno, safe_strerror(errno));
5711 return CMD_WARNING;
5712 }
5713
5714 if (pim_static_add(pim, iif, oif, grp_addr, src_addr)) {
5715 vty_out(vty, "Failed to add route\n");
5716 return CMD_WARNING;
5717 }
5718
5719 return CMD_SUCCESS;
5720 }
5721
5722 DEFUN (interface_no_ip_mroute,
5723 interface_no_ip_mroute_cmd,
5724 "no ip mroute INTERFACE A.B.C.D",
5725 NO_STR
5726 IP_STR
5727 "Add multicast route\n"
5728 "Outgoing interface name\n"
5729 "Group Address\n")
5730 {
5731 VTY_DECLVAR_CONTEXT(interface, iif);
5732 struct pim_interface *pim_ifp;
5733 struct pim_instance *pim;
5734 int idx_interface = 3;
5735 int idx_ipv4 = 4;
5736 struct interface *oif;
5737 const char *oifname;
5738 const char *grp_str;
5739 struct in_addr grp_addr;
5740 struct in_addr src_addr;
5741 int result;
5742
5743 pim_ifp = iif->info;
5744 pim = pim_ifp->pim;
5745
5746 oifname = argv[idx_interface]->arg;
5747 oif = if_lookup_by_name(oifname, pim->vrf_id);
5748 if (!oif) {
5749 vty_out(vty, "No such interface name %s\n", oifname);
5750 return CMD_WARNING;
5751 }
5752
5753 grp_str = argv[idx_ipv4]->arg;
5754 result = inet_pton(AF_INET, grp_str, &grp_addr);
5755 if (result <= 0) {
5756 vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
5757 errno, safe_strerror(errno));
5758 return CMD_WARNING;
5759 }
5760
5761 src_addr.s_addr = INADDR_ANY;
5762
5763 if (pim_static_del(pim, iif, oif, grp_addr, src_addr)) {
5764 vty_out(vty, "Failed to remove route\n");
5765 return CMD_WARNING;
5766 }
5767
5768 return CMD_SUCCESS;
5769 }
5770
5771 DEFUN (interface_no_ip_mroute_source,
5772 interface_no_ip_mroute_source_cmd,
5773 "no ip mroute INTERFACE A.B.C.D A.B.C.D",
5774 NO_STR
5775 IP_STR
5776 "Add multicast route\n"
5777 "Outgoing interface name\n"
5778 "Group Address\n"
5779 "Source Address\n")
5780 {
5781 VTY_DECLVAR_CONTEXT(interface, iif);
5782 struct pim_interface *pim_ifp;
5783 struct pim_instance *pim;
5784 int idx_interface = 3;
5785 int idx_ipv4 = 4;
5786 int idx_ipv4_2 = 5;
5787 struct interface *oif;
5788 const char *oifname;
5789 const char *grp_str;
5790 struct in_addr grp_addr;
5791 const char *src_str;
5792 struct in_addr src_addr;
5793 int result;
5794
5795 pim_ifp = iif->info;
5796 pim = pim_ifp->pim;
5797
5798 oifname = argv[idx_interface]->arg;
5799 oif = if_lookup_by_name(oifname, pim->vrf_id);
5800 if (!oif) {
5801 vty_out(vty, "No such interface name %s\n", oifname);
5802 return CMD_WARNING;
5803 }
5804
5805 grp_str = argv[idx_ipv4]->arg;
5806 result = inet_pton(AF_INET, grp_str, &grp_addr);
5807 if (result <= 0) {
5808 vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
5809 errno, safe_strerror(errno));
5810 return CMD_WARNING;
5811 }
5812
5813 src_str = argv[idx_ipv4_2]->arg;
5814 result = inet_pton(AF_INET, src_str, &src_addr);
5815 if (result <= 0) {
5816 vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str,
5817 errno, safe_strerror(errno));
5818 return CMD_WARNING;
5819 }
5820
5821 if (pim_static_del(pim, iif, oif, grp_addr, src_addr)) {
5822 vty_out(vty, "Failed to remove route\n");
5823 return CMD_WARNING;
5824 }
5825
5826 return CMD_SUCCESS;
5827 }
5828
5829 DEFUN (interface_ip_pim_hello,
5830 interface_ip_pim_hello_cmd,
5831 "ip pim hello (1-180) [(1-180)]",
5832 IP_STR
5833 PIM_STR
5834 IFACE_PIM_HELLO_STR
5835 IFACE_PIM_HELLO_TIME_STR
5836 IFACE_PIM_HELLO_HOLD_STR)
5837 {
5838 VTY_DECLVAR_CONTEXT(interface, ifp);
5839 int idx_time = 3;
5840 int idx_hold = 4;
5841 struct pim_interface *pim_ifp = ifp->info;
5842
5843 if (!pim_ifp) {
5844 if (!pim_cmd_interface_add(ifp)) {
5845 vty_out(vty, "Could not enable PIM SM on interface\n");
5846 return CMD_WARNING_CONFIG_FAILED;
5847 }
5848 }
5849
5850 pim_ifp = ifp->info;
5851 pim_ifp->pim_hello_period = strtol(argv[idx_time]->arg, NULL, 10);
5852
5853 if (argc == idx_hold + 1)
5854 pim_ifp->pim_default_holdtime =
5855 strtol(argv[idx_hold]->arg, NULL, 10);
5856
5857 return CMD_SUCCESS;
5858 }
5859
5860
5861 DEFUN (interface_no_ip_pim_hello,
5862 interface_no_ip_pim_hello_cmd,
5863 "no ip pim hello [(1-180) (1-180)]",
5864 NO_STR
5865 IP_STR
5866 PIM_STR
5867 IFACE_PIM_HELLO_STR
5868 IFACE_PIM_HELLO_TIME_STR
5869 IFACE_PIM_HELLO_HOLD_STR)
5870 {
5871 VTY_DECLVAR_CONTEXT(interface, ifp);
5872 struct pim_interface *pim_ifp = ifp->info;
5873
5874 if (!pim_ifp) {
5875 vty_out(vty, "Pim not enabled on this interface\n");
5876 return CMD_WARNING_CONFIG_FAILED;
5877 }
5878
5879 pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD;
5880 pim_ifp->pim_default_holdtime = -1;
5881
5882 return CMD_SUCCESS;
5883 }
5884
5885 DEFUN (debug_igmp,
5886 debug_igmp_cmd,
5887 "debug igmp",
5888 DEBUG_STR
5889 DEBUG_IGMP_STR)
5890 {
5891 PIM_DO_DEBUG_IGMP_EVENTS;
5892 PIM_DO_DEBUG_IGMP_PACKETS;
5893 PIM_DO_DEBUG_IGMP_TRACE;
5894 return CMD_SUCCESS;
5895 }
5896
5897 DEFUN (no_debug_igmp,
5898 no_debug_igmp_cmd,
5899 "no debug igmp",
5900 NO_STR
5901 DEBUG_STR
5902 DEBUG_IGMP_STR)
5903 {
5904 PIM_DONT_DEBUG_IGMP_EVENTS;
5905 PIM_DONT_DEBUG_IGMP_PACKETS;
5906 PIM_DONT_DEBUG_IGMP_TRACE;
5907 return CMD_SUCCESS;
5908 }
5909
5910
5911 DEFUN (debug_igmp_events,
5912 debug_igmp_events_cmd,
5913 "debug igmp events",
5914 DEBUG_STR
5915 DEBUG_IGMP_STR
5916 DEBUG_IGMP_EVENTS_STR)
5917 {
5918 PIM_DO_DEBUG_IGMP_EVENTS;
5919 return CMD_SUCCESS;
5920 }
5921
5922 DEFUN (no_debug_igmp_events,
5923 no_debug_igmp_events_cmd,
5924 "no debug igmp events",
5925 NO_STR
5926 DEBUG_STR
5927 DEBUG_IGMP_STR
5928 DEBUG_IGMP_EVENTS_STR)
5929 {
5930 PIM_DONT_DEBUG_IGMP_EVENTS;
5931 return CMD_SUCCESS;
5932 }
5933
5934
5935 DEFUN (debug_igmp_packets,
5936 debug_igmp_packets_cmd,
5937 "debug igmp packets",
5938 DEBUG_STR
5939 DEBUG_IGMP_STR
5940 DEBUG_IGMP_PACKETS_STR)
5941 {
5942 PIM_DO_DEBUG_IGMP_PACKETS;
5943 return CMD_SUCCESS;
5944 }
5945
5946 DEFUN (no_debug_igmp_packets,
5947 no_debug_igmp_packets_cmd,
5948 "no debug igmp packets",
5949 NO_STR
5950 DEBUG_STR
5951 DEBUG_IGMP_STR
5952 DEBUG_IGMP_PACKETS_STR)
5953 {
5954 PIM_DONT_DEBUG_IGMP_PACKETS;
5955 return CMD_SUCCESS;
5956 }
5957
5958
5959 DEFUN (debug_igmp_trace,
5960 debug_igmp_trace_cmd,
5961 "debug igmp trace",
5962 DEBUG_STR
5963 DEBUG_IGMP_STR
5964 DEBUG_IGMP_TRACE_STR)
5965 {
5966 PIM_DO_DEBUG_IGMP_TRACE;
5967 return CMD_SUCCESS;
5968 }
5969
5970 DEFUN (no_debug_igmp_trace,
5971 no_debug_igmp_trace_cmd,
5972 "no debug igmp trace",
5973 NO_STR
5974 DEBUG_STR
5975 DEBUG_IGMP_STR
5976 DEBUG_IGMP_TRACE_STR)
5977 {
5978 PIM_DONT_DEBUG_IGMP_TRACE;
5979 return CMD_SUCCESS;
5980 }
5981
5982
5983 DEFUN (debug_mroute,
5984 debug_mroute_cmd,
5985 "debug mroute",
5986 DEBUG_STR
5987 DEBUG_MROUTE_STR)
5988 {
5989 PIM_DO_DEBUG_MROUTE;
5990 return CMD_SUCCESS;
5991 }
5992
5993 DEFUN (debug_mroute_detail,
5994 debug_mroute_detail_cmd,
5995 "debug mroute detail",
5996 DEBUG_STR
5997 DEBUG_MROUTE_STR
5998 "detailed\n")
5999 {
6000 PIM_DO_DEBUG_MROUTE_DETAIL;
6001 return CMD_SUCCESS;
6002 }
6003
6004 DEFUN (no_debug_mroute,
6005 no_debug_mroute_cmd,
6006 "no debug mroute",
6007 NO_STR
6008 DEBUG_STR
6009 DEBUG_MROUTE_STR)
6010 {
6011 PIM_DONT_DEBUG_MROUTE;
6012 return CMD_SUCCESS;
6013 }
6014
6015 DEFUN (no_debug_mroute_detail,
6016 no_debug_mroute_detail_cmd,
6017 "no debug mroute detail",
6018 NO_STR
6019 DEBUG_STR
6020 DEBUG_MROUTE_STR
6021 "detailed\n")
6022 {
6023 PIM_DONT_DEBUG_MROUTE_DETAIL;
6024 return CMD_SUCCESS;
6025 }
6026
6027 DEFUN (debug_static,
6028 debug_static_cmd,
6029 "debug static",
6030 DEBUG_STR
6031 DEBUG_STATIC_STR)
6032 {
6033 PIM_DO_DEBUG_STATIC;
6034 return CMD_SUCCESS;
6035 }
6036
6037 DEFUN (no_debug_static,
6038 no_debug_static_cmd,
6039 "no debug static",
6040 NO_STR
6041 DEBUG_STR
6042 DEBUG_STATIC_STR)
6043 {
6044 PIM_DONT_DEBUG_STATIC;
6045 return CMD_SUCCESS;
6046 }
6047
6048
6049 DEFUN (debug_pim,
6050 debug_pim_cmd,
6051 "debug pim",
6052 DEBUG_STR
6053 DEBUG_PIM_STR)
6054 {
6055 PIM_DO_DEBUG_PIM_EVENTS;
6056 PIM_DO_DEBUG_PIM_PACKETS;
6057 PIM_DO_DEBUG_PIM_TRACE;
6058 PIM_DO_DEBUG_MSDP_EVENTS;
6059 PIM_DO_DEBUG_MSDP_PACKETS;
6060 return CMD_SUCCESS;
6061 }
6062
6063 DEFUN (no_debug_pim,
6064 no_debug_pim_cmd,
6065 "no debug pim",
6066 NO_STR
6067 DEBUG_STR
6068 DEBUG_PIM_STR)
6069 {
6070 PIM_DONT_DEBUG_PIM_EVENTS;
6071 PIM_DONT_DEBUG_PIM_PACKETS;
6072 PIM_DONT_DEBUG_PIM_TRACE;
6073 PIM_DONT_DEBUG_MSDP_EVENTS;
6074 PIM_DONT_DEBUG_MSDP_PACKETS;
6075
6076 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
6077 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
6078
6079 return CMD_SUCCESS;
6080 }
6081
6082
6083 DEFUN (debug_pim_events,
6084 debug_pim_events_cmd,
6085 "debug pim events",
6086 DEBUG_STR
6087 DEBUG_PIM_STR
6088 DEBUG_PIM_EVENTS_STR)
6089 {
6090 PIM_DO_DEBUG_PIM_EVENTS;
6091 return CMD_SUCCESS;
6092 }
6093
6094 DEFUN (no_debug_pim_events,
6095 no_debug_pim_events_cmd,
6096 "no debug pim events",
6097 NO_STR
6098 DEBUG_STR
6099 DEBUG_PIM_STR
6100 DEBUG_PIM_EVENTS_STR)
6101 {
6102 PIM_DONT_DEBUG_PIM_EVENTS;
6103 return CMD_SUCCESS;
6104 }
6105
6106 DEFUN (debug_pim_packets,
6107 debug_pim_packets_cmd,
6108 "debug pim packets [<hello|joins|register>]",
6109 DEBUG_STR
6110 DEBUG_PIM_STR
6111 DEBUG_PIM_PACKETS_STR
6112 DEBUG_PIM_HELLO_PACKETS_STR
6113 DEBUG_PIM_J_P_PACKETS_STR
6114 DEBUG_PIM_PIM_REG_PACKETS_STR)
6115 {
6116 int idx = 0;
6117 if (argv_find(argv, argc, "hello", &idx)) {
6118 PIM_DO_DEBUG_PIM_HELLO;
6119 vty_out(vty, "PIM Hello debugging is on\n");
6120 } else if (argv_find(argv, argc, "joins", &idx)) {
6121 PIM_DO_DEBUG_PIM_J_P;
6122 vty_out(vty, "PIM Join/Prune debugging is on\n");
6123 } else if (argv_find(argv, argc, "register", &idx)) {
6124 PIM_DO_DEBUG_PIM_REG;
6125 vty_out(vty, "PIM Register debugging is on\n");
6126 } else {
6127 PIM_DO_DEBUG_PIM_PACKETS;
6128 vty_out(vty, "PIM Packet debugging is on \n");
6129 }
6130 return CMD_SUCCESS;
6131 }
6132
6133 DEFUN (no_debug_pim_packets,
6134 no_debug_pim_packets_cmd,
6135 "no debug pim packets [<hello|joins|register>]",
6136 NO_STR
6137 DEBUG_STR
6138 DEBUG_PIM_STR
6139 DEBUG_PIM_PACKETS_STR
6140 DEBUG_PIM_HELLO_PACKETS_STR
6141 DEBUG_PIM_J_P_PACKETS_STR
6142 DEBUG_PIM_PIM_REG_PACKETS_STR)
6143 {
6144 int idx = 0;
6145 if (argv_find(argv, argc, "hello", &idx)) {
6146 PIM_DONT_DEBUG_PIM_HELLO;
6147 vty_out(vty, "PIM Hello debugging is off \n");
6148 } else if (argv_find(argv, argc, "joins", &idx)) {
6149 PIM_DONT_DEBUG_PIM_J_P;
6150 vty_out(vty, "PIM Join/Prune debugging is off \n");
6151 } else if (argv_find(argv, argc, "register", &idx)) {
6152 PIM_DONT_DEBUG_PIM_REG;
6153 vty_out(vty, "PIM Register debugging is off\n");
6154 } else
6155 PIM_DONT_DEBUG_PIM_PACKETS;
6156
6157 return CMD_SUCCESS;
6158 }
6159
6160
6161 DEFUN (debug_pim_packetdump_send,
6162 debug_pim_packetdump_send_cmd,
6163 "debug pim packet-dump send",
6164 DEBUG_STR
6165 DEBUG_PIM_STR
6166 DEBUG_PIM_PACKETDUMP_STR
6167 DEBUG_PIM_PACKETDUMP_SEND_STR)
6168 {
6169 PIM_DO_DEBUG_PIM_PACKETDUMP_SEND;
6170 return CMD_SUCCESS;
6171 }
6172
6173 DEFUN (no_debug_pim_packetdump_send,
6174 no_debug_pim_packetdump_send_cmd,
6175 "no debug pim packet-dump send",
6176 NO_STR
6177 DEBUG_STR
6178 DEBUG_PIM_STR
6179 DEBUG_PIM_PACKETDUMP_STR
6180 DEBUG_PIM_PACKETDUMP_SEND_STR)
6181 {
6182 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
6183 return CMD_SUCCESS;
6184 }
6185
6186
6187 DEFUN (debug_pim_packetdump_recv,
6188 debug_pim_packetdump_recv_cmd,
6189 "debug pim packet-dump receive",
6190 DEBUG_STR
6191 DEBUG_PIM_STR
6192 DEBUG_PIM_PACKETDUMP_STR
6193 DEBUG_PIM_PACKETDUMP_RECV_STR)
6194 {
6195 PIM_DO_DEBUG_PIM_PACKETDUMP_RECV;
6196 return CMD_SUCCESS;
6197 }
6198
6199 DEFUN (no_debug_pim_packetdump_recv,
6200 no_debug_pim_packetdump_recv_cmd,
6201 "no debug pim packet-dump receive",
6202 NO_STR
6203 DEBUG_STR
6204 DEBUG_PIM_STR
6205 DEBUG_PIM_PACKETDUMP_STR
6206 DEBUG_PIM_PACKETDUMP_RECV_STR)
6207 {
6208 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
6209 return CMD_SUCCESS;
6210 }
6211
6212
6213 DEFUN (debug_pim_trace,
6214 debug_pim_trace_cmd,
6215 "debug pim trace",
6216 DEBUG_STR
6217 DEBUG_PIM_STR
6218 DEBUG_PIM_TRACE_STR)
6219 {
6220 PIM_DO_DEBUG_PIM_TRACE;
6221 return CMD_SUCCESS;
6222 }
6223
6224 DEFUN (no_debug_pim_trace,
6225 no_debug_pim_trace_cmd,
6226 "no debug pim trace",
6227 NO_STR
6228 DEBUG_STR
6229 DEBUG_PIM_STR
6230 DEBUG_PIM_TRACE_STR)
6231 {
6232 PIM_DONT_DEBUG_PIM_TRACE;
6233 return CMD_SUCCESS;
6234 }
6235
6236
6237 DEFUN (debug_ssmpingd,
6238 debug_ssmpingd_cmd,
6239 "debug ssmpingd",
6240 DEBUG_STR
6241 DEBUG_SSMPINGD_STR)
6242 {
6243 PIM_DO_DEBUG_SSMPINGD;
6244 return CMD_SUCCESS;
6245 }
6246
6247 DEFUN (no_debug_ssmpingd,
6248 no_debug_ssmpingd_cmd,
6249 "no debug ssmpingd",
6250 NO_STR
6251 DEBUG_STR
6252 DEBUG_SSMPINGD_STR)
6253 {
6254 PIM_DONT_DEBUG_SSMPINGD;
6255 return CMD_SUCCESS;
6256 }
6257
6258
6259 DEFUN (debug_pim_zebra,
6260 debug_pim_zebra_cmd,
6261 "debug pim zebra",
6262 DEBUG_STR
6263 DEBUG_PIM_STR
6264 DEBUG_PIM_ZEBRA_STR)
6265 {
6266 PIM_DO_DEBUG_ZEBRA;
6267 return CMD_SUCCESS;
6268 }
6269
6270 DEFUN (no_debug_pim_zebra,
6271 no_debug_pim_zebra_cmd,
6272 "no debug pim zebra",
6273 NO_STR
6274 DEBUG_STR
6275 DEBUG_PIM_STR
6276 DEBUG_PIM_ZEBRA_STR)
6277 {
6278 PIM_DONT_DEBUG_ZEBRA;
6279 return CMD_SUCCESS;
6280 }
6281
6282
6283 DEFUN (debug_msdp,
6284 debug_msdp_cmd,
6285 "debug msdp",
6286 DEBUG_STR
6287 DEBUG_MSDP_STR)
6288 {
6289 PIM_DO_DEBUG_MSDP_EVENTS;
6290 PIM_DO_DEBUG_MSDP_PACKETS;
6291 return CMD_SUCCESS;
6292 }
6293
6294 DEFUN (no_debug_msdp,
6295 no_debug_msdp_cmd,
6296 "no debug msdp",
6297 NO_STR
6298 DEBUG_STR
6299 DEBUG_MSDP_STR)
6300 {
6301 PIM_DONT_DEBUG_MSDP_EVENTS;
6302 PIM_DONT_DEBUG_MSDP_PACKETS;
6303 return CMD_SUCCESS;
6304 }
6305
6306 ALIAS(no_debug_msdp, undebug_msdp_cmd, "undebug msdp",
6307 UNDEBUG_STR DEBUG_MSDP_STR)
6308
6309 DEFUN (debug_msdp_events,
6310 debug_msdp_events_cmd,
6311 "debug msdp events",
6312 DEBUG_STR
6313 DEBUG_MSDP_STR
6314 DEBUG_MSDP_EVENTS_STR)
6315 {
6316 PIM_DO_DEBUG_MSDP_EVENTS;
6317 return CMD_SUCCESS;
6318 }
6319
6320 DEFUN (no_debug_msdp_events,
6321 no_debug_msdp_events_cmd,
6322 "no debug msdp events",
6323 NO_STR
6324 DEBUG_STR
6325 DEBUG_MSDP_STR
6326 DEBUG_MSDP_EVENTS_STR)
6327 {
6328 PIM_DONT_DEBUG_MSDP_EVENTS;
6329 return CMD_SUCCESS;
6330 }
6331
6332 ALIAS(no_debug_msdp_events, undebug_msdp_events_cmd, "undebug msdp events",
6333 UNDEBUG_STR DEBUG_MSDP_STR DEBUG_MSDP_EVENTS_STR)
6334
6335 DEFUN (debug_msdp_packets,
6336 debug_msdp_packets_cmd,
6337 "debug msdp packets",
6338 DEBUG_STR
6339 DEBUG_MSDP_STR
6340 DEBUG_MSDP_PACKETS_STR)
6341 {
6342 PIM_DO_DEBUG_MSDP_PACKETS;
6343 return CMD_SUCCESS;
6344 }
6345
6346 DEFUN (no_debug_msdp_packets,
6347 no_debug_msdp_packets_cmd,
6348 "no debug msdp packets",
6349 NO_STR
6350 DEBUG_STR
6351 DEBUG_MSDP_STR
6352 DEBUG_MSDP_PACKETS_STR)
6353 {
6354 PIM_DONT_DEBUG_MSDP_PACKETS;
6355 return CMD_SUCCESS;
6356 }
6357
6358 ALIAS(no_debug_msdp_packets, undebug_msdp_packets_cmd, "undebug msdp packets",
6359 UNDEBUG_STR DEBUG_MSDP_STR DEBUG_MSDP_PACKETS_STR)
6360
6361 DEFUN (show_debugging_pim,
6362 show_debugging_pim_cmd,
6363 "show debugging pim",
6364 SHOW_STR
6365 DEBUG_STR
6366 PIM_STR)
6367 {
6368 pim_debug_config_write(vty);
6369 return CMD_SUCCESS;
6370 }
6371
6372 static int interface_pim_use_src_cmd_worker(struct vty *vty, const char *source)
6373 {
6374 int result;
6375 struct in_addr source_addr;
6376 VTY_DECLVAR_CONTEXT(interface, ifp);
6377
6378 result = inet_pton(AF_INET, source, &source_addr);
6379 if (result <= 0) {
6380 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", source,
6381 errno, safe_strerror(errno));
6382 return CMD_WARNING_CONFIG_FAILED;
6383 }
6384
6385 result = pim_update_source_set(ifp, source_addr);
6386 switch (result) {
6387 case PIM_SUCCESS:
6388 break;
6389 case PIM_IFACE_NOT_FOUND:
6390 vty_out(vty, "Pim not enabled on this interface\n");
6391 break;
6392 case PIM_UPDATE_SOURCE_DUP:
6393 vty_out(vty, "%% Source already set to %s\n", source);
6394 break;
6395 default:
6396 vty_out(vty, "%% Source set failed\n");
6397 }
6398
6399 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
6400 }
6401
6402 DEFUN (interface_pim_use_source,
6403 interface_pim_use_source_cmd,
6404 "ip pim use-source A.B.C.D",
6405 IP_STR
6406 "pim multicast routing\n"
6407 "Configure primary IP address\n"
6408 "source ip address\n")
6409 {
6410 return interface_pim_use_src_cmd_worker(vty, argv[3]->arg);
6411 }
6412
6413 DEFUN (interface_no_pim_use_source,
6414 interface_no_pim_use_source_cmd,
6415 "no ip pim use-source",
6416 NO_STR
6417 IP_STR
6418 "pim multicast routing\n"
6419 "Delete source IP address\n")
6420 {
6421 return interface_pim_use_src_cmd_worker(vty, "0.0.0.0");
6422 }
6423
6424 DEFUN (ip_pim_bfd,
6425 ip_pim_bfd_cmd,
6426 "ip pim bfd",
6427 IP_STR
6428 PIM_STR
6429 "Enables BFD support\n")
6430 {
6431 VTY_DECLVAR_CONTEXT(interface, ifp);
6432 struct pim_interface *pim_ifp = ifp->info;
6433 struct bfd_info *bfd_info = NULL;
6434
6435 if (!pim_ifp)
6436 return CMD_SUCCESS;
6437 bfd_info = pim_ifp->bfd_info;
6438
6439 if (!bfd_info || !CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG))
6440 pim_bfd_if_param_set(ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
6441 BFD_DEF_DETECT_MULT, 1);
6442
6443 return CMD_SUCCESS;
6444 }
6445
6446 DEFUN (no_ip_pim_bfd,
6447 no_ip_pim_bfd_cmd,
6448 "no ip pim bfd",
6449 NO_STR
6450 IP_STR
6451 PIM_STR
6452 "Disables BFD support\n")
6453 {
6454 VTY_DECLVAR_CONTEXT(interface, ifp);
6455 struct pim_interface *pim_ifp = ifp->info;
6456
6457 if (!pim_ifp)
6458 return CMD_SUCCESS;
6459
6460 if (pim_ifp->bfd_info) {
6461 pim_bfd_reg_dereg_all_nbr(ifp, ZEBRA_BFD_DEST_DEREGISTER);
6462 bfd_info_free(&(pim_ifp->bfd_info));
6463 }
6464
6465 return CMD_SUCCESS;
6466 }
6467
6468 DEFUN (ip_pim_bfd_param,
6469 ip_pim_bfd_param_cmd,
6470 "ip pim bfd (2-255) (50-60000) (50-60000)",
6471 IP_STR
6472 PIM_STR
6473 "Enables BFD support\n"
6474 "Detect Multiplier\n"
6475 "Required min receive interval\n"
6476 "Desired min transmit interval\n")
6477 {
6478 VTY_DECLVAR_CONTEXT(interface, ifp);
6479 int idx_number = 3;
6480 int idx_number_2 = 4;
6481 int idx_number_3 = 5;
6482 u_int32_t rx_val;
6483 u_int32_t tx_val;
6484 u_int8_t dm_val;
6485 int ret;
6486
6487
6488 if ((ret = bfd_validate_param(
6489 vty, argv[idx_number]->arg, argv[idx_number_2]->arg,
6490 argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val))
6491 != CMD_SUCCESS)
6492 return ret;
6493
6494 pim_bfd_if_param_set(ifp, rx_val, tx_val, dm_val, 0);
6495
6496 return CMD_SUCCESS;
6497 }
6498
6499 ALIAS(no_ip_pim_bfd, no_ip_pim_bfd_param_cmd,
6500 "no ip pim bfd (2-255) (50-60000) (50-60000)", NO_STR IP_STR PIM_STR
6501 "Enables BFD support\n"
6502 "Detect Multiplier\n"
6503 "Required min receive interval\n"
6504 "Desired min transmit interval\n")
6505
6506 static int ip_msdp_peer_cmd_worker(struct vty *vty, const char *peer,
6507 const char *local)
6508 {
6509 enum pim_msdp_err result;
6510 struct in_addr peer_addr;
6511 struct in_addr local_addr;
6512
6513 result = inet_pton(AF_INET, peer, &peer_addr);
6514 if (result <= 0) {
6515 vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer,
6516 errno, safe_strerror(errno));
6517 return CMD_WARNING_CONFIG_FAILED;
6518 }
6519
6520 result = inet_pton(AF_INET, local, &local_addr);
6521 if (result <= 0) {
6522 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", local,
6523 errno, safe_strerror(errno));
6524 return CMD_WARNING_CONFIG_FAILED;
6525 }
6526
6527 result = pim_msdp_peer_add(peer_addr, local_addr, "default",
6528 NULL /* mp_p */);
6529 switch (result) {
6530 case PIM_MSDP_ERR_NONE:
6531 break;
6532 case PIM_MSDP_ERR_OOM:
6533 vty_out(vty, "%% Out of memory\n");
6534 break;
6535 case PIM_MSDP_ERR_PEER_EXISTS:
6536 vty_out(vty, "%% Peer exists\n");
6537 break;
6538 case PIM_MSDP_ERR_MAX_MESH_GROUPS:
6539 vty_out(vty, "%% Only one mesh-group allowed currently\n");
6540 break;
6541 default:
6542 vty_out(vty, "%% peer add failed\n");
6543 }
6544
6545 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
6546 }
6547
6548 DEFUN_HIDDEN (ip_msdp_peer,
6549 ip_msdp_peer_cmd,
6550 "ip msdp peer A.B.C.D source A.B.C.D",
6551 IP_STR
6552 CFG_MSDP_STR
6553 "Configure MSDP peer\n"
6554 "peer ip address\n"
6555 "Source address for TCP connection\n"
6556 "local ip address\n")
6557 {
6558 return ip_msdp_peer_cmd_worker(vty, argv[3]->arg, argv[5]->arg);
6559 }
6560
6561 static int ip_no_msdp_peer_cmd_worker(struct vty *vty, const char *peer)
6562 {
6563 enum pim_msdp_err result;
6564 struct in_addr peer_addr;
6565
6566 result = inet_pton(AF_INET, peer, &peer_addr);
6567 if (result <= 0) {
6568 vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer,
6569 errno, safe_strerror(errno));
6570 return CMD_WARNING_CONFIG_FAILED;
6571 }
6572
6573 result = pim_msdp_peer_del(peer_addr);
6574 switch (result) {
6575 case PIM_MSDP_ERR_NONE:
6576 break;
6577 case PIM_MSDP_ERR_NO_PEER:
6578 vty_out(vty, "%% Peer does not exist\n");
6579 break;
6580 default:
6581 vty_out(vty, "%% peer del failed\n");
6582 }
6583
6584 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
6585 }
6586
6587 DEFUN_HIDDEN (no_ip_msdp_peer,
6588 no_ip_msdp_peer_cmd,
6589 "no ip msdp peer A.B.C.D",
6590 NO_STR
6591 IP_STR
6592 CFG_MSDP_STR
6593 "Delete MSDP peer\n"
6594 "peer ip address\n")
6595 {
6596 return ip_no_msdp_peer_cmd_worker(vty, argv[4]->arg);
6597 }
6598
6599 static int ip_msdp_mesh_group_member_cmd_worker(struct vty *vty, const char *mg,
6600 const char *mbr)
6601 {
6602 enum pim_msdp_err result;
6603 struct in_addr mbr_ip;
6604
6605 result = inet_pton(AF_INET, mbr, &mbr_ip);
6606 if (result <= 0) {
6607 vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr,
6608 errno, safe_strerror(errno));
6609 return CMD_WARNING_CONFIG_FAILED;
6610 }
6611
6612 result = pim_msdp_mg_mbr_add(mg, mbr_ip);
6613 switch (result) {
6614 case PIM_MSDP_ERR_NONE:
6615 break;
6616 case PIM_MSDP_ERR_OOM:
6617 vty_out(vty, "%% Out of memory\n");
6618 break;
6619 case PIM_MSDP_ERR_MG_MBR_EXISTS:
6620 vty_out(vty, "%% mesh-group member exists\n");
6621 break;
6622 case PIM_MSDP_ERR_MAX_MESH_GROUPS:
6623 vty_out(vty, "%% Only one mesh-group allowed currently\n");
6624 break;
6625 default:
6626 vty_out(vty, "%% member add failed\n");
6627 }
6628
6629 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
6630 }
6631
6632 DEFUN (ip_msdp_mesh_group_member,
6633 ip_msdp_mesh_group_member_cmd,
6634 "ip msdp mesh-group WORD member A.B.C.D",
6635 IP_STR
6636 CFG_MSDP_STR
6637 "Configure MSDP mesh-group\n"
6638 "mesh group name\n"
6639 "mesh group member\n"
6640 "peer ip address\n")
6641 {
6642 return ip_msdp_mesh_group_member_cmd_worker(vty, argv[3]->arg,
6643 argv[5]->arg);
6644 }
6645
6646 static int ip_no_msdp_mesh_group_member_cmd_worker(struct vty *vty,
6647 const char *mg,
6648 const char *mbr)
6649 {
6650 enum pim_msdp_err result;
6651 struct in_addr mbr_ip;
6652
6653 result = inet_pton(AF_INET, mbr, &mbr_ip);
6654 if (result <= 0) {
6655 vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr,
6656 errno, safe_strerror(errno));
6657 return CMD_WARNING_CONFIG_FAILED;
6658 }
6659
6660 result = pim_msdp_mg_mbr_del(mg, mbr_ip);
6661 switch (result) {
6662 case PIM_MSDP_ERR_NONE:
6663 break;
6664 case PIM_MSDP_ERR_NO_MG:
6665 vty_out(vty, "%% mesh-group does not exist\n");
6666 break;
6667 case PIM_MSDP_ERR_NO_MG_MBR:
6668 vty_out(vty, "%% mesh-group member does not exist\n");
6669 break;
6670 default:
6671 vty_out(vty, "%% mesh-group member del failed\n");
6672 }
6673
6674 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
6675 }
6676 DEFUN (no_ip_msdp_mesh_group_member,
6677 no_ip_msdp_mesh_group_member_cmd,
6678 "no ip msdp mesh-group WORD member A.B.C.D",
6679 NO_STR
6680 IP_STR
6681 CFG_MSDP_STR
6682 "Delete MSDP mesh-group member\n"
6683 "mesh group name\n"
6684 "mesh group member\n"
6685 "peer ip address\n")
6686 {
6687 return ip_no_msdp_mesh_group_member_cmd_worker(vty, argv[4]->arg,
6688 argv[6]->arg);
6689 }
6690
6691 static int ip_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg,
6692 const char *src)
6693 {
6694 enum pim_msdp_err result;
6695 struct in_addr src_ip;
6696
6697 result = inet_pton(AF_INET, src, &src_ip);
6698 if (result <= 0) {
6699 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", src,
6700 errno, safe_strerror(errno));
6701 return CMD_WARNING_CONFIG_FAILED;
6702 }
6703
6704 result = pim_msdp_mg_src_add(mg, src_ip);
6705 switch (result) {
6706 case PIM_MSDP_ERR_NONE:
6707 break;
6708 case PIM_MSDP_ERR_OOM:
6709 vty_out(vty, "%% Out of memory\n");
6710 break;
6711 case PIM_MSDP_ERR_MAX_MESH_GROUPS:
6712 vty_out(vty, "%% Only one mesh-group allowed currently\n");
6713 break;
6714 default:
6715 vty_out(vty, "%% source add failed\n");
6716 }
6717
6718 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
6719 }
6720
6721
6722 DEFUN (ip_msdp_mesh_group_source,
6723 ip_msdp_mesh_group_source_cmd,
6724 "ip msdp mesh-group WORD source A.B.C.D",
6725 IP_STR
6726 CFG_MSDP_STR
6727 "Configure MSDP mesh-group\n"
6728 "mesh group name\n"
6729 "mesh group local address\n"
6730 "source ip address for the TCP connection\n")
6731 {
6732 return ip_msdp_mesh_group_source_cmd_worker(vty, argv[3]->arg,
6733 argv[5]->arg);
6734 }
6735
6736 static int ip_no_msdp_mesh_group_source_cmd_worker(struct vty *vty,
6737 const char *mg)
6738 {
6739 enum pim_msdp_err result;
6740
6741 result = pim_msdp_mg_src_del(mg);
6742 switch (result) {
6743 case PIM_MSDP_ERR_NONE:
6744 break;
6745 case PIM_MSDP_ERR_NO_MG:
6746 vty_out(vty, "%% mesh-group does not exist\n");
6747 break;
6748 default:
6749 vty_out(vty, "%% mesh-group source del failed\n");
6750 }
6751
6752 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
6753 }
6754
6755 static int ip_no_msdp_mesh_group_cmd_worker(struct vty *vty, const char *mg)
6756 {
6757 enum pim_msdp_err result;
6758
6759 result = pim_msdp_mg_del(mg);
6760 switch (result) {
6761 case PIM_MSDP_ERR_NONE:
6762 break;
6763 case PIM_MSDP_ERR_NO_MG:
6764 vty_out(vty, "%% mesh-group does not exist\n");
6765 break;
6766 default:
6767 vty_out(vty, "%% mesh-group source del failed\n");
6768 }
6769
6770 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
6771 }
6772
6773 DEFUN (no_ip_msdp_mesh_group_source,
6774 no_ip_msdp_mesh_group_source_cmd,
6775 "no ip msdp mesh-group WORD source [A.B.C.D]",
6776 NO_STR
6777 IP_STR
6778 CFG_MSDP_STR
6779 "Delete MSDP mesh-group source\n"
6780 "mesh group name\n"
6781 "mesh group source\n"
6782 "mesh group local address\n")
6783 {
6784 if (argc == 7)
6785 return ip_no_msdp_mesh_group_cmd_worker(vty, argv[6]->arg);
6786 else
6787 return ip_no_msdp_mesh_group_source_cmd_worker(vty,
6788 argv[4]->arg);
6789 }
6790
6791 static void print_empty_json_obj(struct vty *vty)
6792 {
6793 json_object *json;
6794 json = json_object_new_object();
6795 vty_out(vty, "%s\n",
6796 json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
6797 json_object_free(json);
6798 }
6799
6800 static void ip_msdp_show_mesh_group(struct vty *vty, u_char uj)
6801 {
6802 struct listnode *mbrnode;
6803 struct pim_msdp_mg_mbr *mbr;
6804 struct pim_msdp_mg *mg = msdp->mg;
6805 char mbr_str[INET_ADDRSTRLEN];
6806 char src_str[INET_ADDRSTRLEN];
6807 char state_str[PIM_MSDP_STATE_STRLEN];
6808 enum pim_msdp_peer_state state;
6809 json_object *json = NULL;
6810 json_object *json_mg_row = NULL;
6811 json_object *json_members = NULL;
6812 json_object *json_row = NULL;
6813
6814 if (!mg) {
6815 if (uj)
6816 print_empty_json_obj(vty);
6817 return;
6818 }
6819
6820 pim_inet4_dump("<source?>", mg->src_ip, src_str, sizeof(src_str));
6821 if (uj) {
6822 json = json_object_new_object();
6823 /* currently there is only one mesh group but we should still
6824 * make
6825 * it a dict with mg-name as key */
6826 json_mg_row = json_object_new_object();
6827 json_object_string_add(json_mg_row, "name",
6828 mg->mesh_group_name);
6829 json_object_string_add(json_mg_row, "source", src_str);
6830 } else {
6831 vty_out(vty, "Mesh group : %s\n", mg->mesh_group_name);
6832 vty_out(vty, " Source : %s\n", src_str);
6833 vty_out(vty, " Member State\n");
6834 }
6835
6836 for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) {
6837 pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str));
6838 if (mbr->mp) {
6839 state = mbr->mp->state;
6840 } else {
6841 state = PIM_MSDP_DISABLED;
6842 }
6843 pim_msdp_state_dump(state, state_str, sizeof(state_str));
6844 if (uj) {
6845 json_row = json_object_new_object();
6846 json_object_string_add(json_row, "member", mbr_str);
6847 json_object_string_add(json_row, "state", state_str);
6848 if (!json_members) {
6849 json_members = json_object_new_object();
6850 json_object_object_add(json_mg_row, "members",
6851 json_members);
6852 }
6853 json_object_object_add(json_members, mbr_str, json_row);
6854 } else {
6855 vty_out(vty, " %-15s %11s\n", mbr_str, state_str);
6856 }
6857 }
6858
6859 if (uj) {
6860 json_object_object_add(json, mg->mesh_group_name, json_mg_row);
6861 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6862 json, JSON_C_TO_STRING_PRETTY));
6863 json_object_free(json);
6864 }
6865 }
6866
6867 DEFUN (show_ip_msdp_mesh_group,
6868 show_ip_msdp_mesh_group_cmd,
6869 "show ip msdp mesh-group [json]",
6870 SHOW_STR
6871 IP_STR
6872 MSDP_STR
6873 "MSDP mesh-group information\n"
6874 "JavaScript Object Notation\n")
6875 {
6876 u_char uj = use_json(argc, argv);
6877 ip_msdp_show_mesh_group(vty, uj);
6878
6879 return CMD_SUCCESS;
6880 }
6881
6882 static void ip_msdp_show_peers(struct vty *vty, u_char uj)
6883 {
6884 struct listnode *mpnode;
6885 struct pim_msdp_peer *mp;
6886 char peer_str[INET_ADDRSTRLEN];
6887 char local_str[INET_ADDRSTRLEN];
6888 char state_str[PIM_MSDP_STATE_STRLEN];
6889 char timebuf[PIM_MSDP_UPTIME_STRLEN];
6890 int64_t now;
6891 json_object *json = NULL;
6892 json_object *json_row = NULL;
6893
6894
6895 if (uj) {
6896 json = json_object_new_object();
6897 } else {
6898 vty_out(vty,
6899 "Peer Local State Uptime SaCnt\n");
6900 }
6901
6902 for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) {
6903 if (mp->state == PIM_MSDP_ESTABLISHED) {
6904 now = pim_time_monotonic_sec();
6905 pim_time_uptime(timebuf, sizeof(timebuf),
6906 now - mp->uptime);
6907 } else {
6908 strcpy(timebuf, "-");
6909 }
6910 pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
6911 pim_inet4_dump("<local?>", mp->local, local_str,
6912 sizeof(local_str));
6913 pim_msdp_state_dump(mp->state, state_str, sizeof(state_str));
6914 if (uj) {
6915 json_row = json_object_new_object();
6916 json_object_string_add(json_row, "peer", peer_str);
6917 json_object_string_add(json_row, "local", local_str);
6918 json_object_string_add(json_row, "state", state_str);
6919 json_object_string_add(json_row, "upTime", timebuf);
6920 json_object_int_add(json_row, "saCount", mp->sa_cnt);
6921 json_object_object_add(json, peer_str, json_row);
6922 } else {
6923 vty_out(vty, "%-15s %15s %11s %8s %6d\n", peer_str,
6924 local_str, state_str, timebuf, mp->sa_cnt);
6925 }
6926 }
6927
6928 if (uj) {
6929 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6930 json, JSON_C_TO_STRING_PRETTY));
6931 json_object_free(json);
6932 }
6933 }
6934
6935 static void ip_msdp_show_peers_detail(struct vty *vty, const char *peer,
6936 u_char uj)
6937 {
6938 struct listnode *mpnode;
6939 struct pim_msdp_peer *mp;
6940 char peer_str[INET_ADDRSTRLEN];
6941 char local_str[INET_ADDRSTRLEN];
6942 char state_str[PIM_MSDP_STATE_STRLEN];
6943 char timebuf[PIM_MSDP_UPTIME_STRLEN];
6944 char katimer[PIM_MSDP_TIMER_STRLEN];
6945 char crtimer[PIM_MSDP_TIMER_STRLEN];
6946 char holdtimer[PIM_MSDP_TIMER_STRLEN];
6947 int64_t now;
6948 json_object *json = NULL;
6949 json_object *json_row = NULL;
6950
6951 if (uj) {
6952 json = json_object_new_object();
6953 }
6954
6955 for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) {
6956 pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
6957 if (strcmp(peer, "detail") && strcmp(peer, peer_str))
6958 continue;
6959
6960 if (mp->state == PIM_MSDP_ESTABLISHED) {
6961 now = pim_time_monotonic_sec();
6962 pim_time_uptime(timebuf, sizeof(timebuf),
6963 now - mp->uptime);
6964 } else {
6965 strcpy(timebuf, "-");
6966 }
6967 pim_inet4_dump("<local?>", mp->local, local_str,
6968 sizeof(local_str));
6969 pim_msdp_state_dump(mp->state, state_str, sizeof(state_str));
6970 pim_time_timer_to_hhmmss(katimer, sizeof(katimer),
6971 mp->ka_timer);
6972 pim_time_timer_to_hhmmss(crtimer, sizeof(crtimer),
6973 mp->cr_timer);
6974 pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer),
6975 mp->hold_timer);
6976
6977 if (uj) {
6978 json_row = json_object_new_object();
6979 json_object_string_add(json_row, "peer", peer_str);
6980 json_object_string_add(json_row, "local", local_str);
6981 json_object_string_add(json_row, "meshGroupName",
6982 mp->mesh_group_name);
6983 json_object_string_add(json_row, "state", state_str);
6984 json_object_string_add(json_row, "upTime", timebuf);
6985 json_object_string_add(json_row, "keepAliveTimer",
6986 katimer);
6987 json_object_string_add(json_row, "connRetryTimer",
6988 crtimer);
6989 json_object_string_add(json_row, "holdTimer",
6990 holdtimer);
6991 json_object_string_add(json_row, "lastReset",
6992 mp->last_reset);
6993 json_object_int_add(json_row, "connAttempts",
6994 mp->conn_attempts);
6995 json_object_int_add(json_row, "establishedChanges",
6996 mp->est_flaps);
6997 json_object_int_add(json_row, "saCount", mp->sa_cnt);
6998 json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt);
6999 json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt);
7000 json_object_int_add(json_row, "saSent", mp->sa_tx_cnt);
7001 json_object_int_add(json_row, "saRcvd", mp->sa_rx_cnt);
7002 json_object_object_add(json, peer_str, json_row);
7003 } else {
7004 vty_out(vty, "Peer : %s\n", peer_str);
7005 vty_out(vty, " Local : %s\n", local_str);
7006 vty_out(vty, " Mesh Group : %s\n",
7007 mp->mesh_group_name);
7008 vty_out(vty, " State : %s\n", state_str);
7009 vty_out(vty, " Uptime : %s\n", timebuf);
7010
7011 vty_out(vty, " Keepalive Timer : %s\n", katimer);
7012 vty_out(vty, " Conn Retry Timer : %s\n", crtimer);
7013 vty_out(vty, " Hold Timer : %s\n", holdtimer);
7014 vty_out(vty, " Last Reset : %s\n",
7015 mp->last_reset);
7016 vty_out(vty, " Conn Attempts : %d\n",
7017 mp->conn_attempts);
7018 vty_out(vty, " Established Changes : %d\n",
7019 mp->est_flaps);
7020 vty_out(vty, " SA Count : %d\n",
7021 mp->sa_cnt);
7022 vty_out(vty, " Statistics :\n");
7023 vty_out(vty,
7024 " Sent Rcvd\n");
7025 vty_out(vty, " Keepalives : %10d %10d\n",
7026 mp->ka_tx_cnt, mp->ka_rx_cnt);
7027 vty_out(vty, " SAs : %10d %10d\n",
7028 mp->sa_tx_cnt, mp->sa_rx_cnt);
7029 vty_out(vty, "\n");
7030 }
7031 }
7032
7033 if (uj) {
7034 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7035 json, JSON_C_TO_STRING_PRETTY));
7036 json_object_free(json);
7037 }
7038 }
7039
7040 DEFUN (show_ip_msdp_peer_detail,
7041 show_ip_msdp_peer_detail_cmd,
7042 "show ip msdp peer [detail|A.B.C.D] [json]",
7043 SHOW_STR
7044 IP_STR
7045 MSDP_STR
7046 "MSDP peer information\n"
7047 "Detailed output\n"
7048 "peer ip address\n"
7049 "JavaScript Object Notation\n")
7050 {
7051 u_char uj = use_json(argc, argv);
7052 if (uj)
7053 argc--;
7054
7055 if (argc > 4)
7056 ip_msdp_show_peers_detail(vty, argv[4]->arg, uj);
7057 else
7058 ip_msdp_show_peers(vty, uj);
7059
7060 return CMD_SUCCESS;
7061 }
7062
7063 static void ip_msdp_show_sa(struct vty *vty, u_char uj)
7064 {
7065 struct listnode *sanode;
7066 struct pim_msdp_sa *sa;
7067 char src_str[INET_ADDRSTRLEN];
7068 char grp_str[INET_ADDRSTRLEN];
7069 char rp_str[INET_ADDRSTRLEN];
7070 char timebuf[PIM_MSDP_UPTIME_STRLEN];
7071 char spt_str[8];
7072 char local_str[8];
7073 int64_t now;
7074 json_object *json = NULL;
7075 json_object *json_group = NULL;
7076 json_object *json_row = NULL;
7077
7078 if (uj) {
7079 json = json_object_new_object();
7080 } else {
7081 vty_out(vty,
7082 "Source Group RP Local SPT Uptime\n");
7083 }
7084
7085 for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
7086 now = pim_time_monotonic_sec();
7087 pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime);
7088 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
7089 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
7090 if (sa->flags & PIM_MSDP_SAF_PEER) {
7091 pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
7092 if (sa->up) {
7093 strcpy(spt_str, "yes");
7094 } else {
7095 strcpy(spt_str, "no");
7096 }
7097 } else {
7098 strcpy(rp_str, "-");
7099 strcpy(spt_str, "-");
7100 }
7101 if (sa->flags & PIM_MSDP_SAF_LOCAL) {
7102 strcpy(local_str, "yes");
7103 } else {
7104 strcpy(local_str, "no");
7105 }
7106 if (uj) {
7107 json_object_object_get_ex(json, grp_str, &json_group);
7108
7109 if (!json_group) {
7110 json_group = json_object_new_object();
7111 json_object_object_add(json, grp_str,
7112 json_group);
7113 }
7114
7115 json_row = json_object_new_object();
7116 json_object_string_add(json_row, "source", src_str);
7117 json_object_string_add(json_row, "group", grp_str);
7118 json_object_string_add(json_row, "rp", rp_str);
7119 json_object_string_add(json_row, "local", local_str);
7120 json_object_string_add(json_row, "sptSetup", spt_str);
7121 json_object_string_add(json_row, "upTime", timebuf);
7122 json_object_object_add(json_group, src_str, json_row);
7123 } else {
7124 vty_out(vty, "%-15s %15s %15s %5c %3c %8s\n",
7125 src_str, grp_str, rp_str, local_str[0],
7126 spt_str[0], timebuf);
7127 }
7128 }
7129
7130
7131 if (uj) {
7132 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7133 json, JSON_C_TO_STRING_PRETTY));
7134 json_object_free(json);
7135 }
7136 }
7137
7138 static void ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa,
7139 const char *src_str,
7140 const char *grp_str, struct vty *vty,
7141 u_char uj, json_object *json)
7142 {
7143 char rp_str[INET_ADDRSTRLEN];
7144 char peer_str[INET_ADDRSTRLEN];
7145 char timebuf[PIM_MSDP_UPTIME_STRLEN];
7146 char spt_str[8];
7147 char local_str[8];
7148 char statetimer[PIM_MSDP_TIMER_STRLEN];
7149 int64_t now;
7150 json_object *json_group = NULL;
7151 json_object *json_row = NULL;
7152
7153 now = pim_time_monotonic_sec();
7154 pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime);
7155 if (sa->flags & PIM_MSDP_SAF_PEER) {
7156 pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
7157 pim_inet4_dump("<peer?>", sa->peer, peer_str, sizeof(peer_str));
7158 if (sa->up) {
7159 strcpy(spt_str, "yes");
7160 } else {
7161 strcpy(spt_str, "no");
7162 }
7163 } else {
7164 strcpy(rp_str, "-");
7165 strcpy(peer_str, "-");
7166 strcpy(spt_str, "-");
7167 }
7168 if (sa->flags & PIM_MSDP_SAF_LOCAL) {
7169 strcpy(local_str, "yes");
7170 } else {
7171 strcpy(local_str, "no");
7172 }
7173 pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer),
7174 sa->sa_state_timer);
7175 if (uj) {
7176 json_object_object_get_ex(json, grp_str, &json_group);
7177
7178 if (!json_group) {
7179 json_group = json_object_new_object();
7180 json_object_object_add(json, grp_str, json_group);
7181 }
7182
7183 json_row = json_object_new_object();
7184 json_object_string_add(json_row, "source", src_str);
7185 json_object_string_add(json_row, "group", grp_str);
7186 json_object_string_add(json_row, "rp", rp_str);
7187 json_object_string_add(json_row, "local", local_str);
7188 json_object_string_add(json_row, "sptSetup", spt_str);
7189 json_object_string_add(json_row, "upTime", timebuf);
7190 json_object_string_add(json_row, "stateTimer", statetimer);
7191 json_object_object_add(json_group, src_str, json_row);
7192 } else {
7193 vty_out(vty, "SA : %s\n", sa->sg_str);
7194 vty_out(vty, " RP : %s\n", rp_str);
7195 vty_out(vty, " Peer : %s\n", peer_str);
7196 vty_out(vty, " Local : %s\n", local_str);
7197 vty_out(vty, " SPT Setup : %s\n", spt_str);
7198 vty_out(vty, " Uptime : %s\n", timebuf);
7199 vty_out(vty, " State Timer : %s\n", statetimer);
7200 vty_out(vty, "\n");
7201 }
7202 }
7203
7204 static void ip_msdp_show_sa_detail(struct vty *vty, u_char uj)
7205 {
7206 struct listnode *sanode;
7207 struct pim_msdp_sa *sa;
7208 char src_str[INET_ADDRSTRLEN];
7209 char grp_str[INET_ADDRSTRLEN];
7210 json_object *json = NULL;
7211
7212 if (uj) {
7213 json = json_object_new_object();
7214 }
7215
7216 for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
7217 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
7218 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
7219 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj,
7220 json);
7221 }
7222
7223 if (uj) {
7224 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7225 json, JSON_C_TO_STRING_PRETTY));
7226 json_object_free(json);
7227 }
7228 }
7229
7230 DEFUN (show_ip_msdp_sa_detail,
7231 show_ip_msdp_sa_detail_cmd,
7232 "show ip msdp sa detail [json]",
7233 SHOW_STR
7234 IP_STR
7235 MSDP_STR
7236 "MSDP active-source information\n"
7237 "Detailed output\n"
7238 "JavaScript Object Notation\n")
7239 {
7240 u_char uj = use_json(argc, argv);
7241 ip_msdp_show_sa_detail(vty, uj);
7242
7243 return CMD_SUCCESS;
7244 }
7245
7246 static void ip_msdp_show_sa_addr(struct vty *vty, const char *addr, u_char uj)
7247 {
7248 struct listnode *sanode;
7249 struct pim_msdp_sa *sa;
7250 char src_str[INET_ADDRSTRLEN];
7251 char grp_str[INET_ADDRSTRLEN];
7252 json_object *json = NULL;
7253
7254 if (uj) {
7255 json = json_object_new_object();
7256 }
7257
7258 for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
7259 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
7260 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
7261 if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) {
7262 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty,
7263 uj, json);
7264 }
7265 }
7266
7267 if (uj) {
7268 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7269 json, JSON_C_TO_STRING_PRETTY));
7270 json_object_free(json);
7271 }
7272 }
7273
7274 static void ip_msdp_show_sa_sg(struct vty *vty, const char *src,
7275 const char *grp, u_char uj)
7276 {
7277 struct listnode *sanode;
7278 struct pim_msdp_sa *sa;
7279 char src_str[INET_ADDRSTRLEN];
7280 char grp_str[INET_ADDRSTRLEN];
7281 json_object *json = NULL;
7282
7283 if (uj) {
7284 json = json_object_new_object();
7285 }
7286
7287 for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {
7288 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
7289 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
7290 if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) {
7291 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty,
7292 uj, json);
7293 }
7294 }
7295
7296 if (uj) {
7297 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7298 json, JSON_C_TO_STRING_PRETTY));
7299 json_object_free(json);
7300 }
7301 }
7302
7303 DEFUN (show_ip_msdp_sa_sg,
7304 show_ip_msdp_sa_sg_cmd,
7305 "show ip msdp sa [A.B.C.D [A.B.C.D]] [json]",
7306 SHOW_STR
7307 IP_STR
7308 MSDP_STR
7309 "MSDP active-source information\n"
7310 "source or group ip\n"
7311 "group ip\n"
7312 "JavaScript Object Notation\n")
7313 {
7314 u_char uj = use_json(argc, argv);
7315
7316 int idx = 0;
7317 char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg
7318 : NULL;
7319 char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx)
7320 ? argv[idx]->arg
7321 : NULL;
7322
7323 if (src_ip && grp_ip)
7324 ip_msdp_show_sa_sg(vty, src_ip, grp_ip, uj);
7325 else if (src_ip)
7326 ip_msdp_show_sa_addr(vty, src_ip, uj);
7327 else
7328 ip_msdp_show_sa(vty, uj);
7329
7330 return CMD_SUCCESS;
7331 }
7332
7333 void pim_cmd_init()
7334 {
7335 install_node(&pim_global_node, pim_global_config_write); /* PIM_NODE */
7336 install_node(&interface_node,
7337 pim_interface_config_write); /* INTERFACE_NODE */
7338 if_cmd_init();
7339
7340 install_node(&debug_node, pim_debug_config_write);
7341
7342 install_element(CONFIG_NODE, &ip_multicast_routing_cmd);
7343 install_element(CONFIG_NODE, &no_ip_multicast_routing_cmd);
7344 install_element(CONFIG_NODE, &ip_pim_rp_cmd);
7345 install_element(CONFIG_NODE, &no_ip_pim_rp_cmd);
7346 install_element(CONFIG_NODE, &ip_pim_rp_prefix_list_cmd);
7347 install_element(CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd);
7348 install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd);
7349 install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
7350 install_element(CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd);
7351 install_element(CONFIG_NODE, &ip_pim_register_suppress_cmd);
7352 install_element(CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
7353 install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd);
7354 install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
7355 install_element(CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
7356 install_element(CONFIG_NODE,
7357 &no_ip_pim_spt_switchover_infinity_plist_cmd);
7358 install_element(CONFIG_NODE, &ip_pim_joinprune_time_cmd);
7359 install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
7360 install_element(CONFIG_NODE, &ip_pim_keep_alive_cmd);
7361 install_element(CONFIG_NODE, &no_ip_pim_keep_alive_cmd);
7362 install_element(CONFIG_NODE, &ip_pim_packets_cmd);
7363 install_element(CONFIG_NODE, &no_ip_pim_packets_cmd);
7364 install_element(CONFIG_NODE, &ip_pim_v6_secondary_cmd);
7365 install_element(CONFIG_NODE, &no_ip_pim_v6_secondary_cmd);
7366 install_element(CONFIG_NODE, &ip_ssmpingd_cmd);
7367 install_element(CONFIG_NODE, &no_ip_ssmpingd_cmd);
7368 install_element(CONFIG_NODE, &ip_msdp_peer_cmd);
7369 install_element(CONFIG_NODE, &no_ip_msdp_peer_cmd);
7370 install_element(CONFIG_NODE, &ip_pim_ecmp_cmd);
7371 install_element(CONFIG_NODE, &no_ip_pim_ecmp_cmd);
7372 install_element(CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd);
7373 install_element(CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd);
7374
7375 install_element(INTERFACE_NODE, &interface_ip_igmp_cmd);
7376 install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd);
7377 install_element(INTERFACE_NODE, &interface_ip_igmp_join_cmd);
7378 install_element(INTERFACE_NODE, &interface_no_ip_igmp_join_cmd);
7379 install_element(INTERFACE_NODE, &interface_ip_igmp_version_cmd);
7380 install_element(INTERFACE_NODE, &interface_no_ip_igmp_version_cmd);
7381 install_element(INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd);
7382 install_element(INTERFACE_NODE,
7383 &interface_no_ip_igmp_query_interval_cmd);
7384 install_element(INTERFACE_NODE,
7385 &interface_ip_igmp_query_max_response_time_cmd);
7386 install_element(INTERFACE_NODE,
7387 &interface_no_ip_igmp_query_max_response_time_cmd);
7388 install_element(INTERFACE_NODE,
7389 &interface_ip_igmp_query_max_response_time_dsec_cmd);
7390 install_element(INTERFACE_NODE,
7391 &interface_no_ip_igmp_query_max_response_time_dsec_cmd);
7392 install_element(INTERFACE_NODE, &interface_ip_pim_ssm_cmd);
7393 install_element(INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd);
7394 install_element(INTERFACE_NODE, &interface_ip_pim_sm_cmd);
7395 install_element(INTERFACE_NODE, &interface_no_ip_pim_sm_cmd);
7396 install_element(INTERFACE_NODE, &interface_ip_pim_drprio_cmd);
7397 install_element(INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd);
7398 install_element(INTERFACE_NODE, &interface_ip_pim_hello_cmd);
7399 install_element(INTERFACE_NODE, &interface_no_ip_pim_hello_cmd);
7400
7401 // Static mroutes NEB
7402 install_element(INTERFACE_NODE, &interface_ip_mroute_cmd);
7403 install_element(INTERFACE_NODE, &interface_ip_mroute_source_cmd);
7404 install_element(INTERFACE_NODE, &interface_no_ip_mroute_cmd);
7405 install_element(INTERFACE_NODE, &interface_no_ip_mroute_source_cmd);
7406
7407 install_element(VIEW_NODE, &show_ip_igmp_interface_cmd);
7408 install_element(VIEW_NODE, &show_ip_igmp_join_cmd);
7409 install_element(VIEW_NODE, &show_ip_igmp_groups_cmd);
7410 install_element(VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd);
7411 install_element(VIEW_NODE, &show_ip_igmp_sources_cmd);
7412 install_element(VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd);
7413 install_element(VIEW_NODE, &show_ip_pim_assert_cmd);
7414 install_element(VIEW_NODE, &show_ip_pim_assert_internal_cmd);
7415 install_element(VIEW_NODE, &show_ip_pim_assert_metric_cmd);
7416 install_element(VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd);
7417 install_element(VIEW_NODE, &show_ip_pim_interface_traffic_cmd);
7418 install_element(VIEW_NODE, &show_ip_pim_interface_cmd);
7419 install_element(VIEW_NODE, &show_ip_pim_join_cmd);
7420 install_element(VIEW_NODE, &show_ip_pim_local_membership_cmd);
7421 install_element(VIEW_NODE, &show_ip_pim_neighbor_cmd);
7422 install_element(VIEW_NODE, &show_ip_pim_rpf_cmd);
7423 install_element(VIEW_NODE, &show_ip_pim_secondary_cmd);
7424 install_element(VIEW_NODE, &show_ip_pim_state_cmd);
7425 install_element(VIEW_NODE, &show_ip_pim_upstream_cmd);
7426 install_element(VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd);
7427 install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd);
7428 install_element(VIEW_NODE, &show_ip_pim_rp_cmd);
7429 install_element(VIEW_NODE, &show_ip_multicast_cmd);
7430 install_element(VIEW_NODE, &show_ip_mroute_cmd);
7431 install_element(VIEW_NODE, &show_ip_mroute_count_cmd);
7432 install_element(VIEW_NODE, &show_ip_rib_cmd);
7433 install_element(VIEW_NODE, &show_ip_ssmpingd_cmd);
7434 install_element(VIEW_NODE, &show_debugging_pim_cmd);
7435 install_element(VIEW_NODE, &show_ip_pim_nexthop_cmd);
7436 install_element(VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd);
7437
7438 install_element(ENABLE_NODE, &clear_ip_interfaces_cmd);
7439 install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd);
7440 install_element(ENABLE_NODE, &clear_ip_mroute_cmd);
7441 install_element(ENABLE_NODE, &clear_ip_pim_interfaces_cmd);
7442 install_element(ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd);
7443 install_element(ENABLE_NODE, &clear_ip_pim_oil_cmd);
7444
7445 install_element(ENABLE_NODE, &debug_igmp_cmd);
7446 install_element(ENABLE_NODE, &no_debug_igmp_cmd);
7447 install_element(ENABLE_NODE, &debug_igmp_events_cmd);
7448 install_element(ENABLE_NODE, &no_debug_igmp_events_cmd);
7449 install_element(ENABLE_NODE, &debug_igmp_packets_cmd);
7450 install_element(ENABLE_NODE, &no_debug_igmp_packets_cmd);
7451 install_element(ENABLE_NODE, &debug_igmp_trace_cmd);
7452 install_element(ENABLE_NODE, &no_debug_igmp_trace_cmd);
7453 install_element(ENABLE_NODE, &debug_mroute_cmd);
7454 install_element(ENABLE_NODE, &debug_mroute_detail_cmd);
7455 install_element(ENABLE_NODE, &no_debug_mroute_cmd);
7456 install_element(ENABLE_NODE, &no_debug_mroute_detail_cmd);
7457 install_element(ENABLE_NODE, &debug_static_cmd);
7458 install_element(ENABLE_NODE, &no_debug_static_cmd);
7459 install_element(ENABLE_NODE, &debug_pim_cmd);
7460 install_element(ENABLE_NODE, &no_debug_pim_cmd);
7461 install_element(ENABLE_NODE, &debug_pim_events_cmd);
7462 install_element(ENABLE_NODE, &no_debug_pim_events_cmd);
7463 install_element(ENABLE_NODE, &debug_pim_packets_cmd);
7464 install_element(ENABLE_NODE, &no_debug_pim_packets_cmd);
7465 install_element(ENABLE_NODE, &debug_pim_packetdump_send_cmd);
7466 install_element(ENABLE_NODE, &no_debug_pim_packetdump_send_cmd);
7467 install_element(ENABLE_NODE, &debug_pim_packetdump_recv_cmd);
7468 install_element(ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd);
7469 install_element(ENABLE_NODE, &debug_pim_trace_cmd);
7470 install_element(ENABLE_NODE, &no_debug_pim_trace_cmd);
7471 install_element(ENABLE_NODE, &debug_ssmpingd_cmd);
7472 install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd);
7473 install_element(ENABLE_NODE, &debug_pim_zebra_cmd);
7474 install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd);
7475 install_element(ENABLE_NODE, &debug_msdp_cmd);
7476 install_element(ENABLE_NODE, &no_debug_msdp_cmd);
7477 install_element(ENABLE_NODE, &undebug_msdp_cmd);
7478 install_element(ENABLE_NODE, &debug_msdp_events_cmd);
7479 install_element(ENABLE_NODE, &no_debug_msdp_events_cmd);
7480 install_element(ENABLE_NODE, &undebug_msdp_events_cmd);
7481 install_element(ENABLE_NODE, &debug_msdp_packets_cmd);
7482 install_element(ENABLE_NODE, &no_debug_msdp_packets_cmd);
7483 install_element(ENABLE_NODE, &undebug_msdp_packets_cmd);
7484
7485 install_element(CONFIG_NODE, &debug_igmp_cmd);
7486 install_element(CONFIG_NODE, &no_debug_igmp_cmd);
7487 install_element(CONFIG_NODE, &debug_igmp_events_cmd);
7488 install_element(CONFIG_NODE, &no_debug_igmp_events_cmd);
7489 install_element(CONFIG_NODE, &debug_igmp_packets_cmd);
7490 install_element(CONFIG_NODE, &no_debug_igmp_packets_cmd);
7491 install_element(CONFIG_NODE, &debug_igmp_trace_cmd);
7492 install_element(CONFIG_NODE, &no_debug_igmp_trace_cmd);
7493 install_element(CONFIG_NODE, &debug_mroute_cmd);
7494 install_element(CONFIG_NODE, &debug_mroute_detail_cmd);
7495 install_element(CONFIG_NODE, &no_debug_mroute_cmd);
7496 install_element(CONFIG_NODE, &no_debug_mroute_detail_cmd);
7497 install_element(CONFIG_NODE, &debug_static_cmd);
7498 install_element(CONFIG_NODE, &no_debug_static_cmd);
7499 install_element(CONFIG_NODE, &debug_pim_cmd);
7500 install_element(CONFIG_NODE, &no_debug_pim_cmd);
7501 install_element(CONFIG_NODE, &debug_pim_events_cmd);
7502 install_element(CONFIG_NODE, &no_debug_pim_events_cmd);
7503 install_element(CONFIG_NODE, &debug_pim_packets_cmd);
7504 install_element(CONFIG_NODE, &no_debug_pim_packets_cmd);
7505 install_element(CONFIG_NODE, &debug_pim_trace_cmd);
7506 install_element(CONFIG_NODE, &no_debug_pim_trace_cmd);
7507 install_element(CONFIG_NODE, &debug_ssmpingd_cmd);
7508 install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd);
7509 install_element(CONFIG_NODE, &debug_pim_zebra_cmd);
7510 install_element(CONFIG_NODE, &no_debug_pim_zebra_cmd);
7511 install_element(CONFIG_NODE, &debug_msdp_cmd);
7512 install_element(CONFIG_NODE, &no_debug_msdp_cmd);
7513 install_element(CONFIG_NODE, &undebug_msdp_cmd);
7514 install_element(CONFIG_NODE, &debug_msdp_events_cmd);
7515 install_element(CONFIG_NODE, &no_debug_msdp_events_cmd);
7516 install_element(CONFIG_NODE, &undebug_msdp_events_cmd);
7517 install_element(CONFIG_NODE, &debug_msdp_packets_cmd);
7518 install_element(CONFIG_NODE, &no_debug_msdp_packets_cmd);
7519 install_element(CONFIG_NODE, &undebug_msdp_packets_cmd);
7520 install_element(CONFIG_NODE, &ip_msdp_mesh_group_member_cmd);
7521 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd);
7522 install_element(CONFIG_NODE, &ip_msdp_mesh_group_source_cmd);
7523 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd);
7524 install_element(VIEW_NODE, &show_ip_msdp_peer_detail_cmd);
7525 install_element(VIEW_NODE, &show_ip_msdp_sa_detail_cmd);
7526 install_element(VIEW_NODE, &show_ip_msdp_sa_sg_cmd);
7527 install_element(VIEW_NODE, &show_ip_msdp_mesh_group_cmd);
7528 install_element(VIEW_NODE, &show_ip_pim_ssm_range_cmd);
7529 install_element(VIEW_NODE, &show_ip_pim_group_type_cmd);
7530 install_element(INTERFACE_NODE, &interface_pim_use_source_cmd);
7531 install_element(INTERFACE_NODE, &interface_no_pim_use_source_cmd);
7532 /* Install BFD command */
7533 install_element(INTERFACE_NODE, &ip_pim_bfd_cmd);
7534 install_element(INTERFACE_NODE, &ip_pim_bfd_param_cmd);
7535 install_element(INTERFACE_NODE, &no_ip_pim_bfd_cmd);
7536 install_element(INTERFACE_NODE, &no_ip_pim_bfd_param_cmd);
7537 }