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