]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_cmd.c
pimd: Fix pim_nexthop_lookup
[mirror_frr.git] / pimd / pim_cmd.c
CommitLineData
12e41d03
DL
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
16 along with this program; see the file COPYING; if not, write to the
17 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
18 MA 02110-1301 USA
19
12e41d03
DL
20*/
21
12e41d03
DL
22#include <zebra.h>
23
9bf3c633 24#include "lib/json.h"
12e41d03
DL
25#include "command.h"
26#include "if.h"
27#include "prefix.h"
28#include "zclient.h"
dfe43e25 29#include "plist.h"
12e41d03
DL
30
31#include "pimd.h"
9867746a 32#include "pim_mroute.h"
12e41d03
DL
33#include "pim_cmd.h"
34#include "pim_iface.h"
35#include "pim_vty.h"
36#include "pim_mroute.h"
37#include "pim_str.h"
38#include "pim_igmp.h"
39#include "pim_igmpv3.h"
40#include "pim_sock.h"
41#include "pim_time.h"
42#include "pim_util.h"
43#include "pim_oil.h"
44#include "pim_neighbor.h"
45#include "pim_pim.h"
46#include "pim_ifchannel.h"
47#include "pim_hello.h"
48#include "pim_msg.h"
49#include "pim_upstream.h"
50#include "pim_rpf.h"
51#include "pim_macro.h"
52#include "pim_ssmpingd.h"
53#include "pim_zebra.h"
6250610a 54#include "pim_static.h"
a920d6e7 55#include "pim_rp.h"
05b0d0d0 56#include "pim_zlookup.h"
12e41d03
DL
57
58static struct cmd_node pim_global_node = {
59 PIM_NODE,
60 "",
61 1 /* vtysh ? yes */
62};
63
64static struct cmd_node interface_node = {
65 INTERFACE_NODE,
66 "%s(config-if)# ",
67 1 /* vtysh ? yes */
68};
69
eb7a976a
DS
70static struct cmd_node debug_node =
71{
72 DEBUG_NODE,
73 "",
74 1
75};
76
12e41d03
DL
77static void pim_if_membership_clear(struct interface *ifp)
78{
79 struct pim_interface *pim_ifp;
80
81 pim_ifp = ifp->info;
82 zassert(pim_ifp);
83
84 if (PIM_IF_TEST_PIM(pim_ifp->options) &&
85 PIM_IF_TEST_IGMP(pim_ifp->options)) {
86 return;
87 }
88
89 pim_ifchannel_membership_clear(ifp);
90}
91
92/*
93 When PIM is disabled on interface, IGMPv3 local membership
94 information is not injected into PIM interface state.
95
96 The function pim_if_membership_refresh() fetches all IGMPv3 local
97 membership information into PIM. It is intented to be called
98 whenever PIM is enabled on the interface in order to collect missed
99 local membership information.
100 */
101static void pim_if_membership_refresh(struct interface *ifp)
102{
103 struct pim_interface *pim_ifp;
104 struct listnode *sock_node;
105 struct igmp_sock *igmp;
106
107 pim_ifp = ifp->info;
108 zassert(pim_ifp);
109
110 if (!PIM_IF_TEST_PIM(pim_ifp->options))
111 return;
112 if (!PIM_IF_TEST_IGMP(pim_ifp->options))
113 return;
114
115 /*
116 First clear off membership from all PIM (S,G) entries on the
117 interface
118 */
119
120 pim_ifchannel_membership_clear(ifp);
121
122 /*
123 Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on
124 the interface
125 */
126
127 /* scan igmp sockets */
128 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
129 struct listnode *grpnode;
130 struct igmp_group *grp;
131
132 /* scan igmp groups */
133 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
134 struct listnode *srcnode;
135 struct igmp_source *src;
136
137 /* scan group sources */
138 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) {
139
140 if (IGMP_SOURCE_TEST_FORWARDING(src->source_flags)) {
4ed0af70 141 struct prefix_sg sg;
69283639 142
4ed0af70
DS
143 memset (&sg, 0, sizeof (struct prefix_sg));
144 sg.src = src->source_addr;
145 sg.grp = grp->group_addr;
69283639 146 pim_ifchannel_local_membership_add(ifp, &sg);
12e41d03
DL
147 }
148
149 } /* scan group sources */
150 } /* scan igmp groups */
151 } /* scan igmp sockets */
152
153 /*
154 Finally delete every PIM (S,G) entry lacking all state info
155 */
156
157 pim_ifchannel_delete_on_noinfo(ifp);
158
159}
160
161static void pim_show_assert(struct vty *vty)
162{
163 struct listnode *ifnode;
164 struct interface *ifp;
165 time_t now;
166
167 now = pim_time_monotonic_sec();
168
169 vty_out(vty,
170 "Interface Address Source Group State Winner Uptime Timer%s",
171 VTY_NEWLINE);
172
469351b3 173 for (ALL_LIST_ELEMENTS_RO(vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
12e41d03
DL
174 struct pim_interface *pim_ifp;
175 struct in_addr ifaddr;
176 struct listnode *ch_node;
177 struct pim_ifchannel *ch;
178
179 pim_ifp = ifp->info;
180
181 if (!pim_ifp)
182 continue;
183
184 ifaddr = pim_ifp->primary_address;
185
186 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
eaa54bdb
DW
187 char ch_src_str[INET_ADDRSTRLEN];
188 char ch_grp_str[INET_ADDRSTRLEN];
189 char winner_str[INET_ADDRSTRLEN];
12e41d03
DL
190 char uptime[10];
191 char timer[10];
192
4ed0af70 193 pim_inet4_dump("<ch_src?>", ch->sg.src,
12e41d03 194 ch_src_str, sizeof(ch_src_str));
4ed0af70 195 pim_inet4_dump("<ch_grp?>", ch->sg.grp,
12e41d03
DL
196 ch_grp_str, sizeof(ch_grp_str));
197 pim_inet4_dump("<assrt_win?>", ch->ifassert_winner,
198 winner_str, sizeof(winner_str));
199
200 pim_time_uptime(uptime, sizeof(uptime), now - ch->ifassert_creation);
201 pim_time_timer_to_mmss(timer, sizeof(timer),
202 ch->t_ifassert_timer);
203
204 vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s%s",
205 ifp->name,
206 inet_ntoa(ifaddr),
207 ch_src_str,
208 ch_grp_str,
209 pim_ifchannel_ifassert_name(ch->ifassert_state),
210 winner_str,
211 uptime,
212 timer,
213 VTY_NEWLINE);
214 } /* scan interface channels */
215 } /* scan interfaces */
216}
217
218static void pim_show_assert_internal(struct vty *vty)
219{
220 struct listnode *ifnode;
221 struct interface *ifp;
222
223 vty_out(vty,
224 "CA: CouldAssert%s"
225 "ECA: Evaluate CouldAssert%s"
226 "ATD: AssertTrackingDesired%s"
227 "eATD: Evaluate AssertTrackingDesired%s%s",
228 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
229
230 vty_out(vty,
231 "Interface Address Source Group CA eCA ATD eATD%s",
232 VTY_NEWLINE);
233
469351b3 234 for (ALL_LIST_ELEMENTS_RO(vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
12e41d03
DL
235 struct pim_interface *pim_ifp;
236 struct in_addr ifaddr;
237 struct listnode *ch_node;
238 struct pim_ifchannel *ch;
239
240 pim_ifp = ifp->info;
241
242 if (!pim_ifp)
243 continue;
244
245 ifaddr = pim_ifp->primary_address;
246
247 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
eaa54bdb
DW
248 char ch_src_str[INET_ADDRSTRLEN];
249 char ch_grp_str[INET_ADDRSTRLEN];
12e41d03 250
4ed0af70 251 pim_inet4_dump("<ch_src?>", ch->sg.src,
12e41d03 252 ch_src_str, sizeof(ch_src_str));
4ed0af70 253 pim_inet4_dump("<ch_grp?>", ch->sg.grp,
12e41d03
DL
254 ch_grp_str, sizeof(ch_grp_str));
255 vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s%s",
256 ifp->name,
257 inet_ntoa(ifaddr),
258 ch_src_str,
259 ch_grp_str,
260 PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no",
261 pim_macro_ch_could_assert_eval(ch) ? "yes" : "no",
262 PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags) ? "yes" : "no",
263 pim_macro_assert_tracking_desired_eval(ch) ? "yes" : "no",
264 VTY_NEWLINE);
265 } /* scan interface channels */
266 } /* scan interfaces */
267}
268
269static void pim_show_assert_metric(struct vty *vty)
270{
271 struct listnode *ifnode;
272 struct interface *ifp;
273
274 vty_out(vty,
275 "Interface Address Source Group RPT Pref Metric Address %s",
276 VTY_NEWLINE);
277
469351b3 278 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
12e41d03
DL
279 struct pim_interface *pim_ifp;
280 struct in_addr ifaddr;
281 struct listnode *ch_node;
282 struct pim_ifchannel *ch;
283
284 pim_ifp = ifp->info;
285
286 if (!pim_ifp)
287 continue;
288
289 ifaddr = pim_ifp->primary_address;
290
291 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
eaa54bdb
DW
292 char ch_src_str[INET_ADDRSTRLEN];
293 char ch_grp_str[INET_ADDRSTRLEN];
294 char addr_str[INET_ADDRSTRLEN];
12e41d03
DL
295 struct pim_assert_metric am;
296
297 am = pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address);
298
4ed0af70 299 pim_inet4_dump("<ch_src?>", ch->sg.src,
12e41d03 300 ch_src_str, sizeof(ch_src_str));
4ed0af70 301 pim_inet4_dump("<ch_grp?>", ch->sg.grp,
12e41d03
DL
302 ch_grp_str, sizeof(ch_grp_str));
303 pim_inet4_dump("<addr?>", am.ip_address,
304 addr_str, sizeof(addr_str));
305
306 vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s%s",
307 ifp->name,
308 inet_ntoa(ifaddr),
309 ch_src_str,
310 ch_grp_str,
311 am.rpt_bit_flag ? "yes" : "no",
312 am.metric_preference,
313 am.route_metric,
314 addr_str,
315 VTY_NEWLINE);
316 } /* scan interface channels */
317 } /* scan interfaces */
318}
319
320static void pim_show_assert_winner_metric(struct vty *vty)
321{
322 struct listnode *ifnode;
323 struct interface *ifp;
324
325 vty_out(vty,
326 "Interface Address Source Group RPT Pref Metric Address %s",
327 VTY_NEWLINE);
328
469351b3 329 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
12e41d03
DL
330 struct pim_interface *pim_ifp;
331 struct in_addr ifaddr;
332 struct listnode *ch_node;
333 struct pim_ifchannel *ch;
334
335 pim_ifp = ifp->info;
336
337 if (!pim_ifp)
338 continue;
339
340 ifaddr = pim_ifp->primary_address;
341
342 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
eaa54bdb
DW
343 char ch_src_str[INET_ADDRSTRLEN];
344 char ch_grp_str[INET_ADDRSTRLEN];
345 char addr_str[INET_ADDRSTRLEN];
12e41d03
DL
346 struct pim_assert_metric *am;
347 char pref_str[5];
348 char metr_str[7];
349
350 am = &ch->ifassert_winner_metric;
351
4ed0af70 352 pim_inet4_dump("<ch_src?>", ch->sg.src,
12e41d03 353 ch_src_str, sizeof(ch_src_str));
4ed0af70 354 pim_inet4_dump("<ch_grp?>", ch->sg.grp,
12e41d03
DL
355 ch_grp_str, sizeof(ch_grp_str));
356 pim_inet4_dump("<addr?>", am->ip_address,
357 addr_str, sizeof(addr_str));
358
359 if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX)
360 snprintf(pref_str, sizeof(pref_str), "INFI");
361 else
362 snprintf(pref_str, sizeof(pref_str), "%4u", am->metric_preference);
363
364 if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX)
365 snprintf(metr_str, sizeof(metr_str), "INFI");
366 else
367 snprintf(metr_str, sizeof(metr_str), "%6u", am->route_metric);
368
369 vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s%s",
370 ifp->name,
371 inet_ntoa(ifaddr),
372 ch_src_str,
373 ch_grp_str,
374 am->rpt_bit_flag ? "yes" : "no",
375 pref_str,
376 metr_str,
377 addr_str,
378 VTY_NEWLINE);
379 } /* scan interface channels */
380 } /* scan interfaces */
381}
382
e775c0a4
DW
383static void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp)
384{
385 struct pim_interface *pim_ifp;
386
387 pim_ifp = ifp->info;
388 json_object_string_add(json, "name", ifp->name);
389 json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down");
390 json_object_string_add(json, "address", inet_ntoa(pim_ifp->primary_address));
391 json_object_int_add(json, "index", ifp->ifindex);
392
393 if (if_is_multicast(ifp))
394 json_object_boolean_true_add(json, "flagMulticast");
395
396 if (if_is_broadcast(ifp))
397 json_object_boolean_true_add(json, "flagBroadcast");
398
399 if (ifp->flags & IFF_ALLMULTI)
400 json_object_boolean_true_add(json, "flagAllMulticast");
401
402 if (ifp->flags & IFF_PROMISC)
403 json_object_boolean_true_add(json, "flagPromiscuous");
404
405 if (PIM_IF_IS_DELETED(ifp))
406 json_object_boolean_true_add(json, "flagDeleted");
407
408 if (pim_if_lan_delay_enabled(ifp))
409 json_object_boolean_true_add(json, "lanDelayEnabled");
410}
411
412static void pim_show_membership(struct vty *vty, u_char uj)
12e41d03
DL
413{
414 struct listnode *ifnode;
415 struct interface *ifp;
e775c0a4
DW
416 json_object *json = NULL;
417 json_object *json_iface = NULL;
418 json_object *json_row = NULL;
12e41d03 419
e775c0a4
DW
420 if (uj)
421 json = json_object_new_object();
422 else
423 vty_out(vty,
424 "Interface Address Source Group Membership%s",
425 VTY_NEWLINE);
12e41d03 426
469351b3 427 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
12e41d03
DL
428 struct pim_interface *pim_ifp;
429 struct in_addr ifaddr;
430 struct listnode *ch_node;
431 struct pim_ifchannel *ch;
432
433 pim_ifp = ifp->info;
434
435 if (!pim_ifp)
436 continue;
437
438 ifaddr = pim_ifp->primary_address;
439
440 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
eaa54bdb
DW
441 char ch_src_str[INET_ADDRSTRLEN];
442 char ch_grp_str[INET_ADDRSTRLEN];
12e41d03 443
4ed0af70 444 pim_inet4_dump("<ch_src?>", ch->sg.src,
12e41d03 445 ch_src_str, sizeof(ch_src_str));
4ed0af70 446 pim_inet4_dump("<ch_grp?>", ch->sg.grp,
12e41d03
DL
447 ch_grp_str, sizeof(ch_grp_str));
448
e775c0a4
DW
449 if (uj) {
450 json_object_object_get_ex(json, ifp->name, &json_iface);
451
452 if (!json_iface) {
453 json_iface = json_object_new_object();
454 json_object_pim_ifp_add(json_iface, ifp);
455 json_object_object_add(json, ifp->name, json_iface);
456 }
457
458 json_row = json_object_new_object();
459 json_object_string_add(json_row, "source", ch_src_str);
460 json_object_string_add(json_row, "group", ch_grp_str);
461 json_object_string_add(json_row, "localMembership",
462 ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ? "NOINFO" : "INCLUDE");
463 json_object_object_add(json_iface, ch_grp_str, json_row);
464
465 } else {
466 vty_out(vty, "%-9s %-15s %-15s %-15s %-10s%s",
467 ifp->name,
468 inet_ntoa(ifaddr),
469 ch_src_str,
470 ch_grp_str,
471 ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ?
472 "NOINFO" : "INCLUDE",
473 VTY_NEWLINE);
474 }
12e41d03
DL
475 } /* scan interface channels */
476 } /* scan interfaces */
477
e775c0a4 478 if (uj) {
17b52be1 479 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
e775c0a4
DW
480 json_object_free(json);
481 }
12e41d03
DL
482}
483
a268493f
DW
484static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp, int mloop)
485{
486 vty_out(vty, "Flags%s", VTY_NEWLINE);
487 vty_out(vty, "-----%s", VTY_NEWLINE);
488 vty_out(vty, "All Multicast : %s%s", (ifp->flags & IFF_ALLMULTI) ? "yes" : "no", VTY_NEWLINE);
489 vty_out(vty, "Broadcast : %s%s", if_is_broadcast(ifp)? "yes" : "no", VTY_NEWLINE);
490 vty_out(vty, "Deleted : %s%s", PIM_IF_IS_DELETED(ifp) ? "yes" : "no", VTY_NEWLINE);
491 vty_out(vty, "Interface Index : %d%s", ifp->ifindex, VTY_NEWLINE);
492 vty_out(vty, "Multicast : %s%s", if_is_multicast(ifp) ? "yes" : "no", VTY_NEWLINE);
493 vty_out(vty, "Multicast Loop : %d%s", mloop, VTY_NEWLINE);
494 vty_out(vty, "Promiscuous : %s%s", (ifp->flags & IFF_PROMISC) ? "yes" : "no", VTY_NEWLINE);
495 vty_out(vty, "%s", VTY_NEWLINE);
496 vty_out(vty, "%s", VTY_NEWLINE);
497}
498
a268493f 499static void igmp_show_interfaces(struct vty *vty, u_char uj)
12e41d03
DL
500{
501 struct listnode *node;
502 struct interface *ifp;
503 time_t now;
a268493f
DW
504 json_object *json = NULL;
505 json_object *json_row = NULL;
506
12e41d03
DL
507 now = pim_time_monotonic_sec();
508
a268493f
DW
509 if (uj)
510 json = json_object_new_object();
511 else
512 vty_out(vty,
b05b72e8 513 "Interface State Address V Querier Query Timer Uptime%s",
a268493f 514 VTY_NEWLINE);
12e41d03 515
469351b3 516 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
12e41d03
DL
517 struct pim_interface *pim_ifp;
518 struct listnode *sock_node;
519 struct igmp_sock *igmp;
520
521 pim_ifp = ifp->info;
a268493f 522
12e41d03
DL
523 if (!pim_ifp)
524 continue;
525
526 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
527 char uptime[10];
a268493f 528 char query_hhmmss[10];
12e41d03
DL
529
530 pim_time_uptime(uptime, sizeof(uptime), now - igmp->sock_creation);
a268493f 531 pim_time_timer_to_hhmmss(query_hhmmss, sizeof(query_hhmmss), igmp->t_igmp_query_timer);
12e41d03 532
a268493f
DW
533 if (uj) {
534 json_row = json_object_new_object();
e775c0a4 535 json_object_pim_ifp_add(json_row, ifp);
a268493f 536 json_object_string_add(json_row, "upTime", uptime);
b05b72e8 537 json_object_int_add(json_row, "version", pim_ifp->igmp_version);
a268493f
DW
538
539 if (igmp->t_igmp_query_timer) {
540 json_object_boolean_true_add(json_row, "querier");
541 json_object_string_add(json_row, "queryTimer", query_hhmmss);
542 }
543
544 json_object_object_add(json, ifp->name, json_row);
545
546 } else {
b05b72e8 547 vty_out(vty, "%-9s %5s %15s %d %7s %11s %8s%s",
a268493f
DW
548 ifp->name,
549 if_is_up(ifp) ? "up" : "down",
550 inet_ntoa(igmp->ifaddr),
b05b72e8 551 pim_ifp->igmp_version,
a268493f
DW
552 igmp->t_igmp_query_timer ? "local" : "other",
553 query_hhmmss,
554 uptime,
555 VTY_NEWLINE);
556 }
557 }
558 }
559
560 if (uj) {
17b52be1 561 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
a268493f
DW
562 json_object_free(json);
563 }
564}
565
566static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, u_char uj)
567{
568 struct igmp_sock *igmp;
569 struct interface *ifp;
570 struct listnode *node;
571 struct listnode *sock_node;
572 struct pim_interface *pim_ifp;
573 char uptime[10];
574 char query_hhmmss[10];
575 char other_hhmmss[10];
576 int found_ifname = 0;
577 int sqi;
578 int mloop;
579 long gmi_msec; /* Group Membership Interval */
580 long lmqt_msec;
581 long ohpi_msec;
582 long oqpi_msec; /* Other Querier Present Interval */
583 long qri_msec;
584 time_t now;
585
586 json_object *json = NULL;
587 json_object *json_row = NULL;
588
9b91bb50
DW
589 if (uj)
590 json = json_object_new_object();
591
a268493f
DW
592 now = pim_time_monotonic_sec();
593
594 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
595 pim_ifp = ifp->info;
596
597 if (!pim_ifp)
598 continue;
599
9b91bb50 600 if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
a268493f
DW
601 continue;
602
603 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
604 found_ifname = 1;
605 pim_time_uptime(uptime, sizeof(uptime), now - igmp->sock_creation);
606 pim_time_timer_to_hhmmss(query_hhmmss, sizeof(query_hhmmss), igmp->t_igmp_query_timer);
607 pim_time_timer_to_hhmmss(other_hhmmss, sizeof(other_hhmmss), igmp->t_other_querier_timer);
608
609 gmi_msec = PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable,
610 igmp->querier_query_interval,
611 pim_ifp->igmp_query_max_response_time_dsec);
612
613 sqi = PIM_IGMP_SQI(pim_ifp->igmp_default_query_interval);
614
615 oqpi_msec = PIM_IGMP_OQPI_MSEC(igmp->querier_robustness_variable,
616 igmp->querier_query_interval,
617 pim_ifp->igmp_query_max_response_time_dsec);
618
619 lmqt_msec = PIM_IGMP_LMQT_MSEC(pim_ifp->igmp_query_max_response_time_dsec,
620 igmp->querier_robustness_variable);
621
622 ohpi_msec = PIM_IGMP_OHPI_DSEC(igmp->querier_robustness_variable,
623 igmp->querier_query_interval,
624 pim_ifp->igmp_query_max_response_time_dsec) * 100;
625
626 qri_msec = pim_ifp->igmp_query_max_response_time_dsec * 100;
627 mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd);
628
629 if (uj) {
a268493f 630 json_row = json_object_new_object();
e775c0a4 631 json_object_pim_ifp_add(json_row, ifp);
a268493f
DW
632 json_object_string_add(json_row, "upTime", uptime);
633 json_object_string_add(json_row, "querier", igmp->t_igmp_query_timer ? "local" : "other");
634 json_object_int_add(json_row, "queryStartCount", igmp->startup_query_count);
635 json_object_string_add(json_row, "queryQueryTimer", query_hhmmss);
636 json_object_string_add(json_row, "queryOtherTimer", other_hhmmss);
b05b72e8 637 json_object_int_add(json_row, "version", pim_ifp->igmp_version);
a268493f
DW
638 json_object_int_add(json_row, "timerGroupMembershipIntervalMsec", gmi_msec);
639 json_object_int_add(json_row, "timerLastMemberQueryMsec", lmqt_msec);
640 json_object_int_add(json_row, "timerOlderHostPresentIntervalMsec", ohpi_msec);
641 json_object_int_add(json_row, "timerOtherQuerierPresentIntervalMsec", oqpi_msec);
642 json_object_int_add(json_row, "timerQueryInterval", igmp->querier_query_interval);
643 json_object_int_add(json_row, "timerQueryResponseIntervalMsec", qri_msec);
644 json_object_int_add(json_row, "timerRobustnessVariable", igmp->querier_robustness_variable);
645 json_object_int_add(json_row, "timerStartupQueryInterval", sqi);
646
647 json_object_object_add(json, ifp->name, json_row);
a268493f
DW
648
649 } else {
650 vty_out(vty, "Interface : %s%s", ifp->name, VTY_NEWLINE);
651 vty_out(vty, "State : %s%s", if_is_up(ifp) ? "up" : "down", VTY_NEWLINE);
652 vty_out(vty, "Address : %s%s", inet_ntoa(pim_ifp->primary_address), VTY_NEWLINE);
653 vty_out(vty, "Uptime : %s%s", uptime, VTY_NEWLINE);
b05b72e8 654 vty_out(vty, "Version : %d%s", pim_ifp->igmp_version, VTY_NEWLINE);
a268493f
DW
655 vty_out(vty, "%s", VTY_NEWLINE);
656 vty_out(vty, "%s", VTY_NEWLINE);
657
658 vty_out(vty, "Querier%s", VTY_NEWLINE);
659 vty_out(vty, "-------%s", VTY_NEWLINE);
660 vty_out(vty, "Querier : %s%s", igmp->t_igmp_query_timer ? "local" : "other", VTY_NEWLINE);
661 vty_out(vty, "Start Count : %d%s", igmp->startup_query_count, VTY_NEWLINE);
662 vty_out(vty, "Query Timer : %s%s", query_hhmmss, VTY_NEWLINE);
663 vty_out(vty, "Other Timer : %s%s", other_hhmmss, VTY_NEWLINE);
664 vty_out(vty, "%s", VTY_NEWLINE);
665 vty_out(vty, "%s", VTY_NEWLINE);
666
667 vty_out(vty, "Timers%s", VTY_NEWLINE);
668 vty_out(vty, "------%s", VTY_NEWLINE);
669 vty_out(vty, "Group Membership Interval : %lis%s", gmi_msec/1000, VTY_NEWLINE);
670 vty_out(vty, "Last Member Query Time : %lis%s", lmqt_msec/1000, VTY_NEWLINE);
671 vty_out(vty, "Older Host Present Interval : %lis%s", ohpi_msec/1000, VTY_NEWLINE);
672 vty_out(vty, "Other Querier Present Interval : %lis%s", oqpi_msec/1000, VTY_NEWLINE);
673 vty_out(vty, "Query Interval : %ds%s", igmp->querier_query_interval, VTY_NEWLINE);
674 vty_out(vty, "Query Response Interval : %lis%s", qri_msec/1000, VTY_NEWLINE);
675 vty_out(vty, "Robustness Variable : %d%s", igmp->querier_robustness_variable, VTY_NEWLINE);
676 vty_out(vty, "Startup Query Interval : %ds%s", sqi, VTY_NEWLINE);
677 vty_out(vty, "%s", VTY_NEWLINE);
678 vty_out(vty, "%s", VTY_NEWLINE);
679
680 pim_print_ifp_flags(vty, ifp, mloop);
681 }
12e41d03
DL
682 }
683 }
a268493f 684
9b91bb50 685 if (uj) {
17b52be1 686 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
9b91bb50
DW
687 json_object_free(json);
688 } else {
689 if (!found_ifname)
690 vty_out (vty, "%% No such interface%s", VTY_NEWLINE);
691 }
12e41d03
DL
692}
693
694static void igmp_show_interface_join(struct vty *vty)
695{
696 struct listnode *node;
697 struct interface *ifp;
698 time_t now;
699
700 now = pim_time_monotonic_sec();
701
702 vty_out(vty,
703 "Interface Address Source Group Socket Uptime %s",
704 VTY_NEWLINE);
705
469351b3 706 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
12e41d03
DL
707 struct pim_interface *pim_ifp;
708 struct listnode *join_node;
709 struct igmp_join *ij;
710 struct in_addr pri_addr;
eaa54bdb 711 char pri_addr_str[INET_ADDRSTRLEN];
12e41d03
DL
712
713 pim_ifp = ifp->info;
714
715 if (!pim_ifp)
716 continue;
717
718 if (!pim_ifp->igmp_join_list)
719 continue;
720
721 pri_addr = pim_find_primary_addr(ifp);
722 pim_inet4_dump("<pri?>", pri_addr, pri_addr_str, sizeof(pri_addr_str));
723
724 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, join_node, ij)) {
eaa54bdb
DW
725 char group_str[INET_ADDRSTRLEN];
726 char source_str[INET_ADDRSTRLEN];
12e41d03
DL
727 char uptime[10];
728
729 pim_time_uptime(uptime, sizeof(uptime), now - ij->sock_creation);
730 pim_inet4_dump("<grp?>", ij->group_addr, group_str, sizeof(group_str));
731 pim_inet4_dump("<src?>", ij->source_addr, source_str, sizeof(source_str));
732
733 vty_out(vty, "%-9s %-15s %-15s %-15s %6d %8s%s",
734 ifp->name,
735 pri_addr_str,
736 source_str,
737 group_str,
738 ij->sock_fd,
739 uptime,
740 VTY_NEWLINE);
741 } /* for (pim_ifp->igmp_join_list) */
742
743 } /* for (iflist) */
744
745}
746
a268493f 747static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_char uj)
12e41d03 748{
a268493f 749 struct in_addr ifaddr;
12e41d03 750 struct interface *ifp;
a268493f
DW
751 struct listnode *neighnode;
752 struct listnode*node;
753 struct listnode *upnode;
754 struct pim_interface *pim_ifp;
755 struct pim_neighbor *neigh;
756 struct pim_upstream *up;
757 time_t now;
eaa54bdb 758 char dr_str[INET_ADDRSTRLEN];
a268493f
DW
759 char dr_uptime[10];
760 char expire[10];
eaa54bdb 761 char grp_str[INET_ADDRSTRLEN];
a268493f
DW
762 char hello_period[10];
763 char hello_timer[10];
eaa54bdb
DW
764 char neigh_src_str[INET_ADDRSTRLEN];
765 char src_str[INET_ADDRSTRLEN];
a268493f
DW
766 char stat_uptime[10];
767 char uptime[10];
768 int mloop;
769 int found_ifname = 0;
770 int print_header;
9bf3c633
DW
771 json_object *json = NULL;
772 json_object *json_row = NULL;
a268493f
DW
773 json_object *json_pim_neighbor = NULL;
774 json_object *json_pim_neighbors = NULL;
775 json_object *json_group = NULL;
a268493f 776 json_object *json_group_source = NULL;
e775c0a4 777 json_object *json_fhr_sources = NULL;
9bf3c633 778
a268493f 779 now = pim_time_monotonic_sec();
12e41d03 780
9b91bb50
DW
781 if (uj)
782 json = json_object_new_object();
783
469351b3 784 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
12e41d03 785 pim_ifp = ifp->info;
a268493f 786
12e41d03
DL
787 if (!pim_ifp)
788 continue;
789
790 if (pim_ifp->pim_sock_fd < 0)
791 continue;
792
9b91bb50 793 if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
a268493f 794 continue;
12e41d03 795
a268493f
DW
796 found_ifname = 1;
797 ifaddr = pim_ifp->primary_address;
798 pim_inet4_dump("<dr?>", pim_ifp->pim_dr_addr, dr_str, sizeof(dr_str));
799 pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now, pim_ifp->pim_dr_election_last);
800 pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer), pim_ifp->t_pim_hello_timer);
801 pim_time_mmss(hello_period, sizeof(hello_period), pim_ifp->pim_hello_period);
802 pim_time_uptime(stat_uptime, sizeof(stat_uptime), now - pim_ifp->pim_ifstat_start);
803 mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd);
12e41d03 804
9bf3c633
DW
805 if (uj) {
806 json_row = json_object_new_object();
e775c0a4 807 json_object_pim_ifp_add(json_row, ifp);
a268493f
DW
808
809 // PIM neighbors
810 if (pim_ifp->pim_neighbor_list->count) {
811 json_pim_neighbors = json_object_new_object();
812
813 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
814 json_pim_neighbor = json_object_new_object();
815 pim_inet4_dump("<src?>", neigh->source_addr, neigh_src_str, sizeof(neigh_src_str));
816 pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation);
817 pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer);
818
819 json_object_string_add(json_pim_neighbor, "address", neigh_src_str);
820 json_object_string_add(json_pim_neighbor, "upTime", uptime);
821 json_object_string_add(json_pim_neighbor, "holdtime", expire);
822
823 json_object_object_add(json_pim_neighbors, neigh_src_str, json_pim_neighbor);
824 }
825
826 json_object_object_add(json_row, "neighbors", json_pim_neighbors);
827 }
828
9bf3c633 829 json_object_string_add(json_row, "drAddress", dr_str);
a268493f
DW
830 json_object_int_add(json_row, "drPriority", pim_ifp->pim_dr_priority);
831 json_object_string_add(json_row, "drUptime", dr_uptime);
9bf3c633
DW
832 json_object_int_add(json_row, "drElections", pim_ifp->pim_dr_election_count);
833 json_object_int_add(json_row, "drChanges", pim_ifp->pim_dr_election_changes);
a268493f
DW
834
835 // FHR
0f588989
DS
836 for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) {
837 if (ifp == up->rpf.source_nexthop.interface) {
a268493f
DW
838 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) {
839 if (!json_fhr_sources) {
840 json_fhr_sources = json_object_new_object();
841 }
842
843 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
844 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
845 pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition);
846
847 /* Does this group live in json_fhr_sources? If not create it. */
9c2df635 848 json_object_object_get_ex(json_fhr_sources, grp_str, &json_group);
a268493f
DW
849
850 if (!json_group) {
851 json_group = json_object_new_object();
852 json_object_object_add(json_fhr_sources, grp_str, json_group);
853 }
854
855 json_group_source = json_object_new_object();
856 json_object_string_add(json_group_source, "source", src_str);
857 json_object_string_add(json_group_source, "group", grp_str);
858 json_object_string_add(json_group_source, "upTime", uptime);
859 json_object_object_add(json_group, src_str, json_group_source);
860 }
861 }
862 }
863
864 if (json_fhr_sources) {
865 json_object_object_add(json_row, "firstHopRouter", json_fhr_sources);
866 }
867
868 json_object_int_add(json_row, "helloPeriod", pim_ifp->pim_hello_period);
869 json_object_string_add(json_row, "helloTimer", hello_timer);
870 json_object_string_add(json_row, "helloStatStart", stat_uptime);
871 json_object_int_add(json_row, "helloReceived", pim_ifp->pim_ifstat_hello_recv);
872 json_object_int_add(json_row, "helloReceivedFailed", pim_ifp->pim_ifstat_hello_recvfail);
873 json_object_int_add(json_row, "helloSend", pim_ifp->pim_ifstat_hello_sent);
874 json_object_int_add(json_row, "hellosendFailed", pim_ifp->pim_ifstat_hello_sendfail);
875 json_object_int_add(json_row, "helloGenerationId", pim_ifp->pim_generation_id);
876 json_object_int_add(json_row, "flagMulticastLoop", mloop);
877
878 json_object_int_add(json_row, "effectivePropagationDelay", pim_if_effective_propagation_delay_msec(ifp));
879 json_object_int_add(json_row, "effectiveOverrideInterval", pim_if_effective_override_interval_msec(ifp));
880 json_object_int_add(json_row, "joinPruneOverrideInterval", pim_if_jp_override_interval_msec(ifp));
881
882 json_object_int_add(json_row, "propagationDelay", pim_ifp->pim_propagation_delay_msec);
883 json_object_int_add(json_row, "propagationDelayHighest", pim_ifp->pim_neighbors_highest_propagation_delay_msec);
884 json_object_int_add(json_row, "overrideInterval", pim_ifp->pim_override_interval_msec);
885 json_object_int_add(json_row, "overrideIntervalHighest", pim_ifp->pim_neighbors_highest_override_interval_msec);
9bf3c633 886 json_object_object_add(json, ifp->name, json_row);
a268493f 887
9bf3c633 888 } else {
a268493f
DW
889 vty_out(vty, "Interface : %s%s", ifp->name, VTY_NEWLINE);
890 vty_out(vty, "State : %s%s", if_is_up(ifp) ? "up" : "down", VTY_NEWLINE);
891 vty_out(vty, "Address : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE);
892 vty_out(vty, "%s", VTY_NEWLINE);
9bf3c633 893
a268493f
DW
894 // PIM neighbors
895 print_header = 1;
12e41d03 896
a268493f 897 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
12e41d03 898
a268493f
DW
899 if (print_header) {
900 vty_out(vty, "PIM Neighbors%s", VTY_NEWLINE);
901 vty_out(vty, "-------------%s", VTY_NEWLINE);
902 print_header = 0;
903 }
12e41d03 904
a268493f
DW
905 pim_inet4_dump("<src?>", neigh->source_addr, neigh_src_str, sizeof(neigh_src_str));
906 pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation);
907 pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer);
908 vty_out(vty, "%-15s : up for %s, holdtime expires in %s%s", neigh_src_str, uptime, expire, VTY_NEWLINE);
909 }
12e41d03 910
a268493f
DW
911 if (!print_header) {
912 vty_out(vty, "%s", VTY_NEWLINE);
913 vty_out(vty, "%s", VTY_NEWLINE);
914 }
12e41d03 915
a268493f
DW
916 vty_out(vty, "Designated Router%s", VTY_NEWLINE);
917 vty_out(vty, "-----------------%s", VTY_NEWLINE);
918 vty_out(vty, "Address : %s%s", dr_str, VTY_NEWLINE);
919 vty_out(vty, "Priority : %d%s", pim_ifp->pim_dr_priority, VTY_NEWLINE);
920 vty_out(vty, "Uptime : %s%s", dr_uptime, VTY_NEWLINE);
921 vty_out(vty, "Elections : %d%s", pim_ifp->pim_dr_election_count, VTY_NEWLINE);
922 vty_out(vty, "Changes : %d%s", pim_ifp->pim_dr_election_changes, VTY_NEWLINE);
923 vty_out(vty, "%s", VTY_NEWLINE);
924 vty_out(vty, "%s", VTY_NEWLINE);
925
926 // FHR
927 print_header = 1;
0f588989 928 for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) {
a268493f
DW
929 if (strcmp(ifp->name, up->rpf.source_nexthop.interface->name) == 0) {
930 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) {
931
932 if (print_header) {
933 vty_out(vty, "FHR - First Hop Router%s", VTY_NEWLINE);
934 vty_out(vty, "----------------------%s", VTY_NEWLINE);
935 print_header = 0;
936 }
937
938 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
939 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
940 pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition);
941 vty_out(vty, "%s : %s is a source, uptime is %s%s", grp_str, src_str, uptime, VTY_NEWLINE);
942 }
943 }
944 }
12e41d03 945
a268493f
DW
946 if (!print_header) {
947 vty_out(vty, "%s", VTY_NEWLINE);
948 vty_out(vty, "%s", VTY_NEWLINE);
949 }
12e41d03 950
a268493f
DW
951 vty_out(vty, "Hellos%s", VTY_NEWLINE);
952 vty_out(vty, "------%s", VTY_NEWLINE);
953 vty_out(vty, "Period : %d%s", pim_ifp->pim_hello_period, VTY_NEWLINE);
954 vty_out(vty, "Timer : %s%s", hello_timer, VTY_NEWLINE);
955 vty_out(vty, "StatStart : %s%s", stat_uptime, VTY_NEWLINE);
956 vty_out(vty, "Receive : %d%s", pim_ifp->pim_ifstat_hello_recv, VTY_NEWLINE);
957 vty_out(vty, "Receive Failed : %d%s", pim_ifp->pim_ifstat_hello_recvfail, VTY_NEWLINE);
958 vty_out(vty, "Send : %d%s", pim_ifp->pim_ifstat_hello_sent, VTY_NEWLINE);
959 vty_out(vty, "Send Failed : %d%s", pim_ifp->pim_ifstat_hello_sendfail, VTY_NEWLINE);
960 vty_out(vty, "Generation ID : %08x%s", pim_ifp->pim_generation_id, VTY_NEWLINE);
961 vty_out(vty, "%s", VTY_NEWLINE);
962 vty_out(vty, "%s", VTY_NEWLINE);
963
964 pim_print_ifp_flags(vty, ifp, mloop);
965
966 vty_out(vty, "Join Prune Interval%s", VTY_NEWLINE);
967 vty_out(vty, "-------------------%s", VTY_NEWLINE);
968 vty_out(vty, "LAN Delay : %s%s", pim_if_lan_delay_enabled(ifp) ? "yes" : "no", VTY_NEWLINE);
969 vty_out(vty, "Effective Propagation Delay : %d msec%s", pim_if_effective_propagation_delay_msec(ifp), VTY_NEWLINE);
970 vty_out(vty, "Effective Override Interval : %d msec%s", pim_if_effective_override_interval_msec(ifp), VTY_NEWLINE);
971 vty_out(vty, "Join Prune Override Interval : %d msec%s", pim_if_jp_override_interval_msec(ifp), VTY_NEWLINE);
972 vty_out(vty, "%s", VTY_NEWLINE);
973 vty_out(vty, "%s", VTY_NEWLINE);
974
975 vty_out(vty, "LAN Prune Delay%s", VTY_NEWLINE);
976 vty_out(vty, "---------------%s", VTY_NEWLINE);
977 vty_out(vty, "Propagation Delay : %d msec%s", pim_ifp->pim_propagation_delay_msec, VTY_NEWLINE);
978 vty_out(vty, "Propagation Delay (Highest) : %d msec%s", pim_ifp->pim_neighbors_highest_propagation_delay_msec, VTY_NEWLINE);
979 vty_out(vty, "Override Interval : %d msec%s", pim_ifp->pim_override_interval_msec, VTY_NEWLINE);
980 vty_out(vty, "Override Interval (Highest) : %d msec%s", pim_ifp->pim_neighbors_highest_override_interval_msec, VTY_NEWLINE);
981 vty_out(vty, "%s", VTY_NEWLINE);
982 vty_out(vty, "%s", VTY_NEWLINE);
9bf3c633
DW
983 }
984 }
985
9b91bb50 986 if (uj) {
17b52be1 987 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
9b91bb50
DW
988 json_object_free(json);
989 } else {
990 if (!found_ifname)
991 vty_out (vty, "%% No such interface%s", VTY_NEWLINE);
992 }
12e41d03
DL
993}
994
9bf3c633 995static void pim_show_interfaces(struct vty *vty, u_char uj)
12e41d03 996{
a268493f 997 struct in_addr ifaddr;
12e41d03 998 struct interface *ifp;
0f588989 999 struct listnode *node;
a268493f
DW
1000 struct listnode *upnode;
1001 struct pim_interface *pim_ifp;
1002 struct pim_upstream *up;
1003 int fhr = 0;
1004 int pim_dr_local = 0;
1005 int pim_nbrs = 0;
9bf3c633
DW
1006 json_object *json = NULL;
1007 json_object *json_row = NULL;
8151e286
DW
1008 char local_ip[INET_ADDRSTRLEN];
1009 char dr_ip[INET_ADDRSTRLEN];
0f588989 1010
a268493f 1011 if (uj) {
9bf3c633 1012 json = json_object_new_object();
a268493f
DW
1013 } else {
1014 vty_out(vty, "Interface State Address PIM Nbrs PIM DR FHR%s", VTY_NEWLINE);
1015 }
12e41d03 1016
469351b3 1017 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
12e41d03
DL
1018 pim_ifp = ifp->info;
1019
1020 if (!pim_ifp)
1021 continue;
1022
1023 if (pim_ifp->pim_sock_fd < 0)
1024 continue;
1025
1026 ifaddr = pim_ifp->primary_address;
a268493f
DW
1027 pim_nbrs = pim_ifp->pim_neighbor_list->count;
1028 pim_dr_local = 0;
1029 fhr = 0;
12e41d03 1030
a268493f
DW
1031 if (pim_ifp->pim_dr_addr.s_addr == pim_ifp->primary_address.s_addr)
1032 pim_dr_local = 1;
1033
0f588989
DS
1034 for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up))
1035 if (ifp == up->rpf.source_nexthop.interface)
a268493f
DW
1036 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
1037 fhr++;
12e41d03 1038
9bf3c633
DW
1039 if (uj) {
1040 json_row = json_object_new_object();
e775c0a4 1041 json_object_pim_ifp_add(json_row, ifp);
a268493f
DW
1042 json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
1043 json_object_int_add(json_row, "firstHopRouter", fhr);
1044 json_object_string_add(json_row, "pimDesignatedRouter", inet_ntoa(pim_ifp->pim_dr_addr));
9bf3c633
DW
1045 json_object_object_add(json, ifp->name, json_row);
1046
1047 } else {
8151e286
DW
1048 strcpy(local_ip, inet_ntoa(ifaddr));
1049 strcpy(dr_ip, inet_ntoa(pim_ifp->pim_dr_addr));
a268493f 1050 vty_out(vty, "%-9s %5s %15s %8d %15s %3d%s",
9bf3c633 1051 ifp->name,
a268493f 1052 if_is_up(ifp) ? "up" : "down",
8151e286 1053 local_ip,
a268493f 1054 pim_nbrs,
8151e286 1055 pim_dr_local ? "local" : dr_ip,
a268493f 1056 fhr,
9bf3c633
DW
1057 VTY_NEWLINE);
1058 }
1059 }
1060
1061 if (uj) {
17b52be1 1062 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
9bf3c633 1063 json_object_free(json);
12e41d03
DL
1064 }
1065}
1066
e775c0a4 1067static void pim_show_join(struct vty *vty, u_char uj)
12e41d03
DL
1068{
1069 struct listnode *ifnode;
1070 struct interface *ifp;
1071 time_t now;
e775c0a4
DW
1072 json_object *json = NULL;
1073 json_object *json_iface = NULL;
1074 json_object *json_row = NULL;
12e41d03
DL
1075
1076 now = pim_time_monotonic_sec();
1077
e775c0a4
DW
1078 if (uj)
1079 json = json_object_new_object();
1080 else
1081 vty_out(vty,
1082 "Interface Address Source Group State Uptime Expire Prune%s",
1083 VTY_NEWLINE);
12e41d03 1084
469351b3 1085 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
12e41d03
DL
1086 struct pim_interface *pim_ifp;
1087 struct in_addr ifaddr;
1088 struct listnode *ch_node;
1089 struct pim_ifchannel *ch;
1090
1091 pim_ifp = ifp->info;
1092
1093 if (!pim_ifp)
1094 continue;
1095
1096 ifaddr = pim_ifp->primary_address;
1097
1098 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
eaa54bdb
DW
1099 char ch_src_str[INET_ADDRSTRLEN];
1100 char ch_grp_str[INET_ADDRSTRLEN];
12e41d03
DL
1101 char uptime[10];
1102 char expire[10];
1103 char prune[10];
1104
4ed0af70 1105 pim_inet4_dump("<ch_src?>", ch->sg.src,
12e41d03 1106 ch_src_str, sizeof(ch_src_str));
4ed0af70 1107 pim_inet4_dump("<ch_grp?>", ch->sg.grp,
12e41d03
DL
1108 ch_grp_str, sizeof(ch_grp_str));
1109
1110 pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation);
1111 pim_time_timer_to_mmss(expire, sizeof(expire),
1112 ch->t_ifjoin_expiry_timer);
1113 pim_time_timer_to_mmss(prune, sizeof(prune),
1114 ch->t_ifjoin_prune_pending_timer);
1115
e775c0a4
DW
1116 if (uj) {
1117 json_object_object_get_ex(json, ifp->name, &json_iface);
1118
1119 if (!json_iface) {
1120 json_iface = json_object_new_object();
1121 json_object_pim_ifp_add(json_iface, ifp);
1122 json_object_object_add(json, ifp->name, json_iface);
1123 }
1124
1125 json_row = json_object_new_object();
1126 json_object_string_add(json_row, "source", ch_src_str);
1127 json_object_string_add(json_row, "group", ch_grp_str);
1128 json_object_string_add(json_row, "upTime", uptime);
1129 json_object_string_add(json_row, "expire", expire);
1130 json_object_string_add(json_row, "prune", prune);
1131 json_object_string_add(json_row, "channelJoinName", pim_ifchannel_ifjoin_name(ch->ifjoin_state));
1132 json_object_object_add(json_iface, ch_grp_str, json_row);
1133
1134 } else {
1135 vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s%s",
1136 ifp->name,
1137 inet_ntoa(ifaddr),
1138 ch_src_str,
1139 ch_grp_str,
1140 pim_ifchannel_ifjoin_name(ch->ifjoin_state),
1141 uptime,
1142 expire,
1143 prune,
1144 VTY_NEWLINE);
1145 }
12e41d03
DL
1146 } /* scan interface channels */
1147 } /* scan interfaces */
1148
e775c0a4 1149 if (uj) {
17b52be1 1150 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
e775c0a4
DW
1151 json_object_free(json);
1152 }
12e41d03
DL
1153}
1154
a268493f 1155static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, u_char uj)
12e41d03
DL
1156{
1157 struct listnode *node;
a268493f 1158 struct listnode *neighnode;
12e41d03 1159 struct interface *ifp;
a268493f
DW
1160 struct pim_interface *pim_ifp;
1161 struct pim_neighbor *neigh;
12e41d03 1162 time_t now;
a268493f
DW
1163 int found_neighbor = 0;
1164 int option_address_list;
1165 int option_dr_priority;
1166 int option_generation_id;
1167 int option_holdtime;
1168 int option_lan_prune_delay;
1169 int option_t_bit;
1170 char uptime[10];
1171 char expire[10];
eaa54bdb 1172 char neigh_src_str[INET_ADDRSTRLEN];
a268493f 1173
9bf3c633 1174 json_object *json = NULL;
a268493f 1175 json_object *json_ifp = NULL;
9bf3c633
DW
1176 json_object *json_row = NULL;
1177
12e41d03
DL
1178 now = pim_time_monotonic_sec();
1179
a268493f 1180 if (uj)
9bf3c633 1181 json = json_object_new_object();
12e41d03 1182
469351b3 1183 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
12e41d03 1184 pim_ifp = ifp->info;
9bf3c633 1185
12e41d03
DL
1186 if (!pim_ifp)
1187 continue;
1188
1189 if (pim_ifp->pim_sock_fd < 0)
1190 continue;
1191
12e41d03 1192 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
12e41d03
DL
1193 pim_inet4_dump("<src?>", neigh->source_addr,
1194 neigh_src_str, sizeof(neigh_src_str));
a268493f
DW
1195
1196 /*
1197 * The user can specify either the interface name or the PIM neighbor IP.
1198 * If this pim_ifp matches neither then skip.
1199 */
9b91bb50
DW
1200 if (strcmp(neighbor, "detail") &&
1201 strcmp(neighbor, ifp->name) &&
1202 strcmp(neighbor, neigh_src_str))
a268493f
DW
1203 continue;
1204
1205 found_neighbor = 1;
12e41d03 1206 pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation);
a268493f
DW
1207 pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer);
1208
1209 option_address_list = 0;
1210 option_dr_priority = 0;
1211 option_generation_id = 0;
1212 option_holdtime = 0;
1213 option_lan_prune_delay = 0;
1214 option_t_bit = 0;
1215
1216 if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_ADDRESS_LIST))
1217 option_address_list = 1;
1218
1219 if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY))
1220 option_dr_priority = 1;
1221
1222 if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID))
1223 option_generation_id = 1;
1224
1225 if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_HOLDTIME))
1226 option_holdtime = 1;
1227
1228 if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY))
1229 option_lan_prune_delay = 1;
1230
1231 if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION))
1232 option_t_bit = 1;
12e41d03 1233
9bf3c633 1234 if (uj) {
a268493f
DW
1235
1236 /* Does this ifp live in json? If not create it. */
9c2df635 1237 json_object_object_get_ex(json, ifp->name, &json_ifp);
a268493f
DW
1238
1239 if (!json_ifp) {
1240 json_ifp = json_object_new_object();
e775c0a4 1241 json_object_pim_ifp_add(json_ifp, ifp);
a268493f
DW
1242 json_object_object_add(json, ifp->name, json_ifp);
1243 }
1244
9bf3c633
DW
1245 json_row = json_object_new_object();
1246 json_object_string_add(json_row, "interface", ifp->name);
a268493f 1247 json_object_string_add(json_row, "address", neigh_src_str);
9bf3c633 1248 json_object_string_add(json_row, "upTime", uptime);
a268493f 1249 json_object_string_add(json_row, "holdtime", expire);
9bf3c633
DW
1250 json_object_int_add(json_row, "drPriority", neigh->dr_priority);
1251 json_object_int_add(json_row, "generationId", neigh->generation_id);
1252
a268493f
DW
1253 if (option_address_list)
1254 json_object_boolean_true_add(json_row, "helloOptionAddressList");
9bf3c633 1255
a268493f
DW
1256 if (option_dr_priority)
1257 json_object_boolean_true_add(json_row, "helloOptionDrPriority");
9bf3c633 1258
a268493f
DW
1259 if (option_generation_id)
1260 json_object_boolean_true_add(json_row, "helloOptionGenerationId");
9bf3c633 1261
a268493f
DW
1262 if (option_holdtime)
1263 json_object_boolean_true_add(json_row, "helloOptionHoldtime");
9bf3c633 1264
a268493f
DW
1265 if (option_lan_prune_delay)
1266 json_object_boolean_true_add(json_row, "helloOptionLanPruneDelay");
9bf3c633 1267
a268493f
DW
1268 if (option_t_bit)
1269 json_object_boolean_true_add(json_row, "helloOptionTBit");
9bf3c633 1270
a268493f 1271 json_object_object_add(json_ifp, neigh_src_str, json_row);
9bf3c633
DW
1272
1273 } else {
a268493f
DW
1274 vty_out(vty, "Interface : %s%s", ifp->name, VTY_NEWLINE);
1275 vty_out(vty, "Neighbor : %s%s", neigh_src_str, VTY_NEWLINE);
1276 vty_out(vty, " Uptime : %s%s", uptime, VTY_NEWLINE);
1277 vty_out(vty, " Holdtime : %s%s", expire, VTY_NEWLINE);
1278 vty_out(vty, " DR Priority : %d%s", neigh->dr_priority, VTY_NEWLINE);
1279 vty_out(vty, " Generation ID : %08x%s", neigh->generation_id, VTY_NEWLINE);
1280 vty_out(vty, " Override Interval (msec) : %d%s", neigh->override_interval_msec, VTY_NEWLINE);
1281 vty_out(vty, " Propagation Delay (msec) : %d%s", neigh->propagation_delay_msec, VTY_NEWLINE);
1282 vty_out(vty, " Hello Option - Address List : %s%s", option_address_list ? "yes" : "no", VTY_NEWLINE);
1283 vty_out(vty, " Hello Option - DR Priority : %s%s", option_dr_priority ? "yes" : "no", VTY_NEWLINE);
1284 vty_out(vty, " Hello Option - Generation ID : %s%s", option_generation_id? "yes" : "no", VTY_NEWLINE);
1285 vty_out(vty, " Hello Option - Holdtime : %s%s", option_holdtime ? "yes" : "no", VTY_NEWLINE);
1286 vty_out(vty, " Hello Option - LAN Prune Delay : %s%s", option_lan_prune_delay ? "yes" : "no", VTY_NEWLINE);
1287 vty_out(vty, " Hello Option - T-bit : %s%s", option_t_bit ? "yes" : "no", VTY_NEWLINE);
1288 vty_out(vty, "%s", VTY_NEWLINE);
9bf3c633 1289 }
12e41d03 1290 }
9bf3c633 1291 }
12e41d03 1292
9bf3c633 1293 if (uj) {
17b52be1 1294 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
9bf3c633 1295 json_object_free(json);
a268493f
DW
1296 } else {
1297 {
1298 if (!found_neighbor)
1299 vty_out (vty, "%% No such interface or neighbor%s", VTY_NEWLINE);
1300 }
12e41d03
DL
1301 }
1302}
1303
31a21c9c
DW
1304static void
1305pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_char uj)
1306{
1307 struct channel_oil *c_oil;
1308 struct listnode *node;
1309 json_object *json = NULL;
1310 json_object *json_group = NULL;
1311 json_object *json_ifp_in = NULL;
1312 json_object *json_ifp_out = NULL;
1313 json_object *json_source = NULL;
1314 time_t now;
1315 int first_oif;
1316 now = pim_time_monotonic_sec();
1317
1318 if (uj) {
1319 json = json_object_new_object();
1320 } else {
1321 vty_out(vty, "%sSource Group IIF OIL%s", VTY_NEWLINE, VTY_NEWLINE);
1322 }
1323
040d86ad 1324 for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) {
eaa54bdb
DW
1325 char grp_str[INET_ADDRSTRLEN];
1326 char src_str[INET_ADDRSTRLEN];
31a21c9c
DW
1327 char in_ifname[16];
1328 char out_ifname[16];
1329 int oif_vif_index;
1330 struct interface *ifp_in;
1331 first_oif = 1;
1332
1333 if (!c_oil->installed)
1334 continue;
1335
1336 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, sizeof(grp_str));
1337 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str, sizeof(src_str));
1338 ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
1339
1340 if (ifp_in)
1341 strcpy(in_ifname, ifp_in->name);
1342 else
1343 strcpy(in_ifname, "<iif?>");
1344
1345 if (src_or_group)
1346 {
1347 if (strcmp(src_or_group, src_str) && strcmp(src_or_group, grp_str))
1348 continue;
1349
1350 if (group && strcmp(group, grp_str))
1351 continue;
1352 }
1353
1354 if (uj) {
1355
1356 /* Find the group, create it if it doesn't exist */
1357 json_object_object_get_ex(json, grp_str, &json_group);
1358
1359 if (!json_group) {
1360 json_group = json_object_new_object();
1361 json_object_object_add(json, grp_str, json_group);
1362 }
1363
1364 /* Find the source nested under the group, create it if it doesn't exist */
1365 json_object_object_get_ex(json_group, src_str, &json_source);
1366
1367 if (!json_source) {
1368 json_source = json_object_new_object();
1369 json_object_object_add(json_group, src_str, json_source);
1370 }
1371
1372 /* Find the inbound interface nested under the source, create it if it doesn't exist */
1373 json_object_object_get_ex(json_source, in_ifname, &json_ifp_in);
1374
1375 if (!json_ifp_in) {
1376 json_ifp_in = json_object_new_object();
1377 json_object_object_add(json_source, in_ifname, json_ifp_in);
1378 }
1379 } else {
1380 vty_out(vty, "%-15s %-15s %-5s ",
1381 src_str,
1382 grp_str,
1383 ifp_in->name);
1384 }
1385
1386 for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) {
1387 struct interface *ifp_out;
1388 char oif_uptime[10];
1389 int ttl;
1390
1391 ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
1392 if (ttl < 1)
1393 continue;
1394
1395 ifp_out = pim_if_find_by_vif_index(oif_vif_index);
1396 pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - c_oil->oif_creation[oif_vif_index]);
1397
1398 if (ifp_out)
1399 strcpy(out_ifname, ifp_out->name);
1400 else
1401 strcpy(out_ifname, "<oif?>");
1402
1403 if (uj) {
1404 json_ifp_out = json_object_new_object();
1405 json_object_string_add(json_ifp_out, "source", src_str);
1406 json_object_string_add(json_ifp_out, "group", grp_str);
1407 json_object_string_add(json_ifp_out, "inboundInterface", in_ifname);
1408 json_object_string_add(json_ifp_out, "outboundInterface", out_ifname);
1409
1410 json_object_object_add(json_ifp_in, out_ifname, json_ifp_out);
1411 } else {
1412 if (first_oif)
1413 {
1414 first_oif = 0;
1415 vty_out(vty, "%s", out_ifname);
1416 }
1417 else
1418 vty_out(vty, ",%s", out_ifname);
1419 }
1420 }
1421
1422 if (!uj)
1423 vty_out(vty, "%s", VTY_NEWLINE);
1424 }
1425
1426
1427 if (uj) {
72b39b9e 1428 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
31a21c9c
DW
1429 json_object_free(json);
1430 } else {
1431 vty_out(vty, "%s", VTY_NEWLINE);
1432 }
1433}
1434
a268493f 1435static void pim_show_neighbors(struct vty *vty, u_char uj)
12e41d03 1436{
a268493f
DW
1437 struct listnode *node;
1438 struct listnode *neighnode;
12e41d03 1439 struct interface *ifp;
a268493f
DW
1440 struct pim_interface *pim_ifp;
1441 struct pim_neighbor *neigh;
1442 time_t now;
1443 char uptime[10];
1444 char expire[10];
eaa54bdb 1445 char neigh_src_str[INET_ADDRSTRLEN];
a268493f
DW
1446 json_object *json = NULL;
1447 json_object *json_ifp_rows = NULL;
1448 json_object *json_row = NULL;
12e41d03 1449
a268493f 1450 now = pim_time_monotonic_sec();
12e41d03 1451
a268493f
DW
1452 if (uj) {
1453 json = json_object_new_object();
1454 } else {
1455 vty_out(vty, "Interface Neighbor Uptime Holdtime DR Pri%s", VTY_NEWLINE);
1456 }
12e41d03 1457
469351b3 1458 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
12e41d03 1459 pim_ifp = ifp->info;
a268493f 1460
12e41d03
DL
1461 if (!pim_ifp)
1462 continue;
1463
1464 if (pim_ifp->pim_sock_fd < 0)
1465 continue;
1466
a268493f
DW
1467 if (uj)
1468 json_ifp_rows = json_object_new_object();
12e41d03
DL
1469
1470 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
12e41d03
DL
1471 pim_inet4_dump("<src?>", neigh->source_addr,
1472 neigh_src_str, sizeof(neigh_src_str));
a268493f
DW
1473 pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation);
1474 pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer);
12e41d03 1475
a268493f
DW
1476 if (uj) {
1477 json_row = json_object_new_object();
1478 json_object_string_add(json_row, "interface", ifp->name);
1479 json_object_string_add(json_row, "neighbor", neigh_src_str);
1480 json_object_string_add(json_row, "upTime", uptime);
1481 json_object_string_add(json_row, "holdTime", expire);
1482 json_object_int_add(json_row, "holdTimeMax", neigh->holdtime);
1483 json_object_int_add(json_row, "drPriority", neigh->dr_priority);
1484 json_object_object_add(json_ifp_rows, neigh_src_str, json_row);
1485
1486 } else {
1487 vty_out(vty, "%-9s %15s %8s %8s %6d%s",
1488 ifp->name,
1489 neigh_src_str,
1490 uptime,
1491 expire,
1492 neigh->dr_priority,
1493 VTY_NEWLINE);
1494 }
12e41d03
DL
1495 }
1496
a268493f
DW
1497 if (uj) {
1498 json_object_object_add(json, ifp->name, json_ifp_rows);
1499 json_ifp_rows = NULL;
1500 }
12e41d03 1501 }
12e41d03 1502
a268493f 1503 if (uj) {
17b52be1 1504 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
a268493f 1505 json_object_free(json);
12e41d03
DL
1506 }
1507}
1508
1509static void pim_show_neighbors_secondary(struct vty *vty)
1510{
1511 struct listnode *node;
1512 struct interface *ifp;
1513
1514 vty_out(vty, "Interface Address Neighbor Secondary %s", VTY_NEWLINE);
1515
469351b3 1516 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
12e41d03
DL
1517 struct pim_interface *pim_ifp;
1518 struct in_addr ifaddr;
1519 struct listnode *neighnode;
1520 struct pim_neighbor *neigh;
1521
1522 pim_ifp = ifp->info;
1523
1524 if (!pim_ifp)
1525 continue;
1526
1527 if (pim_ifp->pim_sock_fd < 0)
1528 continue;
1529
1530 ifaddr = pim_ifp->primary_address;
1531
1532 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
eaa54bdb 1533 char neigh_src_str[INET_ADDRSTRLEN];
12e41d03
DL
1534 struct listnode *prefix_node;
1535 struct prefix *p;
1536
1537 if (!neigh->prefix_list)
1538 continue;
1539
1540 pim_inet4_dump("<src?>", neigh->source_addr,
1541 neigh_src_str, sizeof(neigh_src_str));
1542
1543 for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) {
eaa54bdb 1544 char neigh_sec_str[INET_ADDRSTRLEN];
12e41d03
DL
1545
1546 if (p->family != AF_INET)
1547 continue;
1548
1549 pim_inet4_dump("<src?>", p->u.prefix4,
1550 neigh_sec_str, sizeof(neigh_sec_str));
1551
1552 vty_out(vty, "%-9s %-15s %-15s %-15s%s",
1553 ifp->name,
1554 inet_ntoa(ifaddr),
1555 neigh_src_str,
1556 neigh_sec_str,
1557 VTY_NEWLINE);
1558 }
1559 }
1560 }
1561}
1562
9bf3c633 1563static void
e775c0a4 1564json_object_pim_upstream_add (json_object *json, struct pim_upstream *up)
9bf3c633
DW
1565{
1566 if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
e775c0a4 1567 json_object_boolean_true_add(json, "drJoinDesired");
9bf3c633
DW
1568
1569 if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
e775c0a4 1570 json_object_boolean_true_add(json, "drJoinDesiredUpdated");
9bf3c633
DW
1571
1572 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
e775c0a4 1573 json_object_boolean_true_add(json, "firstHopRouter");
9bf3c633
DW
1574
1575 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
e775c0a4 1576 json_object_boolean_true_add(json, "sourceIgmp");
9bf3c633
DW
1577
1578 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
e775c0a4 1579 json_object_boolean_true_add(json, "sourcePim");
9bf3c633
DW
1580
1581 if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
e775c0a4 1582 json_object_boolean_true_add(json, "sourceStream");
9bf3c633
DW
1583}
1584
1585static void pim_show_upstream(struct vty *vty, u_char uj)
12e41d03
DL
1586{
1587 struct listnode *upnode;
1588 struct pim_upstream *up;
1589 time_t now;
9bf3c633 1590 json_object *json = NULL;
e775c0a4 1591 json_object *json_group = NULL;
9bf3c633 1592 json_object *json_row = NULL;
12e41d03
DL
1593
1594 now = pim_time_monotonic_sec();
1595
9bf3c633
DW
1596 if (uj)
1597 json = json_object_new_object();
1598 else
b3fb2c27 1599 vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt%s", VTY_NEWLINE);
12e41d03 1600
0f588989 1601 for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) {
eaa54bdb
DW
1602 char src_str[INET_ADDRSTRLEN];
1603 char grp_str[INET_ADDRSTRLEN];
9bf3c633
DW
1604 char uptime[10];
1605 char join_timer[10];
1606 char rs_timer[10];
1607 char ka_timer[10];
12e41d03 1608
9bf3c633
DW
1609 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
1610 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
1611 pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition);
1612 pim_time_timer_to_hhmmss (join_timer, sizeof(join_timer), up->t_join_timer);
1613 pim_time_timer_to_hhmmss (rs_timer, sizeof (rs_timer), up->t_rs_timer);
1614 pim_time_timer_to_hhmmss (ka_timer, sizeof (ka_timer), up->t_ka_timer);
12e41d03 1615
9bf3c633 1616 if (uj) {
e775c0a4 1617 json_object_object_get_ex(json, grp_str, &json_group);
9bf3c633 1618
e775c0a4
DW
1619 if (!json_group) {
1620 json_group = json_object_new_object();
1621 json_object_object_add(json, grp_str, json_group);
9bf3c633
DW
1622 }
1623
9bf3c633 1624 json_row = json_object_new_object();
e775c0a4 1625 json_object_pim_upstream_add(json_row, up);
9bf3c633
DW
1626 json_object_string_add(json_row, "inboundInterface", up->rpf.source_nexthop.interface->name);
1627 json_object_string_add(json_row, "source", src_str);
1628 json_object_string_add(json_row, "group", grp_str);
1629 json_object_string_add(json_row, "state", pim_upstream_state2str (up->join_state));
1630 json_object_string_add(json_row, "upTime", uptime);
1631 json_object_string_add(json_row, "joinTimer", join_timer);
1632 json_object_string_add(json_row, "resetTimer", rs_timer);
1633 json_object_string_add(json_row, "keepaliveTimer", ka_timer);
1634 json_object_int_add(json_row, "refCount", up->ref_count);
e775c0a4 1635 json_object_object_add(json_group, src_str, json_row);
9bf3c633 1636 } else {
e775c0a4 1637 vty_out(vty, "%-10s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d%s",
9bf3c633
DW
1638 up->rpf.source_nexthop.interface->name,
1639 src_str,
1640 grp_str,
1641 pim_upstream_state2str (up->join_state),
1642 uptime,
1643 join_timer,
1644 rs_timer,
2ecb76d3 1645 ka_timer,
9bf3c633
DW
1646 up->ref_count,
1647 VTY_NEWLINE);
1648 }
1649 }
1650
1651 if (uj) {
17b52be1 1652 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
9bf3c633 1653 json_object_free(json);
12e41d03
DL
1654 }
1655}
1656
9bf3c633 1657static void pim_show_join_desired(struct vty *vty, u_char uj)
12e41d03
DL
1658{
1659 struct listnode *ifnode;
1660 struct listnode *chnode;
1661 struct interface *ifp;
1662 struct pim_interface *pim_ifp;
1663 struct pim_ifchannel *ch;
eaa54bdb
DW
1664 char src_str[INET_ADDRSTRLEN];
1665 char grp_str[INET_ADDRSTRLEN];
9bf3c633 1666 json_object *json = NULL;
e775c0a4 1667 json_object *json_group = NULL;
9bf3c633
DW
1668 json_object *json_row = NULL;
1669
1670 if (uj)
1671 json = json_object_new_object();
1672 else
1673 vty_out(vty,
1674 "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD%s",
1675 VTY_NEWLINE);
12e41d03
DL
1676
1677 /* scan all interfaces */
469351b3 1678 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
12e41d03
DL
1679 pim_ifp = ifp->info;
1680 if (!pim_ifp)
1681 continue;
1682
1683 /* scan per-interface (S,G) state */
1684 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, chnode, ch)) {
1685 struct pim_upstream *up = ch->upstream;
1686
4ed0af70
DS
1687 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
1688 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
12e41d03 1689
9bf3c633 1690 if (uj) {
e775c0a4 1691 json_object_object_get_ex(json, grp_str, &json_group);
9bf3c633 1692
e775c0a4
DW
1693 if (!json_group) {
1694 json_group = json_object_new_object();
1695 json_object_object_add(json, grp_str, json_group);
1696 }
9bf3c633
DW
1697
1698 json_row = json_object_new_object();
e775c0a4 1699 json_object_pim_upstream_add(json_row, up);
9bf3c633
DW
1700 json_object_string_add(json_row, "interface", ifp->name);
1701 json_object_string_add(json_row, "source", src_str);
1702 json_object_string_add(json_row, "group", grp_str);
9bf3c633
DW
1703
1704 if (pim_macro_ch_lost_assert(ch))
1705 json_object_boolean_true_add(json_row, "lostAssert");
1706
1707 if (pim_macro_chisin_joins(ch))
1708 json_object_boolean_true_add(json_row, "joins");
1709
1710 if (pim_macro_chisin_pim_include(ch))
1711 json_object_boolean_true_add(json_row, "pimInclude");
1712
1713 if (pim_upstream_evaluate_join_desired(up))
1714 json_object_boolean_true_add(json_row, "evaluateJoinDesired");
1715
e775c0a4 1716 json_object_object_add(json_group, src_str, json_row);
9bf3c633
DW
1717
1718 } else {
1719 vty_out(vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s%s",
1720 ifp->name,
1721 src_str,
1722 grp_str,
1723 pim_macro_ch_lost_assert(ch) ? "yes" : "no",
1724 pim_macro_chisin_joins(ch) ? "yes" : "no",
1725 pim_macro_chisin_pim_include(ch) ? "yes" : "no",
1726 PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags) ? "yes" : "no",
1727 pim_upstream_evaluate_join_desired(up) ? "yes" : "no",
1728 VTY_NEWLINE);
1729 }
12e41d03
DL
1730 }
1731 }
9bf3c633
DW
1732
1733 if (uj) {
17b52be1 1734 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
9bf3c633
DW
1735 json_object_free(json);
1736 }
12e41d03
DL
1737}
1738
9bf3c633 1739static void pim_show_upstream_rpf(struct vty *vty, u_char uj)
12e41d03
DL
1740{
1741 struct listnode *upnode;
1742 struct pim_upstream *up;
9bf3c633 1743 json_object *json = NULL;
e775c0a4 1744 json_object *json_group = NULL;
9bf3c633
DW
1745 json_object *json_row = NULL;
1746
1747 if (uj)
1748 json = json_object_new_object();
1749 else
1750 vty_out(vty,
1751 "Source Group RpfIface RibNextHop RpfAddress %s",
1752 VTY_NEWLINE);
12e41d03 1753
0f588989 1754 for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) {
eaa54bdb
DW
1755 char src_str[INET_ADDRSTRLEN];
1756 char grp_str[INET_ADDRSTRLEN];
1757 char rpf_nexthop_str[PREFIX_STRLEN];
1758 char rpf_addr_str[PREFIX_STRLEN];
12e41d03
DL
1759 struct pim_rpf *rpf;
1760 const char *rpf_ifname;
9bf3c633 1761
12e41d03 1762 rpf = &up->rpf;
9bf3c633 1763
4ed0af70
DS
1764 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
1765 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
63c59d0c
DS
1766 pim_addr_dump("<nexthop?>", &rpf->source_nexthop.mrib_nexthop_addr, rpf_nexthop_str, sizeof(rpf_nexthop_str));
1767 pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str));
9bf3c633 1768
12e41d03 1769 rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
9bf3c633
DW
1770
1771 if (uj) {
e775c0a4 1772 json_object_object_get_ex(json, grp_str, &json_group);
9bf3c633 1773
e775c0a4
DW
1774 if (!json_group) {
1775 json_group = json_object_new_object();
1776 json_object_object_add(json, grp_str, json_group);
9bf3c633
DW
1777 }
1778
9bf3c633 1779 json_row = json_object_new_object();
e775c0a4 1780 json_object_pim_upstream_add(json_row, up);
9bf3c633
DW
1781 json_object_string_add(json_row, "source", src_str);
1782 json_object_string_add(json_row, "group", grp_str);
1783 json_object_string_add(json_row, "rpfInterface", rpf_ifname);
1784 json_object_string_add(json_row, "ribNexthop", rpf_nexthop_str);
1785 json_object_string_add(json_row, "rpfAddress", rpf_addr_str);
e775c0a4 1786 json_object_object_add(json_group, src_str, json_row);
9bf3c633
DW
1787 } else {
1788 vty_out(vty, "%-15s %-15s %-8s %-15s %-15s%s",
1789 src_str,
1790 grp_str,
1791 rpf_ifname,
1792 rpf_nexthop_str,
1793 rpf_addr_str,
1794 VTY_NEWLINE);
1795 }
1796 }
1797
1798 if (uj) {
17b52be1 1799 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
9bf3c633 1800 json_object_free(json);
12e41d03
DL
1801 }
1802}
1803
9bf3c633 1804static void show_rpf_refresh_stats(struct vty *vty, time_t now, json_object *json)
12e41d03
DL
1805{
1806 char refresh_uptime[10];
1807
1808 pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now, qpim_rpf_cache_refresh_last);
1809
9bf3c633
DW
1810 if (json) {
1811 json_object_int_add(json, "rpfCacheRefreshDelayMsecs", qpim_rpf_cache_refresh_delay_msec);
1812 json_object_int_add(json, "rpfCacheRefreshTimer", pim_time_timer_remain_msec(qpim_rpf_cache_refresher));
1813 json_object_int_add(json, "rpfCacheRefreshRequests", qpim_rpf_cache_refresh_requests);
1814 json_object_int_add(json, "rpfCacheRefreshEvents", qpim_rpf_cache_refresh_events);
1815 json_object_string_add(json, "rpfCacheRefreshLast", refresh_uptime);
1816 json_object_int_add(json, "nexthopLookups", qpim_nexthop_lookups);
1817 } else {
1818 vty_out(vty,
1819 "RPF Cache Refresh Delay: %ld msecs%s"
1820 "RPF Cache Refresh Timer: %ld msecs%s"
1821 "RPF Cache Refresh Requests: %lld%s"
1822 "RPF Cache Refresh Events: %lld%s"
1823 "RPF Cache Refresh Last: %s%s"
1824 "Nexthop Lookups: %lld%s",
1825 qpim_rpf_cache_refresh_delay_msec, VTY_NEWLINE,
1826 pim_time_timer_remain_msec(qpim_rpf_cache_refresher), VTY_NEWLINE,
1827 (long long)qpim_rpf_cache_refresh_requests, VTY_NEWLINE,
1828 (long long)qpim_rpf_cache_refresh_events, VTY_NEWLINE,
1829 refresh_uptime, VTY_NEWLINE,
1830 (long long) qpim_nexthop_lookups, VTY_NEWLINE);
1831 }
12e41d03
DL
1832}
1833
1834static void show_scan_oil_stats(struct vty *vty, time_t now)
1835{
1836 char uptime_scan_oil[10];
1837 char uptime_mroute_add[10];
1838 char uptime_mroute_del[10];
1839
1840 pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now, qpim_scan_oil_last);
1841 pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now, qpim_mroute_add_last);
1842 pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now, qpim_mroute_del_last);
1843
1844 vty_out(vty,
1845 "Scan OIL - Last: %s Events: %lld%s"
1846 "MFC Add - Last: %s Events: %lld%s"
1847 "MFC Del - Last: %s Events: %lld%s",
1848 uptime_scan_oil, (long long) qpim_scan_oil_events, VTY_NEWLINE,
1849 uptime_mroute_add, (long long) qpim_mroute_add_events, VTY_NEWLINE,
1850 uptime_mroute_del, (long long) qpim_mroute_del_events, VTY_NEWLINE);
1851}
1852
9bf3c633 1853static void pim_show_rpf(struct vty *vty, u_char uj)
12e41d03
DL
1854{
1855 struct listnode *up_node;
1856 struct pim_upstream *up;
1857 time_t now = pim_time_monotonic_sec();
9bf3c633 1858 json_object *json = NULL;
e775c0a4 1859 json_object *json_group = NULL;
9bf3c633
DW
1860 json_object *json_row = NULL;
1861
9bf3c633
DW
1862 if (uj) {
1863 json = json_object_new_object();
1864 show_rpf_refresh_stats(vty, now, json);
1865 } else {
1866 show_rpf_refresh_stats(vty, now, json);
1867 vty_out(vty, "%s", VTY_NEWLINE);
1868 vty_out(vty,
1869 "Source Group RpfIface RpfAddress RibNextHop Metric Pref%s",
1870 VTY_NEWLINE);
1871 }
12e41d03 1872
0f588989 1873 for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) {
eaa54bdb
DW
1874 char src_str[INET_ADDRSTRLEN];
1875 char grp_str[INET_ADDRSTRLEN];
1876 char rpf_addr_str[PREFIX_STRLEN];
1877 char rib_nexthop_str[PREFIX_STRLEN];
12e41d03
DL
1878 const char *rpf_ifname;
1879 struct pim_rpf *rpf = &up->rpf;
1880
4ed0af70
DS
1881 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
1882 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
63c59d0c
DS
1883 pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str));
1884 pim_addr_dump("<nexthop?>", &rpf->source_nexthop.mrib_nexthop_addr, rib_nexthop_str, sizeof(rib_nexthop_str));
12e41d03
DL
1885
1886 rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
1887
9bf3c633 1888 if (uj) {
e775c0a4 1889 json_object_object_get_ex(json, grp_str, &json_group);
9bf3c633 1890
e775c0a4
DW
1891 if (!json_group) {
1892 json_group = json_object_new_object();
1893 json_object_object_add(json, grp_str, json_group);
1894 }
9bf3c633
DW
1895
1896 json_row = json_object_new_object();
1897 json_object_string_add(json_row, "source", src_str);
1898 json_object_string_add(json_row, "group", grp_str);
1899 json_object_string_add(json_row, "rpfInterface", rpf_ifname);
1900 json_object_string_add(json_row, "rpfAddress", rpf_addr_str);
1901 json_object_string_add(json_row, "ribNexthop", rib_nexthop_str);
1902 json_object_int_add(json_row, "routeMetric", rpf->source_nexthop.mrib_route_metric);
1903 json_object_int_add(json_row, "routePreference", rpf->source_nexthop.mrib_metric_preference);
e775c0a4 1904 json_object_object_add(json_group, src_str, json_row);
9bf3c633 1905
9bf3c633
DW
1906 } else {
1907 vty_out(vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d%s",
1908 src_str,
1909 grp_str,
1910 rpf_ifname,
1911 rpf_addr_str,
1912 rib_nexthop_str,
1913 rpf->source_nexthop.mrib_route_metric,
1914 rpf->source_nexthop.mrib_metric_preference,
1915 VTY_NEWLINE);
1916 }
1917 }
1918
1919 if (uj) {
17b52be1 1920 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
9bf3c633 1921 json_object_free(json);
12e41d03
DL
1922 }
1923}
1924
9b91bb50 1925static void igmp_show_groups(struct vty *vty, u_char uj)
12e41d03
DL
1926{
1927 struct listnode *ifnode;
1928 struct interface *ifp;
1929 time_t now;
9b91bb50
DW
1930 json_object *json = NULL;
1931 json_object *json_iface = NULL;
1932 json_object *json_row = NULL;
12e41d03
DL
1933
1934 now = pim_time_monotonic_sec();
1935
9b91bb50
DW
1936 if (uj)
1937 json = json_object_new_object();
1938 else
1939 vty_out(vty, "Interface Address Group Mode Timer Srcs V Uptime %s", VTY_NEWLINE);
12e41d03
DL
1940
1941 /* scan interfaces */
469351b3 1942 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
12e41d03
DL
1943 struct pim_interface *pim_ifp = ifp->info;
1944 struct listnode *sock_node;
1945 struct igmp_sock *igmp;
1946
1947 if (!pim_ifp)
1948 continue;
1949
1950 /* scan igmp sockets */
1951 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
eaa54bdb 1952 char ifaddr_str[INET_ADDRSTRLEN];
12e41d03
DL
1953 struct listnode *grpnode;
1954 struct igmp_group *grp;
1955
1956 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1957
1958 /* scan igmp groups */
1959 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
eaa54bdb 1960 char group_str[INET_ADDRSTRLEN];
12e41d03
DL
1961 char hhmmss[10];
1962 char uptime[10];
1963
1964 pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
1965 pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss), grp->t_group_timer);
1966 pim_time_uptime(uptime, sizeof(uptime), now - grp->group_creation);
1967
9b91bb50
DW
1968 if (uj) {
1969 json_object_object_get_ex(json, ifp->name, &json_iface);
12e41d03 1970
9b91bb50
DW
1971 if (!json_iface) {
1972 json_iface = json_object_new_object();
1973 json_object_pim_ifp_add(json_iface, ifp);
1974 json_object_object_add(json, ifp->name, json_iface);
1975 }
1976
1977 json_row = json_object_new_object();
1978 json_object_string_add(json_row, "source", ifaddr_str);
1979 json_object_string_add(json_row, "group", group_str);
b05b72e8
DW
1980
1981 if (grp->igmp_version == 3)
1982 json_object_string_add(json_row, "mode", grp->group_filtermode_isexcl ? "EXCLUDE" : "INCLUDE");
1983
9b91bb50
DW
1984 json_object_string_add(json_row, "timer", hhmmss);
1985 json_object_int_add(json_row, "sourcesCount", grp->group_source_list ? listcount(grp->group_source_list) : 0);
b05b72e8 1986 json_object_int_add(json_row, "version", grp->igmp_version);
9b91bb50
DW
1987 json_object_string_add(json_row, "uptime", uptime);
1988 json_object_object_add(json_iface, group_str, json_row);
1989
1990 } else {
1991 vty_out(vty, "%-9s %-15s %-15s %4s %8s %4d %d %8s%s",
1992 ifp->name,
1993 ifaddr_str,
1994 group_str,
b05b72e8 1995 grp->igmp_version == 3 ? (grp->group_filtermode_isexcl ? "EXCL" : "INCL") : "----",
9b91bb50
DW
1996 hhmmss,
1997 grp->group_source_list ? listcount(grp->group_source_list) : 0,
b05b72e8 1998 grp->igmp_version,
9b91bb50
DW
1999 uptime,
2000 VTY_NEWLINE);
2001 }
12e41d03
DL
2002 } /* scan igmp groups */
2003 } /* scan igmp sockets */
2004 } /* scan interfaces */
9b91bb50
DW
2005
2006 if (uj) {
17b52be1 2007 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
9b91bb50
DW
2008 json_object_free(json);
2009 }
12e41d03
DL
2010}
2011
2012static void igmp_show_group_retransmission(struct vty *vty)
2013{
2014 struct listnode *ifnode;
2015 struct interface *ifp;
2016
2017 vty_out(vty, "Interface Address Group RetTimer Counter RetSrcs%s", VTY_NEWLINE);
2018
2019 /* scan interfaces */
469351b3 2020 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
12e41d03
DL
2021 struct pim_interface *pim_ifp = ifp->info;
2022 struct listnode *sock_node;
2023 struct igmp_sock *igmp;
2024
2025 if (!pim_ifp)
2026 continue;
2027
2028 /* scan igmp sockets */
2029 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
eaa54bdb 2030 char ifaddr_str[INET_ADDRSTRLEN];
12e41d03
DL
2031 struct listnode *grpnode;
2032 struct igmp_group *grp;
2033
2034 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
2035
2036 /* scan igmp groups */
2037 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
eaa54bdb 2038 char group_str[INET_ADDRSTRLEN];
12e41d03
DL
2039 char grp_retr_mmss[10];
2040 struct listnode *src_node;
2041 struct igmp_source *src;
2042 int grp_retr_sources = 0;
2043
2044 pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
2045 pim_time_timer_to_mmss(grp_retr_mmss, sizeof(grp_retr_mmss), grp->t_group_query_retransmit_timer);
2046
2047
2048 /* count group sources with retransmission state */
2049 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node, src)) {
2050 if (src->source_query_retransmit_count > 0) {
2051 ++grp_retr_sources;
2052 }
2053 }
2054
2055 vty_out(vty, "%-9s %-15s %-15s %-8s %7d %7d%s",
2056 ifp->name,
2057 ifaddr_str,
2058 group_str,
2059 grp_retr_mmss,
2060 grp->group_specific_query_retransmit_count,
2061 grp_retr_sources,
2062 VTY_NEWLINE);
2063
2064 } /* scan igmp groups */
2065 } /* scan igmp sockets */
2066 } /* scan interfaces */
2067}
2068
12e41d03
DL
2069static void igmp_show_sources(struct vty *vty)
2070{
2071 struct listnode *ifnode;
2072 struct interface *ifp;
2073 time_t now;
2074
2075 now = pim_time_monotonic_sec();
2076
2077 vty_out(vty, "Interface Address Group Source Timer Fwd Uptime %s", VTY_NEWLINE);
2078
2079 /* scan interfaces */
469351b3 2080 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
12e41d03
DL
2081 struct pim_interface *pim_ifp = ifp->info;
2082 struct listnode *sock_node;
2083 struct igmp_sock *igmp;
2084
2085 if (!pim_ifp)
2086 continue;
2087
2088 /* scan igmp sockets */
2089 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
eaa54bdb 2090 char ifaddr_str[INET_ADDRSTRLEN];
12e41d03
DL
2091 struct listnode *grpnode;
2092 struct igmp_group *grp;
2093
2094 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
2095
2096 /* scan igmp groups */
2097 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
eaa54bdb 2098 char group_str[INET_ADDRSTRLEN];
12e41d03
DL
2099 struct listnode *srcnode;
2100 struct igmp_source *src;
2101
2102 pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
2103
2104 /* scan group sources */
2105 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) {
eaa54bdb 2106 char source_str[INET_ADDRSTRLEN];
12e41d03
DL
2107 char mmss[10];
2108 char uptime[10];
2109
2110 pim_inet4_dump("<source?>", src->source_addr, source_str, sizeof(source_str));
2111
2112 pim_time_timer_to_mmss(mmss, sizeof(mmss), src->t_source_timer);
2113
2114 pim_time_uptime(uptime, sizeof(uptime), now - src->source_creation);
2115
2116 vty_out(vty, "%-9s %-15s %-15s %-15s %5s %3s %8s%s",
2117 ifp->name,
2118 ifaddr_str,
2119 group_str,
2120 source_str,
2121 mmss,
2122 IGMP_SOURCE_TEST_FORWARDING(src->source_flags) ? "Y" : "N",
2123 uptime,
2124 VTY_NEWLINE);
2125
2126 } /* scan group sources */
2127 } /* scan igmp groups */
2128 } /* scan igmp sockets */
2129 } /* scan interfaces */
2130}
2131
2132static void igmp_show_source_retransmission(struct vty *vty)
2133{
2134 struct listnode *ifnode;
2135 struct interface *ifp;
2136
2137 vty_out(vty, "Interface Address Group Source Counter%s", VTY_NEWLINE);
2138
2139 /* scan interfaces */
469351b3 2140 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
12e41d03
DL
2141 struct pim_interface *pim_ifp = ifp->info;
2142 struct listnode *sock_node;
2143 struct igmp_sock *igmp;
2144
2145 if (!pim_ifp)
2146 continue;
2147
2148 /* scan igmp sockets */
2149 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
eaa54bdb 2150 char ifaddr_str[INET_ADDRSTRLEN];
12e41d03
DL
2151 struct listnode *grpnode;
2152 struct igmp_group *grp;
2153
2154 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
2155
2156 /* scan igmp groups */
2157 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
eaa54bdb 2158 char group_str[INET_ADDRSTRLEN];
12e41d03
DL
2159 struct listnode *srcnode;
2160 struct igmp_source *src;
2161
2162 pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
2163
2164 /* scan group sources */
2165 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) {
eaa54bdb 2166 char source_str[INET_ADDRSTRLEN];
12e41d03
DL
2167
2168 pim_inet4_dump("<source?>", src->source_addr, source_str, sizeof(source_str));
2169
2170 vty_out(vty, "%-9s %-15s %-15s %-15s %7d%s",
2171 ifp->name,
2172 ifaddr_str,
2173 group_str,
2174 source_str,
2175 src->source_query_retransmit_count,
2176 VTY_NEWLINE);
2177
2178 } /* scan group sources */
2179 } /* scan igmp groups */
2180 } /* scan igmp sockets */
2181 } /* scan interfaces */
2182}
2183
2184static void clear_igmp_interfaces()
2185{
2186 struct listnode *ifnode;
2187 struct listnode *ifnextnode;
2188 struct interface *ifp;
2189
469351b3 2190 for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) {
12e41d03
DL
2191 pim_if_addr_del_all_igmp(ifp);
2192 }
2193
469351b3 2194 for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) {
12e41d03
DL
2195 pim_if_addr_add_all(ifp);
2196 }
2197}
2198
2199static void clear_pim_interfaces()
2200{
2201 struct listnode *ifnode;
2202 struct listnode *ifnextnode;
2203 struct interface *ifp;
2204
469351b3 2205 for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) {
12e41d03
DL
2206 if (ifp->info) {
2207 pim_neighbor_delete_all(ifp, "interface cleared");
2208 }
2209 }
2210}
2211
2212static void clear_interfaces()
2213{
2214 clear_igmp_interfaces();
2215 clear_pim_interfaces();
2216}
2217
12e41d03
DL
2218DEFUN (clear_ip_interfaces,
2219 clear_ip_interfaces_cmd,
2220 "clear ip interfaces",
2221 CLEAR_STR
2222 IP_STR
2223 "Reset interfaces\n")
2224{
2225 clear_interfaces();
2226
2227 return CMD_SUCCESS;
2228}
2229
2230DEFUN (clear_ip_igmp_interfaces,
2231 clear_ip_igmp_interfaces_cmd,
2232 "clear ip igmp interfaces",
2233 CLEAR_STR
2234 IP_STR
2235 CLEAR_IP_IGMP_STR
2236 "Reset IGMP interfaces\n")
2237{
2238 clear_igmp_interfaces();
2239
2240 return CMD_SUCCESS;
2241}
2242
2243static void mroute_add_all()
2244{
2245 struct listnode *node;
2246 struct channel_oil *c_oil;
2247
040d86ad 2248 for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) {
c171d6d8 2249 if (pim_mroute_add(c_oil)) {
12e41d03 2250 /* just log warning */
eaa54bdb
DW
2251 char source_str[INET_ADDRSTRLEN];
2252 char group_str[INET_ADDRSTRLEN];
12e41d03
DL
2253 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
2254 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
2255 zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC",
2256 __FILE__, __PRETTY_FUNCTION__,
2257 source_str, group_str);
2258 }
2259 }
2260}
2261
2262static void mroute_del_all()
2263{
2264 struct listnode *node;
2265 struct channel_oil *c_oil;
2266
040d86ad 2267 for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) {
c171d6d8 2268 if (pim_mroute_del(c_oil)) {
12e41d03 2269 /* just log warning */
eaa54bdb
DW
2270 char source_str[INET_ADDRSTRLEN];
2271 char group_str[INET_ADDRSTRLEN];
12e41d03
DL
2272 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
2273 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
2274 zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC",
2275 __FILE__, __PRETTY_FUNCTION__,
2276 source_str, group_str);
2277 }
2278 }
2279}
2280
6250610a
JAG
2281static void static_mroute_add_all()
2282{
2283 struct listnode *node;
2284 struct static_route *s_route;
2285
2286 for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
c171d6d8 2287 if (pim_mroute_add(&s_route->c_oil)) {
6250610a 2288 /* just log warning */
eaa54bdb
DW
2289 char source_str[INET_ADDRSTRLEN];
2290 char group_str[INET_ADDRSTRLEN];
9867746a
DS
2291 pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str));
2292 pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str));
6250610a
JAG
2293 zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC",
2294 __FILE__, __PRETTY_FUNCTION__,
2295 source_str, group_str);
2296 }
2297 }
2298}
2299
2300static void static_mroute_del_all()
2301{
2302 struct listnode *node;
2303 struct static_route *s_route;
2304
2305 for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
c171d6d8 2306 if (pim_mroute_del(&s_route->c_oil)) {
6250610a 2307 /* just log warning */
eaa54bdb
DW
2308 char source_str[INET_ADDRSTRLEN];
2309 char group_str[INET_ADDRSTRLEN];
9867746a
DS
2310 pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str));
2311 pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str));
6250610a
JAG
2312 zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC",
2313 __FILE__, __PRETTY_FUNCTION__,
2314 source_str, group_str);
2315 }
2316 }
2317}
2318
12e41d03
DL
2319DEFUN (clear_ip_mroute,
2320 clear_ip_mroute_cmd,
2321 "clear ip mroute",
2322 CLEAR_STR
2323 IP_STR
2324 "Reset multicast routes\n")
2325{
2326 mroute_del_all();
2327 mroute_add_all();
2328
2329 return CMD_SUCCESS;
2330}
2331
2332DEFUN (clear_ip_pim_interfaces,
2333 clear_ip_pim_interfaces_cmd,
2334 "clear ip pim interfaces",
2335 CLEAR_STR
2336 IP_STR
2337 CLEAR_IP_PIM_STR
2338 "Reset PIM interfaces\n")
2339{
2340 clear_pim_interfaces();
2341
2342 return CMD_SUCCESS;
2343}
2344
2345DEFUN (clear_ip_pim_oil,
2346 clear_ip_pim_oil_cmd,
2347 "clear ip pim oil",
2348 CLEAR_STR
2349 IP_STR
2350 CLEAR_IP_PIM_STR
2351 "Rescan PIM OIL (output interface list)\n")
2352{
2353 pim_scan_oil();
2354
2355 return CMD_SUCCESS;
2356}
2357
2358DEFUN (show_ip_igmp_interface,
2359 show_ip_igmp_interface_cmd,
9b91bb50 2360 "show ip igmp interface [detail|WORD] [json]",
12e41d03
DL
2361 SHOW_STR
2362 IP_STR
2363 IGMP_STR
a268493f 2364 "IGMP interface information\n"
9b91bb50 2365 "Detailed output\n"
a268493f
DW
2366 "interface name\n"
2367 "JavaScript Object Notation\n")
12e41d03 2368{
a268493f
DW
2369 u_char uj = use_json(argc, argv);
2370 if (argv[4]->arg)
2371 igmp_show_interfaces_single(vty, argv[4]->arg, uj);
2372 else
2373 igmp_show_interfaces(vty, uj);
12e41d03
DL
2374
2375 return CMD_SUCCESS;
2376}
2377
2378DEFUN (show_ip_igmp_join,
2379 show_ip_igmp_join_cmd,
2380 "show ip igmp join",
2381 SHOW_STR
2382 IP_STR
2383 IGMP_STR
2384 "IGMP static join information\n")
2385{
2386 igmp_show_interface_join(vty);
2387
2388 return CMD_SUCCESS;
2389}
2390
2391DEFUN (show_ip_igmp_groups,
2392 show_ip_igmp_groups_cmd,
9b91bb50 2393 "show ip igmp groups [json]",
12e41d03
DL
2394 SHOW_STR
2395 IP_STR
2396 IGMP_STR
9b91bb50
DW
2397 IGMP_GROUP_STR
2398 "JavaScript Object Notation\n")
12e41d03 2399{
9b91bb50
DW
2400 u_char uj = use_json(argc, argv);
2401 igmp_show_groups(vty, uj);
12e41d03
DL
2402
2403 return CMD_SUCCESS;
2404}
2405
2406DEFUN (show_ip_igmp_groups_retransmissions,
2407 show_ip_igmp_groups_retransmissions_cmd,
2408 "show ip igmp groups retransmissions",
2409 SHOW_STR
2410 IP_STR
2411 IGMP_STR
2412 IGMP_GROUP_STR
2413 "IGMP group retransmissions\n")
2414{
2415 igmp_show_group_retransmission(vty);
2416
2417 return CMD_SUCCESS;
2418}
2419
12e41d03
DL
2420DEFUN (show_ip_igmp_sources,
2421 show_ip_igmp_sources_cmd,
2422 "show ip igmp sources",
2423 SHOW_STR
2424 IP_STR
2425 IGMP_STR
2426 IGMP_SOURCE_STR)
2427{
2428 igmp_show_sources(vty);
2429
2430 return CMD_SUCCESS;
2431}
2432
2433DEFUN (show_ip_igmp_sources_retransmissions,
2434 show_ip_igmp_sources_retransmissions_cmd,
2435 "show ip igmp sources retransmissions",
2436 SHOW_STR
2437 IP_STR
2438 IGMP_STR
2439 IGMP_SOURCE_STR
2440 "IGMP source retransmissions\n")
2441{
2442 igmp_show_source_retransmission(vty);
2443
2444 return CMD_SUCCESS;
2445}
2446
12e41d03
DL
2447DEFUN (show_ip_pim_assert,
2448 show_ip_pim_assert_cmd,
2449 "show ip pim assert",
2450 SHOW_STR
2451 IP_STR
2452 PIM_STR
2453 "PIM interface assert\n")
2454{
2455 pim_show_assert(vty);
2456
2457 return CMD_SUCCESS;
2458}
2459
2460DEFUN (show_ip_pim_assert_internal,
2461 show_ip_pim_assert_internal_cmd,
2462 "show ip pim assert-internal",
2463 SHOW_STR
2464 IP_STR
2465 PIM_STR
2466 "PIM interface internal assert state\n")
2467{
2468 pim_show_assert_internal(vty);
2469
2470 return CMD_SUCCESS;
2471}
2472
2473DEFUN (show_ip_pim_assert_metric,
2474 show_ip_pim_assert_metric_cmd,
2475 "show ip pim assert-metric",
2476 SHOW_STR
2477 IP_STR
2478 PIM_STR
2479 "PIM interface assert metric\n")
2480{
2481 pim_show_assert_metric(vty);
2482
2483 return CMD_SUCCESS;
2484}
2485
2486DEFUN (show_ip_pim_assert_winner_metric,
2487 show_ip_pim_assert_winner_metric_cmd,
2488 "show ip pim assert-winner-metric",
2489 SHOW_STR
2490 IP_STR
2491 PIM_STR
2492 "PIM interface assert winner metric\n")
2493{
2494 pim_show_assert_winner_metric(vty);
2495
2496 return CMD_SUCCESS;
2497}
2498
2499DEFUN (show_ip_pim_dr,
2500 show_ip_pim_dr_cmd,
9bf3c633 2501 "show ip pim designated-router [json]",
12e41d03
DL
2502 SHOW_STR
2503 IP_STR
2504 PIM_STR
2505 "PIM interface designated router\n")
2506{
9bf3c633
DW
2507 u_char uj = use_json(argc, argv);
2508 pim_show_dr(vty, uj);
12e41d03
DL
2509
2510 return CMD_SUCCESS;
2511}
2512
2513DEFUN (show_ip_pim_hello,
2514 show_ip_pim_hello_cmd,
9bf3c633 2515 "show ip pim hello [json]",
12e41d03
DL
2516 SHOW_STR
2517 IP_STR
2518 PIM_STR
2519 "PIM interface hello information\n")
2520{
9bf3c633
DW
2521 u_char uj = use_json(argc, argv);
2522 pim_show_hello(vty, uj);
12e41d03
DL
2523
2524 return CMD_SUCCESS;
2525}
2526
2527DEFUN (show_ip_pim_interface,
2528 show_ip_pim_interface_cmd,
9b91bb50 2529 "show ip pim interface [detail|WORD] [json]",
12e41d03
DL
2530 SHOW_STR
2531 IP_STR
2532 PIM_STR
a268493f 2533 "PIM interface information\n"
9b91bb50 2534 "Detailed output\n"
a268493f
DW
2535 "interface name\n"
2536 "JavaScript Object Notation\n")
12e41d03 2537{
9bf3c633 2538 u_char uj = use_json(argc, argv);
a268493f
DW
2539 if (argv[4]->arg)
2540 pim_show_interfaces_single(vty, argv[4]->arg, uj);
2541 else
2542 pim_show_interfaces(vty, uj);
12e41d03
DL
2543
2544 return CMD_SUCCESS;
2545}
2546
2547DEFUN (show_ip_pim_join,
2548 show_ip_pim_join_cmd,
e775c0a4 2549 "show ip pim join [json]",
12e41d03
DL
2550 SHOW_STR
2551 IP_STR
2552 PIM_STR
2553 "PIM interface join information\n")
2554{
e775c0a4
DW
2555 u_char uj = use_json(argc, argv);
2556 pim_show_join(vty, uj);
12e41d03
DL
2557
2558 return CMD_SUCCESS;
2559}
2560
12e41d03
DL
2561DEFUN (show_ip_pim_local_membership,
2562 show_ip_pim_local_membership_cmd,
e775c0a4 2563 "show ip pim local-membership [json]",
12e41d03
DL
2564 SHOW_STR
2565 IP_STR
2566 PIM_STR
2567 "PIM interface local-membership\n")
2568{
e775c0a4
DW
2569 u_char uj = use_json(argc, argv);
2570 pim_show_membership(vty, uj);
12e41d03
DL
2571
2572 return CMD_SUCCESS;
2573}
2574
12e41d03
DL
2575DEFUN (show_ip_pim_neighbor,
2576 show_ip_pim_neighbor_cmd,
9b91bb50 2577 "show ip pim neighbor [detail|WORD] [json]",
12e41d03
DL
2578 SHOW_STR
2579 IP_STR
2580 PIM_STR
a268493f 2581 "PIM neighbor information\n"
9b91bb50 2582 "Detailed output\n"
a268493f
DW
2583 "Name of interface or neighbor\n"
2584 "JavaScript Object Notation\n")
12e41d03 2585{
9bf3c633 2586 u_char uj = use_json(argc, argv);
a268493f
DW
2587 if (argv[4]->arg)
2588 pim_show_neighbors_single(vty, argv[4]->arg, uj);
2589 else
2590 pim_show_neighbors(vty, uj);
12e41d03
DL
2591
2592 return CMD_SUCCESS;
2593}
2594
2595DEFUN (show_ip_pim_secondary,
2596 show_ip_pim_secondary_cmd,
2597 "show ip pim secondary",
2598 SHOW_STR
2599 IP_STR
2600 PIM_STR
2601 "PIM neighbor addresses\n")
2602{
2603 pim_show_neighbors_secondary(vty);
2604
2605 return CMD_SUCCESS;
2606}
2607
31a21c9c
DW
2608DEFUN (show_ip_pim_state,
2609 show_ip_pim_state_cmd,
2610 "show ip pim state [A.B.C.D] [A.B.C.D] [json]",
2611 SHOW_STR
2612 IP_STR
2613 PIM_STR
2614 "PIM state information\n"
2615 "Unicast or Multicast address\n"
2616 "Multicast address\n"
2617 "JavaScript Object Notation\n")
2618{
2619 const char *src_or_group = NULL;
2620 const char *group = NULL;
2621 u_char uj = use_json(argc, argv);
2622
2623 src_or_group = argv[4]->arg;
2624 group = argv[5]->arg;
2625
2626 pim_show_state(vty, src_or_group, group, uj);
2627
2628 return CMD_SUCCESS;
2629}
2630
12e41d03
DL
2631DEFUN (show_ip_pim_upstream,
2632 show_ip_pim_upstream_cmd,
9bf3c633 2633 "show ip pim upstream [json]",
12e41d03
DL
2634 SHOW_STR
2635 IP_STR
2636 PIM_STR
a268493f
DW
2637 "PIM upstream information\n"
2638 "JavaScript Object Notation\n")
12e41d03 2639{
9bf3c633
DW
2640 u_char uj = use_json(argc, argv);
2641 pim_show_upstream(vty, uj);
12e41d03
DL
2642
2643 return CMD_SUCCESS;
2644}
2645
2646DEFUN (show_ip_pim_upstream_join_desired,
2647 show_ip_pim_upstream_join_desired_cmd,
9bf3c633 2648 "show ip pim upstream-join-desired [json]",
12e41d03
DL
2649 SHOW_STR
2650 IP_STR
2651 PIM_STR
a268493f
DW
2652 "PIM upstream join-desired\n"
2653 "JavaScript Object Notation\n")
12e41d03 2654{
9bf3c633
DW
2655 u_char uj = use_json(argc, argv);
2656 pim_show_join_desired(vty, uj);
12e41d03
DL
2657
2658 return CMD_SUCCESS;
2659}
2660
2661DEFUN (show_ip_pim_upstream_rpf,
2662 show_ip_pim_upstream_rpf_cmd,
9bf3c633 2663 "show ip pim upstream-rpf [json]",
12e41d03
DL
2664 SHOW_STR
2665 IP_STR
2666 PIM_STR
a268493f
DW
2667 "PIM upstream source rpf\n"
2668 "JavaScript Object Notation\n")
12e41d03 2669{
9bf3c633
DW
2670 u_char uj = use_json(argc, argv);
2671 pim_show_upstream_rpf(vty, uj);
12e41d03
DL
2672
2673 return CMD_SUCCESS;
2674}
2675
00d07c6f
DS
2676DEFUN (show_ip_pim_rp,
2677 show_ip_pim_rp_cmd,
9bf3c633 2678 "show ip pim rp-info [json]",
00d07c6f
DS
2679 SHOW_STR
2680 IP_STR
2681 PIM_STR
a268493f
DW
2682 "PIM RP information\n"
2683 "JavaScript Object Notation\n")
00d07c6f 2684{
9bf3c633
DW
2685 u_char uj = use_json(argc, argv);
2686 pim_rp_show_information (vty, uj);
00d07c6f
DS
2687
2688 return CMD_SUCCESS;
2689}
2690
12e41d03
DL
2691DEFUN (show_ip_pim_rpf,
2692 show_ip_pim_rpf_cmd,
9bf3c633 2693 "show ip pim rpf [json]",
12e41d03
DL
2694 SHOW_STR
2695 IP_STR
2696 PIM_STR
a268493f
DW
2697 "PIM cached source rpf information\n"
2698 "JavaScript Object Notation\n")
12e41d03 2699{
9bf3c633
DW
2700 u_char uj = use_json(argc, argv);
2701 pim_show_rpf(vty, uj);
12e41d03
DL
2702
2703 return CMD_SUCCESS;
2704}
2705
2706static void show_multicast_interfaces(struct vty *vty)
2707{
2708 struct listnode *node;
2709 struct interface *ifp;
2710
2711 vty_out(vty, "%s", VTY_NEWLINE);
2712
2713 vty_out(vty, "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut%s",
2714 VTY_NEWLINE);
2715
469351b3 2716 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
12e41d03
DL
2717 struct pim_interface *pim_ifp;
2718 struct in_addr ifaddr;
2719 struct sioc_vif_req vreq;
2720
2721 pim_ifp = ifp->info;
2722
2723 if (!pim_ifp)
2724 continue;
2725
2726 memset(&vreq, 0, sizeof(vreq));
2727 vreq.vifi = pim_ifp->mroute_vif_index;
2728
2729 if (ioctl(qpim_mroute_socket_fd, SIOCGETVIFCNT, &vreq)) {
6c44fe22
DS
2730 zlog_warn("ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s%s",
2731 (unsigned long)SIOCGETVIFCNT,
2732 ifp->name,
2733 pim_ifp->mroute_vif_index,
2734 errno,
2735 safe_strerror(errno),
2736 VTY_NEWLINE);
12e41d03
DL
2737 }
2738
2739 ifaddr = pim_ifp->primary_address;
2740
2741 vty_out(vty, "%-9s %-15s %3d %3d %7lu %7lu %10lu %10lu%s",
2742 ifp->name,
2743 inet_ntoa(ifaddr),
2744 ifp->ifindex,
2745 pim_ifp->mroute_vif_index,
ea8b7c71
RW
2746 (unsigned long) vreq.icount,
2747 (unsigned long) vreq.ocount,
2748 (unsigned long) vreq.ibytes,
2749 (unsigned long) vreq.obytes,
12e41d03
DL
2750 VTY_NEWLINE);
2751 }
2752}
2753
2754DEFUN (show_ip_multicast,
2755 show_ip_multicast_cmd,
2756 "show ip multicast",
2757 SHOW_STR
2758 IP_STR
2759 "Multicast global information\n")
2760{
2761 time_t now = pim_time_monotonic_sec();
2762
2763 if (PIM_MROUTE_IS_ENABLED) {
2764 char uptime[10];
2765
2766 vty_out(vty, "Mroute socket descriptor: %d%s",
2767 qpim_mroute_socket_fd,
2768 VTY_NEWLINE);
2769
2770 pim_time_uptime(uptime, sizeof(uptime), now - qpim_mroute_socket_creation);
2771 vty_out(vty, "Mroute socket uptime: %s%s",
2772 uptime,
2773 VTY_NEWLINE);
2774 }
2775 else {
2776 vty_out(vty, "Multicast disabled%s",
2777 VTY_NEWLINE);
2778 }
2779
2780 vty_out(vty, "%s", VTY_NEWLINE);
2781 vty_out(vty, "Zclient update socket: ");
2782 if (qpim_zclient_update) {
2783 vty_out(vty, "%d failures=%d%s", qpim_zclient_update->sock,
2784 qpim_zclient_update->fail, VTY_NEWLINE);
2785 }
2786 else {
2787 vty_out(vty, "<null zclient>%s", VTY_NEWLINE);
2788 }
05b0d0d0
DS
2789
2790 pim_zlookup_show_ip_multicast (vty);
12e41d03
DL
2791
2792 vty_out(vty, "%s", VTY_NEWLINE);
2793 vty_out(vty, "Current highest VifIndex: %d%s",
2794 qpim_mroute_oif_highest_vif_index,
2795 VTY_NEWLINE);
2796 vty_out(vty, "Maximum highest VifIndex: %d%s",
1865a44a 2797 PIM_MAX_USABLE_VIFS,
12e41d03
DL
2798 VTY_NEWLINE);
2799
2800 vty_out(vty, "%s", VTY_NEWLINE);
2801 vty_out(vty, "Upstream Join Timer: %d secs%s",
2802 qpim_t_periodic,
2803 VTY_NEWLINE);
2804 vty_out(vty, "Join/Prune Holdtime: %d secs%s",
2805 PIM_JP_HOLDTIME,
2806 VTY_NEWLINE);
2807
2808 vty_out(vty, "%s", VTY_NEWLINE);
2809
9bf3c633 2810 show_rpf_refresh_stats(vty, now, NULL);
12e41d03
DL
2811
2812 vty_out(vty, "%s", VTY_NEWLINE);
2813
2814 show_scan_oil_stats(vty, now);
2815
2816 show_multicast_interfaces(vty);
2817
2818 return CMD_SUCCESS;
2819}
2820
b3fb2c27 2821static void show_mroute(struct vty *vty, u_char uj)
12e41d03
DL
2822{
2823 struct listnode *node;
2824 struct channel_oil *c_oil;
6250610a 2825 struct static_route *s_route;
12e41d03 2826 time_t now;
b3fb2c27
DW
2827 json_object *json = NULL;
2828 json_object *json_group = NULL;
2829 json_object *json_source = NULL;
2830 json_object *json_ifp_in = NULL;
2831 json_object *json_ifp_out = NULL;
91c6aec4 2832 int found_oif = 0;
f59a8217 2833 int first = 1;
12e41d03 2834
b3fb2c27
DW
2835 if (uj) {
2836 json = json_object_new_object();
2837 } else {
f59a8217 2838 vty_out(vty, "Source Group Proto Input Output TTL Uptime%s",
b3fb2c27
DW
2839 VTY_NEWLINE);
2840 }
12e41d03
DL
2841
2842 now = pim_time_monotonic_sec();
2843
6250610a 2844 /* print list of PIM and IGMP routes */
040d86ad 2845 for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) {
eaa54bdb
DW
2846 char grp_str[INET_ADDRSTRLEN];
2847 char src_str[INET_ADDRSTRLEN];
b3fb2c27
DW
2848 char in_ifname[16];
2849 char out_ifname[16];
12e41d03 2850 int oif_vif_index;
f59a8217 2851 char proto[100];
b3fb2c27 2852 struct interface *ifp_in;
91c6aec4 2853 found_oif = 0;
f59a8217 2854 first = 1;
58302dc7
DS
2855 if (!c_oil->installed)
2856 continue;
2857
b3fb2c27
DW
2858 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, sizeof(grp_str));
2859 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str, sizeof(src_str));
2860 ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
2861
2862 if (ifp_in)
2863 strcpy(in_ifname, ifp_in->name);
2864 else
2865 strcpy(in_ifname, "<iif?>");
2866
2867 if (uj) {
2868
2869 /* Find the group, create it if it doesn't exist */
2870 json_object_object_get_ex(json, grp_str, &json_group);
2871
2872 if (!json_group) {
2873 json_group = json_object_new_object();
2874 json_object_object_add(json, grp_str, json_group);
2875 }
2876
2877 /* Find the source nested under the group, create it if it doesn't exist */
2878 json_object_object_get_ex(json_group, src_str, &json_source);
2879
2880 if (!json_source) {
2881 json_source = json_object_new_object();
2882 json_object_object_add(json_group, src_str, json_source);
2883 }
2884
2885 /* Find the inbound interface nested under the source, create it if it doesn't exist */
2886 json_object_object_get_ex(json_source, in_ifname, &json_ifp_in);
2887
2888 if (!json_ifp_in) {
2889 json_ifp_in = json_object_new_object();
2890 json_object_object_add(json_source, in_ifname, json_ifp_in);
2891 }
2892 }
2893
12e41d03 2894 for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) {
12e41d03
DL
2895 struct interface *ifp_out;
2896 char oif_uptime[10];
2897 int ttl;
12e41d03
DL
2898
2899 ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
2900 if (ttl < 1)
2901 continue;
2902
12e41d03 2903 ifp_out = pim_if_find_by_vif_index(oif_vif_index);
12e41d03 2904 pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - c_oil->oif_creation[oif_vif_index]);
91c6aec4 2905 found_oif = 1;
12e41d03 2906
b3fb2c27
DW
2907 if (ifp_out)
2908 strcpy(out_ifname, ifp_out->name);
2909 else
2910 strcpy(out_ifname, "<oif?>");
12e41d03 2911
b3fb2c27
DW
2912 if (uj) {
2913 json_ifp_out = json_object_new_object();
2914 json_object_string_add(json_ifp_out, "source", src_str);
2915 json_object_string_add(json_ifp_out, "group", grp_str);
2916
2917 if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM)
2918 json_object_boolean_true_add(json_ifp_out, "protocolPim");
2919
2920 if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP)
2921 json_object_boolean_true_add(json_ifp_out, "protocolIgmp");
2922
2923 if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE)
2924 json_object_boolean_true_add(json_ifp_out, "protocolSource");
2925
2926 json_object_string_add(json_ifp_out, "inboundInterface", in_ifname);
2927 json_object_int_add(json_ifp_out, "iVifI", c_oil->oil.mfcc_parent);
2928 json_object_string_add(json_ifp_out, "outboundInterface", out_ifname);
2929 json_object_int_add(json_ifp_out, "oVifI", oif_vif_index);
2930 json_object_int_add(json_ifp_out, "ttl", ttl);
2931 json_object_string_add(json_ifp_out, "upTime", oif_uptime);
2932 json_object_object_add(json_ifp_in, out_ifname, json_ifp_out);
2933 } else {
b3fb2c27 2934 if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) {
f59a8217 2935 strcpy(proto, "PIM");
b3fb2c27
DW
2936 }
2937
2938 if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) {
f59a8217 2939 strcpy(proto, "IGMP");
b3fb2c27
DW
2940 }
2941
2942 if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) {
f59a8217 2943 strcpy(proto, "SRC");
b3fb2c27
DW
2944 }
2945
f59a8217 2946 vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s%s",
b3fb2c27
DW
2947 src_str,
2948 grp_str,
2949 proto,
2950 in_ifname,
b3fb2c27 2951 out_ifname,
b3fb2c27
DW
2952 ttl,
2953 oif_uptime,
2954 VTY_NEWLINE);
f59a8217
DS
2955
2956 if (first)
2957 {
2958 src_str[0] = '\0';
2959 grp_str[0] = '\0';
2960 in_ifname[0] = '\0';
2961 first = 0;
2962 }
b3fb2c27 2963 }
12e41d03 2964 }
91c6aec4
DW
2965
2966 if (!uj && !found_oif) {
31a21c9c 2967 vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s%s",
91c6aec4
DW
2968 src_str,
2969 grp_str,
31a21c9c 2970 "none",
91c6aec4 2971 in_ifname,
91c6aec4
DW
2972 "none",
2973 0,
91c6aec4
DW
2974 "--:--:--",
2975 VTY_NEWLINE);
2976 }
12e41d03 2977 }
6250610a
JAG
2978
2979 /* Print list of static routes */
2980 for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
eaa54bdb
DW
2981 char grp_str[INET_ADDRSTRLEN];
2982 char src_str[INET_ADDRSTRLEN];
b3fb2c27
DW
2983 char in_ifname[16];
2984 char out_ifname[16];
6250610a 2985 int oif_vif_index;
b3fb2c27 2986 struct interface *ifp_in;
f59a8217
DS
2987 char proto[100];
2988 first = 1;
6250610a 2989
58302dc7
DS
2990 if (!s_route->c_oil.installed)
2991 continue;
2992
b3fb2c27
DW
2993 pim_inet4_dump("<group?>", s_route->group, grp_str, sizeof(grp_str));
2994 pim_inet4_dump("<source?>", s_route->source, src_str, sizeof(src_str));
2995 ifp_in = pim_if_find_by_vif_index(s_route->iif);
91c6aec4 2996 found_oif = 0;
b3fb2c27
DW
2997
2998 if (ifp_in)
2999 strcpy(in_ifname, ifp_in->name);
3000 else
3001 strcpy(in_ifname, "<iif?>");
3002
3003 if (uj) {
3004
3005 /* Find the group, create it if it doesn't exist */
3006 json_object_object_get_ex(json, grp_str, &json_group);
3007
3008 if (!json_group) {
3009 json_group = json_object_new_object();
3010 json_object_object_add(json, grp_str, json_group);
3011 }
3012
3013 /* Find the source nested under the group, create it if it doesn't exist */
3014 json_object_object_get_ex(json_group, src_str, &json_source);
3015
3016 if (!json_source) {
3017 json_source = json_object_new_object();
3018 json_object_object_add(json_group, src_str, json_source);
3019 }
3020
3021 /* Find the inbound interface nested under the source, create it if it doesn't exist */
3022 json_object_object_get_ex(json_source, in_ifname, &json_ifp_in);
3023
3024 if (!json_ifp_in) {
3025 json_ifp_in = json_object_new_object();
3026 json_object_object_add(json_source, in_ifname, json_ifp_in);
3027 }
3028
3029 } else {
f59a8217 3030 strcpy(proto, "STATIC");
b3fb2c27 3031 }
6250610a
JAG
3032
3033 for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) {
6250610a
JAG
3034 struct interface *ifp_out;
3035 char oif_uptime[10];
3036 int ttl;
6250610a
JAG
3037
3038 ttl = s_route->oif_ttls[oif_vif_index];
3039 if (ttl < 1)
3040 continue;
3041
6250610a 3042 ifp_out = pim_if_find_by_vif_index(oif_vif_index);
9867746a 3043 pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - s_route->c_oil.oif_creation[oif_vif_index]);
91c6aec4 3044 found_oif = 1;
6250610a 3045
b3fb2c27
DW
3046 if (ifp_out)
3047 strcpy(out_ifname, ifp_out->name);
3048 else
3049 strcpy(out_ifname, "<oif?>");
6250610a 3050
b3fb2c27
DW
3051 if (uj) {
3052 json_ifp_out = json_object_new_object();
3053 json_object_string_add(json_ifp_out, "source", src_str);
3054 json_object_string_add(json_ifp_out, "group", grp_str);
3055 json_object_boolean_true_add(json_ifp_out, "protocolStatic");
3056 json_object_string_add(json_ifp_out, "inboundInterface", in_ifname);
3057 json_object_int_add(json_ifp_out, "iVifI", c_oil->oil.mfcc_parent);
3058 json_object_string_add(json_ifp_out, "outboundInterface", out_ifname);
3059 json_object_int_add(json_ifp_out, "oVifI", oif_vif_index);
3060 json_object_int_add(json_ifp_out, "ttl", ttl);
3061 json_object_string_add(json_ifp_out, "upTime", oif_uptime);
3062 json_object_object_add(json_ifp_in, out_ifname, json_ifp_out);
3063 } else {
f59a8217 3064 vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s%s",
b3fb2c27
DW
3065 src_str,
3066 grp_str,
3067 proto,
3068 in_ifname,
b3fb2c27 3069 out_ifname,
b3fb2c27
DW
3070 ttl,
3071 oif_uptime,
3072 VTY_NEWLINE);
f59a8217
DS
3073 if (first)
3074 {
3075 src_str[0] = '\0';
3076 grp_str[0] = '\0';
3077 in_ifname[0] = '\0';
3078 first = 0;
3079 }
b3fb2c27 3080 }
6250610a 3081 }
91c6aec4
DW
3082
3083 if (!uj && !found_oif) {
f59a8217 3084 vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s%s",
91c6aec4
DW
3085 src_str,
3086 grp_str,
3087 proto,
3088 in_ifname,
91c6aec4
DW
3089 "none",
3090 0,
91c6aec4
DW
3091 "--:--:--",
3092 VTY_NEWLINE);
3093 }
6250610a 3094 }
b3fb2c27
DW
3095
3096 if (uj) {
17b52be1 3097 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
b3fb2c27
DW
3098 json_object_free(json);
3099 }
12e41d03
DL
3100}
3101
3102DEFUN (show_ip_mroute,
3103 show_ip_mroute_cmd,
b3fb2c27 3104 "show ip mroute [json]",
12e41d03
DL
3105 SHOW_STR
3106 IP_STR
3107 MROUTE_STR)
3108{
b3fb2c27
DW
3109 u_char uj = use_json(argc, argv);
3110 show_mroute(vty, uj);
12e41d03
DL
3111 return CMD_SUCCESS;
3112}
3113
3114static void show_mroute_count(struct vty *vty)
3115{
3116 struct listnode *node;
3117 struct channel_oil *c_oil;
6250610a 3118 struct static_route *s_route;
12e41d03
DL
3119
3120 vty_out(vty, "%s", VTY_NEWLINE);
3121
eccf56d2 3122 vty_out(vty, "Source Group LastUsed Packets Bytes WrongIf %s",
12e41d03
DL
3123 VTY_NEWLINE);
3124
6250610a 3125 /* Print PIM and IGMP route counts */
040d86ad 3126 for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) {
eaa54bdb
DW
3127 char group_str[INET_ADDRSTRLEN];
3128 char source_str[INET_ADDRSTRLEN];
12e41d03 3129
58302dc7
DS
3130 if (!c_oil->installed)
3131 continue;
3132
3667e8a0 3133 pim_mroute_update_counters (c_oil);
12e41d03
DL
3134
3135 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
3136 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
3137
eccf56d2 3138 vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld%s",
12e41d03
DL
3139 source_str,
3140 group_str,
eccf56d2 3141 c_oil->cc.lastused/100,
3667e8a0
DS
3142 c_oil->cc.pktcnt,
3143 c_oil->cc.bytecnt,
3144 c_oil->cc.wrong_if,
12e41d03 3145 VTY_NEWLINE);
6250610a
JAG
3146 }
3147
3148 /* Print static route counts */
3149 for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
eaa54bdb
DW
3150 char group_str[INET_ADDRSTRLEN];
3151 char source_str[INET_ADDRSTRLEN];
6250610a 3152
58302dc7
DS
3153 if (!s_route->c_oil.installed)
3154 continue;
3155
3667e8a0 3156 pim_mroute_update_counters (&s_route->c_oil);
6250610a 3157
9867746a
DS
3158 pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str));
3159 pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str));
6250610a 3160
eccf56d2 3161 vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld%s",
6250610a
JAG
3162 source_str,
3163 group_str,
eccf56d2 3164 s_route->c_oil.cc.lastused,
3667e8a0
DS
3165 s_route->c_oil.cc.pktcnt,
3166 s_route->c_oil.cc.bytecnt,
3167 s_route->c_oil.cc.wrong_if,
6250610a 3168 VTY_NEWLINE);
12e41d03
DL
3169 }
3170}
3171
3172DEFUN (show_ip_mroute_count,
3173 show_ip_mroute_count_cmd,
3174 "show ip mroute count",
3175 SHOW_STR
3176 IP_STR
3177 MROUTE_STR
3178 "Route and packet count data\n")
3179{
3180 show_mroute_count(vty);
3181 return CMD_SUCCESS;
3182}
3183
3184DEFUN (show_ip_rib,
3185 show_ip_rib_cmd,
3186 "show ip rib A.B.C.D",
3187 SHOW_STR
3188 IP_STR
3189 RIB_STR
3190 "Unicast address\n")
3191{
b181fa04 3192 int idx_ipv4 = 3;
12e41d03
DL
3193 struct in_addr addr;
3194 const char *addr_str;
3195 struct pim_nexthop nexthop;
eaa54bdb 3196 char nexthop_addr_str[PREFIX_STRLEN];
12e41d03
DL
3197 int result;
3198
b181fa04 3199 addr_str = argv[idx_ipv4]->arg;
12e41d03
DL
3200 result = inet_pton(AF_INET, addr_str, &addr);
3201 if (result <= 0) {
3202 vty_out(vty, "Bad unicast address %s: errno=%d: %s%s",
3203 addr_str, errno, safe_strerror(errno), VTY_NEWLINE);
3204 return CMD_WARNING;
3205 }
3206
63b8f7a3 3207 if (pim_nexthop_lookup(&nexthop, addr, 0)) {
12e41d03
DL
3208 vty_out(vty, "Failure querying RIB nexthop for unicast address %s%s",
3209 addr_str, VTY_NEWLINE);
3210 return CMD_WARNING;
3211 }
3212
3213 vty_out(vty, "Address NextHop Interface Metric Preference%s",
3214 VTY_NEWLINE);
3215
63c59d0c
DS
3216 pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr,
3217 nexthop_addr_str, sizeof(nexthop_addr_str));
12e41d03
DL
3218
3219 vty_out(vty, "%-15s %-15s %-9s %6d %10d%s",
3220 addr_str,
3221 nexthop_addr_str,
3222 nexthop.interface ? nexthop.interface->name : "<ifname?>",
3223 nexthop.mrib_route_metric,
3224 nexthop.mrib_metric_preference,
3225 VTY_NEWLINE);
3226
3227 return CMD_SUCCESS;
3228}
3229
3230static void show_ssmpingd(struct vty *vty)
3231{
3232 struct listnode *node;
3233 struct ssmpingd_sock *ss;
3234 time_t now;
3235
3236 vty_out(vty, "Source Socket Address Port Uptime Requests%s",
3237 VTY_NEWLINE);
3238
3239 if (!qpim_ssmpingd_list)
3240 return;
3241
3242 now = pim_time_monotonic_sec();
3243
3244 for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) {
eaa54bdb 3245 char source_str[INET_ADDRSTRLEN];
12e41d03
DL
3246 char ss_uptime[10];
3247 struct sockaddr_in bind_addr;
3248 socklen_t len = sizeof(bind_addr);
eaa54bdb 3249 char bind_addr_str[INET_ADDRSTRLEN];
12e41d03
DL
3250
3251 pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str));
3252
3253 if (pim_socket_getsockname(ss->sock_fd, (struct sockaddr *) &bind_addr, &len)) {
3254 vty_out(vty, "%% Failure reading socket name for ssmpingd source %s on fd=%d%s",
3255 source_str, ss->sock_fd, VTY_NEWLINE);
3256 }
3257
3258 pim_inet4_dump("<addr?>", bind_addr.sin_addr, bind_addr_str, sizeof(bind_addr_str));
3259 pim_time_uptime(ss_uptime, sizeof(ss_uptime), now - ss->creation);
3260
3261 vty_out(vty, "%-15s %6d %-15s %5d %8s %8lld%s",
3262 source_str,
3263 ss->sock_fd,
3264 bind_addr_str,
3265 ntohs(bind_addr.sin_port),
3266 ss_uptime,
3267 (long long)ss->requests,
3268 VTY_NEWLINE);
3269 }
3270}
3271
3272DEFUN (show_ip_ssmpingd,
3273 show_ip_ssmpingd_cmd,
3274 "show ip ssmpingd",
3275 SHOW_STR
3276 IP_STR
3277 SHOW_SSMPINGD_STR)
3278{
3279 show_ssmpingd(vty);
3280 return CMD_SUCCESS;
3281}
3282
36d6bd7d 3283static int
dfe43e25 3284pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const char *plist)
36d6bd7d
DS
3285{
3286 int result;
36d6bd7d 3287
dfe43e25
DW
3288 result = pim_rp_new (rp, group, plist);
3289
3290 if (result == PIM_MALLOC_FAIL)
3291 {
3292 vty_out (vty, "%% Out of memory%s", VTY_NEWLINE);
3293 return CMD_WARNING;
3294 }
3295
3296 if (result == PIM_GROUP_BAD_ADDRESS)
3297 {
3298 vty_out (vty, "%% Bad group address specified: %s%s", group, VTY_NEWLINE);
3299 return CMD_WARNING;
3300 }
3301
3302 if (result == PIM_RP_BAD_ADDRESS)
36d6bd7d 3303 {
dfe43e25 3304 vty_out (vty, "%% Bad RP address specified: %s%s", rp, VTY_NEWLINE);
36d6bd7d
DS
3305 return CMD_WARNING;
3306 }
3307
dfe43e25 3308 if (result == PIM_RP_NO_PATH)
36d6bd7d 3309 {
dfe43e25
DW
3310 vty_out (vty, "%% No Path to RP address specified: %s%s", rp, VTY_NEWLINE);
3311 return CMD_WARNING;
3312 }
3313
3314 if (result == PIM_GROUP_OVERLAP)
3315 {
3316 vty_out (vty, "%% Group range specified cannot overlap%s", VTY_NEWLINE);
3317 return CMD_WARNING;
3318 }
3319
3320 if (result == PIM_GROUP_PFXLIST_OVERLAP)
3321 {
3322 vty_out (vty, "%% This group is already covered by a RP prefix-list%s", VTY_NEWLINE);
3323 return CMD_WARNING;
36d6bd7d
DS
3324 }
3325
dfe43e25 3326 if (result == PIM_RP_PFXLIST_IN_USE)
36d6bd7d 3327 {
dfe43e25
DW
3328 vty_out (vty, "%% The same prefix-list cannot be applied to multiple RPs%s", VTY_NEWLINE);
3329 return CMD_WARNING;
36d6bd7d
DS
3330 }
3331
3332 return CMD_SUCCESS;
3333}
3334
4304f95c
DS
3335DEFUN (ip_pim_keep_alive,
3336 ip_pim_keep_alive_cmd,
e8e277d5 3337 "ip pim keep-alive-timer <31-60000>",
4304f95c
DS
3338 IP_STR
3339 "pim multicast routing\n"
3340 "Keep alive Timer"
3341 "Seconds")
3342{
3343 qpim_keep_alive_time = atoi (argv[3]->arg);
3344 return CMD_SUCCESS;
3345}
3346
3347DEFUN (no_ip_pim_keep_alive,
3348 no_ip_pim_keep_alive_cmd,
e8e277d5 3349 "no ip pim keep-alive-timer <31-60000>",
4304f95c
DS
3350 NO_STR
3351 IP_STR
3352 "pim multicast routing\n"
01408ede
DS
3353 "Keep alive Timer\n"
3354 "Seconds\n")
4304f95c
DS
3355{
3356 qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD;
3357 return CMD_SUCCESS;
3358}
3359
01408ede
DS
3360DEFUN (ip_pim_rp_keep_alive,
3361 ip_pim_rp_keep_alive_cmd,
e8e277d5 3362 "ip pim rp keep-alive-timer <31-60000>",
01408ede
DS
3363 IP_STR
3364 "pim multicast routing\n"
3365 "Rendevous Point\n"
3366 "Keep alive Timer\n"
3367 "Seconds\n")
3368{
3369 qpim_rp_keep_alive_time = atoi (argv[4]->arg);
3370 return CMD_SUCCESS;
3371}
3372
3373DEFUN (no_ip_pim_rp_keep_alive,
3374 no_ip_pim_rp_keep_alive_cmd,
e8e277d5 3375 "no ip pim rp keep-alive-timer <31-60000>",
01408ede
DS
3376 NO_STR
3377 IP_STR
3378 "pim multicast routing\n"
3379 "Rendevous Point\n"
3380 "Keep alive Timer\n"
3381 "Seconds\n")
3382{
3383 qpim_rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD;
3384 return CMD_SUCCESS;
3385}
3386
981d6c7a
DS
3387DEFUN (ip_pim_rp,
3388 ip_pim_rp_cmd,
75a26779 3389 "ip pim rp A.B.C.D [A.B.C.D/M]",
981d6c7a 3390 IP_STR
9b34069d
QY
3391 "pim multicast routing\n"
3392 "Rendevous Point\n"
3393 "ip address of RP\n")
981d6c7a 3394{
b181fa04 3395 int idx_ipv4 = 3;
dfe43e25
DW
3396 return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL);
3397}
3398
3399DEFUN (ip_pim_rp_prefix_list,
3400 ip_pim_rp_prefix_list_cmd,
3401 "ip pim rp A.B.C.D prefix-list WORD",
3402 IP_STR
3403 "pim multicast routing\n"
3404 "Rendevous Point\n"
3405 "ip address of RP\n"
3406 "group prefix-list filter\n"
3407 "Name of a prefix-list\n")
3408{
3409 return pim_rp_cmd_worker (vty, argv[3]->arg, NULL, argv[5]->arg);
36d6bd7d 3410}
981d6c7a 3411
36d6bd7d 3412static int
dfe43e25
DW
3413pim_no_rp_cmd_worker (struct vty *vty, const char *rp, const char *group,
3414 const char *plist)
36d6bd7d 3415{
dfe43e25
DW
3416 int result = pim_rp_del (rp, group, plist);
3417
3418 if (result == PIM_GROUP_BAD_ADDRESS)
3419 {
3420 vty_out (vty, "%% Bad group address specified: %s%s", group, VTY_NEWLINE);
3421 return CMD_WARNING;
3422 }
75a26779 3423
dfe43e25 3424 if (result == PIM_RP_BAD_ADDRESS)
75a26779 3425 {
dfe43e25 3426 vty_out (vty, "%% Bad RP address specified: %s%s", rp, VTY_NEWLINE);
36d6bd7d 3427 return CMD_WARNING;
75a26779 3428 }
981d6c7a 3429
dfe43e25 3430 if (result == PIM_RP_NOT_FOUND)
13afbd05 3431 {
dfe43e25 3432 vty_out (vty, "%% Unable to find specified RP%s", VTY_NEWLINE);
13afbd05
DS
3433 return CMD_WARNING;
3434 }
c8ae3ce8 3435
981d6c7a
DS
3436 return CMD_SUCCESS;
3437}
3438
3439DEFUN (no_ip_pim_rp,
3440 no_ip_pim_rp_cmd,
75a26779 3441 "no ip pim rp A.B.C.D [A.B.C.D/M]",
981d6c7a
DS
3442 NO_STR
3443 IP_STR
9b34069d
QY
3444 "pim multicast routing\n"
3445 "Rendevous Point\n"
3446 "ip address of RP\n")
981d6c7a 3447{
75a26779 3448 int idx_ipv4 = 4;
dfe43e25
DW
3449 return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL);
3450}
3451
3452DEFUN (no_ip_pim_rp_prefix_list,
3453 no_ip_pim_rp_prefix_list_cmd,
3454 "no ip pim rp A.B.C.D prefix-list WORD",
3455 NO_STR
3456 IP_STR
3457 "pim multicast routing\n"
3458 "Rendevous Point\n"
3459 "ip address of RP\n"
3460 "group prefix-list filter\n"
3461 "Name of a prefix-list\n")
3462{
3463 return pim_no_rp_cmd_worker (vty, argv[4]->arg, NULL, argv[6]->arg);
981d6c7a
DS
3464}
3465
12e41d03
DL
3466DEFUN (ip_multicast_routing,
3467 ip_multicast_routing_cmd,
9ccf14f7 3468 "ip multicast-routing",
12e41d03
DL
3469 IP_STR
3470 "Enable IP multicast forwarding\n")
3471{
3472 pim_mroute_socket_enable();
3473 pim_if_add_vif_all();
3474 mroute_add_all();
6250610a 3475 static_mroute_add_all();
12e41d03
DL
3476 return CMD_SUCCESS;
3477}
3478
3479DEFUN (no_ip_multicast_routing,
3480 no_ip_multicast_routing_cmd,
9ccf14f7 3481 "no ip multicast-routing",
12e41d03
DL
3482 NO_STR
3483 IP_STR
3484 "Global IP configuration subcommands\n"
3485 "Enable IP multicast forwarding\n")
3486{
3487 mroute_del_all();
6250610a 3488 static_mroute_del_all();
12e41d03
DL
3489 pim_if_del_vif_all();
3490 pim_mroute_socket_disable();
3491 return CMD_SUCCESS;
3492}
3493
3494DEFUN (ip_ssmpingd,
3495 ip_ssmpingd_cmd,
3496 "ip ssmpingd [A.B.C.D]",
3497 IP_STR
3498 CONF_SSMPINGD_STR
3499 "Source address\n")
3500{
b181fa04 3501 int idx_ipv4 = 2;
12e41d03
DL
3502 int result;
3503 struct in_addr source_addr;
abddf075 3504 const char *source_str = (argc > idx_ipv4) ? argv[idx_ipv4]->arg : "0.0.0.0";
12e41d03
DL
3505
3506 result = inet_pton(AF_INET, source_str, &source_addr);
3507 if (result <= 0) {
3508 vty_out(vty, "%% Bad source address %s: errno=%d: %s%s",
3509 source_str, errno, safe_strerror(errno), VTY_NEWLINE);
3510 return CMD_WARNING;
3511 }
3512
3513 result = pim_ssmpingd_start(source_addr);
3514 if (result) {
3515 vty_out(vty, "%% Failure starting ssmpingd for source %s: %d%s",
3516 source_str, result, VTY_NEWLINE);
3517 return CMD_WARNING;
3518 }
3519
3520 return CMD_SUCCESS;
3521}
3522
3523DEFUN (no_ip_ssmpingd,
3524 no_ip_ssmpingd_cmd,
3525 "no ip ssmpingd [A.B.C.D]",
3526 NO_STR
3527 IP_STR
3528 CONF_SSMPINGD_STR
3529 "Source address\n")
3530{
b181fa04 3531 int idx_ipv4 = 3;
12e41d03
DL
3532 int result;
3533 struct in_addr source_addr;
abddf075 3534 const char *source_str = (argc > idx_ipv4) ? argv[idx_ipv4]->arg : "0.0.0.0";
12e41d03
DL
3535
3536 result = inet_pton(AF_INET, source_str, &source_addr);
3537 if (result <= 0) {
3538 vty_out(vty, "%% Bad source address %s: errno=%d: %s%s",
3539 source_str, errno, safe_strerror(errno), VTY_NEWLINE);
3540 return CMD_WARNING;
3541 }
3542
3543 result = pim_ssmpingd_stop(source_addr);
3544 if (result) {
3545 vty_out(vty, "%% Failure stopping ssmpingd for source %s: %d%s",
3546 source_str, result, VTY_NEWLINE);
3547 return CMD_WARNING;
3548 }
3549
3550 return CMD_SUCCESS;
3551}
3552
3553DEFUN (interface_ip_igmp,
3554 interface_ip_igmp_cmd,
3555 "ip igmp",
3556 IP_STR
3557 IFACE_IGMP_STR)
3558{
cdc2d765 3559 VTY_DECLVAR_CONTEXT(interface, ifp);
12e41d03
DL
3560 struct pim_interface *pim_ifp;
3561
12e41d03
DL
3562 pim_ifp = ifp->info;
3563
3564 if (!pim_ifp) {
3565 pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */);
3566 if (!pim_ifp) {
3567 vty_out(vty, "Could not enable IGMP on interface %s%s",
3568 ifp->name, VTY_NEWLINE);
3569 return CMD_WARNING;
3570 }
3571 }
3572 else {
3573 PIM_IF_DO_IGMP(pim_ifp->options);
3574 }
3575
3576 pim_if_addr_add_all(ifp);
3577 pim_if_membership_refresh(ifp);
3578
3579 return CMD_SUCCESS;
3580}
3581
3582DEFUN (interface_no_ip_igmp,
3583 interface_no_ip_igmp_cmd,
3584 "no ip igmp",
3585 NO_STR
3586 IP_STR
3587 IFACE_IGMP_STR)
3588{
cdc2d765 3589 VTY_DECLVAR_CONTEXT(interface, ifp);
12e41d03
DL
3590 struct pim_interface *pim_ifp;
3591
12e41d03
DL
3592 pim_ifp = ifp->info;
3593 if (!pim_ifp)
3594 return CMD_SUCCESS;
3595
3596 PIM_IF_DONT_IGMP(pim_ifp->options);
3597
3598 pim_if_membership_clear(ifp);
3599
3600 pim_if_addr_del_all_igmp(ifp);
3601
3602 if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
3603 pim_if_delete(ifp);
3604 }
3605
3606 return CMD_SUCCESS;
3607}
3608
3609DEFUN (interface_ip_igmp_join,
3610 interface_ip_igmp_join_cmd,
3611 "ip igmp join A.B.C.D A.B.C.D",
3612 IP_STR
3613 IFACE_IGMP_STR
3614 "IGMP join multicast group\n"
3615 "Multicast group address\n"
3616 "Source address\n")
3617{
cdc2d765 3618 VTY_DECLVAR_CONTEXT(interface, ifp);
b181fa04
DW
3619 int idx_ipv4 = 3;
3620 int idx_ipv4_2 = 4;
12e41d03
DL
3621 const char *group_str;
3622 const char *source_str;
3623 struct in_addr group_addr;
3624 struct in_addr source_addr;
3625 int result;
3626
12e41d03 3627 /* Group address */
b181fa04 3628 group_str = argv[idx_ipv4]->arg;
12e41d03
DL
3629 result = inet_pton(AF_INET, group_str, &group_addr);
3630 if (result <= 0) {
3631 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
3632 group_str, errno, safe_strerror(errno), VTY_NEWLINE);
3633 return CMD_WARNING;
3634 }
3635
3636 /* Source address */
b181fa04 3637 source_str = argv[idx_ipv4_2]->arg;
12e41d03
DL
3638 result = inet_pton(AF_INET, source_str, &source_addr);
3639 if (result <= 0) {
3640 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
3641 source_str, errno, safe_strerror(errno), VTY_NEWLINE);
3642 return CMD_WARNING;
3643 }
3644
3645 result = pim_if_igmp_join_add(ifp, group_addr, source_addr);
3646 if (result) {
3647 vty_out(vty, "%% Failure joining IGMP group %s source %s on interface %s: %d%s",
3648 group_str, source_str, ifp->name, result, VTY_NEWLINE);
3649 return CMD_WARNING;
3650 }
3651
3652 return CMD_SUCCESS;
3653}
3654
3655DEFUN (interface_no_ip_igmp_join,
3656 interface_no_ip_igmp_join_cmd,
3657 "no ip igmp join A.B.C.D A.B.C.D",
3658 NO_STR
3659 IP_STR
3660 IFACE_IGMP_STR
3661 "IGMP join multicast group\n"
3662 "Multicast group address\n"
3663 "Source address\n")
3664{
cdc2d765 3665 VTY_DECLVAR_CONTEXT(interface, ifp);
b181fa04
DW
3666 int idx_ipv4 = 4;
3667 int idx_ipv4_2 = 5;
12e41d03
DL
3668 const char *group_str;
3669 const char *source_str;
3670 struct in_addr group_addr;
3671 struct in_addr source_addr;
3672 int result;
3673
12e41d03 3674 /* Group address */
b181fa04 3675 group_str = argv[idx_ipv4]->arg;
12e41d03
DL
3676 result = inet_pton(AF_INET, group_str, &group_addr);
3677 if (result <= 0) {
3678 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
3679 group_str, errno, safe_strerror(errno), VTY_NEWLINE);
3680 return CMD_WARNING;
3681 }
3682
3683 /* Source address */
b181fa04 3684 source_str = argv[idx_ipv4_2]->arg;
12e41d03
DL
3685 result = inet_pton(AF_INET, source_str, &source_addr);
3686 if (result <= 0) {
3687 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
3688 source_str, errno, safe_strerror(errno), VTY_NEWLINE);
3689 return CMD_WARNING;
3690 }
3691
3692 result = pim_if_igmp_join_del(ifp, group_addr, source_addr);
3693 if (result) {
3694 vty_out(vty, "%% Failure leaving IGMP group %s source %s on interface %s: %d%s",
3695 group_str, source_str, ifp->name, result, VTY_NEWLINE);
3696 return CMD_WARNING;
3697 }
3698
3699 return CMD_SUCCESS;
3700}
3701
3702/*
3703 CLI reconfiguration affects the interface level (struct pim_interface).
3704 This function propagates the reconfiguration to every active socket
3705 for that interface.
3706 */
3707static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp)
3708{
3709 struct interface *ifp;
3710 struct pim_interface *pim_ifp;
3711
3712 zassert(igmp);
3713
3714 /* other querier present? */
3715
3716 if (igmp->t_other_querier_timer)
3717 return;
3718
3719 /* this is the querier */
3720
3721 zassert(igmp->interface);
3722 zassert(igmp->interface->info);
3723
3724 ifp = igmp->interface;
3725 pim_ifp = ifp->info;
3726
3727 if (PIM_DEBUG_IGMP_TRACE) {
eaa54bdb 3728 char ifaddr_str[INET_ADDRSTRLEN];
12e41d03
DL
3729 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
3730 zlog_debug("%s: Querier %s on %s reconfig query_interval=%d",
3731 __PRETTY_FUNCTION__,
3732 ifaddr_str,
3733 ifp->name,
3734 pim_ifp->igmp_default_query_interval);
3735 }
3736
3737 /*
3738 igmp_startup_mode_on() will reset QQI:
3739
3740 igmp->querier_query_interval = pim_ifp->igmp_default_query_interval;
3741 */
3742 igmp_startup_mode_on(igmp);
3743}
3744
3745static void igmp_sock_query_reschedule(struct igmp_sock *igmp)
3746{
3747 if (igmp->t_igmp_query_timer) {
3748 /* other querier present */
3749 zassert(igmp->t_igmp_query_timer);
3750 zassert(!igmp->t_other_querier_timer);
3751
3752 pim_igmp_general_query_off(igmp);
3753 pim_igmp_general_query_on(igmp);
3754
3755 zassert(igmp->t_igmp_query_timer);
3756 zassert(!igmp->t_other_querier_timer);
3757 }
3758 else {
3759 /* this is the querier */
3760
3761 zassert(!igmp->t_igmp_query_timer);
3762 zassert(igmp->t_other_querier_timer);
3763
3764 pim_igmp_other_querier_timer_off(igmp);
3765 pim_igmp_other_querier_timer_on(igmp);
3766
3767 zassert(!igmp->t_igmp_query_timer);
3768 zassert(igmp->t_other_querier_timer);
3769 }
3770}
3771
3772static void change_query_interval(struct pim_interface *pim_ifp,
3773 int query_interval)
3774{
3775 struct listnode *sock_node;
3776 struct igmp_sock *igmp;
3777
3778 pim_ifp->igmp_default_query_interval = query_interval;
3779
3780 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
3781 igmp_sock_query_interval_reconfig(igmp);
3782 igmp_sock_query_reschedule(igmp);
3783 }
3784}
3785
3786static void change_query_max_response_time(struct pim_interface *pim_ifp,
3787 int query_max_response_time_dsec)
3788{
3789 struct listnode *sock_node;
3790 struct igmp_sock *igmp;
3791
3792 pim_ifp->igmp_query_max_response_time_dsec = query_max_response_time_dsec;
3793
3794 /*
3795 Below we modify socket/group/source timers in order to quickly
3796 reflect the change. Otherwise, those timers would eventually catch
3797 up.
3798 */
3799
3800 /* scan all sockets */
3801 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
3802 struct listnode *grp_node;
3803 struct igmp_group *grp;
3804
3805 /* reschedule socket general query */
3806 igmp_sock_query_reschedule(igmp);
3807
3808 /* scan socket groups */
3809 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node, grp)) {
3810 struct listnode *src_node;
3811 struct igmp_source *src;
3812
3813 /* reset group timers for groups in EXCLUDE mode */
3814 if (grp->group_filtermode_isexcl) {
3815 igmp_group_reset_gmi(grp);
3816 }
3817
3818 /* scan group sources */
3819 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node, src)) {
3820
3821 /* reset source timers for sources with running timers */
3822 if (src->t_source_timer) {
3823 igmp_source_reset_gmi(igmp, grp, src);
3824 }
3825 }
3826 }
3827 }
3828}
3829
3830#define IGMP_QUERY_INTERVAL_MIN (1)
3831#define IGMP_QUERY_INTERVAL_MAX (1800)
3832
3833DEFUN (interface_ip_igmp_query_interval,
3834 interface_ip_igmp_query_interval_cmd,
9ccf14f7 3835 "ip igmp query-interval (1-1800)",
12e41d03
DL
3836 IP_STR
3837 IFACE_IGMP_STR
3838 IFACE_IGMP_QUERY_INTERVAL_STR
3839 "Query interval in seconds\n")
3840{
cdc2d765 3841 VTY_DECLVAR_CONTEXT(interface, ifp);
12e41d03
DL
3842 struct pim_interface *pim_ifp;
3843 int query_interval;
3844 int query_interval_dsec;
3845
12e41d03
DL
3846 pim_ifp = ifp->info;
3847
3848 if (!pim_ifp) {
3849 vty_out(vty,
3850 "IGMP not enabled on interface %s. Please enable IGMP first.%s",
3851 ifp->name,
3852 VTY_NEWLINE);
3853 return CMD_WARNING;
3854 }
3855
91ac1d43 3856 query_interval = atoi(argv[4]->arg);
12e41d03
DL
3857 query_interval_dsec = 10 * query_interval;
3858
3859 /*
3860 It seems we don't need to check bounds since command.c does it
3861 already, but we verify them anyway for extra safety.
3862 */
3863 if (query_interval < IGMP_QUERY_INTERVAL_MIN) {
3864 vty_out(vty, "General query interval %d lower than minimum %d%s",
3865 query_interval,
3866 IGMP_QUERY_INTERVAL_MIN,
3867 VTY_NEWLINE);
3868 return CMD_WARNING;
3869 }
3870 if (query_interval > IGMP_QUERY_INTERVAL_MAX) {
3871 vty_out(vty, "General query interval %d higher than maximum %d%s",
3872 query_interval,
3873 IGMP_QUERY_INTERVAL_MAX,
3874 VTY_NEWLINE);
3875 return CMD_WARNING;
3876 }
3877
3878 if (query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) {
3879 vty_out(vty,
3880 "Can't set general query interval %d dsec <= query max response time %d dsec.%s",
3881 query_interval_dsec, pim_ifp->igmp_query_max_response_time_dsec,
3882 VTY_NEWLINE);
3883 return CMD_WARNING;
3884 }
3885
3886 change_query_interval(pim_ifp, query_interval);
3887
3888 return CMD_SUCCESS;
3889}
3890
3891DEFUN (interface_no_ip_igmp_query_interval,
3892 interface_no_ip_igmp_query_interval_cmd,
9ccf14f7 3893 "no ip igmp query-interval",
12e41d03
DL
3894 NO_STR
3895 IP_STR
3896 IFACE_IGMP_STR
3897 IFACE_IGMP_QUERY_INTERVAL_STR)
3898{
cdc2d765 3899 VTY_DECLVAR_CONTEXT(interface, ifp);
12e41d03
DL
3900 struct pim_interface *pim_ifp;
3901 int default_query_interval_dsec;
3902
12e41d03
DL
3903 pim_ifp = ifp->info;
3904
3905 if (!pim_ifp)
3906 return CMD_SUCCESS;
3907
3908 default_query_interval_dsec = IGMP_GENERAL_QUERY_INTERVAL * 10;
3909
3910 if (default_query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) {
3911 vty_out(vty,
3912 "Can't set default general query interval %d dsec <= query max response time %d dsec.%s",
3913 default_query_interval_dsec, pim_ifp->igmp_query_max_response_time_dsec,
3914 VTY_NEWLINE);
3915 return CMD_WARNING;
3916 }
3917
3918 change_query_interval(pim_ifp, IGMP_GENERAL_QUERY_INTERVAL);
3919
3920 return CMD_SUCCESS;
3921}
3922
b05b72e8
DW
3923DEFUN (interface_ip_igmp_version,
3924 interface_ip_igmp_version_cmd,
3925 "ip igmp version <2-3>",
3926 IP_STR
3927 IFACE_IGMP_STR
3928 "IGMP version\n"
3929 "IGMP version number\n")
3930{
3931 VTY_DECLVAR_CONTEXT(interface,ifp);
3932 struct pim_interface *pim_ifp;
3933 int igmp_version;
3934
3935 pim_ifp = ifp->info;
3936
3937 if (!pim_ifp) {
3938 vty_out(vty,
3939 "IGMP not enabled on interface %s. Please enable IGMP first.%s",
3940 ifp->name,
3941 VTY_NEWLINE);
3942 return CMD_WARNING;
3943 }
3944
3945 igmp_version = atoi(argv[3]->arg);
3946 pim_ifp->igmp_version = igmp_version;
3947
3948 return CMD_SUCCESS;
3949}
3950
3951DEFUN (interface_no_ip_igmp_version,
3952 interface_no_ip_igmp_version_cmd,
3953 "no ip igmp version <2-3>",
3954 NO_STR
3955 IP_STR
3956 IFACE_IGMP_STR
3957 "IGMP version\n"
3958 "IGMP version number\n")
3959{
3960 VTY_DECLVAR_CONTEXT(interface, ifp);
3961 struct pim_interface *pim_ifp;
3962
3963 pim_ifp = ifp->info;
3964
3965 if (!pim_ifp)
3966 return CMD_SUCCESS;
3967
3968 pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
3969
3970 return CMD_SUCCESS;
3971}
3972
12e41d03
DL
3973#define IGMP_QUERY_MAX_RESPONSE_TIME_MIN (1)
3974#define IGMP_QUERY_MAX_RESPONSE_TIME_MAX (25)
3975
3976DEFUN (interface_ip_igmp_query_max_response_time,
3977 interface_ip_igmp_query_max_response_time_cmd,
9ccf14f7 3978 "ip igmp query-max-response-time (1-25)",
12e41d03
DL
3979 IP_STR
3980 IFACE_IGMP_STR
3981 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
3982 "Query response value in seconds\n")
3983{
cdc2d765 3984 VTY_DECLVAR_CONTEXT(interface, ifp);
12e41d03
DL
3985 struct pim_interface *pim_ifp;
3986 int query_max_response_time;
3987
12e41d03
DL
3988 pim_ifp = ifp->info;
3989
3990 if (!pim_ifp) {
3991 vty_out(vty,
3992 "IGMP not enabled on interface %s. Please enable IGMP first.%s",
3993 ifp->name,
3994 VTY_NEWLINE);
3995 return CMD_WARNING;
3996 }
3997
91ac1d43 3998 query_max_response_time = atoi(argv[4]->arg);
12e41d03
DL
3999
4000 /*
4001 It seems we don't need to check bounds since command.c does it
4002 already, but we verify them anyway for extra safety.
4003 */
4004 if (query_max_response_time < IGMP_QUERY_MAX_RESPONSE_TIME_MIN) {
4005 vty_out(vty, "Query max response time %d sec lower than minimum %d sec%s",
4006 query_max_response_time,
4007 IGMP_QUERY_MAX_RESPONSE_TIME_MIN,
4008 VTY_NEWLINE);
4009 return CMD_WARNING;
4010 }
4011 if (query_max_response_time > IGMP_QUERY_MAX_RESPONSE_TIME_MAX) {
4012 vty_out(vty, "Query max response time %d sec higher than maximum %d sec%s",
4013 query_max_response_time,
4014 IGMP_QUERY_MAX_RESPONSE_TIME_MAX,
4015 VTY_NEWLINE);
4016 return CMD_WARNING;
4017 }
4018
4019 if (query_max_response_time >= pim_ifp->igmp_default_query_interval) {
4020 vty_out(vty,
4021 "Can't set query max response time %d sec >= general query interval %d sec%s",
4022 query_max_response_time, pim_ifp->igmp_default_query_interval,
4023 VTY_NEWLINE);
4024 return CMD_WARNING;
4025 }
4026
4027 change_query_max_response_time(pim_ifp, 10 * query_max_response_time);
4028
4029 return CMD_SUCCESS;
4030}
4031
4032DEFUN (interface_no_ip_igmp_query_max_response_time,
4033 interface_no_ip_igmp_query_max_response_time_cmd,
9ccf14f7 4034 "no ip igmp query-max-response-time",
12e41d03
DL
4035 NO_STR
4036 IP_STR
4037 IFACE_IGMP_STR
4038 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR)
4039{
cdc2d765 4040 VTY_DECLVAR_CONTEXT(interface, ifp);
12e41d03
DL
4041 struct pim_interface *pim_ifp;
4042 int default_query_interval_dsec;
4043
12e41d03
DL
4044 pim_ifp = ifp->info;
4045
4046 if (!pim_ifp)
4047 return CMD_SUCCESS;
4048
4049 default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
4050
4051 if (IGMP_QUERY_MAX_RESPONSE_TIME_DSEC >= default_query_interval_dsec) {
4052 vty_out(vty,
4053 "Can't set default query max response time %d dsec >= general query interval %d dsec.%s",
4054 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC, default_query_interval_dsec,
4055 VTY_NEWLINE);
4056 return CMD_WARNING;
4057 }
4058
4059 change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
4060
4061 return CMD_SUCCESS;
4062}
4063
4064#define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10)
4065#define IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC (250)
4066
4067DEFUN (interface_ip_igmp_query_max_response_time_dsec,
4068 interface_ip_igmp_query_max_response_time_dsec_cmd,
9ccf14f7 4069 "ip igmp query-max-response-time-dsec (10-250)",
12e41d03
DL
4070 IP_STR
4071 IFACE_IGMP_STR
4072 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR
4073 "Query response value in deciseconds\n")
4074{
cdc2d765 4075 VTY_DECLVAR_CONTEXT(interface, ifp);
12e41d03
DL
4076 struct pim_interface *pim_ifp;
4077 int query_max_response_time_dsec;
4078 int default_query_interval_dsec;
4079
12e41d03
DL
4080 pim_ifp = ifp->info;
4081
4082 if (!pim_ifp) {
4083 vty_out(vty,
4084 "IGMP not enabled on interface %s. Please enable IGMP first.%s",
4085 ifp->name,
4086 VTY_NEWLINE);
4087 return CMD_WARNING;
4088 }
4089
91ac1d43 4090 query_max_response_time_dsec = atoi(argv[4]->arg);
12e41d03
DL
4091
4092 /*
4093 It seems we don't need to check bounds since command.c does it
4094 already, but we verify them anyway for extra safety.
4095 */
4096 if (query_max_response_time_dsec < IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC) {
4097 vty_out(vty, "Query max response time %d dsec lower than minimum %d dsec%s",
4098 query_max_response_time_dsec,
4099 IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC,
4100 VTY_NEWLINE);
4101 return CMD_WARNING;
4102 }
4103 if (query_max_response_time_dsec > IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC) {
4104 vty_out(vty, "Query max response time %d dsec higher than maximum %d dsec%s",
4105 query_max_response_time_dsec,
4106 IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC,
4107 VTY_NEWLINE);
4108 return CMD_WARNING;
4109 }
4110
4111 default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
4112
4113 if (query_max_response_time_dsec >= default_query_interval_dsec) {
4114 vty_out(vty,
4115 "Can't set query max response time %d dsec >= general query interval %d dsec%s",
4116 query_max_response_time_dsec, default_query_interval_dsec,
4117 VTY_NEWLINE);
4118 return CMD_WARNING;
4119 }
4120
4121 change_query_max_response_time(pim_ifp, query_max_response_time_dsec);
4122
4123 return CMD_SUCCESS;
4124}
4125
4126DEFUN (interface_no_ip_igmp_query_max_response_time_dsec,
4127 interface_no_ip_igmp_query_max_response_time_dsec_cmd,
9ccf14f7 4128 "no ip igmp query-max-response-time-dsec",
12e41d03
DL
4129 NO_STR
4130 IP_STR
4131 IFACE_IGMP_STR
4132 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR)
4133{
cdc2d765 4134 VTY_DECLVAR_CONTEXT(interface, ifp);
12e41d03
DL
4135 struct pim_interface *pim_ifp;
4136 int default_query_interval_dsec;
4137
12e41d03
DL
4138 pim_ifp = ifp->info;
4139
4140 if (!pim_ifp)
4141 return CMD_SUCCESS;
4142
4143 default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
4144
4145 if (IGMP_QUERY_MAX_RESPONSE_TIME_DSEC >= default_query_interval_dsec) {
4146 vty_out(vty,
4147 "Can't set default query max response time %d dsec >= general query interval %d dsec.%s",
4148 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC, default_query_interval_dsec,
4149 VTY_NEWLINE);
4150 return CMD_WARNING;
4151 }
4152
4153 change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
4154
4155 return CMD_SUCCESS;
4156}
4157
dedccda6
DS
4158DEFUN (interface_ip_pim_drprio,
4159 interface_ip_pim_drprio_cmd,
b181fa04 4160 "ip pim drpriority (1-4294967295)",
dedccda6
DS
4161 IP_STR
4162 PIM_STR
4163 "Set the Designated Router Election Priority\n"
4164 "Value of the new DR Priority\n")
4165{
cdc2d765 4166 VTY_DECLVAR_CONTEXT(interface, ifp);
b181fa04 4167 int idx_number = 3;
dedccda6
DS
4168 struct pim_interface *pim_ifp;
4169 uint32_t old_dr_prio;
4170
dedccda6
DS
4171 pim_ifp = ifp->info;
4172
4173 if (!pim_ifp) {
4174 vty_out(vty, "Please enable PIM on interface, first%s", VTY_NEWLINE);
4175 return CMD_WARNING;
4176 }
4177
4178 old_dr_prio = pim_ifp->pim_dr_priority;
4179
b181fa04 4180 pim_ifp->pim_dr_priority = strtol(argv[idx_number]->arg, NULL, 10);
dedccda6
DS
4181
4182 if (old_dr_prio != pim_ifp->pim_dr_priority) {
4183 if (pim_if_dr_election(ifp))
4184 pim_hello_restart_now(ifp);
4185 }
4186
4187 return CMD_SUCCESS;
4188}
4189
4190DEFUN (interface_no_ip_pim_drprio,
4191 interface_no_ip_pim_drprio_cmd,
b181fa04 4192 "no ip pim drpriority [(1-4294967295)]",
d7fa34c1 4193 NO_STR
dedccda6
DS
4194 IP_STR
4195 PIM_STR
4196 "Revert the Designated Router Priority to default\n"
4197 "Old Value of the Priority\n")
4198{
cdc2d765 4199 VTY_DECLVAR_CONTEXT(interface, ifp);
dedccda6
DS
4200 struct pim_interface *pim_ifp;
4201
dedccda6
DS
4202 pim_ifp = ifp->info;
4203
4204 if (!pim_ifp) {
7960fa8f 4205 vty_out(vty, "Pim not enabled on this interface%s", VTY_NEWLINE);
dedccda6
DS
4206 return CMD_WARNING;
4207 }
4208
4209 if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) {
4210 pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY;
4211 if (pim_if_dr_election(ifp))
4212 pim_hello_restart_now(ifp);
4213 }
4214
4215 return CMD_SUCCESS;
4216}
4217
981d6c7a
DS
4218static int
4219pim_cmd_interface_add (struct interface *ifp, enum pim_interface_type itype)
12e41d03 4220{
981d6c7a 4221 struct pim_interface *pim_ifp = ifp->info;
a920d6e7 4222 struct in_addr null = { .s_addr = 0 };
12e41d03
DL
4223
4224 if (!pim_ifp) {
4225 pim_ifp = pim_if_new(ifp, 0 /* igmp=false */, 1 /* pim=true */);
4226 if (!pim_ifp) {
981d6c7a 4227 return 0;
12e41d03
DL
4228 }
4229 }
4230 else {
4231 PIM_IF_DO_PIM(pim_ifp->options);
4232 }
4233
981d6c7a 4234 pim_ifp->itype = itype;
12e41d03
DL
4235 pim_if_addr_add_all(ifp);
4236 pim_if_membership_refresh(ifp);
4237
a920d6e7 4238 pim_rp_check_rp (null, pim_ifp->primary_address);
981d6c7a
DS
4239 return 1;
4240}
4241
4242
4243DEFUN (interface_ip_pim_ssm,
4244 interface_ip_pim_ssm_cmd,
4245 "ip pim ssm",
4246 IP_STR
4247 PIM_STR
4248 IFACE_PIM_STR)
4249{
cdc2d765 4250 VTY_DECLVAR_CONTEXT(interface, ifp);
981d6c7a
DS
4251
4252 if (!pim_cmd_interface_add(ifp, PIM_INTERFACE_SSM)) {
4253 vty_out(vty, "Could not enable PIM SSM on interface%s", VTY_NEWLINE);
4254 return CMD_WARNING;
4255 }
4256
12e41d03
DL
4257 return CMD_SUCCESS;
4258}
4259
981d6c7a
DS
4260DEFUN (interface_ip_pim_sm,
4261 interface_ip_pim_sm_cmd,
4262 "ip pim sm",
12e41d03
DL
4263 IP_STR
4264 PIM_STR
8371bd60 4265 IFACE_PIM_SM_STR)
12e41d03 4266{
cdc2d765 4267 VTY_DECLVAR_CONTEXT(interface, ifp);
981d6c7a
DS
4268 if (!pim_cmd_interface_add(ifp, PIM_INTERFACE_SM)) {
4269 vty_out(vty, "Could not enable PIM SM on interface%s", VTY_NEWLINE);
4270 return CMD_WARNING;
4271 }
4272
c992c9a0
DS
4273 pim_if_create_pimreg();
4274
981d6c7a
DS
4275 return CMD_SUCCESS;
4276}
4277
4278static int
4279pim_cmd_interface_delete (struct interface *ifp)
4280{
4281 struct pim_interface *pim_ifp = ifp->info;
4282
12e41d03 4283 if (!pim_ifp)
981d6c7a 4284 return 1;
12e41d03
DL
4285
4286 PIM_IF_DONT_PIM(pim_ifp->options);
4287
4288 pim_if_membership_clear(ifp);
4289
4290 /*
4291 pim_if_addr_del_all() removes all sockets from
4292 pim_ifp->igmp_socket_list.
4293 */
4294 pim_if_addr_del_all(ifp);
4295
4296 /*
4297 pim_sock_delete() removes all neighbors from
4298 pim_ifp->pim_neighbor_list.
4299 */
4300 pim_sock_delete(ifp, "pim unconfigured on interface");
4301
4302 if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
4303 pim_if_delete(ifp);
4304 }
4305
981d6c7a
DS
4306 return 1;
4307}
4308
4309DEFUN (interface_no_ip_pim_ssm,
4310 interface_no_ip_pim_ssm_cmd,
4311 "no ip pim ssm",
4312 NO_STR
4313 IP_STR
4314 PIM_STR
4315 IFACE_PIM_STR)
4316{
cdc2d765 4317 VTY_DECLVAR_CONTEXT(interface, ifp);
981d6c7a
DS
4318 if (!pim_cmd_interface_delete(ifp)) {
4319 vty_out(vty, "Unable to delete interface information%s", VTY_NEWLINE);
4320 return CMD_WARNING;
4321 }
4322
4323 return CMD_SUCCESS;
4324}
4325
4326DEFUN (interface_no_ip_pim_sm,
4327 interface_no_ip_pim_sm_cmd,
4328 "no ip pim sm",
4329 NO_STR
4330 IP_STR
4331 PIM_STR
8371bd60 4332 IFACE_PIM_SM_STR)
981d6c7a 4333{
cdc2d765 4334 VTY_DECLVAR_CONTEXT(interface, ifp);
981d6c7a
DS
4335 if (!pim_cmd_interface_delete(ifp)) {
4336 vty_out(vty, "Unable to delete interface information%s", VTY_NEWLINE);
4337 return CMD_WARNING;
4338 }
4339
12e41d03
DL
4340 return CMD_SUCCESS;
4341}
4342
6250610a
JAG
4343DEFUN (interface_ip_mroute,
4344 interface_ip_mroute_cmd,
4345 "ip mroute INTERFACE A.B.C.D",
4346 IP_STR
4347 "Add multicast route\n"
4348 "Outgoing interface name\n"
4349 "Group address\n")
4350{
cdc2d765 4351 VTY_DECLVAR_CONTEXT(interface, iif);
b181fa04
DW
4352 int idx_interface = 2;
4353 int idx_ipv4 = 3;
6250610a
JAG
4354 struct interface *oif;
4355 const char *oifname;
4356 const char *grp_str;
4357 struct in_addr grp_addr;
4358 struct in_addr src_addr;
4359 int result;
4360
b181fa04 4361 oifname = argv[idx_interface]->arg;
6250610a
JAG
4362 oif = if_lookup_by_name(oifname);
4363 if (!oif) {
4364 vty_out(vty, "No such interface name %s%s",
4365 oifname, VTY_NEWLINE);
4366 return CMD_WARNING;
4367 }
4368
b181fa04 4369 grp_str = argv[idx_ipv4]->arg;
6250610a
JAG
4370 result = inet_pton(AF_INET, grp_str, &grp_addr);
4371 if (result <= 0) {
4372 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
4373 grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
4374 return CMD_WARNING;
4375 }
4376
4377 src_addr.s_addr = INADDR_ANY;
4378
4379 if (pim_static_add(iif, oif, grp_addr, src_addr)) {
4380 vty_out(vty, "Failed to add route%s", VTY_NEWLINE);
4381 return CMD_WARNING;
4382 }
4383
4384 return CMD_SUCCESS;
4385}
4386
4387DEFUN (interface_ip_mroute_source,
4388 interface_ip_mroute_source_cmd,
4389 "ip mroute INTERFACE A.B.C.D A.B.C.D",
4390 IP_STR
4391 "Add multicast route\n"
4392 "Outgoing interface name\n"
4393 "Group address\n"
4394 "Source address\n")
4395{
cdc2d765 4396 VTY_DECLVAR_CONTEXT(interface, iif);
b181fa04
DW
4397 int idx_interface = 2;
4398 int idx_ipv4 = 3;
4399 int idx_ipv4_2 = 4;
6250610a
JAG
4400 struct interface *oif;
4401 const char *oifname;
4402 const char *grp_str;
4403 struct in_addr grp_addr;
4404 const char *src_str;
4405 struct in_addr src_addr;
4406 int result;
4407
b181fa04 4408 oifname = argv[idx_interface]->arg;
6250610a
JAG
4409 oif = if_lookup_by_name(oifname);
4410 if (!oif) {
4411 vty_out(vty, "No such interface name %s%s",
4412 oifname, VTY_NEWLINE);
4413 return CMD_WARNING;
4414 }
4415
b181fa04 4416 grp_str = argv[idx_ipv4]->arg;
6250610a
JAG
4417 result = inet_pton(AF_INET, grp_str, &grp_addr);
4418 if (result <= 0) {
4419 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
4420 grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
4421 return CMD_WARNING;
4422 }
4423
b181fa04 4424 src_str = argv[idx_ipv4_2]->arg;
6250610a
JAG
4425 result = inet_pton(AF_INET, src_str, &src_addr);
4426 if (result <= 0) {
4427 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
4428 src_str, errno, safe_strerror(errno), VTY_NEWLINE);
4429 return CMD_WARNING;
4430 }
4431
4432 if (pim_static_add(iif, oif, grp_addr, src_addr)) {
4433 vty_out(vty, "Failed to add route%s", VTY_NEWLINE);
4434 return CMD_WARNING;
4435 }
4436
4437 return CMD_SUCCESS;
4438}
4439
4440DEFUN (interface_no_ip_mroute,
4441 interface_no_ip_mroute_cmd,
4442 "no ip mroute INTERFACE A.B.C.D",
4443 NO_STR
4444 IP_STR
4445 "Add multicast route\n"
4446 "Outgoing interface name\n"
4447 "Group Address\n")
4448{
cdc2d765 4449 VTY_DECLVAR_CONTEXT(interface, iif);
b181fa04
DW
4450 int idx_interface = 3;
4451 int idx_ipv4 = 4;
6250610a
JAG
4452 struct interface *oif;
4453 const char *oifname;
4454 const char *grp_str;
4455 struct in_addr grp_addr;
4456 struct in_addr src_addr;
4457 int result;
4458
b181fa04 4459 oifname = argv[idx_interface]->arg;
6250610a
JAG
4460 oif = if_lookup_by_name(oifname);
4461 if (!oif) {
4462 vty_out(vty, "No such interface name %s%s",
4463 oifname, VTY_NEWLINE);
4464 return CMD_WARNING;
4465 }
4466
b181fa04 4467 grp_str = argv[idx_ipv4]->arg;
6250610a
JAG
4468 result = inet_pton(AF_INET, grp_str, &grp_addr);
4469 if (result <= 0) {
4470 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
4471 grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
4472 return CMD_WARNING;
4473 }
4474
4475 src_addr.s_addr = INADDR_ANY;
4476
4477 if (pim_static_del(iif, oif, grp_addr, src_addr)) {
4478 vty_out(vty, "Failed to remove route%s", VTY_NEWLINE);
4479 return CMD_WARNING;
4480 }
4481
4482 return CMD_SUCCESS;
4483}
4484
4485DEFUN (interface_no_ip_mroute_source,
4486 interface_no_ip_mroute_source_cmd,
4487 "no ip mroute INTERFACE A.B.C.D A.B.C.D",
4488 NO_STR
4489 IP_STR
4490 "Add multicast route\n"
4491 "Outgoing interface name\n"
4492 "Group Address\n"
4493 "Source Address\n")
4494{
cdc2d765 4495 VTY_DECLVAR_CONTEXT(interface, iif);
b181fa04
DW
4496 int idx_interface = 3;
4497 int idx_ipv4 = 4;
4498 int idx_ipv4_2 = 5;
6250610a
JAG
4499 struct interface *oif;
4500 const char *oifname;
4501 const char *grp_str;
4502 struct in_addr grp_addr;
4503 const char *src_str;
4504 struct in_addr src_addr;
4505 int result;
4506
b181fa04 4507 oifname = argv[idx_interface]->arg;
6250610a
JAG
4508 oif = if_lookup_by_name(oifname);
4509 if (!oif) {
4510 vty_out(vty, "No such interface name %s%s",
4511 oifname, VTY_NEWLINE);
4512 return CMD_WARNING;
4513 }
4514
b181fa04 4515 grp_str = argv[idx_ipv4]->arg;
6250610a
JAG
4516 result = inet_pton(AF_INET, grp_str, &grp_addr);
4517 if (result <= 0) {
4518 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
4519 grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
4520 return CMD_WARNING;
4521 }
4522
b181fa04 4523 src_str = argv[idx_ipv4_2]->arg;
6250610a
JAG
4524 result = inet_pton(AF_INET, src_str, &src_addr);
4525 if (result <= 0) {
4526 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
4527 src_str, errno, safe_strerror(errno), VTY_NEWLINE);
4528 return CMD_WARNING;
4529 }
4530
4531 if (pim_static_del(iif, oif, grp_addr, src_addr)) {
4532 vty_out(vty, "Failed to remove route%s", VTY_NEWLINE);
4533 return CMD_WARNING;
4534 }
4535
4536 return CMD_SUCCESS;
4537}
4538
7960fa8f
DS
4539DEFUN (interface_ip_pim_hello,
4540 interface_ip_pim_hello_cmd,
80d3d26b 4541 "ip pim hello (1-180) [(1-180)]",
7960fa8f
DS
4542 IP_STR
4543 PIM_STR
4544 IFACE_PIM_HELLO_STR
80d3d26b
DW
4545 IFACE_PIM_HELLO_TIME_STR
4546 IFACE_PIM_HELLO_HOLD_STR)
7960fa8f 4547{
cdc2d765 4548 VTY_DECLVAR_CONTEXT(interface, ifp);
80d3d26b
DW
4549 int idx_time = 3;
4550 int idx_hold = 4;
7960fa8f
DS
4551 struct pim_interface *pim_ifp;
4552
7960fa8f
DS
4553 pim_ifp = ifp->info;
4554
4555 if (!pim_ifp) {
4556 vty_out(vty, "Pim not enabled on this interface%s", VTY_NEWLINE);
4557 return CMD_WARNING;
4558 }
4559
80d3d26b 4560 pim_ifp->pim_hello_period = strtol(argv[idx_time]->arg, NULL, 10);
7960fa8f 4561
80d3d26b
DW
4562 if (argc > idx_hold)
4563 pim_ifp->pim_default_holdtime = strtol(argv[idx_hold]->arg, NULL, 10);
7960fa8f
DS
4564
4565 return CMD_SUCCESS;
4566}
4567
7960fa8f
DS
4568
4569
4570DEFUN (interface_no_ip_pim_hello,
4571 interface_no_ip_pim_hello_cmd,
b181fa04 4572 "no ip pim hello [(1-180) (1-180)]",
7960fa8f
DS
4573 NO_STR
4574 IP_STR
4575 PIM_STR
4576 IFACE_PIM_HELLO_STR
4577 IFACE_PIM_HELLO_TIME_STR
4578 IFACE_PIM_HELLO_HOLD_STR)
4579{
cdc2d765 4580 VTY_DECLVAR_CONTEXT(interface, ifp);
7960fa8f
DS
4581 struct pim_interface *pim_ifp;
4582
7960fa8f
DS
4583 pim_ifp = ifp->info;
4584
4585 if (!pim_ifp) {
4586 vty_out(vty, "Pim not enabled on this interface%s", VTY_NEWLINE);
4587 return CMD_WARNING;
4588 }
4589
4590 pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD;
4591 pim_ifp->pim_default_holdtime = -1;
4592
4593 return CMD_SUCCESS;
4594}
4595
12e41d03
DL
4596DEFUN (debug_igmp,
4597 debug_igmp_cmd,
4598 "debug igmp",
4599 DEBUG_STR
4600 DEBUG_IGMP_STR)
4601{
4602 PIM_DO_DEBUG_IGMP_EVENTS;
4603 PIM_DO_DEBUG_IGMP_PACKETS;
4604 PIM_DO_DEBUG_IGMP_TRACE;
4605 return CMD_SUCCESS;
4606}
4607
4608DEFUN (no_debug_igmp,
4609 no_debug_igmp_cmd,
4610 "no debug igmp",
4611 NO_STR
4612 DEBUG_STR
4613 DEBUG_IGMP_STR)
4614{
4615 PIM_DONT_DEBUG_IGMP_EVENTS;
4616 PIM_DONT_DEBUG_IGMP_PACKETS;
4617 PIM_DONT_DEBUG_IGMP_TRACE;
4618 return CMD_SUCCESS;
4619}
4620
12e41d03
DL
4621
4622DEFUN (debug_igmp_events,
4623 debug_igmp_events_cmd,
4624 "debug igmp events",
4625 DEBUG_STR
4626 DEBUG_IGMP_STR
4627 DEBUG_IGMP_EVENTS_STR)
4628{
4629 PIM_DO_DEBUG_IGMP_EVENTS;
4630 return CMD_SUCCESS;
4631}
4632
4633DEFUN (no_debug_igmp_events,
4634 no_debug_igmp_events_cmd,
4635 "no debug igmp events",
4636 NO_STR
4637 DEBUG_STR
4638 DEBUG_IGMP_STR
4639 DEBUG_IGMP_EVENTS_STR)
4640{
4641 PIM_DONT_DEBUG_IGMP_EVENTS;
4642 return CMD_SUCCESS;
4643}
4644
12e41d03
DL
4645
4646DEFUN (debug_igmp_packets,
4647 debug_igmp_packets_cmd,
4648 "debug igmp packets",
4649 DEBUG_STR
4650 DEBUG_IGMP_STR
4651 DEBUG_IGMP_PACKETS_STR)
4652{
4653 PIM_DO_DEBUG_IGMP_PACKETS;
4654 return CMD_SUCCESS;
4655}
4656
4657DEFUN (no_debug_igmp_packets,
4658 no_debug_igmp_packets_cmd,
4659 "no debug igmp packets",
4660 NO_STR
4661 DEBUG_STR
4662 DEBUG_IGMP_STR
4663 DEBUG_IGMP_PACKETS_STR)
4664{
4665 PIM_DONT_DEBUG_IGMP_PACKETS;
4666 return CMD_SUCCESS;
4667}
4668
12e41d03
DL
4669
4670DEFUN (debug_igmp_trace,
4671 debug_igmp_trace_cmd,
4672 "debug igmp trace",
4673 DEBUG_STR
4674 DEBUG_IGMP_STR
4675 DEBUG_IGMP_TRACE_STR)
4676{
4677 PIM_DO_DEBUG_IGMP_TRACE;
4678 return CMD_SUCCESS;
4679}
4680
4681DEFUN (no_debug_igmp_trace,
4682 no_debug_igmp_trace_cmd,
4683 "no debug igmp trace",
4684 NO_STR
4685 DEBUG_STR
4686 DEBUG_IGMP_STR
4687 DEBUG_IGMP_TRACE_STR)
4688{
4689 PIM_DONT_DEBUG_IGMP_TRACE;
4690 return CMD_SUCCESS;
4691}
4692
12e41d03
DL
4693
4694DEFUN (debug_mroute,
4695 debug_mroute_cmd,
4696 "debug mroute",
4697 DEBUG_STR
4698 DEBUG_MROUTE_STR)
4699{
4700 PIM_DO_DEBUG_MROUTE;
4701 return CMD_SUCCESS;
4702}
4703
6c7197b1
DS
4704DEFUN (debug_mroute_detail,
4705 debug_mroute_detail_cmd,
4706 "debug mroute detail",
4707 DEBUG_STR
4708 DEBUG_MROUTE_STR
4709 "detailed\n")
4710{
4711 PIM_DO_DEBUG_MROUTE_DETAIL;
4712 return CMD_SUCCESS;
4713}
4714
12e41d03
DL
4715DEFUN (no_debug_mroute,
4716 no_debug_mroute_cmd,
4717 "no debug mroute",
4718 NO_STR
4719 DEBUG_STR
4720 DEBUG_MROUTE_STR)
4721{
4722 PIM_DONT_DEBUG_MROUTE;
4723 return CMD_SUCCESS;
4724}
4725
6c7197b1
DS
4726DEFUN (no_debug_mroute_detail,
4727 no_debug_mroute_detail_cmd,
4728 "no debug mroute detail",
4729 NO_STR
4730 DEBUG_STR
4731 DEBUG_MROUTE_STR
4732 "detailed\n")
4733{
4734 PIM_DONT_DEBUG_MROUTE_DETAIL;
4735 return CMD_SUCCESS;
4736}
12e41d03 4737
6250610a
JAG
4738DEFUN (debug_static,
4739 debug_static_cmd,
4740 "debug static",
4741 DEBUG_STR
4742 DEBUG_STATIC_STR)
4743{
4744 PIM_DO_DEBUG_STATIC;
4745 return CMD_SUCCESS;
4746}
4747
4748DEFUN (no_debug_static,
4749 no_debug_static_cmd,
4750 "no debug static",
4751 NO_STR
4752 DEBUG_STR
4753 DEBUG_STATIC_STR)
4754{
4755 PIM_DONT_DEBUG_STATIC;
4756 return CMD_SUCCESS;
4757}
4758
6250610a 4759
12e41d03
DL
4760DEFUN (debug_pim,
4761 debug_pim_cmd,
4762 "debug pim",
4763 DEBUG_STR
4764 DEBUG_PIM_STR)
4765{
4766 PIM_DO_DEBUG_PIM_EVENTS;
4767 PIM_DO_DEBUG_PIM_PACKETS;
4768 PIM_DO_DEBUG_PIM_TRACE;
4769 return CMD_SUCCESS;
4770}
4771
4772DEFUN (no_debug_pim,
4773 no_debug_pim_cmd,
4774 "no debug pim",
4775 NO_STR
4776 DEBUG_STR
4777 DEBUG_PIM_STR)
4778{
4779 PIM_DONT_DEBUG_PIM_EVENTS;
4780 PIM_DONT_DEBUG_PIM_PACKETS;
4781 PIM_DONT_DEBUG_PIM_TRACE;
4782
4783 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
4784 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
4785
4786 return CMD_SUCCESS;
4787}
4788
12e41d03
DL
4789
4790DEFUN (debug_pim_events,
4791 debug_pim_events_cmd,
4792 "debug pim events",
4793 DEBUG_STR
4794 DEBUG_PIM_STR
4795 DEBUG_PIM_EVENTS_STR)
4796{
4797 PIM_DO_DEBUG_PIM_EVENTS;
4798 return CMD_SUCCESS;
4799}
4800
4801DEFUN (no_debug_pim_events,
4802 no_debug_pim_events_cmd,
4803 "no debug pim events",
4804 NO_STR
4805 DEBUG_STR
4806 DEBUG_PIM_STR
4807 DEBUG_PIM_EVENTS_STR)
4808{
4809 PIM_DONT_DEBUG_PIM_EVENTS;
4810 return CMD_SUCCESS;
4811}
4812
12e41d03
DL
4813
4814DEFUN (debug_pim_packets,
4815 debug_pim_packets_cmd,
4816 "debug pim packets",
4817 DEBUG_STR
4818 DEBUG_PIM_STR
4819 DEBUG_PIM_PACKETS_STR)
4820{
4821 PIM_DO_DEBUG_PIM_PACKETS;
4822 vty_out (vty, "PIM Packet debugging is on %s", VTY_NEWLINE);
4823 return CMD_SUCCESS;
4824}
4825
4826DEFUN (debug_pim_packets_filter,
4827 debug_pim_packets_filter_cmd,
9add3b88 4828 "debug pim packets <hello|joins|register>",
12e41d03
DL
4829 DEBUG_STR
4830 DEBUG_PIM_STR
4831 DEBUG_PIM_PACKETS_STR
4832 DEBUG_PIM_HELLO_PACKETS_STR
9add3b88
DS
4833 DEBUG_PIM_J_P_PACKETS_STR
4834 DEBUG_PIM_PIM_REG_PACKETS_STR)
12e41d03 4835{
b181fa04 4836 int idx_hello_join = 3;
9add3b88 4837 if (strncmp(argv[idx_hello_join]->arg,"h",1) == 0)
12e41d03
DL
4838 {
4839 PIM_DO_DEBUG_PIM_HELLO;
9add3b88 4840 vty_out (vty, "PIM Hello debugging is on%s", VTY_NEWLINE);
12e41d03 4841 }
9add3b88 4842 else if (strncmp(argv[idx_hello_join]->arg,"j",1) == 0)
12e41d03
DL
4843 {
4844 PIM_DO_DEBUG_PIM_J_P;
9add3b88
DS
4845 vty_out (vty, "PIM Join/Prune debugging is on%s", VTY_NEWLINE);
4846 }
4847 else if (strncmp(argv[idx_hello_join]->arg,"r",1) == 0)
4848 {
4849 PIM_DO_DEBUG_PIM_REG;
4850 vty_out (vty, "PIM Register debugging is on%s", VTY_NEWLINE);
12e41d03
DL
4851 }
4852 return CMD_SUCCESS;
4853}
4854
4855DEFUN (no_debug_pim_packets,
4856 no_debug_pim_packets_cmd,
4857 "no debug pim packets",
4858 NO_STR
4859 DEBUG_STR
4860 DEBUG_PIM_STR
4861 DEBUG_PIM_PACKETS_STR
4862 DEBUG_PIM_HELLO_PACKETS_STR
4863 DEBUG_PIM_J_P_PACKETS_STR)
4864{
4865 PIM_DONT_DEBUG_PIM_PACKETS;
4866 vty_out (vty, "PIM Packet debugging is off %s", VTY_NEWLINE);
4867 return CMD_SUCCESS;
4868}
4869
4870DEFUN (no_debug_pim_packets_filter,
4871 no_debug_pim_packets_filter_cmd,
9add3b88 4872 "no debug pim packets <hello|joins|register>",
12e41d03
DL
4873 NO_STR
4874 DEBUG_STR
4875 DEBUG_PIM_STR
4876 DEBUG_PIM_PACKETS_STR
4877 DEBUG_PIM_HELLO_PACKETS_STR
4878 DEBUG_PIM_J_P_PACKETS_STR)
4879{
b181fa04 4880 int idx_hello_join = 4;
9add3b88 4881 if (strncmp(argv[idx_hello_join]->arg,"h",1) == 0)
12e41d03
DL
4882 {
4883 PIM_DONT_DEBUG_PIM_HELLO;
4884 vty_out (vty, "PIM Hello debugging is off %s", VTY_NEWLINE);
4885 }
9add3b88 4886 else if (strncmp(argv[idx_hello_join]->arg,"j",1) == 0)
12e41d03
DL
4887 {
4888 PIM_DONT_DEBUG_PIM_J_P;
4889 vty_out (vty, "PIM Join/Prune debugging is off %s", VTY_NEWLINE);
4890 }
9add3b88
DS
4891 else if (strncmp (argv[idx_hello_join]->arg, "r", 1) == 0)
4892 {
4893 PIM_DONT_DEBUG_PIM_REG;
4894 vty_out (vty, "PIM Register debugging is off%s", VTY_NEWLINE);
4895 }
4896 return CMD_SUCCESS;
12e41d03
DL
4897}
4898
12e41d03
DL
4899
4900DEFUN (debug_pim_packetdump_send,
4901 debug_pim_packetdump_send_cmd,
4902 "debug pim packet-dump send",
4903 DEBUG_STR
4904 DEBUG_PIM_STR
4905 DEBUG_PIM_PACKETDUMP_STR
4906 DEBUG_PIM_PACKETDUMP_SEND_STR)
4907{
4908 PIM_DO_DEBUG_PIM_PACKETDUMP_SEND;
4909 return CMD_SUCCESS;
4910}
4911
4912DEFUN (no_debug_pim_packetdump_send,
4913 no_debug_pim_packetdump_send_cmd,
4914 "no debug pim packet-dump send",
4915 NO_STR
4916 DEBUG_STR
4917 DEBUG_PIM_STR
4918 DEBUG_PIM_PACKETDUMP_STR
4919 DEBUG_PIM_PACKETDUMP_SEND_STR)
4920{
4921 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
4922 return CMD_SUCCESS;
4923}
4924
12e41d03
DL
4925
4926DEFUN (debug_pim_packetdump_recv,
4927 debug_pim_packetdump_recv_cmd,
4928 "debug pim packet-dump receive",
4929 DEBUG_STR
4930 DEBUG_PIM_STR
4931 DEBUG_PIM_PACKETDUMP_STR
4932 DEBUG_PIM_PACKETDUMP_RECV_STR)
4933{
4934 PIM_DO_DEBUG_PIM_PACKETDUMP_RECV;
4935 return CMD_SUCCESS;
4936}
4937
4938DEFUN (no_debug_pim_packetdump_recv,
4939 no_debug_pim_packetdump_recv_cmd,
4940 "no debug pim packet-dump receive",
4941 NO_STR
4942 DEBUG_STR
4943 DEBUG_PIM_STR
4944 DEBUG_PIM_PACKETDUMP_STR
4945 DEBUG_PIM_PACKETDUMP_RECV_STR)
4946{
4947 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
4948 return CMD_SUCCESS;
4949}
4950
12e41d03
DL
4951
4952DEFUN (debug_pim_trace,
4953 debug_pim_trace_cmd,
4954 "debug pim trace",
4955 DEBUG_STR
4956 DEBUG_PIM_STR
4957 DEBUG_PIM_TRACE_STR)
4958{
4959 PIM_DO_DEBUG_PIM_TRACE;
4960 return CMD_SUCCESS;
4961}
4962
4963DEFUN (no_debug_pim_trace,
4964 no_debug_pim_trace_cmd,
4965 "no debug pim trace",
4966 NO_STR
4967 DEBUG_STR
4968 DEBUG_PIM_STR
4969 DEBUG_PIM_TRACE_STR)
4970{
4971 PIM_DONT_DEBUG_PIM_TRACE;
4972 return CMD_SUCCESS;
4973}
4974
12e41d03
DL
4975
4976DEFUN (debug_ssmpingd,
4977 debug_ssmpingd_cmd,
4978 "debug ssmpingd",
4979 DEBUG_STR
4980 DEBUG_PIM_STR
4981 DEBUG_SSMPINGD_STR)
4982{
4983 PIM_DO_DEBUG_SSMPINGD;
4984 return CMD_SUCCESS;
4985}
4986
4987DEFUN (no_debug_ssmpingd,
4988 no_debug_ssmpingd_cmd,
4989 "no debug ssmpingd",
4990 NO_STR
4991 DEBUG_STR
4992 DEBUG_PIM_STR
4993 DEBUG_SSMPINGD_STR)
4994{
4995 PIM_DONT_DEBUG_SSMPINGD;
4996 return CMD_SUCCESS;
4997}
4998
12e41d03
DL
4999
5000DEFUN (debug_pim_zebra,
5001 debug_pim_zebra_cmd,
5002 "debug pim zebra",
5003 DEBUG_STR
5004 DEBUG_PIM_STR
5005 DEBUG_PIM_ZEBRA_STR)
5006{
5007 PIM_DO_DEBUG_ZEBRA;
5008 return CMD_SUCCESS;
5009}
5010
5011DEFUN (no_debug_pim_zebra,
5012 no_debug_pim_zebra_cmd,
5013 "no debug pim zebra",
5014 NO_STR
5015 DEBUG_STR
5016 DEBUG_PIM_STR
5017 DEBUG_PIM_ZEBRA_STR)
5018{
5019 PIM_DONT_DEBUG_ZEBRA;
5020 return CMD_SUCCESS;
5021}
5022
12e41d03 5023
7a1d58ce
DS
5024DEFUN (show_debugging_pim,
5025 show_debugging_pim_cmd,
5026 "show debugging pim",
12e41d03 5027 SHOW_STR
7a1d58ce
DS
5028 DEBUG_STR
5029 PIM_STR)
12e41d03
DL
5030{
5031 pim_debug_config_write(vty);
5032 return CMD_SUCCESS;
5033}
5034
5035static struct igmp_sock *find_igmp_sock_by_fd(int fd)
5036{
5037 struct listnode *ifnode;
5038 struct interface *ifp;
5039
5040 /* scan all interfaces */
469351b3 5041 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
12e41d03
DL
5042 struct pim_interface *pim_ifp;
5043 struct igmp_sock *igmp;
5044
5045 if (!ifp->info)
5046 continue;
5047
5048 pim_ifp = ifp->info;
5049
5050 /* lookup igmp socket under current interface */
5051 igmp = igmp_sock_lookup_by_fd(pim_ifp->igmp_socket_list, fd);
5052 if (igmp)
5053 return igmp;
5054 }
5055
5056 return 0;
5057}
5058
5059DEFUN (test_igmp_receive_report,
5060 test_igmp_receive_report_cmd,
e961923c 5061 "test igmp receive report (0-65535) A.B.C.D (1-6) LINE...",
12e41d03
DL
5062 "Test\n"
5063 "Test IGMP protocol\n"
5064 "Test IGMP message\n"
5065 "Test IGMP report\n"
5066 "Socket\n"
5067 "IGMP group address\n"
5068 "Record type\n"
5069 "Sources\n")
5070{
b181fa04
DW
5071 int idx_number = 4;
5072 int idx_ipv4 = 5;
5073 int idx_number_2 = 6;
58749582 5074 int idx_line = 7;
12e41d03
DL
5075 char buf[1000];
5076 char *igmp_msg;
5077 struct ip *ip_hdr;
5078 size_t ip_hlen; /* ip header length in bytes */
5079 int ip_msg_len;
5080 int igmp_msg_len;
5081 const char *socket;
5082 int socket_fd;
5083 const char *grp_str;
5084 struct in_addr grp_addr;
5085 const char *record_type_str;
5086 int record_type;
5087 const char *src_str;
5088 int result;
5089 struct igmp_sock *igmp;
5090 char *group_record;
5091 int num_sources;
5092 struct in_addr *sources;
5093 struct in_addr *src_addr;
5094 int argi;
5095
b181fa04 5096 socket = argv[idx_number]->arg;
12e41d03
DL
5097 socket_fd = atoi(socket);
5098 igmp = find_igmp_sock_by_fd(socket_fd);
5099 if (!igmp) {
5100 vty_out(vty, "Could not find IGMP socket %s: fd=%d%s",
5101 socket, socket_fd, VTY_NEWLINE);
5102 return CMD_WARNING;
5103 }
5104
b181fa04 5105 grp_str = argv[idx_ipv4]->arg;
12e41d03
DL
5106 result = inet_pton(AF_INET, grp_str, &grp_addr);
5107 if (result <= 0) {
5108 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
5109 grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
5110 return CMD_WARNING;
5111 }
5112
b181fa04 5113 record_type_str = argv[idx_number_2]->arg;
12e41d03
DL
5114 record_type = atoi(record_type_str);
5115
5116 /*
5117 Tweak IP header
5118 */
5119 ip_hdr = (struct ip *) buf;
5120 ip_hdr->ip_p = PIM_IP_PROTO_IGMP;
5121 ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
5122 ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */
5123 ip_hdr->ip_src = igmp->ifaddr;
5124 ip_hdr->ip_dst = igmp->ifaddr;
5125
5126 /*
5127 Build IGMP v3 report message
5128 */
5129 igmp_msg = buf + ip_hlen;
5130 group_record = igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET;
5131 *igmp_msg = PIM_IGMP_V3_MEMBERSHIP_REPORT; /* type */
b05b72e8 5132 *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; /* for computing checksum */
12e41d03
DL
5133 *(uint16_t *) (igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET) = htons(1); /* one group record */
5134 *(uint8_t *) (group_record + IGMP_V3_GROUP_RECORD_TYPE_OFFSET) = record_type;
5135 memcpy(group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET, &grp_addr, sizeof(struct in_addr));
5136
5137 /* Scan LINE sources */
5138 sources = (struct in_addr *) (group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET);
5139 src_addr = sources;
58749582 5140 for (argi = idx_line; argi < argc; ++argi,++src_addr) {
91ac1d43 5141 src_str = argv[argi]->arg;
12e41d03
DL
5142 result = inet_pton(AF_INET, src_str, src_addr);
5143 if (result <= 0) {
5144 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
5145 src_str, errno, safe_strerror(errno), VTY_NEWLINE);
5146 return CMD_WARNING;
5147 }
5148 }
5149 num_sources = src_addr - sources;
5150
5151 *(uint16_t *)(group_record + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET) = htons(num_sources);
5152
5153 igmp_msg_len = IGMP_V3_MSG_MIN_SIZE + (num_sources << 4); /* v3 report for one single group record */
5154
5155 /* compute checksum */
b05b72e8 5156 *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET) = in_cksum(igmp_msg, igmp_msg_len);
12e41d03
DL
5157
5158 /* "receive" message */
5159
5160 ip_msg_len = ip_hlen + igmp_msg_len;
5161 result = pim_igmp_packet(igmp, buf, ip_msg_len);
5162 if (result) {
5163 vty_out(vty, "pim_igmp_packet(len=%d) returned: %d%s",
5164 ip_msg_len, result, VTY_NEWLINE);
5165 return CMD_WARNING;
5166 }
5167
5168 return CMD_SUCCESS;
5169}
5170
5171static int hexval(uint8_t ch)
5172{
5173 return isdigit(ch) ? (ch - '0') : (10 + tolower(ch) - 'a');
5174}
5175
5176DEFUN (test_pim_receive_dump,
5177 test_pim_receive_dump_cmd,
e961923c 5178 "test pim receive dump INTERFACE A.B.C.D LINE...",
12e41d03
DL
5179 "Test\n"
5180 "Test PIM protocol\n"
5181 "Test PIM message reception\n"
5182 "Test PIM packet dump reception from neighbor\n"
5183 "Interface\n"
5184 "Neighbor address\n"
5185 "Packet dump\n")
5186{
b181fa04
DW
5187 int idx_interface = 4;
5188 int idx_ipv4 = 5;
58749582 5189 int idx_line = 6;
12e41d03
DL
5190 uint8_t buf[1000];
5191 uint8_t *pim_msg;
5192 struct ip *ip_hdr;
5193 size_t ip_hlen; /* ip header length in bytes */
5194 int ip_msg_len;
5195 int pim_msg_size;
5196 const char *neigh_str;
5197 struct in_addr neigh_addr;
5198 const char *ifname;
5199 struct interface *ifp;
5200 int argi;
5201 int result;
5202
5203 /* Find interface */
b181fa04 5204 ifname = argv[idx_interface]->arg;
12e41d03
DL
5205 ifp = if_lookup_by_name(ifname);
5206 if (!ifp) {
5207 vty_out(vty, "No such interface name %s%s",
5208 ifname, VTY_NEWLINE);
5209 return CMD_WARNING;
5210 }
5211
5212 /* Neighbor address */
b181fa04 5213 neigh_str = argv[idx_ipv4]->arg;
12e41d03
DL
5214 result = inet_pton(AF_INET, neigh_str, &neigh_addr);
5215 if (result <= 0) {
5216 vty_out(vty, "Bad neighbor address %s: errno=%d: %s%s",
5217 neigh_str, errno, safe_strerror(errno), VTY_NEWLINE);
5218 return CMD_WARNING;
5219 }
5220
5221 /*
5222 Tweak IP header
5223 */
5224 ip_hdr = (struct ip *) buf;
5225 ip_hdr->ip_p = PIM_IP_PROTO_PIM;
5226 ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
5227 ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */
5228 ip_hdr->ip_src = neigh_addr;
5229 ip_hdr->ip_dst = qpim_all_pim_routers_addr;
5230
5231 /*
5232 Build PIM hello message
5233 */
5234 pim_msg = buf + ip_hlen;
5235 pim_msg_size = 0;
5236
5237 /* Scan LINE dump into buffer */
58749582 5238 for (argi = idx_line; argi < argc; ++argi) {
91ac1d43 5239 const char *str = argv[argi]->arg;
12e41d03
DL
5240 int str_len = strlen(str);
5241 int str_last = str_len - 1;
5242 int i;
5243
5244 if (str_len % 2) {
5245 vty_out(vty, "%% Uneven hex array arg %d=%s%s",
5246 argi, str, VTY_NEWLINE);
5247 return CMD_WARNING;
5248 }
5249
5250 for (i = 0; i < str_last; i += 2) {
5251 uint8_t octet;
5252 int left;
5253 uint8_t h1 = str[i];
5254 uint8_t h2 = str[i + 1];
5255
5256 if (!isxdigit(h1) || !isxdigit(h2)) {
5257 vty_out(vty, "%% Non-hex octet %c%c at hex array arg %d=%s%s",
5258 h1, h2, argi, str, VTY_NEWLINE);
5259 return CMD_WARNING;
5260 }
5261 octet = (hexval(h1) << 4) + hexval(h2);
5262
5263 left = sizeof(buf) - ip_hlen - pim_msg_size;
5264 if (left < 1) {
5265 vty_out(vty, "%% Overflow buf_size=%zu buf_left=%d at hex array arg %d=%s octet %02x%s",
5266 sizeof(buf), left, argi, str, octet, VTY_NEWLINE);
5267 return CMD_WARNING;
5268 }
5269
5270 pim_msg[pim_msg_size++] = octet;
5271 }
5272 }
5273
5274 ip_msg_len = ip_hlen + pim_msg_size;
5275
5276 vty_out(vty, "Receiving: buf_size=%zu ip_msg_size=%d pim_msg_size=%d%s",
5277 sizeof(buf), ip_msg_len, pim_msg_size, VTY_NEWLINE);
5278
5279 /* "receive" message */
5280
5281 result = pim_pim_packet(ifp, buf, ip_msg_len);
5282 if (result) {
5283 vty_out(vty, "%% pim_pim_packet(len=%d) returned failure: %d%s",
5284 ip_msg_len, result, VTY_NEWLINE);
5285 return CMD_WARNING;
5286 }
5287
5288 return CMD_SUCCESS;
5289}
5290
5291DEFUN (test_pim_receive_hello,
5292 test_pim_receive_hello_cmd,
b181fa04 5293 "test pim receive hello INTERFACE A.B.C.D (0-65535) (0-65535) (0-65535) (0-32767) (0-65535) (0-1) [LINE]",
12e41d03
DL
5294 "Test\n"
5295 "Test PIM protocol\n"
5296 "Test PIM message reception\n"
5297 "Test PIM hello reception from neighbor\n"
5298 "Interface\n"
5299 "Neighbor address\n"
5300 "Neighbor holdtime\n"
5301 "Neighbor DR priority\n"
5302 "Neighbor generation ID\n"
5303 "Neighbor propagation delay (msec)\n"
5304 "Neighbor override interval (msec)\n"
5305 "Neighbor LAN prune delay T-bit\n"
5306 "Neighbor secondary addresses\n")
5307{
b181fa04
DW
5308 int idx_interface = 4;
5309 int idx_ipv4 = 5;
5310 int idx_number = 6;
5311 int idx_number_2 = 7;
5312 int idx_number_3 = 8;
5313 int idx_number_4 = 9;
5314 int idx_number_5 = 10;
5315 int idx_number_6 = 11;
58749582 5316 int idx_line = 12;
12e41d03
DL
5317 uint8_t buf[1000];
5318 uint8_t *pim_msg;
5319 struct ip *ip_hdr;
5320 size_t ip_hlen; /* ip header length in bytes */
5321 int ip_msg_len;
5322 int pim_tlv_size;
5323 int pim_msg_size;
5324 const char *neigh_str;
5325 struct in_addr neigh_addr;
5326 const char *ifname;
5327 struct interface *ifp;
5328 uint16_t neigh_holdtime;
5329 uint16_t neigh_propagation_delay;
5330 uint16_t neigh_override_interval;
5331 int neigh_can_disable_join_suppression;
5332 uint32_t neigh_dr_priority;
5333 uint32_t neigh_generation_id;
5334 int argi;
5335 int result;
5336
5337 /* Find interface */
b181fa04 5338 ifname = argv[idx_interface]->arg;
12e41d03
DL
5339 ifp = if_lookup_by_name(ifname);
5340 if (!ifp) {
5341 vty_out(vty, "No such interface name %s%s",
5342 ifname, VTY_NEWLINE);
5343 return CMD_WARNING;
5344 }
5345
5346 /* Neighbor address */
b181fa04 5347 neigh_str = argv[idx_ipv4]->arg;
12e41d03
DL
5348 result = inet_pton(AF_INET, neigh_str, &neigh_addr);
5349 if (result <= 0) {
5350 vty_out(vty, "Bad neighbor address %s: errno=%d: %s%s",
5351 neigh_str, errno, safe_strerror(errno), VTY_NEWLINE);
5352 return CMD_WARNING;
5353 }
5354
b181fa04
DW
5355 neigh_holdtime = atoi(argv[idx_number]->arg);
5356 neigh_dr_priority = atoi(argv[idx_number_2]->arg);
5357 neigh_generation_id = atoi(argv[idx_number_3]->arg);
5358 neigh_propagation_delay = atoi(argv[idx_number_4]->arg);
5359 neigh_override_interval = atoi(argv[idx_number_5]->arg);
5360 neigh_can_disable_join_suppression = atoi(argv[idx_number_6]->arg);
12e41d03
DL
5361
5362 /*
5363 Tweak IP header
5364 */
5365 ip_hdr = (struct ip *) buf;
5366 ip_hdr->ip_p = PIM_IP_PROTO_PIM;
5367 ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
5368 ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */
5369 ip_hdr->ip_src = neigh_addr;
5370 ip_hdr->ip_dst = qpim_all_pim_routers_addr;
5371
5372 /*
5373 Build PIM hello message
5374 */
5375 pim_msg = buf + ip_hlen;
5376
5377 /* Scan LINE addresses */
58749582 5378 for (argi = idx_line; argi < argc; ++argi) {
91ac1d43 5379 const char *sec_str = argv[argi]->arg;
12e41d03
DL
5380 struct in_addr sec_addr;
5381 result = inet_pton(AF_INET, sec_str, &sec_addr);
5382 if (result <= 0) {
5383 vty_out(vty, "Bad neighbor secondary address %s: errno=%d: %s%s",
5384 sec_str, errno, safe_strerror(errno), VTY_NEWLINE);
5385 return CMD_WARNING;
5386 }
5387
5388 vty_out(vty,
5389 "FIXME WRITEME consider neighbor secondary address %s%s",
5390 sec_str, VTY_NEWLINE);
5391 }
5392
5393 pim_tlv_size = pim_hello_build_tlv(ifp->name,
5394 pim_msg + PIM_PIM_MIN_LEN,
5395 sizeof(buf) - ip_hlen - PIM_PIM_MIN_LEN,
5396 neigh_holdtime,
5397 neigh_dr_priority,
5398 neigh_generation_id,
5399 neigh_propagation_delay,
5400 neigh_override_interval,
5401 neigh_can_disable_join_suppression,
5402 0 /* FIXME secondary address list */);
5403 if (pim_tlv_size < 0) {
5404 vty_out(vty, "pim_hello_build_tlv() returned failure: %d%s",
5405 pim_tlv_size, VTY_NEWLINE);
5406 return CMD_WARNING;
5407 }
5408
5409 pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN;
5410
5411 pim_msg_build_header(pim_msg, pim_msg_size,
5412 PIM_MSG_TYPE_HELLO);
5413
5414 /* "receive" message */
5415
5416 ip_msg_len = ip_hlen + pim_msg_size;
5417 result = pim_pim_packet(ifp, buf, ip_msg_len);
5418 if (result) {
5419 vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s",
5420 ip_msg_len, result, VTY_NEWLINE);
5421 return CMD_WARNING;
5422 }
5423
5424 return CMD_SUCCESS;
5425}
5426
5427DEFUN (test_pim_receive_assert,
5428 test_pim_receive_assert_cmd,
b181fa04 5429 "test pim receive assert INTERFACE A.B.C.D A.B.C.D A.B.C.D (0-65535) (0-65535) (0-1)",
12e41d03
DL
5430 "Test\n"
5431 "Test PIM protocol\n"
5432 "Test PIM message reception\n"
5433 "Test reception of PIM assert\n"
5434 "Interface\n"
5435 "Neighbor address\n"
5436 "Assert multicast group address\n"
5437 "Assert unicast source address\n"
5438 "Assert metric preference\n"
5439 "Assert route metric\n"
5440 "Assert RPT bit flag\n")
5441{
b181fa04
DW
5442 int idx_interface = 4;
5443 int idx_ipv4 = 5;
5444 int idx_ipv4_2 = 6;
5445 int idx_ipv4_3 = 7;
5446 int idx_number = 8;
5447 int idx_number_2 = 9;
5448 int idx_number_3 = 10;
12e41d03
DL
5449 uint8_t buf[1000];
5450 uint8_t *buf_pastend = buf + sizeof(buf);
5451 uint8_t *pim_msg;
5452 struct ip *ip_hdr;
5453 size_t ip_hlen; /* ip header length in bytes */
5454 int ip_msg_len;
5455 int pim_msg_size;
5456 const char *neigh_str;
5457 struct in_addr neigh_addr;
5458 const char *group_str;
5459 struct in_addr group_addr;
5460 const char *source_str;
5461 struct in_addr source_addr;
5462 const char *ifname;
5463 struct interface *ifp;
5464 uint32_t assert_metric_preference;
5465 uint32_t assert_route_metric;
5466 uint32_t assert_rpt_bit_flag;
5467 int remain;
5468 int result;
5469
5470 /* Find interface */
b181fa04 5471 ifname = argv[idx_interface]->arg;
12e41d03
DL
5472 ifp = if_lookup_by_name(ifname);
5473 if (!ifp) {
5474 vty_out(vty, "No such interface name %s%s",
5475 ifname, VTY_NEWLINE);
5476 return CMD_WARNING;
5477 }
5478
5479 /* Neighbor address */
b181fa04 5480 neigh_str = argv[idx_ipv4]->arg;
12e41d03
DL
5481 result = inet_pton(AF_INET, neigh_str, &neigh_addr);
5482 if (result <= 0) {
5483 vty_out(vty, "Bad neighbor address %s: errno=%d: %s%s",
5484 neigh_str, errno, safe_strerror(errno), VTY_NEWLINE);
5485 return CMD_WARNING;
5486 }
5487
5488 /* Group address */
b181fa04 5489 group_str = argv[idx_ipv4_2]->arg;
12e41d03
DL
5490 result = inet_pton(AF_INET, group_str, &group_addr);
5491 if (result <= 0) {
5492 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
5493 group_str, errno, safe_strerror(errno), VTY_NEWLINE);
5494 return CMD_WARNING;
5495 }
5496
5497 /* Source address */
b181fa04 5498 source_str = argv[idx_ipv4_3]->arg;
12e41d03
DL
5499 result = inet_pton(AF_INET, source_str, &source_addr);
5500 if (result <= 0) {
5501 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
5502 source_str, errno, safe_strerror(errno), VTY_NEWLINE);
5503 return CMD_WARNING;
5504 }
5505
b181fa04
DW
5506 assert_metric_preference = atoi(argv[idx_number]->arg);
5507 assert_route_metric = atoi(argv[idx_number_2]->arg);
5508 assert_rpt_bit_flag = atoi(argv[idx_number_3]->arg);
12e41d03
DL
5509
5510 remain = buf_pastend - buf;
5511 if (remain < (int) sizeof(struct ip)) {
5512 vty_out(vty, "No room for ip header: buf_size=%d < ip_header_size=%zu%s",
5513 remain, sizeof(struct ip), VTY_NEWLINE);
5514 return CMD_WARNING;
5515 }
5516
5517 /*
5518 Tweak IP header
5519 */
5520 ip_hdr = (struct ip *) buf;
5521 ip_hdr->ip_p = PIM_IP_PROTO_PIM;
5522 ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
5523 ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */
5524 ip_hdr->ip_src = neigh_addr;
5525 ip_hdr->ip_dst = qpim_all_pim_routers_addr;
5526
5527 /*
5528 Build PIM assert message
5529 */
5530 pim_msg = buf + ip_hlen; /* skip ip header */
5531
5532 pim_msg_size = pim_assert_build_msg(pim_msg, buf_pastend - pim_msg, ifp,
5533 group_addr, source_addr,
5534 assert_metric_preference,
5535 assert_route_metric,
5536 assert_rpt_bit_flag);
5537 if (pim_msg_size < 0) {
5538 vty_out(vty, "Failure building PIM assert message: size=%d%s",
5539 pim_msg_size, VTY_NEWLINE);
5540 return CMD_WARNING;
5541 }
5542
5543 /* "receive" message */
5544
5545 ip_msg_len = ip_hlen + pim_msg_size;
5546 result = pim_pim_packet(ifp, buf, ip_msg_len);
5547 if (result) {
5548 vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s",
5549 ip_msg_len, result, VTY_NEWLINE);
5550 return CMD_WARNING;
5551 }
5552
5553 return CMD_SUCCESS;
5554}
5555
5556static int recv_joinprune(struct vty *vty,
91ac1d43 5557 struct cmd_token **argv,
12e41d03
DL
5558 int src_is_join)
5559{
5560 uint8_t buf[1000];
5561 const uint8_t *buf_pastend = buf + sizeof(buf);
5562 uint8_t *pim_msg;
12e41d03
DL
5563 int pim_msg_size;
5564 struct ip *ip_hdr;
5565 size_t ip_hlen; /* ip header length in bytes */
5566 int ip_msg_len;
5567 uint16_t neigh_holdtime;
5568 const char *neigh_dst_str;
5569 struct in_addr neigh_dst_addr;
5570 const char *neigh_src_str;
5571 struct in_addr neigh_src_addr;
5572 const char *group_str;
5573 struct in_addr group_addr;
5574 const char *source_str;
5575 struct in_addr source_addr;
5576 const char *ifname;
5577 struct interface *ifp;
5578 int result;
12e41d03
DL
5579
5580 /* Find interface */
91ac1d43 5581 ifname = argv[0]->arg;
12e41d03
DL
5582 ifp = if_lookup_by_name(ifname);
5583 if (!ifp) {
5584 vty_out(vty, "No such interface name %s%s",
5585 ifname, VTY_NEWLINE);
5586 return CMD_WARNING;
5587 }
5588
91ac1d43 5589 neigh_holdtime = atoi(argv[1]->arg);
12e41d03
DL
5590
5591 /* Neighbor destination address */
91ac1d43 5592 neigh_dst_str = argv[2]->arg;
12e41d03
DL
5593 result = inet_pton(AF_INET, neigh_dst_str, &neigh_dst_addr);
5594 if (result <= 0) {
5595 vty_out(vty, "Bad neighbor destination address %s: errno=%d: %s%s",
5596 neigh_dst_str, errno, safe_strerror(errno), VTY_NEWLINE);
5597 return CMD_WARNING;
5598 }
5599
5600 /* Neighbor source address */
91ac1d43 5601 neigh_src_str = argv[3]->arg;
12e41d03
DL
5602 result = inet_pton(AF_INET, neigh_src_str, &neigh_src_addr);
5603 if (result <= 0) {
5604 vty_out(vty, "Bad neighbor source address %s: errno=%d: %s%s",
5605 neigh_src_str, errno, safe_strerror(errno), VTY_NEWLINE);
5606 return CMD_WARNING;
5607 }
5608
5609 /* Multicast group address */
91ac1d43 5610 group_str = argv[4]->arg;
12e41d03
DL
5611 result = inet_pton(AF_INET, group_str, &group_addr);
5612 if (result <= 0) {
5613 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
5614 group_str, errno, safe_strerror(errno), VTY_NEWLINE);
5615 return CMD_WARNING;
5616 }
5617
5618 /* Multicast source address */
91ac1d43 5619 source_str = argv[5]->arg;
12e41d03
DL
5620 result = inet_pton(AF_INET, source_str, &source_addr);
5621 if (result <= 0) {
5622 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
5623 source_str, errno, safe_strerror(errno), VTY_NEWLINE);
5624 return CMD_WARNING;
5625 }
5626
5627 /*
5628 Tweak IP header
5629 */
5630 ip_hdr = (struct ip *) buf;
5631 ip_hdr->ip_p = PIM_IP_PROTO_PIM;
5632 ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
5633 ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */
5634 ip_hdr->ip_src = neigh_src_addr;
5635 ip_hdr->ip_dst = qpim_all_pim_routers_addr;
5636
5637 /*
5638 Build PIM message
5639 */
5640 pim_msg = buf + ip_hlen;
5641
346cffe3
DS
5642 pim_msg_size = pim_msg_join_prune_encode (pim_msg, buf_pastend - pim_msg, src_is_join,
5643 source_addr, group_addr, neigh_dst_addr,
5644 neigh_holdtime);
12e41d03
DL
5645
5646 /*
5647 "Receive" message
5648 */
5649
5650 ip_msg_len = ip_hlen + pim_msg_size;
5651 result = pim_pim_packet(ifp, buf, ip_msg_len);
5652 if (result) {
5653 vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s",
5654 ip_msg_len, result, VTY_NEWLINE);
5655 return CMD_WARNING;
5656 }
5657
5658 return CMD_SUCCESS;
5659}
5660
5661DEFUN (test_pim_receive_join,
5662 test_pim_receive_join_cmd,
b181fa04 5663 "test pim receive join INTERFACE (0-65535) A.B.C.D A.B.C.D A.B.C.D A.B.C.D",
12e41d03
DL
5664 "Test\n"
5665 "Test PIM protocol\n"
5666 "Test PIM message reception\n"
5667 "Test PIM join reception from neighbor\n"
5668 "Interface\n"
5669 "Neighbor holdtime\n"
5670 "Upstream neighbor unicast destination address\n"
5671 "Downstream neighbor unicast source address\n"
5672 "Multicast group address\n"
5673 "Unicast source address\n")
5674{
5675 return recv_joinprune(vty, argv, 1 /* src_is_join=true */);
5676}
5677
5678DEFUN (test_pim_receive_prune,
5679 test_pim_receive_prune_cmd,
b181fa04 5680 "test pim receive prune INTERFACE (0-65535) A.B.C.D A.B.C.D A.B.C.D A.B.C.D",
12e41d03
DL
5681 "Test\n"
5682 "Test PIM protocol\n"
5683 "Test PIM message reception\n"
5684 "Test PIM prune reception from neighbor\n"
5685 "Interface\n"
5686 "Neighbor holdtime\n"
5687 "Upstream neighbor unicast destination address\n"
5688 "Downstream neighbor unicast source address\n"
5689 "Multicast group address\n"
5690 "Unicast source address\n")
5691{
5692 return recv_joinprune(vty, argv, 0 /* src_is_join=false */);
5693}
5694
5695DEFUN (test_pim_receive_upcall,
5696 test_pim_receive_upcall_cmd,
b181fa04 5697 "test pim receive upcall <nocache|wrongvif|wholepkt> (0-65535) A.B.C.D A.B.C.D",
12e41d03
DL
5698 "Test\n"
5699 "Test PIM protocol\n"
5700 "Test PIM message reception\n"
5701 "Test reception of kernel upcall\n"
5702 "NOCACHE kernel upcall\n"
5703 "WRONGVIF kernel upcall\n"
5704 "WHOLEPKT kernel upcall\n"
5705 "Input interface vif index\n"
5706 "Multicast group address\n"
5707 "Multicast source address\n")
5708{
b181fa04
DW
5709 int idx_type = 4;
5710 int idx_number = 5;
5711 int idx_ipv4 = 6;
5712 int idx_ipv4_2 = 7;
12e41d03
DL
5713 struct igmpmsg msg;
5714 const char *upcall_type;
5715 const char *group_str;
5716 const char *source_str;
5717 int result;
5718
b181fa04 5719 upcall_type = argv[idx_type]->arg;
12e41d03
DL
5720
5721 if (upcall_type[0] == 'n')
5722 msg.im_msgtype = IGMPMSG_NOCACHE;
5723 else if (upcall_type[1] == 'r')
5724 msg.im_msgtype = IGMPMSG_WRONGVIF;
5725 else if (upcall_type[1] == 'h')
5726 msg.im_msgtype = IGMPMSG_WHOLEPKT;
5727 else {
5728 vty_out(vty, "Unknown kernel upcall type: %s%s",
5729 upcall_type, VTY_NEWLINE);
5730 return CMD_WARNING;
5731 }
5732
b181fa04 5733 msg.im_vif = atoi(argv[idx_number]->arg);
12e41d03
DL
5734
5735 /* Group address */
b181fa04 5736 group_str = argv[idx_ipv4]->arg;
12e41d03
DL
5737 result = inet_pton(AF_INET, group_str, &msg.im_dst);
5738 if (result <= 0) {
5739 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
5740 group_str, errno, safe_strerror(errno), VTY_NEWLINE);
5741 return CMD_WARNING;
5742 }
5743
5744 /* Source address */
b181fa04 5745 source_str = argv[idx_ipv4_2]->arg;
12e41d03
DL
5746 result = inet_pton(AF_INET, source_str, &msg.im_src);
5747 if (result <= 0) {
5748 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
5749 source_str, errno, safe_strerror(errno), VTY_NEWLINE);
5750 return CMD_WARNING;
5751 }
5752
5753 msg.im_mbz = 0; /* Must be zero */
5754
5755 result = pim_mroute_msg(-1, (char *) &msg, sizeof(msg));
5756 if (result) {
5757 vty_out(vty, "pim_mroute_msg(len=%zu) returned failure: %d%s",
5758 sizeof(msg), result, VTY_NEWLINE);
5759 return CMD_WARNING;
5760 }
5761
5762 return CMD_SUCCESS;
5763}
5764
5765void pim_cmd_init()
5766{
5767 install_node (&pim_global_node, pim_global_config_write); /* PIM_NODE */
5768 install_node (&interface_node, pim_interface_config_write); /* INTERFACE_NODE */
0b84f294 5769 if_cmd_init ();
12e41d03 5770
eb7a976a
DS
5771 install_node (&debug_node, pim_debug_config_write);
5772
12e41d03
DL
5773 install_element (CONFIG_NODE, &ip_multicast_routing_cmd);
5774 install_element (CONFIG_NODE, &no_ip_multicast_routing_cmd);
981d6c7a
DS
5775 install_element (CONFIG_NODE, &ip_pim_rp_cmd);
5776 install_element (CONFIG_NODE, &no_ip_pim_rp_cmd);
dfe43e25
DW
5777 install_element (CONFIG_NODE, &ip_pim_rp_prefix_list_cmd);
5778 install_element (CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd);
4304f95c
DS
5779 install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd);
5780 install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd);
01408ede
DS
5781 install_element (CONFIG_NODE, &ip_pim_rp_keep_alive_cmd);
5782 install_element (CONFIG_NODE, &no_ip_pim_rp_keep_alive_cmd);
12e41d03
DL
5783 install_element (CONFIG_NODE, &ip_ssmpingd_cmd);
5784 install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd);
0b84f294 5785
12e41d03
DL
5786 install_element (INTERFACE_NODE, &interface_ip_igmp_cmd);
5787 install_element (INTERFACE_NODE, &interface_no_ip_igmp_cmd);
5788 install_element (INTERFACE_NODE, &interface_ip_igmp_join_cmd);
5789 install_element (INTERFACE_NODE, &interface_no_ip_igmp_join_cmd);
b05b72e8
DW
5790 install_element (INTERFACE_NODE, &interface_ip_igmp_version_cmd);
5791 install_element (INTERFACE_NODE, &interface_no_ip_igmp_version_cmd);
12e41d03
DL
5792 install_element (INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd);
5793 install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_interval_cmd);
5794 install_element (INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_cmd);
5795 install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_max_response_time_cmd);
5796 install_element (INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_dsec_cmd);
5797 install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_max_response_time_dsec_cmd);
5798 install_element (INTERFACE_NODE, &interface_ip_pim_ssm_cmd);
dedccda6 5799 install_element (INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd);
981d6c7a 5800 install_element (INTERFACE_NODE, &interface_ip_pim_sm_cmd);
8371bd60 5801 install_element (INTERFACE_NODE, &interface_no_ip_pim_sm_cmd);
dedccda6
DS
5802 install_element (INTERFACE_NODE, &interface_ip_pim_drprio_cmd);
5803 install_element (INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd);
7960fa8f 5804 install_element (INTERFACE_NODE, &interface_ip_pim_hello_cmd);
7960fa8f 5805 install_element (INTERFACE_NODE, &interface_no_ip_pim_hello_cmd);
12e41d03 5806
6250610a
JAG
5807 // Static mroutes NEB
5808 install_element (INTERFACE_NODE, &interface_ip_mroute_cmd);
5809 install_element (INTERFACE_NODE, &interface_ip_mroute_source_cmd);
5810 install_element (INTERFACE_NODE, &interface_no_ip_mroute_cmd);
5811 install_element (INTERFACE_NODE, &interface_no_ip_mroute_source_cmd);
5812
12e41d03
DL
5813 install_element (VIEW_NODE, &show_ip_igmp_interface_cmd);
5814 install_element (VIEW_NODE, &show_ip_igmp_join_cmd);
12e41d03
DL
5815 install_element (VIEW_NODE, &show_ip_igmp_groups_cmd);
5816 install_element (VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd);
5817 install_element (VIEW_NODE, &show_ip_igmp_sources_cmd);
5818 install_element (VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd);
12e41d03
DL
5819 install_element (VIEW_NODE, &show_ip_pim_assert_cmd);
5820 install_element (VIEW_NODE, &show_ip_pim_assert_internal_cmd);
5821 install_element (VIEW_NODE, &show_ip_pim_assert_metric_cmd);
5822 install_element (VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd);
12e41d03
DL
5823 install_element (VIEW_NODE, &show_ip_pim_interface_cmd);
5824 install_element (VIEW_NODE, &show_ip_pim_join_cmd);
12e41d03
DL
5825 install_element (VIEW_NODE, &show_ip_pim_local_membership_cmd);
5826 install_element (VIEW_NODE, &show_ip_pim_neighbor_cmd);
5827 install_element (VIEW_NODE, &show_ip_pim_rpf_cmd);
5828 install_element (VIEW_NODE, &show_ip_pim_secondary_cmd);
31a21c9c 5829 install_element (VIEW_NODE, &show_ip_pim_state_cmd);
12e41d03
DL
5830 install_element (VIEW_NODE, &show_ip_pim_upstream_cmd);
5831 install_element (VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd);
5832 install_element (VIEW_NODE, &show_ip_pim_upstream_rpf_cmd);
00d07c6f 5833 install_element (VIEW_NODE, &show_ip_pim_rp_cmd);
12e41d03
DL
5834 install_element (VIEW_NODE, &show_ip_multicast_cmd);
5835 install_element (VIEW_NODE, &show_ip_mroute_cmd);
5836 install_element (VIEW_NODE, &show_ip_mroute_count_cmd);
5837 install_element (VIEW_NODE, &show_ip_rib_cmd);
5838 install_element (VIEW_NODE, &show_ip_ssmpingd_cmd);
7a1d58ce 5839 install_element (VIEW_NODE, &show_debugging_pim_cmd);
12e41d03
DL
5840
5841 install_element (ENABLE_NODE, &clear_ip_interfaces_cmd);
5842 install_element (ENABLE_NODE, &clear_ip_igmp_interfaces_cmd);
5843 install_element (ENABLE_NODE, &clear_ip_mroute_cmd);
5844 install_element (ENABLE_NODE, &clear_ip_pim_interfaces_cmd);
5845 install_element (ENABLE_NODE, &clear_ip_pim_oil_cmd);
5846
12e41d03
DL
5847 install_element (ENABLE_NODE, &test_igmp_receive_report_cmd);
5848 install_element (ENABLE_NODE, &test_pim_receive_assert_cmd);
5849 install_element (ENABLE_NODE, &test_pim_receive_dump_cmd);
5850 install_element (ENABLE_NODE, &test_pim_receive_hello_cmd);
5851 install_element (ENABLE_NODE, &test_pim_receive_join_cmd);
5852 install_element (ENABLE_NODE, &test_pim_receive_prune_cmd);
5853 install_element (ENABLE_NODE, &test_pim_receive_upcall_cmd);
5854
5855 install_element (ENABLE_NODE, &debug_igmp_cmd);
5856 install_element (ENABLE_NODE, &no_debug_igmp_cmd);
12e41d03
DL
5857 install_element (ENABLE_NODE, &debug_igmp_events_cmd);
5858 install_element (ENABLE_NODE, &no_debug_igmp_events_cmd);
12e41d03
DL
5859 install_element (ENABLE_NODE, &debug_igmp_packets_cmd);
5860 install_element (ENABLE_NODE, &no_debug_igmp_packets_cmd);
12e41d03
DL
5861 install_element (ENABLE_NODE, &debug_igmp_trace_cmd);
5862 install_element (ENABLE_NODE, &no_debug_igmp_trace_cmd);
12e41d03 5863 install_element (ENABLE_NODE, &debug_mroute_cmd);
6c7197b1 5864 install_element (ENABLE_NODE, &debug_mroute_detail_cmd);
12e41d03 5865 install_element (ENABLE_NODE, &no_debug_mroute_cmd);
6c7197b1 5866 install_element (ENABLE_NODE, &no_debug_mroute_detail_cmd);
6250610a
JAG
5867 install_element (ENABLE_NODE, &debug_static_cmd);
5868 install_element (ENABLE_NODE, &no_debug_static_cmd);
12e41d03
DL
5869 install_element (ENABLE_NODE, &debug_pim_cmd);
5870 install_element (ENABLE_NODE, &no_debug_pim_cmd);
12e41d03
DL
5871 install_element (ENABLE_NODE, &debug_pim_events_cmd);
5872 install_element (ENABLE_NODE, &no_debug_pim_events_cmd);
12e41d03
DL
5873 install_element (ENABLE_NODE, &debug_pim_packets_cmd);
5874 install_element (ENABLE_NODE, &debug_pim_packets_filter_cmd);
5875 install_element (ENABLE_NODE, &no_debug_pim_packets_cmd);
5876 install_element (ENABLE_NODE, &no_debug_pim_packets_filter_cmd);
12e41d03
DL
5877 install_element (ENABLE_NODE, &debug_pim_packetdump_send_cmd);
5878 install_element (ENABLE_NODE, &no_debug_pim_packetdump_send_cmd);
12e41d03
DL
5879 install_element (ENABLE_NODE, &debug_pim_packetdump_recv_cmd);
5880 install_element (ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd);
12e41d03
DL
5881 install_element (ENABLE_NODE, &debug_pim_trace_cmd);
5882 install_element (ENABLE_NODE, &no_debug_pim_trace_cmd);
12e41d03
DL
5883 install_element (ENABLE_NODE, &debug_ssmpingd_cmd);
5884 install_element (ENABLE_NODE, &no_debug_ssmpingd_cmd);
12e41d03
DL
5885 install_element (ENABLE_NODE, &debug_pim_zebra_cmd);
5886 install_element (ENABLE_NODE, &no_debug_pim_zebra_cmd);
12e41d03
DL
5887
5888 install_element (CONFIG_NODE, &debug_igmp_cmd);
5889 install_element (CONFIG_NODE, &no_debug_igmp_cmd);
12e41d03
DL
5890 install_element (CONFIG_NODE, &debug_igmp_events_cmd);
5891 install_element (CONFIG_NODE, &no_debug_igmp_events_cmd);
12e41d03
DL
5892 install_element (CONFIG_NODE, &debug_igmp_packets_cmd);
5893 install_element (CONFIG_NODE, &no_debug_igmp_packets_cmd);
12e41d03
DL
5894 install_element (CONFIG_NODE, &debug_igmp_trace_cmd);
5895 install_element (CONFIG_NODE, &no_debug_igmp_trace_cmd);
12e41d03 5896 install_element (CONFIG_NODE, &debug_mroute_cmd);
6c7197b1 5897 install_element (CONFIG_NODE, &debug_mroute_detail_cmd);
12e41d03 5898 install_element (CONFIG_NODE, &no_debug_mroute_cmd);
6c7197b1 5899 install_element (CONFIG_NODE, &no_debug_mroute_detail_cmd);
6250610a
JAG
5900 install_element (CONFIG_NODE, &debug_static_cmd);
5901 install_element (CONFIG_NODE, &no_debug_static_cmd);
12e41d03
DL
5902 install_element (CONFIG_NODE, &debug_pim_cmd);
5903 install_element (CONFIG_NODE, &no_debug_pim_cmd);
12e41d03
DL
5904 install_element (CONFIG_NODE, &debug_pim_events_cmd);
5905 install_element (CONFIG_NODE, &no_debug_pim_events_cmd);
12e41d03
DL
5906 install_element (CONFIG_NODE, &debug_pim_packets_cmd);
5907 install_element (CONFIG_NODE, &debug_pim_packets_filter_cmd);
5908 install_element (CONFIG_NODE, &no_debug_pim_packets_cmd);
5909 install_element (CONFIG_NODE, &no_debug_pim_packets_filter_cmd);
12e41d03
DL
5910 install_element (CONFIG_NODE, &debug_pim_trace_cmd);
5911 install_element (CONFIG_NODE, &no_debug_pim_trace_cmd);
12e41d03
DL
5912 install_element (CONFIG_NODE, &debug_ssmpingd_cmd);
5913 install_element (CONFIG_NODE, &no_debug_ssmpingd_cmd);
12e41d03
DL
5914 install_element (CONFIG_NODE, &debug_pim_zebra_cmd);
5915 install_element (CONFIG_NODE, &no_debug_pim_zebra_cmd);
12e41d03 5916}