]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_cmd.c
Merge pull request #1653 from Orange-OpenSource/SR-Routing
[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_NOSH (show_debugging_pim,
7315 show_debugging_pim_cmd,
7316 "show debugging [pim]",
7317 SHOW_STR
7318 DEBUG_STR
7319 PIM_STR)
7320 {
7321 vty_out(vty, "PIM debugging status\n");
7322
7323 pim_debug_config_write(vty);
7324
7325 return CMD_SUCCESS;
7326 }
7327
7328 static int interface_pim_use_src_cmd_worker(struct vty *vty, const char *source)
7329 {
7330 int result;
7331 struct in_addr source_addr;
7332 int ret = CMD_SUCCESS;
7333 VTY_DECLVAR_CONTEXT(interface, ifp);
7334
7335 result = inet_pton(AF_INET, source, &source_addr);
7336 if (result <= 0) {
7337 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", source,
7338 errno, safe_strerror(errno));
7339 return CMD_WARNING_CONFIG_FAILED;
7340 }
7341
7342 result = pim_update_source_set(ifp, source_addr);
7343 switch (result) {
7344 case PIM_SUCCESS:
7345 break;
7346 case PIM_IFACE_NOT_FOUND:
7347 ret = CMD_WARNING_CONFIG_FAILED;
7348 vty_out(vty, "Pim not enabled on this interface\n");
7349 break;
7350 case PIM_UPDATE_SOURCE_DUP:
7351 ret = CMD_WARNING;
7352 vty_out(vty, "%% Source already set to %s\n", source);
7353 break;
7354 default:
7355 ret = CMD_WARNING_CONFIG_FAILED;
7356 vty_out(vty, "%% Source set failed\n");
7357 }
7358
7359 return ret;
7360 }
7361
7362 DEFUN (interface_pim_use_source,
7363 interface_pim_use_source_cmd,
7364 "ip pim use-source A.B.C.D",
7365 IP_STR
7366 "pim multicast routing\n"
7367 "Configure primary IP address\n"
7368 "source ip address\n")
7369 {
7370 return interface_pim_use_src_cmd_worker(vty, argv[3]->arg);
7371 }
7372
7373 DEFUN (interface_no_pim_use_source,
7374 interface_no_pim_use_source_cmd,
7375 "no ip pim use-source [A.B.C.D]",
7376 NO_STR
7377 IP_STR
7378 "pim multicast routing\n"
7379 "Delete source IP address\n"
7380 "source ip address\n")
7381 {
7382 return interface_pim_use_src_cmd_worker(vty, "0.0.0.0");
7383 }
7384
7385 DEFUN (ip_pim_bfd,
7386 ip_pim_bfd_cmd,
7387 "ip pim bfd",
7388 IP_STR
7389 PIM_STR
7390 "Enables BFD support\n")
7391 {
7392 VTY_DECLVAR_CONTEXT(interface, ifp);
7393 struct pim_interface *pim_ifp = ifp->info;
7394 struct bfd_info *bfd_info = NULL;
7395
7396 if (!pim_ifp) {
7397 if (!pim_cmd_interface_add(ifp)) {
7398 vty_out(vty, "Could not enable PIM SM on interface\n");
7399 return CMD_WARNING;
7400 }
7401 }
7402 pim_ifp = ifp->info;
7403
7404 bfd_info = pim_ifp->bfd_info;
7405
7406 if (!bfd_info || !CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG))
7407 pim_bfd_if_param_set(ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
7408 BFD_DEF_DETECT_MULT, 1);
7409
7410 return CMD_SUCCESS;
7411 }
7412
7413 DEFUN (no_ip_pim_bfd,
7414 no_ip_pim_bfd_cmd,
7415 "no ip pim bfd",
7416 NO_STR
7417 IP_STR
7418 PIM_STR
7419 "Disables BFD support\n")
7420 {
7421 VTY_DECLVAR_CONTEXT(interface, ifp);
7422 struct pim_interface *pim_ifp = ifp->info;
7423
7424 if (!pim_ifp) {
7425 vty_out(vty, "Pim not enabled on this interface\n");
7426 return CMD_WARNING;
7427 }
7428
7429 if (pim_ifp->bfd_info) {
7430 pim_bfd_reg_dereg_all_nbr(ifp, ZEBRA_BFD_DEST_DEREGISTER);
7431 bfd_info_free(&(pim_ifp->bfd_info));
7432 }
7433
7434 return CMD_SUCCESS;
7435 }
7436
7437 DEFUN (ip_pim_bfd_param,
7438 ip_pim_bfd_param_cmd,
7439 "ip pim bfd (2-255) (50-60000) (50-60000)",
7440 IP_STR
7441 PIM_STR
7442 "Enables BFD support\n"
7443 "Detect Multiplier\n"
7444 "Required min receive interval\n"
7445 "Desired min transmit interval\n")
7446 {
7447 VTY_DECLVAR_CONTEXT(interface, ifp);
7448 int idx_number = 3;
7449 int idx_number_2 = 4;
7450 int idx_number_3 = 5;
7451 u_int32_t rx_val;
7452 u_int32_t tx_val;
7453 u_int8_t dm_val;
7454 int ret;
7455 struct pim_interface *pim_ifp = ifp->info;
7456
7457 if (!pim_ifp) {
7458 if (!pim_cmd_interface_add(ifp)) {
7459 vty_out(vty, "Could not enable PIM SM on interface\n");
7460 return CMD_WARNING;
7461 }
7462 }
7463
7464 if ((ret = bfd_validate_param(
7465 vty, argv[idx_number]->arg, argv[idx_number_2]->arg,
7466 argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val))
7467 != CMD_SUCCESS)
7468 return ret;
7469
7470 pim_bfd_if_param_set(ifp, rx_val, tx_val, dm_val, 0);
7471
7472 return CMD_SUCCESS;
7473 }
7474
7475 ALIAS(no_ip_pim_bfd, no_ip_pim_bfd_param_cmd,
7476 "no ip pim bfd (2-255) (50-60000) (50-60000)", NO_STR IP_STR PIM_STR
7477 "Enables BFD support\n"
7478 "Detect Multiplier\n"
7479 "Required min receive interval\n"
7480 "Desired min transmit interval\n")
7481
7482 static int ip_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty,
7483 const char *peer, const char *local)
7484 {
7485 enum pim_msdp_err result;
7486 struct in_addr peer_addr;
7487 struct in_addr local_addr;
7488 int ret = CMD_SUCCESS;
7489
7490 result = inet_pton(AF_INET, peer, &peer_addr);
7491 if (result <= 0) {
7492 vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer,
7493 errno, safe_strerror(errno));
7494 return CMD_WARNING_CONFIG_FAILED;
7495 }
7496
7497 result = inet_pton(AF_INET, local, &local_addr);
7498 if (result <= 0) {
7499 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", local,
7500 errno, safe_strerror(errno));
7501 return CMD_WARNING_CONFIG_FAILED;
7502 }
7503
7504 result = pim_msdp_peer_add(pim, peer_addr, local_addr, "default",
7505 NULL /* mp_p */);
7506 switch (result) {
7507 case PIM_MSDP_ERR_NONE:
7508 break;
7509 case PIM_MSDP_ERR_OOM:
7510 ret = CMD_WARNING_CONFIG_FAILED;
7511 vty_out(vty, "%% Out of memory\n");
7512 break;
7513 case PIM_MSDP_ERR_PEER_EXISTS:
7514 ret = CMD_WARNING;
7515 vty_out(vty, "%% Peer exists\n");
7516 break;
7517 case PIM_MSDP_ERR_MAX_MESH_GROUPS:
7518 ret = CMD_WARNING_CONFIG_FAILED;
7519 vty_out(vty, "%% Only one mesh-group allowed currently\n");
7520 break;
7521 default:
7522 ret = CMD_WARNING_CONFIG_FAILED;
7523 vty_out(vty, "%% peer add failed\n");
7524 }
7525
7526 return ret;
7527 }
7528
7529 DEFUN_HIDDEN (ip_msdp_peer,
7530 ip_msdp_peer_cmd,
7531 "ip msdp peer A.B.C.D source A.B.C.D",
7532 IP_STR
7533 CFG_MSDP_STR
7534 "Configure MSDP peer\n"
7535 "peer ip address\n"
7536 "Source address for TCP connection\n"
7537 "local ip address\n")
7538 {
7539 PIM_DECLVAR_CONTEXT(vrf, pim);
7540 return ip_msdp_peer_cmd_worker(pim, vty, argv[3]->arg, argv[5]->arg);
7541 }
7542
7543 static int ip_no_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty,
7544 const char *peer)
7545 {
7546 enum pim_msdp_err result;
7547 struct in_addr peer_addr;
7548
7549 result = inet_pton(AF_INET, peer, &peer_addr);
7550 if (result <= 0) {
7551 vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer,
7552 errno, safe_strerror(errno));
7553 return CMD_WARNING_CONFIG_FAILED;
7554 }
7555
7556 result = pim_msdp_peer_del(pim, peer_addr);
7557 switch (result) {
7558 case PIM_MSDP_ERR_NONE:
7559 break;
7560 case PIM_MSDP_ERR_NO_PEER:
7561 vty_out(vty, "%% Peer does not exist\n");
7562 break;
7563 default:
7564 vty_out(vty, "%% peer del failed\n");
7565 }
7566
7567 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
7568 }
7569
7570 DEFUN_HIDDEN (no_ip_msdp_peer,
7571 no_ip_msdp_peer_cmd,
7572 "no ip msdp peer A.B.C.D",
7573 NO_STR
7574 IP_STR
7575 CFG_MSDP_STR
7576 "Delete MSDP peer\n"
7577 "peer ip address\n")
7578 {
7579 PIM_DECLVAR_CONTEXT(vrf, pim);
7580 return ip_no_msdp_peer_cmd_worker(pim, vty, argv[4]->arg);
7581 }
7582
7583 static int ip_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim,
7584 struct vty *vty, const char *mg,
7585 const char *mbr)
7586 {
7587 enum pim_msdp_err result;
7588 struct in_addr mbr_ip;
7589 int ret = CMD_SUCCESS;
7590
7591 result = inet_pton(AF_INET, mbr, &mbr_ip);
7592 if (result <= 0) {
7593 vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr,
7594 errno, safe_strerror(errno));
7595 return CMD_WARNING_CONFIG_FAILED;
7596 }
7597
7598 result = pim_msdp_mg_mbr_add(pim, mg, mbr_ip);
7599 switch (result) {
7600 case PIM_MSDP_ERR_NONE:
7601 break;
7602 case PIM_MSDP_ERR_OOM:
7603 ret = CMD_WARNING_CONFIG_FAILED;
7604 vty_out(vty, "%% Out of memory\n");
7605 break;
7606 case PIM_MSDP_ERR_MG_MBR_EXISTS:
7607 ret = CMD_WARNING;
7608 vty_out(vty, "%% mesh-group member exists\n");
7609 break;
7610 case PIM_MSDP_ERR_MAX_MESH_GROUPS:
7611 ret = CMD_WARNING_CONFIG_FAILED;
7612 vty_out(vty, "%% Only one mesh-group allowed currently\n");
7613 break;
7614 default:
7615 ret = CMD_WARNING_CONFIG_FAILED;
7616 vty_out(vty, "%% member add failed\n");
7617 }
7618
7619 return ret;
7620 }
7621
7622 DEFUN (ip_msdp_mesh_group_member,
7623 ip_msdp_mesh_group_member_cmd,
7624 "ip msdp mesh-group WORD member A.B.C.D",
7625 IP_STR
7626 CFG_MSDP_STR
7627 "Configure MSDP mesh-group\n"
7628 "mesh group name\n"
7629 "mesh group member\n"
7630 "peer ip address\n")
7631 {
7632 PIM_DECLVAR_CONTEXT(vrf, pim);
7633 return ip_msdp_mesh_group_member_cmd_worker(pim, vty, argv[3]->arg,
7634 argv[5]->arg);
7635 }
7636
7637 static int ip_no_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim,
7638 struct vty *vty,
7639 const char *mg,
7640 const char *mbr)
7641 {
7642 enum pim_msdp_err result;
7643 struct in_addr mbr_ip;
7644
7645 result = inet_pton(AF_INET, mbr, &mbr_ip);
7646 if (result <= 0) {
7647 vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr,
7648 errno, safe_strerror(errno));
7649 return CMD_WARNING_CONFIG_FAILED;
7650 }
7651
7652 result = pim_msdp_mg_mbr_del(pim, mg, mbr_ip);
7653 switch (result) {
7654 case PIM_MSDP_ERR_NONE:
7655 break;
7656 case PIM_MSDP_ERR_NO_MG:
7657 vty_out(vty, "%% mesh-group does not exist\n");
7658 break;
7659 case PIM_MSDP_ERR_NO_MG_MBR:
7660 vty_out(vty, "%% mesh-group member does not exist\n");
7661 break;
7662 default:
7663 vty_out(vty, "%% mesh-group member del failed\n");
7664 }
7665
7666 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
7667 }
7668 DEFUN (no_ip_msdp_mesh_group_member,
7669 no_ip_msdp_mesh_group_member_cmd,
7670 "no ip msdp mesh-group WORD member A.B.C.D",
7671 NO_STR
7672 IP_STR
7673 CFG_MSDP_STR
7674 "Delete MSDP mesh-group member\n"
7675 "mesh group name\n"
7676 "mesh group member\n"
7677 "peer ip address\n")
7678 {
7679 PIM_DECLVAR_CONTEXT(vrf, pim);
7680 return ip_no_msdp_mesh_group_member_cmd_worker(pim, vty, argv[4]->arg,
7681 argv[6]->arg);
7682 }
7683
7684 static int ip_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim,
7685 struct vty *vty, const char *mg,
7686 const char *src)
7687 {
7688 enum pim_msdp_err result;
7689 struct in_addr src_ip;
7690
7691 result = inet_pton(AF_INET, src, &src_ip);
7692 if (result <= 0) {
7693 vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", src,
7694 errno, safe_strerror(errno));
7695 return CMD_WARNING_CONFIG_FAILED;
7696 }
7697
7698 result = pim_msdp_mg_src_add(pim, mg, src_ip);
7699 switch (result) {
7700 case PIM_MSDP_ERR_NONE:
7701 break;
7702 case PIM_MSDP_ERR_OOM:
7703 vty_out(vty, "%% Out of memory\n");
7704 break;
7705 case PIM_MSDP_ERR_MAX_MESH_GROUPS:
7706 vty_out(vty, "%% Only one mesh-group allowed currently\n");
7707 break;
7708 default:
7709 vty_out(vty, "%% source add failed\n");
7710 }
7711
7712 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
7713 }
7714
7715
7716 DEFUN (ip_msdp_mesh_group_source,
7717 ip_msdp_mesh_group_source_cmd,
7718 "ip msdp mesh-group WORD source A.B.C.D",
7719 IP_STR
7720 CFG_MSDP_STR
7721 "Configure MSDP mesh-group\n"
7722 "mesh group name\n"
7723 "mesh group local address\n"
7724 "source ip address for the TCP connection\n")
7725 {
7726 PIM_DECLVAR_CONTEXT(vrf, pim);
7727 return ip_msdp_mesh_group_source_cmd_worker(pim, vty, argv[3]->arg,
7728 argv[5]->arg);
7729 }
7730
7731 static int ip_no_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim,
7732 struct vty *vty,
7733 const char *mg)
7734 {
7735 enum pim_msdp_err result;
7736
7737 result = pim_msdp_mg_src_del(pim, mg);
7738 switch (result) {
7739 case PIM_MSDP_ERR_NONE:
7740 break;
7741 case PIM_MSDP_ERR_NO_MG:
7742 vty_out(vty, "%% mesh-group does not exist\n");
7743 break;
7744 default:
7745 vty_out(vty, "%% mesh-group source del failed\n");
7746 }
7747
7748 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
7749 }
7750
7751 static int ip_no_msdp_mesh_group_cmd_worker(struct pim_instance *pim,
7752 struct vty *vty, const char *mg)
7753 {
7754 enum pim_msdp_err result;
7755
7756 result = pim_msdp_mg_del(pim, mg);
7757 switch (result) {
7758 case PIM_MSDP_ERR_NONE:
7759 break;
7760 case PIM_MSDP_ERR_NO_MG:
7761 vty_out(vty, "%% mesh-group does not exist\n");
7762 break;
7763 default:
7764 vty_out(vty, "%% mesh-group source del failed\n");
7765 }
7766
7767 return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
7768 }
7769
7770 DEFUN (no_ip_msdp_mesh_group_source,
7771 no_ip_msdp_mesh_group_source_cmd,
7772 "no ip msdp mesh-group WORD source [A.B.C.D]",
7773 NO_STR
7774 IP_STR
7775 CFG_MSDP_STR
7776 "Delete MSDP mesh-group source\n"
7777 "mesh group name\n"
7778 "mesh group source\n"
7779 "mesh group local address\n")
7780 {
7781 PIM_DECLVAR_CONTEXT(vrf, pim);
7782 if (argc == 7)
7783 return ip_no_msdp_mesh_group_cmd_worker(pim, vty, argv[6]->arg);
7784 else
7785 return ip_no_msdp_mesh_group_source_cmd_worker(pim, vty,
7786 argv[4]->arg);
7787 }
7788
7789 static void print_empty_json_obj(struct vty *vty)
7790 {
7791 json_object *json;
7792 json = json_object_new_object();
7793 vty_out(vty, "%s\n",
7794 json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
7795 json_object_free(json);
7796 }
7797
7798 static void ip_msdp_show_mesh_group(struct pim_instance *pim, struct vty *vty,
7799 u_char uj)
7800 {
7801 struct listnode *mbrnode;
7802 struct pim_msdp_mg_mbr *mbr;
7803 struct pim_msdp_mg *mg = pim->msdp.mg;
7804 char mbr_str[INET_ADDRSTRLEN];
7805 char src_str[INET_ADDRSTRLEN];
7806 char state_str[PIM_MSDP_STATE_STRLEN];
7807 enum pim_msdp_peer_state state;
7808 json_object *json = NULL;
7809 json_object *json_mg_row = NULL;
7810 json_object *json_members = NULL;
7811 json_object *json_row = NULL;
7812
7813 if (!mg) {
7814 if (uj)
7815 print_empty_json_obj(vty);
7816 return;
7817 }
7818
7819 pim_inet4_dump("<source?>", mg->src_ip, src_str, sizeof(src_str));
7820 if (uj) {
7821 json = json_object_new_object();
7822 /* currently there is only one mesh group but we should still
7823 * make
7824 * it a dict with mg-name as key */
7825 json_mg_row = json_object_new_object();
7826 json_object_string_add(json_mg_row, "name",
7827 mg->mesh_group_name);
7828 json_object_string_add(json_mg_row, "source", src_str);
7829 } else {
7830 vty_out(vty, "Mesh group : %s\n", mg->mesh_group_name);
7831 vty_out(vty, " Source : %s\n", src_str);
7832 vty_out(vty, " Member State\n");
7833 }
7834
7835 for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) {
7836 pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str));
7837 if (mbr->mp) {
7838 state = mbr->mp->state;
7839 } else {
7840 state = PIM_MSDP_DISABLED;
7841 }
7842 pim_msdp_state_dump(state, state_str, sizeof(state_str));
7843 if (uj) {
7844 json_row = json_object_new_object();
7845 json_object_string_add(json_row, "member", mbr_str);
7846 json_object_string_add(json_row, "state", state_str);
7847 if (!json_members) {
7848 json_members = json_object_new_object();
7849 json_object_object_add(json_mg_row, "members",
7850 json_members);
7851 }
7852 json_object_object_add(json_members, mbr_str, json_row);
7853 } else {
7854 vty_out(vty, " %-15s %11s\n", mbr_str, state_str);
7855 }
7856 }
7857
7858 if (uj) {
7859 json_object_object_add(json, mg->mesh_group_name, json_mg_row);
7860 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7861 json, JSON_C_TO_STRING_PRETTY));
7862 json_object_free(json);
7863 }
7864 }
7865
7866 DEFUN (show_ip_msdp_mesh_group,
7867 show_ip_msdp_mesh_group_cmd,
7868 "show ip msdp [vrf NAME] mesh-group [json]",
7869 SHOW_STR
7870 IP_STR
7871 MSDP_STR
7872 VRF_CMD_HELP_STR
7873 "MSDP mesh-group information\n"
7874 JSON_STR)
7875 {
7876 u_char uj = use_json(argc, argv);
7877 int idx = 2;
7878 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
7879
7880 if (!vrf)
7881 return CMD_WARNING;
7882
7883 ip_msdp_show_mesh_group(vrf->info, vty, uj);
7884
7885 return CMD_SUCCESS;
7886 }
7887
7888 DEFUN (show_ip_msdp_mesh_group_vrf_all,
7889 show_ip_msdp_mesh_group_vrf_all_cmd,
7890 "show ip msdp vrf all mesh-group [json]",
7891 SHOW_STR
7892 IP_STR
7893 MSDP_STR
7894 VRF_CMD_HELP_STR
7895 "MSDP mesh-group information\n"
7896 JSON_STR)
7897 {
7898 u_char uj = use_json(argc, argv);
7899 struct vrf *vrf;
7900 bool first = true;
7901
7902 if (uj)
7903 vty_out(vty, "{ ");
7904 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
7905 if (uj) {
7906 if (!first)
7907 vty_out(vty, ", ");
7908 vty_out(vty, " \"%s\": ", vrf->name);
7909 first = false;
7910 } else
7911 vty_out(vty, "VRF: %s\n", vrf->name);
7912 ip_msdp_show_mesh_group(vrf->info, vty, uj);
7913 }
7914 if (uj)
7915 vty_out(vty, "}\n");
7916
7917 return CMD_SUCCESS;
7918 }
7919
7920 static void ip_msdp_show_peers(struct pim_instance *pim, struct vty *vty,
7921 u_char uj)
7922 {
7923 struct listnode *mpnode;
7924 struct pim_msdp_peer *mp;
7925 char peer_str[INET_ADDRSTRLEN];
7926 char local_str[INET_ADDRSTRLEN];
7927 char state_str[PIM_MSDP_STATE_STRLEN];
7928 char timebuf[PIM_MSDP_UPTIME_STRLEN];
7929 int64_t now;
7930 json_object *json = NULL;
7931 json_object *json_row = NULL;
7932
7933
7934 if (uj) {
7935 json = json_object_new_object();
7936 } else {
7937 vty_out(vty,
7938 "Peer Local State Uptime SaCnt\n");
7939 }
7940
7941 for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, mpnode, mp)) {
7942 if (mp->state == PIM_MSDP_ESTABLISHED) {
7943 now = pim_time_monotonic_sec();
7944 pim_time_uptime(timebuf, sizeof(timebuf),
7945 now - mp->uptime);
7946 } else {
7947 strcpy(timebuf, "-");
7948 }
7949 pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
7950 pim_inet4_dump("<local?>", mp->local, local_str,
7951 sizeof(local_str));
7952 pim_msdp_state_dump(mp->state, state_str, sizeof(state_str));
7953 if (uj) {
7954 json_row = json_object_new_object();
7955 json_object_string_add(json_row, "peer", peer_str);
7956 json_object_string_add(json_row, "local", local_str);
7957 json_object_string_add(json_row, "state", state_str);
7958 json_object_string_add(json_row, "upTime", timebuf);
7959 json_object_int_add(json_row, "saCount", mp->sa_cnt);
7960 json_object_object_add(json, peer_str, json_row);
7961 } else {
7962 vty_out(vty, "%-15s %15s %11s %8s %6d\n", peer_str,
7963 local_str, state_str, timebuf, mp->sa_cnt);
7964 }
7965 }
7966
7967 if (uj) {
7968 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7969 json, JSON_C_TO_STRING_PRETTY));
7970 json_object_free(json);
7971 }
7972 }
7973
7974 static void ip_msdp_show_peers_detail(struct pim_instance *pim, struct vty *vty,
7975 const char *peer, u_char uj)
7976 {
7977 struct listnode *mpnode;
7978 struct pim_msdp_peer *mp;
7979 char peer_str[INET_ADDRSTRLEN];
7980 char local_str[INET_ADDRSTRLEN];
7981 char state_str[PIM_MSDP_STATE_STRLEN];
7982 char timebuf[PIM_MSDP_UPTIME_STRLEN];
7983 char katimer[PIM_MSDP_TIMER_STRLEN];
7984 char crtimer[PIM_MSDP_TIMER_STRLEN];
7985 char holdtimer[PIM_MSDP_TIMER_STRLEN];
7986 int64_t now;
7987 json_object *json = NULL;
7988 json_object *json_row = NULL;
7989
7990 if (uj) {
7991 json = json_object_new_object();
7992 }
7993
7994 for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, mpnode, mp)) {
7995 pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
7996 if (strcmp(peer, "detail") && strcmp(peer, peer_str))
7997 continue;
7998
7999 if (mp->state == PIM_MSDP_ESTABLISHED) {
8000 now = pim_time_monotonic_sec();
8001 pim_time_uptime(timebuf, sizeof(timebuf),
8002 now - mp->uptime);
8003 } else {
8004 strcpy(timebuf, "-");
8005 }
8006 pim_inet4_dump("<local?>", mp->local, local_str,
8007 sizeof(local_str));
8008 pim_msdp_state_dump(mp->state, state_str, sizeof(state_str));
8009 pim_time_timer_to_hhmmss(katimer, sizeof(katimer),
8010 mp->ka_timer);
8011 pim_time_timer_to_hhmmss(crtimer, sizeof(crtimer),
8012 mp->cr_timer);
8013 pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer),
8014 mp->hold_timer);
8015
8016 if (uj) {
8017 json_row = json_object_new_object();
8018 json_object_string_add(json_row, "peer", peer_str);
8019 json_object_string_add(json_row, "local", local_str);
8020 json_object_string_add(json_row, "meshGroupName",
8021 mp->mesh_group_name);
8022 json_object_string_add(json_row, "state", state_str);
8023 json_object_string_add(json_row, "upTime", timebuf);
8024 json_object_string_add(json_row, "keepAliveTimer",
8025 katimer);
8026 json_object_string_add(json_row, "connRetryTimer",
8027 crtimer);
8028 json_object_string_add(json_row, "holdTimer",
8029 holdtimer);
8030 json_object_string_add(json_row, "lastReset",
8031 mp->last_reset);
8032 json_object_int_add(json_row, "connAttempts",
8033 mp->conn_attempts);
8034 json_object_int_add(json_row, "establishedChanges",
8035 mp->est_flaps);
8036 json_object_int_add(json_row, "saCount", mp->sa_cnt);
8037 json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt);
8038 json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt);
8039 json_object_int_add(json_row, "saSent", mp->sa_tx_cnt);
8040 json_object_int_add(json_row, "saRcvd", mp->sa_rx_cnt);
8041 json_object_object_add(json, peer_str, json_row);
8042 } else {
8043 vty_out(vty, "Peer : %s\n", peer_str);
8044 vty_out(vty, " Local : %s\n", local_str);
8045 vty_out(vty, " Mesh Group : %s\n",
8046 mp->mesh_group_name);
8047 vty_out(vty, " State : %s\n", state_str);
8048 vty_out(vty, " Uptime : %s\n", timebuf);
8049
8050 vty_out(vty, " Keepalive Timer : %s\n", katimer);
8051 vty_out(vty, " Conn Retry Timer : %s\n", crtimer);
8052 vty_out(vty, " Hold Timer : %s\n", holdtimer);
8053 vty_out(vty, " Last Reset : %s\n",
8054 mp->last_reset);
8055 vty_out(vty, " Conn Attempts : %d\n",
8056 mp->conn_attempts);
8057 vty_out(vty, " Established Changes : %d\n",
8058 mp->est_flaps);
8059 vty_out(vty, " SA Count : %d\n",
8060 mp->sa_cnt);
8061 vty_out(vty, " Statistics :\n");
8062 vty_out(vty,
8063 " Sent Rcvd\n");
8064 vty_out(vty, " Keepalives : %10d %10d\n",
8065 mp->ka_tx_cnt, mp->ka_rx_cnt);
8066 vty_out(vty, " SAs : %10d %10d\n",
8067 mp->sa_tx_cnt, mp->sa_rx_cnt);
8068 vty_out(vty, "\n");
8069 }
8070 }
8071
8072 if (uj) {
8073 vty_out(vty, "%s\n", json_object_to_json_string_ext(
8074 json, JSON_C_TO_STRING_PRETTY));
8075 json_object_free(json);
8076 }
8077 }
8078
8079 DEFUN (show_ip_msdp_peer_detail,
8080 show_ip_msdp_peer_detail_cmd,
8081 "show ip msdp [vrf NAME] peer [detail|A.B.C.D] [json]",
8082 SHOW_STR
8083 IP_STR
8084 MSDP_STR
8085 VRF_CMD_HELP_STR
8086 "MSDP peer information\n"
8087 "Detailed output\n"
8088 "peer ip address\n"
8089 JSON_STR)
8090 {
8091 u_char uj = use_json(argc, argv);
8092 int idx = 2;
8093 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
8094
8095 if (!vrf)
8096 return CMD_WARNING;
8097
8098 char *arg = NULL;
8099
8100 if (argv_find(argv, argc, "detail", &idx))
8101 arg = argv[idx]->text;
8102 else if (argv_find(argv, argc, "A.B.C.D", &idx))
8103 arg = argv[idx]->arg;
8104
8105 if (arg)
8106 ip_msdp_show_peers_detail(vrf->info, vty, argv[idx]->arg, uj);
8107 else
8108 ip_msdp_show_peers(vrf->info, vty, uj);
8109
8110 return CMD_SUCCESS;
8111 }
8112
8113 DEFUN (show_ip_msdp_peer_detail_vrf_all,
8114 show_ip_msdp_peer_detail_vrf_all_cmd,
8115 "show ip msdp vrf all peer [detail|A.B.C.D] [json]",
8116 SHOW_STR
8117 IP_STR
8118 MSDP_STR
8119 VRF_CMD_HELP_STR
8120 "MSDP peer information\n"
8121 "Detailed output\n"
8122 "peer ip address\n"
8123 JSON_STR)
8124 {
8125 int idx = 2;
8126 u_char uj = use_json(argc, argv);
8127 struct vrf *vrf;
8128 bool first = true;
8129
8130 if (uj)
8131 vty_out(vty, "{ ");
8132 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
8133 if (uj) {
8134 if (!first)
8135 vty_out(vty, ", ");
8136 vty_out(vty, " \"%s\": ", vrf->name);
8137 first = false;
8138 } else
8139 vty_out(vty, "VRF: %s\n", vrf->name);
8140 if (argv_find(argv, argc, "detail", &idx)
8141 || argv_find(argv, argc, "A.B.C.D", &idx))
8142 ip_msdp_show_peers_detail(vrf->info, vty,
8143 argv[idx]->arg, uj);
8144 else
8145 ip_msdp_show_peers(vrf->info, vty, uj);
8146 }
8147 if (uj)
8148 vty_out(vty, "}\n");
8149
8150 return CMD_SUCCESS;
8151 }
8152
8153 static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty,
8154 u_char uj)
8155 {
8156 struct listnode *sanode;
8157 struct pim_msdp_sa *sa;
8158 char src_str[INET_ADDRSTRLEN];
8159 char grp_str[INET_ADDRSTRLEN];
8160 char rp_str[INET_ADDRSTRLEN];
8161 char timebuf[PIM_MSDP_UPTIME_STRLEN];
8162 char spt_str[8];
8163 char local_str[8];
8164 int64_t now;
8165 json_object *json = NULL;
8166 json_object *json_group = NULL;
8167 json_object *json_row = NULL;
8168
8169 if (uj) {
8170 json = json_object_new_object();
8171 } else {
8172 vty_out(vty,
8173 "Source Group RP Local SPT Uptime\n");
8174 }
8175
8176 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
8177 now = pim_time_monotonic_sec();
8178 pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime);
8179 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
8180 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
8181 if (sa->flags & PIM_MSDP_SAF_PEER) {
8182 pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
8183 if (sa->up) {
8184 strcpy(spt_str, "yes");
8185 } else {
8186 strcpy(spt_str, "no");
8187 }
8188 } else {
8189 strcpy(rp_str, "-");
8190 strcpy(spt_str, "-");
8191 }
8192 if (sa->flags & PIM_MSDP_SAF_LOCAL) {
8193 strcpy(local_str, "yes");
8194 } else {
8195 strcpy(local_str, "no");
8196 }
8197 if (uj) {
8198 json_object_object_get_ex(json, grp_str, &json_group);
8199
8200 if (!json_group) {
8201 json_group = json_object_new_object();
8202 json_object_object_add(json, grp_str,
8203 json_group);
8204 }
8205
8206 json_row = json_object_new_object();
8207 json_object_string_add(json_row, "source", src_str);
8208 json_object_string_add(json_row, "group", grp_str);
8209 json_object_string_add(json_row, "rp", rp_str);
8210 json_object_string_add(json_row, "local", local_str);
8211 json_object_string_add(json_row, "sptSetup", spt_str);
8212 json_object_string_add(json_row, "upTime", timebuf);
8213 json_object_object_add(json_group, src_str, json_row);
8214 } else {
8215 vty_out(vty, "%-15s %15s %15s %5c %3c %8s\n",
8216 src_str, grp_str, rp_str, local_str[0],
8217 spt_str[0], timebuf);
8218 }
8219 }
8220
8221 if (uj) {
8222 vty_out(vty, "%s\n", json_object_to_json_string_ext(
8223 json, JSON_C_TO_STRING_PRETTY));
8224 json_object_free(json);
8225 }
8226 }
8227
8228 static void ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa,
8229 const char *src_str,
8230 const char *grp_str, struct vty *vty,
8231 u_char uj, json_object *json)
8232 {
8233 char rp_str[INET_ADDRSTRLEN];
8234 char peer_str[INET_ADDRSTRLEN];
8235 char timebuf[PIM_MSDP_UPTIME_STRLEN];
8236 char spt_str[8];
8237 char local_str[8];
8238 char statetimer[PIM_MSDP_TIMER_STRLEN];
8239 int64_t now;
8240 json_object *json_group = NULL;
8241 json_object *json_row = NULL;
8242
8243 now = pim_time_monotonic_sec();
8244 pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime);
8245 if (sa->flags & PIM_MSDP_SAF_PEER) {
8246 pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str));
8247 pim_inet4_dump("<peer?>", sa->peer, peer_str, sizeof(peer_str));
8248 if (sa->up) {
8249 strcpy(spt_str, "yes");
8250 } else {
8251 strcpy(spt_str, "no");
8252 }
8253 } else {
8254 strcpy(rp_str, "-");
8255 strcpy(peer_str, "-");
8256 strcpy(spt_str, "-");
8257 }
8258 if (sa->flags & PIM_MSDP_SAF_LOCAL) {
8259 strcpy(local_str, "yes");
8260 } else {
8261 strcpy(local_str, "no");
8262 }
8263 pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer),
8264 sa->sa_state_timer);
8265 if (uj) {
8266 json_object_object_get_ex(json, grp_str, &json_group);
8267
8268 if (!json_group) {
8269 json_group = json_object_new_object();
8270 json_object_object_add(json, grp_str, json_group);
8271 }
8272
8273 json_row = json_object_new_object();
8274 json_object_string_add(json_row, "source", src_str);
8275 json_object_string_add(json_row, "group", grp_str);
8276 json_object_string_add(json_row, "rp", rp_str);
8277 json_object_string_add(json_row, "local", local_str);
8278 json_object_string_add(json_row, "sptSetup", spt_str);
8279 json_object_string_add(json_row, "upTime", timebuf);
8280 json_object_string_add(json_row, "stateTimer", statetimer);
8281 json_object_object_add(json_group, src_str, json_row);
8282 } else {
8283 vty_out(vty, "SA : %s\n", sa->sg_str);
8284 vty_out(vty, " RP : %s\n", rp_str);
8285 vty_out(vty, " Peer : %s\n", peer_str);
8286 vty_out(vty, " Local : %s\n", local_str);
8287 vty_out(vty, " SPT Setup : %s\n", spt_str);
8288 vty_out(vty, " Uptime : %s\n", timebuf);
8289 vty_out(vty, " State Timer : %s\n", statetimer);
8290 vty_out(vty, "\n");
8291 }
8292 }
8293
8294 static void ip_msdp_show_sa_detail(struct pim_instance *pim, struct vty *vty,
8295 u_char uj)
8296 {
8297 struct listnode *sanode;
8298 struct pim_msdp_sa *sa;
8299 char src_str[INET_ADDRSTRLEN];
8300 char grp_str[INET_ADDRSTRLEN];
8301 json_object *json = NULL;
8302
8303 if (uj) {
8304 json = json_object_new_object();
8305 }
8306
8307 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
8308 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
8309 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
8310 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj,
8311 json);
8312 }
8313
8314 if (uj) {
8315 vty_out(vty, "%s\n", json_object_to_json_string_ext(
8316 json, JSON_C_TO_STRING_PRETTY));
8317 json_object_free(json);
8318 }
8319 }
8320
8321 DEFUN (show_ip_msdp_sa_detail,
8322 show_ip_msdp_sa_detail_cmd,
8323 "show ip msdp [vrf NAME] sa detail [json]",
8324 SHOW_STR
8325 IP_STR
8326 MSDP_STR
8327 VRF_CMD_HELP_STR
8328 "MSDP active-source information\n"
8329 "Detailed output\n"
8330 JSON_STR)
8331 {
8332 u_char uj = use_json(argc, argv);
8333 int idx = 2;
8334 struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
8335
8336 if (!vrf)
8337 return CMD_WARNING;
8338
8339 ip_msdp_show_sa_detail(vrf->info, vty, uj);
8340
8341 return CMD_SUCCESS;
8342 }
8343
8344 DEFUN (show_ip_msdp_sa_detail_vrf_all,
8345 show_ip_msdp_sa_detail_vrf_all_cmd,
8346 "show ip msdp vrf all sa detail [json]",
8347 SHOW_STR
8348 IP_STR
8349 MSDP_STR
8350 VRF_CMD_HELP_STR
8351 "MSDP active-source information\n"
8352 "Detailed output\n"
8353 JSON_STR)
8354 {
8355 u_char uj = use_json(argc, argv);
8356 struct vrf *vrf;
8357 bool first = true;
8358
8359 if (uj)
8360 vty_out(vty, "{ ");
8361 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
8362 if (uj) {
8363 if (!first)
8364 vty_out(vty, ", ");
8365 vty_out(vty, " \"%s\": ", vrf->name);
8366 first = false;
8367 } else
8368 vty_out(vty, "VRF: %s\n", vrf->name);
8369 ip_msdp_show_sa_detail(vrf->info, vty, uj);
8370 }
8371 if (uj)
8372 vty_out(vty, "}\n");
8373
8374 return CMD_SUCCESS;
8375 }
8376
8377 static void ip_msdp_show_sa_addr(struct pim_instance *pim, struct vty *vty,
8378 const char *addr, u_char uj)
8379 {
8380 struct listnode *sanode;
8381 struct pim_msdp_sa *sa;
8382 char src_str[INET_ADDRSTRLEN];
8383 char grp_str[INET_ADDRSTRLEN];
8384 json_object *json = NULL;
8385
8386 if (uj) {
8387 json = json_object_new_object();
8388 }
8389
8390 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
8391 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
8392 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
8393 if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) {
8394 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty,
8395 uj, json);
8396 }
8397 }
8398
8399 if (uj) {
8400 vty_out(vty, "%s\n", json_object_to_json_string_ext(
8401 json, JSON_C_TO_STRING_PRETTY));
8402 json_object_free(json);
8403 }
8404 }
8405
8406 static void ip_msdp_show_sa_sg(struct pim_instance *pim, struct vty *vty,
8407 const char *src, const char *grp, u_char uj)
8408 {
8409 struct listnode *sanode;
8410 struct pim_msdp_sa *sa;
8411 char src_str[INET_ADDRSTRLEN];
8412 char grp_str[INET_ADDRSTRLEN];
8413 json_object *json = NULL;
8414
8415 if (uj) {
8416 json = json_object_new_object();
8417 }
8418
8419 for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) {
8420 pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str));
8421 pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));
8422 if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) {
8423 ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty,
8424 uj, json);
8425 }
8426 }
8427
8428 if (uj) {
8429 vty_out(vty, "%s\n", json_object_to_json_string_ext(
8430 json, JSON_C_TO_STRING_PRETTY));
8431 json_object_free(json);
8432 }
8433 }
8434
8435 DEFUN (show_ip_msdp_sa_sg,
8436 show_ip_msdp_sa_sg_cmd,
8437 "show ip msdp [vrf NAME] sa [A.B.C.D [A.B.C.D]] [json]",
8438 SHOW_STR
8439 IP_STR
8440 MSDP_STR
8441 VRF_CMD_HELP_STR
8442 "MSDP active-source information\n"
8443 "source or group ip\n"
8444 "group ip\n"
8445 JSON_STR)
8446 {
8447 u_char uj = use_json(argc, argv);
8448 struct vrf *vrf;
8449 int idx = 2;
8450
8451 vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
8452
8453 if (!vrf)
8454 return CMD_WARNING;
8455
8456 char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg
8457 : NULL;
8458 char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx)
8459 ? argv[idx]->arg
8460 : NULL;
8461
8462 if (src_ip && grp_ip)
8463 ip_msdp_show_sa_sg(vrf->info, vty, src_ip, grp_ip, uj);
8464 else if (src_ip)
8465 ip_msdp_show_sa_addr(vrf->info, vty, src_ip, uj);
8466 else
8467 ip_msdp_show_sa(vrf->info, vty, uj);
8468
8469 return CMD_SUCCESS;
8470 }
8471
8472 DEFUN (show_ip_msdp_sa_sg_vrf_all,
8473 show_ip_msdp_sa_sg_vrf_all_cmd,
8474 "show ip msdp vrf all sa [A.B.C.D [A.B.C.D]] [json]",
8475 SHOW_STR
8476 IP_STR
8477 MSDP_STR
8478 VRF_CMD_HELP_STR
8479 "MSDP active-source information\n"
8480 "source or group ip\n"
8481 "group ip\n"
8482 JSON_STR)
8483 {
8484 u_char uj = use_json(argc, argv);
8485 struct vrf *vrf;
8486 bool first = true;
8487 int idx = 2;
8488
8489 char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg
8490 : NULL;
8491 char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx)
8492 ? argv[idx]->arg
8493 : NULL;
8494
8495 if (uj)
8496 vty_out(vty, "{ ");
8497 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
8498 if (uj) {
8499 if (!first)
8500 vty_out(vty, ", ");
8501 vty_out(vty, " \"%s\": ", vrf->name);
8502 first = false;
8503 } else
8504 vty_out(vty, "VRF: %s\n", vrf->name);
8505
8506 if (src_ip && grp_ip)
8507 ip_msdp_show_sa_sg(vrf->info, vty, src_ip, grp_ip, uj);
8508 else if (src_ip)
8509 ip_msdp_show_sa_addr(vrf->info, vty, src_ip, uj);
8510 else
8511 ip_msdp_show_sa(vrf->info, vty, uj);
8512 }
8513 if (uj)
8514 vty_out(vty, "}\n");
8515
8516 return CMD_SUCCESS;
8517 }
8518
8519
8520 void pim_cmd_init(void)
8521 {
8522 install_node(&interface_node,
8523 pim_interface_config_write); /* INTERFACE_NODE */
8524 if_cmd_init();
8525
8526 install_node(&debug_node, pim_debug_config_write);
8527
8528 install_element(CONFIG_NODE, &ip_multicast_routing_cmd);
8529 install_element(CONFIG_NODE, &no_ip_multicast_routing_cmd);
8530 install_element(CONFIG_NODE, &ip_pim_rp_cmd);
8531 install_element(VRF_NODE, &ip_pim_rp_cmd);
8532 install_element(CONFIG_NODE, &no_ip_pim_rp_cmd);
8533 install_element(VRF_NODE, &no_ip_pim_rp_cmd);
8534 install_element(CONFIG_NODE, &ip_pim_rp_prefix_list_cmd);
8535 install_element(VRF_NODE, &ip_pim_rp_prefix_list_cmd);
8536 install_element(CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd);
8537 install_element(VRF_NODE, &no_ip_pim_rp_prefix_list_cmd);
8538 install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd);
8539 install_element(VRF_NODE, &no_ip_pim_ssm_prefix_list_cmd);
8540 install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
8541 install_element(VRF_NODE, &no_ip_pim_ssm_prefix_list_name_cmd);
8542 install_element(CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd);
8543 install_element(VRF_NODE, &ip_pim_ssm_prefix_list_cmd);
8544 install_element(CONFIG_NODE, &ip_pim_register_suppress_cmd);
8545 install_element(VRF_NODE, &ip_pim_register_suppress_cmd);
8546 install_element(CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
8547 install_element(VRF_NODE, &no_ip_pim_register_suppress_cmd);
8548 install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd);
8549 install_element(VRF_NODE, &ip_pim_spt_switchover_infinity_cmd);
8550 install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
8551 install_element(VRF_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
8552 install_element(CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
8553 install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
8554 install_element(CONFIG_NODE,
8555 &no_ip_pim_spt_switchover_infinity_plist_cmd);
8556 install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd);
8557 install_element(CONFIG_NODE, &ip_pim_joinprune_time_cmd);
8558 install_element(VRF_NODE, &ip_pim_joinprune_time_cmd);
8559 install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
8560 install_element(VRF_NODE, &no_ip_pim_joinprune_time_cmd);
8561 install_element(CONFIG_NODE, &ip_pim_keep_alive_cmd);
8562 install_element(VRF_NODE, &ip_pim_keep_alive_cmd);
8563 install_element(CONFIG_NODE, &ip_pim_rp_keep_alive_cmd);
8564 install_element(VRF_NODE, &ip_pim_rp_keep_alive_cmd);
8565 install_element(CONFIG_NODE, &no_ip_pim_keep_alive_cmd);
8566 install_element(VRF_NODE, &no_ip_pim_keep_alive_cmd);
8567 install_element(CONFIG_NODE, &no_ip_pim_rp_keep_alive_cmd);
8568 install_element(VRF_NODE, &no_ip_pim_rp_keep_alive_cmd);
8569 install_element(CONFIG_NODE, &ip_pim_packets_cmd);
8570 install_element(VRF_NODE, &ip_pim_packets_cmd);
8571 install_element(CONFIG_NODE, &no_ip_pim_packets_cmd);
8572 install_element(VRF_NODE, &no_ip_pim_packets_cmd);
8573 install_element(CONFIG_NODE, &ip_pim_v6_secondary_cmd);
8574 install_element(VRF_NODE, &ip_pim_v6_secondary_cmd);
8575 install_element(CONFIG_NODE, &no_ip_pim_v6_secondary_cmd);
8576 install_element(VRF_NODE, &no_ip_pim_v6_secondary_cmd);
8577 install_element(CONFIG_NODE, &ip_ssmpingd_cmd);
8578 install_element(VRF_NODE, &ip_ssmpingd_cmd);
8579 install_element(CONFIG_NODE, &no_ip_ssmpingd_cmd);
8580 install_element(VRF_NODE, &no_ip_ssmpingd_cmd);
8581 install_element(CONFIG_NODE, &ip_msdp_peer_cmd);
8582 install_element(VRF_NODE, &ip_msdp_peer_cmd);
8583 install_element(CONFIG_NODE, &no_ip_msdp_peer_cmd);
8584 install_element(VRF_NODE, &no_ip_msdp_peer_cmd);
8585 install_element(CONFIG_NODE, &ip_pim_ecmp_cmd);
8586 install_element(VRF_NODE, &ip_pim_ecmp_cmd);
8587 install_element(CONFIG_NODE, &no_ip_pim_ecmp_cmd);
8588 install_element(VRF_NODE, &no_ip_pim_ecmp_cmd);
8589 install_element(CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd);
8590 install_element(VRF_NODE, &ip_pim_ecmp_rebalance_cmd);
8591 install_element(CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd);
8592 install_element(VRF_NODE, &no_ip_pim_ecmp_rebalance_cmd);
8593
8594 install_element(INTERFACE_NODE, &interface_ip_igmp_cmd);
8595 install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd);
8596 install_element(INTERFACE_NODE, &interface_ip_igmp_join_cmd);
8597 install_element(INTERFACE_NODE, &interface_no_ip_igmp_join_cmd);
8598 install_element(INTERFACE_NODE, &interface_ip_igmp_version_cmd);
8599 install_element(INTERFACE_NODE, &interface_no_ip_igmp_version_cmd);
8600 install_element(INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd);
8601 install_element(INTERFACE_NODE,
8602 &interface_no_ip_igmp_query_interval_cmd);
8603 install_element(INTERFACE_NODE,
8604 &interface_ip_igmp_query_max_response_time_cmd);
8605 install_element(INTERFACE_NODE,
8606 &interface_no_ip_igmp_query_max_response_time_cmd);
8607 install_element(INTERFACE_NODE,
8608 &interface_ip_igmp_query_max_response_time_dsec_cmd);
8609 install_element(INTERFACE_NODE,
8610 &interface_no_ip_igmp_query_max_response_time_dsec_cmd);
8611 install_element(INTERFACE_NODE, &interface_ip_pim_ssm_cmd);
8612 install_element(INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd);
8613 install_element(INTERFACE_NODE, &interface_ip_pim_sm_cmd);
8614 install_element(INTERFACE_NODE, &interface_no_ip_pim_sm_cmd);
8615 install_element(INTERFACE_NODE, &interface_ip_pim_drprio_cmd);
8616 install_element(INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd);
8617 install_element(INTERFACE_NODE, &interface_ip_pim_hello_cmd);
8618 install_element(INTERFACE_NODE, &interface_no_ip_pim_hello_cmd);
8619 install_element(INTERFACE_NODE, &interface_ip_pim_boundary_oil_cmd);
8620 install_element(INTERFACE_NODE, &interface_no_ip_pim_boundary_oil_cmd);
8621
8622 // Static mroutes NEB
8623 install_element(INTERFACE_NODE, &interface_ip_mroute_cmd);
8624 install_element(INTERFACE_NODE, &interface_ip_mroute_source_cmd);
8625 install_element(INTERFACE_NODE, &interface_no_ip_mroute_cmd);
8626 install_element(INTERFACE_NODE, &interface_no_ip_mroute_source_cmd);
8627
8628 install_element(VIEW_NODE, &show_ip_igmp_interface_cmd);
8629 install_element(VIEW_NODE, &show_ip_igmp_interface_vrf_all_cmd);
8630 install_element(VIEW_NODE, &show_ip_igmp_join_cmd);
8631 install_element(VIEW_NODE, &show_ip_igmp_join_vrf_all_cmd);
8632 install_element(VIEW_NODE, &show_ip_igmp_groups_cmd);
8633 install_element(VIEW_NODE, &show_ip_igmp_groups_vrf_all_cmd);
8634 install_element(VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd);
8635 install_element(VIEW_NODE, &show_ip_igmp_sources_cmd);
8636 install_element(VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd);
8637 install_element(VIEW_NODE, &show_ip_pim_assert_cmd);
8638 install_element(VIEW_NODE, &show_ip_pim_assert_internal_cmd);
8639 install_element(VIEW_NODE, &show_ip_pim_assert_metric_cmd);
8640 install_element(VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd);
8641 install_element(VIEW_NODE, &show_ip_pim_interface_traffic_cmd);
8642 install_element(VIEW_NODE, &show_ip_pim_interface_cmd);
8643 install_element(VIEW_NODE, &show_ip_pim_interface_vrf_all_cmd);
8644 install_element(VIEW_NODE, &show_ip_pim_join_cmd);
8645 install_element(VIEW_NODE, &show_ip_pim_join_vrf_all_cmd);
8646 install_element(VIEW_NODE, &show_ip_pim_local_membership_cmd);
8647 install_element(VIEW_NODE, &show_ip_pim_neighbor_cmd);
8648 install_element(VIEW_NODE, &show_ip_pim_neighbor_vrf_all_cmd);
8649 install_element(VIEW_NODE, &show_ip_pim_rpf_cmd);
8650 install_element(VIEW_NODE, &show_ip_pim_rpf_vrf_all_cmd);
8651 install_element(VIEW_NODE, &show_ip_pim_secondary_cmd);
8652 install_element(VIEW_NODE, &show_ip_pim_state_cmd);
8653 install_element(VIEW_NODE, &show_ip_pim_state_vrf_all_cmd);
8654 install_element(VIEW_NODE, &show_ip_pim_upstream_cmd);
8655 install_element(VIEW_NODE, &show_ip_pim_upstream_vrf_all_cmd);
8656 install_element(VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd);
8657 install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd);
8658 install_element(VIEW_NODE, &show_ip_pim_rp_cmd);
8659 install_element(VIEW_NODE, &show_ip_pim_rp_vrf_all_cmd);
8660 install_element(VIEW_NODE, &show_ip_multicast_cmd);
8661 install_element(VIEW_NODE, &show_ip_multicast_vrf_all_cmd);
8662 install_element(VIEW_NODE, &show_ip_mroute_cmd);
8663 install_element(VIEW_NODE, &show_ip_mroute_vrf_all_cmd);
8664 install_element(VIEW_NODE, &show_ip_mroute_count_cmd);
8665 install_element(VIEW_NODE, &show_ip_mroute_count_vrf_all_cmd);
8666 install_element(VIEW_NODE, &show_ip_rib_cmd);
8667 install_element(VIEW_NODE, &show_ip_ssmpingd_cmd);
8668 install_element(VIEW_NODE, &show_debugging_pim_cmd);
8669 install_element(VIEW_NODE, &show_ip_pim_nexthop_cmd);
8670 install_element(VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd);
8671
8672 install_element(ENABLE_NODE, &clear_ip_interfaces_cmd);
8673 install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd);
8674 install_element(ENABLE_NODE, &clear_ip_mroute_cmd);
8675 install_element(ENABLE_NODE, &clear_ip_pim_interfaces_cmd);
8676 install_element(ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd);
8677 install_element(ENABLE_NODE, &clear_ip_pim_oil_cmd);
8678
8679 install_element(ENABLE_NODE, &debug_igmp_cmd);
8680 install_element(ENABLE_NODE, &no_debug_igmp_cmd);
8681 install_element(ENABLE_NODE, &debug_igmp_events_cmd);
8682 install_element(ENABLE_NODE, &no_debug_igmp_events_cmd);
8683 install_element(ENABLE_NODE, &debug_igmp_packets_cmd);
8684 install_element(ENABLE_NODE, &no_debug_igmp_packets_cmd);
8685 install_element(ENABLE_NODE, &debug_igmp_trace_cmd);
8686 install_element(ENABLE_NODE, &no_debug_igmp_trace_cmd);
8687 install_element(ENABLE_NODE, &debug_mroute_cmd);
8688 install_element(ENABLE_NODE, &debug_mroute_detail_cmd);
8689 install_element(ENABLE_NODE, &no_debug_mroute_cmd);
8690 install_element(ENABLE_NODE, &no_debug_mroute_detail_cmd);
8691 install_element(ENABLE_NODE, &debug_static_cmd);
8692 install_element(ENABLE_NODE, &no_debug_static_cmd);
8693 install_element(ENABLE_NODE, &debug_pim_cmd);
8694 install_element(ENABLE_NODE, &no_debug_pim_cmd);
8695 install_element(ENABLE_NODE, &debug_pim_nht_cmd);
8696 install_element(ENABLE_NODE, &no_debug_pim_nht_cmd);
8697 install_element(ENABLE_NODE, &debug_pim_nht_rp_cmd);
8698 install_element(ENABLE_NODE, &no_debug_pim_nht_rp_cmd);
8699 install_element(ENABLE_NODE, &debug_pim_events_cmd);
8700 install_element(ENABLE_NODE, &no_debug_pim_events_cmd);
8701 install_element(ENABLE_NODE, &debug_pim_packets_cmd);
8702 install_element(ENABLE_NODE, &no_debug_pim_packets_cmd);
8703 install_element(ENABLE_NODE, &debug_pim_packetdump_send_cmd);
8704 install_element(ENABLE_NODE, &no_debug_pim_packetdump_send_cmd);
8705 install_element(ENABLE_NODE, &debug_pim_packetdump_recv_cmd);
8706 install_element(ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd);
8707 install_element(ENABLE_NODE, &debug_pim_trace_cmd);
8708 install_element(ENABLE_NODE, &no_debug_pim_trace_cmd);
8709 install_element(ENABLE_NODE, &debug_pim_trace_detail_cmd);
8710 install_element(ENABLE_NODE, &no_debug_pim_trace_detail_cmd);
8711 install_element(ENABLE_NODE, &debug_ssmpingd_cmd);
8712 install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd);
8713 install_element(ENABLE_NODE, &debug_pim_zebra_cmd);
8714 install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd);
8715 install_element(ENABLE_NODE, &debug_msdp_cmd);
8716 install_element(ENABLE_NODE, &no_debug_msdp_cmd);
8717 install_element(ENABLE_NODE, &undebug_msdp_cmd);
8718 install_element(ENABLE_NODE, &debug_msdp_events_cmd);
8719 install_element(ENABLE_NODE, &no_debug_msdp_events_cmd);
8720 install_element(ENABLE_NODE, &undebug_msdp_events_cmd);
8721 install_element(ENABLE_NODE, &debug_msdp_packets_cmd);
8722 install_element(ENABLE_NODE, &no_debug_msdp_packets_cmd);
8723 install_element(ENABLE_NODE, &undebug_msdp_packets_cmd);
8724
8725 install_element(CONFIG_NODE, &debug_igmp_cmd);
8726 install_element(CONFIG_NODE, &no_debug_igmp_cmd);
8727 install_element(CONFIG_NODE, &debug_igmp_events_cmd);
8728 install_element(CONFIG_NODE, &no_debug_igmp_events_cmd);
8729 install_element(CONFIG_NODE, &debug_igmp_packets_cmd);
8730 install_element(CONFIG_NODE, &no_debug_igmp_packets_cmd);
8731 install_element(CONFIG_NODE, &debug_igmp_trace_cmd);
8732 install_element(CONFIG_NODE, &no_debug_igmp_trace_cmd);
8733 install_element(CONFIG_NODE, &debug_mroute_cmd);
8734 install_element(CONFIG_NODE, &debug_mroute_detail_cmd);
8735 install_element(CONFIG_NODE, &no_debug_mroute_cmd);
8736 install_element(CONFIG_NODE, &no_debug_mroute_detail_cmd);
8737 install_element(CONFIG_NODE, &debug_static_cmd);
8738 install_element(CONFIG_NODE, &no_debug_static_cmd);
8739 install_element(CONFIG_NODE, &debug_pim_cmd);
8740 install_element(CONFIG_NODE, &no_debug_pim_cmd);
8741 install_element(CONFIG_NODE, &debug_pim_nht_cmd);
8742 install_element(CONFIG_NODE, &no_debug_pim_nht_cmd);
8743 install_element(CONFIG_NODE, &debug_pim_nht_rp_cmd);
8744 install_element(CONFIG_NODE, &no_debug_pim_nht_rp_cmd);
8745 install_element(CONFIG_NODE, &debug_pim_events_cmd);
8746 install_element(CONFIG_NODE, &no_debug_pim_events_cmd);
8747 install_element(CONFIG_NODE, &debug_pim_packets_cmd);
8748 install_element(CONFIG_NODE, &no_debug_pim_packets_cmd);
8749 install_element(CONFIG_NODE, &debug_pim_trace_cmd);
8750 install_element(CONFIG_NODE, &no_debug_pim_trace_cmd);
8751 install_element(CONFIG_NODE, &debug_pim_trace_detail_cmd);
8752 install_element(CONFIG_NODE, &no_debug_pim_trace_detail_cmd);
8753 install_element(CONFIG_NODE, &debug_ssmpingd_cmd);
8754 install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd);
8755 install_element(CONFIG_NODE, &debug_pim_zebra_cmd);
8756 install_element(CONFIG_NODE, &no_debug_pim_zebra_cmd);
8757 install_element(CONFIG_NODE, &debug_msdp_cmd);
8758 install_element(CONFIG_NODE, &no_debug_msdp_cmd);
8759 install_element(CONFIG_NODE, &undebug_msdp_cmd);
8760 install_element(CONFIG_NODE, &debug_msdp_events_cmd);
8761 install_element(CONFIG_NODE, &no_debug_msdp_events_cmd);
8762 install_element(CONFIG_NODE, &undebug_msdp_events_cmd);
8763 install_element(CONFIG_NODE, &debug_msdp_packets_cmd);
8764 install_element(CONFIG_NODE, &no_debug_msdp_packets_cmd);
8765 install_element(CONFIG_NODE, &undebug_msdp_packets_cmd);
8766
8767 install_element(CONFIG_NODE, &ip_msdp_mesh_group_member_cmd);
8768 install_element(VRF_NODE, &ip_msdp_mesh_group_member_cmd);
8769 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd);
8770 install_element(VRF_NODE, &no_ip_msdp_mesh_group_member_cmd);
8771 install_element(CONFIG_NODE, &ip_msdp_mesh_group_source_cmd);
8772 install_element(VRF_NODE, &ip_msdp_mesh_group_source_cmd);
8773 install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd);
8774 install_element(VRF_NODE, &no_ip_msdp_mesh_group_source_cmd);
8775 install_element(VIEW_NODE, &show_ip_msdp_peer_detail_cmd);
8776 install_element(VIEW_NODE, &show_ip_msdp_peer_detail_vrf_all_cmd);
8777 install_element(VIEW_NODE, &show_ip_msdp_sa_detail_cmd);
8778 install_element(VIEW_NODE, &show_ip_msdp_sa_detail_vrf_all_cmd);
8779 install_element(VIEW_NODE, &show_ip_msdp_sa_sg_cmd);
8780 install_element(VIEW_NODE, &show_ip_msdp_sa_sg_vrf_all_cmd);
8781 install_element(VIEW_NODE, &show_ip_msdp_mesh_group_cmd);
8782 install_element(VIEW_NODE, &show_ip_msdp_mesh_group_vrf_all_cmd);
8783 install_element(VIEW_NODE, &show_ip_pim_ssm_range_cmd);
8784 install_element(VIEW_NODE, &show_ip_pim_group_type_cmd);
8785 install_element(INTERFACE_NODE, &interface_pim_use_source_cmd);
8786 install_element(INTERFACE_NODE, &interface_no_pim_use_source_cmd);
8787 /* Install BFD command */
8788 install_element(INTERFACE_NODE, &ip_pim_bfd_cmd);
8789 install_element(INTERFACE_NODE, &ip_pim_bfd_param_cmd);
8790 install_element(INTERFACE_NODE, &no_ip_pim_bfd_cmd);
8791 install_element(INTERFACE_NODE, &no_ip_pim_bfd_param_cmd);
8792 }