3 * Copyright (C) 2008 Everton da Silva Marques
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.
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.
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
31 #include "pim_iface.h"
33 #include "pim_ssmpingd.h"
36 #include "pim_static.h"
42 #include "pim_vxlan.h"
45 int pim_debug_config_write(struct vty
*vty
)
49 if (PIM_DEBUG_MSDP_EVENTS
) {
50 vty_out(vty
, "debug msdp events\n");
53 if (PIM_DEBUG_MSDP_PACKETS
) {
54 vty_out(vty
, "debug msdp packets\n");
57 if (PIM_DEBUG_MSDP_INTERNAL
) {
58 vty_out(vty
, "debug msdp internal\n");
61 if (PIM_DEBUG_GM_EVENTS
) {
62 vty_out(vty
, "debug igmp events\n");
65 if (PIM_DEBUG_GM_PACKETS
) {
66 vty_out(vty
, "debug igmp packets\n");
69 /* PIM_DEBUG_IGMP_TRACE catches _DETAIL too */
70 if (router
->debugs
& PIM_MASK_IGMP_TRACE
) {
71 vty_out(vty
, "debug igmp trace\n");
74 if (PIM_DEBUG_IGMP_TRACE_DETAIL
) {
75 vty_out(vty
, "debug igmp trace detail\n");
79 /* PIM_DEBUG_MROUTE catches _DETAIL too */
80 if (router
->debugs
& PIM_MASK_MROUTE
) {
81 vty_out(vty
, "debug " PIM_MROUTE_DBG
"\n");
84 if (PIM_DEBUG_MROUTE_DETAIL
) {
85 vty_out(vty
, "debug " PIM_MROUTE_DBG
" detail\n");
89 if (PIM_DEBUG_MTRACE
) {
90 vty_out(vty
, "debug mtrace\n");
94 if (PIM_DEBUG_PIM_EVENTS
) {
95 vty_out(vty
, "debug " PIM_AF_DBG
" events\n");
98 if (PIM_DEBUG_PIM_PACKETS
) {
99 vty_out(vty
, "debug " PIM_AF_DBG
" packets\n");
102 if (PIM_DEBUG_PIM_PACKETDUMP_SEND
) {
103 vty_out(vty
, "debug " PIM_AF_DBG
" packet-dump send\n");
106 if (PIM_DEBUG_PIM_PACKETDUMP_RECV
) {
107 vty_out(vty
, "debug " PIM_AF_DBG
" packet-dump receive\n");
111 /* PIM_DEBUG_PIM_TRACE catches _DETAIL too */
112 if (router
->debugs
& PIM_MASK_PIM_TRACE
) {
113 vty_out(vty
, "debug " PIM_AF_DBG
" trace\n");
116 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
117 vty_out(vty
, "debug " PIM_AF_DBG
" trace detail\n");
121 if (PIM_DEBUG_ZEBRA
) {
122 vty_out(vty
, "debug " PIM_AF_DBG
" zebra\n");
126 if (PIM_DEBUG_MLAG
) {
127 vty_out(vty
, "debug pim mlag\n");
132 vty_out(vty
, "debug " PIM_AF_DBG
" bsm\n");
136 if (PIM_DEBUG_VXLAN
) {
137 vty_out(vty
, "debug " PIM_AF_DBG
" vxlan\n");
141 if (PIM_DEBUG_SSMPINGD
) {
142 vty_out(vty
, "debug ssmpingd\n");
146 if (PIM_DEBUG_PIM_HELLO
) {
147 vty_out(vty
, "debug " PIM_AF_DBG
" packets hello\n");
151 if (PIM_DEBUG_PIM_J_P
) {
152 vty_out(vty
, "debug " PIM_AF_DBG
" packets joins\n");
156 if (PIM_DEBUG_PIM_REG
) {
157 vty_out(vty
, "debug " PIM_AF_DBG
" packets register\n");
161 if (PIM_DEBUG_STATIC
) {
162 vty_out(vty
, "debug pim static\n");
166 if (PIM_DEBUG_PIM_NHT
) {
167 vty_out(vty
, "debug " PIM_AF_DBG
" nht\n");
171 if (PIM_DEBUG_PIM_NHT_RP
) {
172 vty_out(vty
, "debug pim nht rp\n");
176 if (PIM_DEBUG_PIM_NHT_DETAIL
) {
177 vty_out(vty
, "debug " PIM_AF_DBG
" nht detail\n");
184 int pim_global_config_write_worker(struct pim_instance
*pim
, struct vty
*vty
)
187 struct pim_ssm
*ssm
= pim
->ssm_info
;
190 if (pim
->vrf
->vrf_id
== VRF_DEFAULT
)
191 snprintf(spaces
, sizeof(spaces
), "%s", "");
193 snprintf(spaces
, sizeof(spaces
), "%s", " ");
195 writes
+= pim_msdp_peer_config_write(vty
, pim
, spaces
);
196 writes
+= pim_msdp_config_write(pim
, vty
, spaces
);
198 if (!pim
->send_v6_secondary
) {
199 vty_out(vty
, "%sno ip pim send-v6-secondary\n", spaces
);
203 writes
+= pim_rp_config_write(pim
, vty
, spaces
);
205 if (pim
->vrf
->vrf_id
== VRF_DEFAULT
) {
206 if (router
->register_suppress_time
207 != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT
) {
208 vty_out(vty
, "%s" PIM_AF_NAME
" pim register-suppress-time %d\n",
209 spaces
, router
->register_suppress_time
);
212 if (router
->t_periodic
!= PIM_DEFAULT_T_PERIODIC
) {
213 vty_out(vty
, "%s" PIM_AF_NAME
" pim join-prune-interval %d\n",
214 spaces
, router
->t_periodic
);
218 if (router
->packet_process
!= PIM_DEFAULT_PACKET_PROCESS
) {
219 vty_out(vty
, "%s" PIM_AF_NAME
" pim packets %d\n", spaces
,
220 router
->packet_process
);
224 if (pim
->keep_alive_time
!= PIM_KEEPALIVE_PERIOD
) {
225 vty_out(vty
, "%s" PIM_AF_NAME
" pim keep-alive-timer %d\n",
226 spaces
, pim
->keep_alive_time
);
229 if (pim
->rp_keep_alive_time
!= (unsigned int)PIM_RP_KEEPALIVE_PERIOD
) {
230 vty_out(vty
, "%s" PIM_AF_NAME
" pim rp keep-alive-timer %d\n",
231 spaces
, pim
->rp_keep_alive_time
);
234 if (ssm
->plist_name
) {
235 vty_out(vty
, "%sip pim ssm prefix-list %s\n", spaces
,
239 if (pim
->register_plist
) {
240 vty_out(vty
, "%sip pim register-accept-list %s\n", spaces
,
241 pim
->register_plist
);
244 if (pim
->spt
.switchover
== PIM_SPT_INFINITY
) {
247 "%s" PIM_AF_NAME
" pim spt-switchover infinity-and-beyond prefix-list %s\n",
248 spaces
, pim
->spt
.plist
);
251 "%s" PIM_AF_NAME
" pim spt-switchover infinity-and-beyond\n",
255 if (pim
->ecmp_rebalance_enable
) {
256 vty_out(vty
, "%sip pim ecmp rebalance\n", spaces
);
258 } else if (pim
->ecmp_enable
) {
259 vty_out(vty
, "%sip pim ecmp\n", spaces
);
263 if (pim
->gm_watermark_limit
!= 0) {
265 vty_out(vty
, "%s" PIM_AF_NAME
" igmp watermark-warn %u\n",
266 spaces
, pim
->gm_watermark_limit
);
268 vty_out(vty
, "%s" PIM_AF_NAME
" mld watermark-warn %u\n",
269 spaces
, pim
->gm_watermark_limit
);
274 if (pim
->ssmpingd_list
) {
275 struct listnode
*node
;
276 struct ssmpingd_sock
*ss
;
278 for (ALL_LIST_ELEMENTS_RO(pim
->ssmpingd_list
, node
, ss
)) {
279 vty_out(vty
, "%s" PIM_AF_NAME
" ssmpingd %pPA\n",
280 spaces
, &ss
->source_addr
);
285 if (pim
->msdp
.hold_time
!= PIM_MSDP_PEER_HOLD_TIME
286 || pim
->msdp
.keep_alive
!= PIM_MSDP_PEER_KA_TIME
287 || pim
->msdp
.connection_retry
!= PIM_MSDP_PEER_CONNECT_RETRY_TIME
) {
288 vty_out(vty
, "%sip msdp timers %u %u", spaces
,
289 pim
->msdp
.hold_time
, pim
->msdp
.keep_alive
);
290 if (pim
->msdp
.connection_retry
291 != PIM_MSDP_PEER_CONNECT_RETRY_TIME
)
292 vty_out(vty
, " %u", pim
->msdp
.connection_retry
);
300 static int gm_config_write(struct vty
*vty
, int writes
,
301 struct pim_interface
*pim_ifp
)
304 if (pim_ifp
->gm_enable
) {
305 vty_out(vty
, " ip igmp\n");
309 /* ip igmp version */
310 if (pim_ifp
->igmp_version
!= IGMP_DEFAULT_VERSION
) {
311 vty_out(vty
, " ip igmp version %d\n", pim_ifp
->igmp_version
);
315 /* IF ip igmp query-max-response-time */
316 if (pim_ifp
->gm_query_max_response_time_dsec
!=
317 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC
) {
318 vty_out(vty
, " ip igmp query-max-response-time %d\n",
319 pim_ifp
->gm_query_max_response_time_dsec
);
323 /* IF ip igmp query-interval */
324 if (pim_ifp
->gm_default_query_interval
!= IGMP_GENERAL_QUERY_INTERVAL
) {
325 vty_out(vty
, " ip igmp query-interval %d\n",
326 pim_ifp
->gm_default_query_interval
);
330 /* IF ip igmp last-member_query-count */
331 if (pim_ifp
->gm_last_member_query_count
!=
332 IGMP_DEFAULT_ROBUSTNESS_VARIABLE
) {
333 vty_out(vty
, " ip igmp last-member-query-count %d\n",
334 pim_ifp
->gm_last_member_query_count
);
338 /* IF ip igmp last-member_query-interval */
339 if (pim_ifp
->gm_specific_query_max_response_time_dsec
!=
340 IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC
) {
341 vty_out(vty
, " ip igmp last-member-query-interval %d\n",
342 pim_ifp
->gm_specific_query_max_response_time_dsec
);
346 /* IF ip igmp join */
347 if (pim_ifp
->gm_join_list
) {
348 struct listnode
*node
;
350 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->gm_join_list
, node
, ij
)) {
351 char group_str
[INET_ADDRSTRLEN
];
352 char source_str
[INET_ADDRSTRLEN
];
353 pim_inet4_dump("<grp?>", ij
->group_addr
, group_str
,
355 if (ij
->source_addr
.s_addr
== INADDR_ANY
) {
356 vty_out(vty
, " ip igmp join %s\n", group_str
);
358 inet_ntop(AF_INET
, &ij
->source_addr
, source_str
,
360 vty_out(vty
, " ip igmp join %s %s\n", group_str
,
370 static int gm_config_write(struct vty
*vty
, int writes
,
371 struct pim_interface
*pim_ifp
)
374 if (pim_ifp
->gm_enable
) {
375 vty_out(vty
, " ipv6 mld\n");
379 if (pim_ifp
->mld_version
!= MLD_DEFAULT_VERSION
)
380 vty_out(vty
, " ipv6 mld version %d\n", pim_ifp
->mld_version
);
382 /* IF ipv6 mld query-max-response-time */
383 if (pim_ifp
->gm_query_max_response_time_dsec
!=
384 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC
)
385 vty_out(vty
, " ipv6 mld query-max-response-time %d\n",
386 pim_ifp
->gm_query_max_response_time_dsec
);
388 if (pim_ifp
->gm_default_query_interval
!= IGMP_GENERAL_QUERY_INTERVAL
)
389 vty_out(vty
, " ipv6 mld query-interval %d\n",
390 pim_ifp
->gm_default_query_interval
);
392 /* IF ipv6 mld last-member_query-count */
393 if (pim_ifp
->gm_last_member_query_count
!=
394 IGMP_DEFAULT_ROBUSTNESS_VARIABLE
)
395 vty_out(vty
, " ipv6 mld last-member-query-count %d\n",
396 pim_ifp
->gm_last_member_query_count
);
398 /* IF ipv6 mld last-member_query-interval */
399 if (pim_ifp
->gm_specific_query_max_response_time_dsec
!=
400 IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC
)
401 vty_out(vty
, " ipv6 mld last-member-query-interval %d\n",
402 pim_ifp
->gm_specific_query_max_response_time_dsec
);
408 int pim_config_write(struct vty
*vty
, int writes
, struct interface
*ifp
,
409 struct pim_instance
*pim
)
411 struct pim_interface
*pim_ifp
= ifp
->info
;
413 if (pim_ifp
->pim_enable
) {
414 vty_out(vty
, " " PIM_AF_NAME
" pim\n");
418 /* IF ip pim drpriority */
419 if (pim_ifp
->pim_dr_priority
!= PIM_DEFAULT_DR_PRIORITY
) {
420 vty_out(vty
, " " PIM_AF_NAME
" pim drpriority %u\n",
421 pim_ifp
->pim_dr_priority
);
425 /* IF ip pim hello */
426 if (pim_ifp
->pim_hello_period
!= PIM_DEFAULT_HELLO_PERIOD
) {
427 vty_out(vty
, " " PIM_AF_NAME
" pim hello %d", pim_ifp
->pim_hello_period
);
428 if (pim_ifp
->pim_default_holdtime
!= -1)
429 vty_out(vty
, " %d", pim_ifp
->pim_default_holdtime
);
434 writes
+= gm_config_write(vty
, writes
, pim_ifp
);
437 if (!pim_addr_is_any(pim_ifp
->update_source
)) {
438 vty_out(vty
, " " PIM_AF_NAME
" pim use-source %pPA\n",
439 &pim_ifp
->update_source
);
443 if (pim_ifp
->activeactive
)
444 vty_out(vty
, " " PIM_AF_NAME
" pim active-active\n");
447 if (pim_ifp
->boundary_oil_plist
) {
448 vty_out(vty
, " " PIM_AF_NAME
" multicast boundary oil %s\n",
449 pim_ifp
->boundary_oil_plist
);
453 if (pim_ifp
->pim_passive_enable
) {
454 vty_out(vty
, " " PIM_AF_NAME
" pim passive\n");
458 writes
+= pim_static_write_mroute(pim
, vty
, ifp
);
459 pim_bsm_write_config(vty
, ifp
);
461 pim_bfd_write_config(vty
, ifp
);
467 int pim_interface_config_write(struct vty
*vty
)
469 struct pim_instance
*pim
;
470 struct interface
*ifp
;
474 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
479 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
480 /* pim is enabled internally/implicitly on the vxlan
481 * termination device ipmr-lo. skip displaying that
482 * config to avoid confusion
484 if (pim_vxlan_is_term_dev_cfg(pim
, ifp
))
488 if_vty_config_start(vty
, ifp
);
493 vty_out(vty
, " description %s\n", ifp
->desc
);
498 pim_config_write(vty
, writes
, ifp
, pim
);
500 if_vty_config_end(vty
);