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