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