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"
44 int pim_debug_config_write(struct vty
*vty
)
48 if (PIM_DEBUG_MSDP_EVENTS
) {
49 vty_out(vty
, "debug msdp events\n");
52 if (PIM_DEBUG_MSDP_PACKETS
) {
53 vty_out(vty
, "debug msdp packets\n");
56 if (PIM_DEBUG_MSDP_INTERNAL
) {
57 vty_out(vty
, "debug msdp internal\n");
60 if (PIM_DEBUG_IGMP_EVENTS
) {
61 vty_out(vty
, "debug igmp events\n");
64 if (PIM_DEBUG_IGMP_PACKETS
) {
65 vty_out(vty
, "debug igmp packets\n");
68 if (PIM_DEBUG_IGMP_TRACE
) {
69 vty_out(vty
, "debug igmp trace\n");
73 if (PIM_DEBUG_MROUTE
) {
74 vty_out(vty
, "debug mroute\n");
78 if (PIM_DEBUG_MTRACE
) {
79 vty_out(vty
, "debug mtrace\n");
83 if (PIM_DEBUG_MROUTE_DETAIL_ONLY
) {
84 vty_out(vty
, "debug mroute detail\n");
88 if (PIM_DEBUG_PIM_EVENTS
) {
89 vty_out(vty
, "debug pim events\n");
92 if (PIM_DEBUG_PIM_PACKETS
) {
93 vty_out(vty
, "debug pim packets\n");
96 if (PIM_DEBUG_PIM_PACKETDUMP_SEND
) {
97 vty_out(vty
, "debug pim packet-dump send\n");
100 if (PIM_DEBUG_PIM_PACKETDUMP_RECV
) {
101 vty_out(vty
, "debug pim packet-dump receive\n");
105 if (PIM_DEBUG_PIM_TRACE
) {
106 vty_out(vty
, "debug pim trace\n");
109 if (PIM_DEBUG_PIM_TRACE_DETAIL_ONLY
) {
110 vty_out(vty
, "debug pim trace detail\n");
114 if (PIM_DEBUG_ZEBRA
) {
115 vty_out(vty
, "debug pim zebra\n");
119 if (PIM_DEBUG_MLAG
) {
120 vty_out(vty
, "debug pim mlag\n");
125 vty_out(vty
, "debug pim bsm\n");
129 if (PIM_DEBUG_VXLAN
) {
130 vty_out(vty
, "debug pim vxlan\n");
134 if (PIM_DEBUG_SSMPINGD
) {
135 vty_out(vty
, "debug ssmpingd\n");
139 if (PIM_DEBUG_PIM_HELLO
) {
140 vty_out(vty
, "debug pim packets hello\n");
144 if (PIM_DEBUG_PIM_J_P
) {
145 vty_out(vty
, "debug pim packets joins\n");
149 if (PIM_DEBUG_PIM_REG
) {
150 vty_out(vty
, "debug pim packets register\n");
154 if (PIM_DEBUG_STATIC
) {
155 vty_out(vty
, "debug pim static\n");
159 if (PIM_DEBUG_PIM_NHT
) {
160 vty_out(vty
, "debug pim nht\n");
164 if (PIM_DEBUG_PIM_NHT_RP
) {
165 vty_out(vty
, "debug pim nht rp\n");
172 int pim_global_config_write_worker(struct pim_instance
*pim
, struct vty
*vty
)
175 struct pim_ssm
*ssm
= pim
->ssm_info
;
178 if (pim
->vrf
->vrf_id
== VRF_DEFAULT
)
179 snprintf(spaces
, sizeof(spaces
), "%s", "");
181 snprintf(spaces
, sizeof(spaces
), "%s", " ");
183 writes
+= pim_msdp_peer_config_write(vty
, pim
, spaces
);
184 writes
+= pim_msdp_config_write(pim
, vty
, spaces
);
186 if (!pim
->send_v6_secondary
) {
187 vty_out(vty
, "%sno ip pim send-v6-secondary\n", spaces
);
191 writes
+= pim_rp_config_write(pim
, vty
, spaces
);
193 if (pim
->vrf
->vrf_id
== VRF_DEFAULT
) {
194 if (router
->register_suppress_time
195 != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT
) {
196 vty_out(vty
, "%s" PIM_AF_NAME
" pim register-suppress-time %d\n",
197 spaces
, router
->register_suppress_time
);
200 if (router
->t_periodic
!= PIM_DEFAULT_T_PERIODIC
) {
201 vty_out(vty
, "%s" PIM_AF_NAME
" pim join-prune-interval %d\n",
202 spaces
, router
->t_periodic
);
206 if (router
->packet_process
!= PIM_DEFAULT_PACKET_PROCESS
) {
207 vty_out(vty
, "%s" PIM_AF_NAME
" pim packets %d\n", spaces
,
208 router
->packet_process
);
212 if (pim
->keep_alive_time
!= PIM_KEEPALIVE_PERIOD
) {
213 vty_out(vty
, "%s" PIM_AF_NAME
" pim keep-alive-timer %d\n",
214 spaces
, pim
->keep_alive_time
);
217 if (pim
->rp_keep_alive_time
!= (unsigned int)PIM_RP_KEEPALIVE_PERIOD
) {
218 vty_out(vty
, "%s" PIM_AF_NAME
" pim rp keep-alive-timer %d\n",
219 spaces
, pim
->rp_keep_alive_time
);
222 if (ssm
->plist_name
) {
223 vty_out(vty
, "%sip pim ssm prefix-list %s\n", spaces
,
227 if (pim
->register_plist
) {
228 vty_out(vty
, "%sip pim register-accept-list %s\n", spaces
,
229 pim
->register_plist
);
232 if (pim
->spt
.switchover
== PIM_SPT_INFINITY
) {
235 "%s" PIM_AF_NAME
" pim spt-switchover infinity-and-beyond prefix-list %s\n",
236 spaces
, pim
->spt
.plist
);
239 "%s" PIM_AF_NAME
" pim spt-switchover infinity-and-beyond\n",
243 if (pim
->ecmp_rebalance_enable
) {
244 vty_out(vty
, "%sip pim ecmp rebalance\n", spaces
);
246 } else if (pim
->ecmp_enable
) {
247 vty_out(vty
, "%sip pim ecmp\n", spaces
);
251 if (pim
->igmp_watermark_limit
!= 0) {
252 vty_out(vty
, "%sip igmp watermark-warn %u\n", spaces
,
253 pim
->igmp_watermark_limit
);
257 if (pim
->ssmpingd_list
) {
258 struct listnode
*node
;
259 struct ssmpingd_sock
*ss
;
261 for (ALL_LIST_ELEMENTS_RO(pim
->ssmpingd_list
, node
, ss
)) {
262 char source_str
[INET_ADDRSTRLEN
];
263 pim_inet4_dump("<src?>", ss
->source_addr
, source_str
,
265 vty_out(vty
, "%sip ssmpingd %s\n", spaces
, source_str
);
270 if (pim
->msdp
.hold_time
!= PIM_MSDP_PEER_HOLD_TIME
271 || pim
->msdp
.keep_alive
!= PIM_MSDP_PEER_KA_TIME
272 || pim
->msdp
.connection_retry
!= PIM_MSDP_PEER_CONNECT_RETRY_TIME
) {
273 vty_out(vty
, "%sip msdp timers %u %u", spaces
,
274 pim
->msdp
.hold_time
, pim
->msdp
.keep_alive
);
275 if (pim
->msdp
.connection_retry
276 != PIM_MSDP_PEER_CONNECT_RETRY_TIME
)
277 vty_out(vty
, " %u", pim
->msdp
.connection_retry
);
285 static int pim_igmp_config_write(struct vty
*vty
, int writes
,
286 struct pim_interface
*pim_ifp
)
289 if (PIM_IF_TEST_IGMP(pim_ifp
->options
)) {
290 vty_out(vty
, " ip igmp\n");
294 /* ip igmp version */
295 if (pim_ifp
->igmp_version
!= IGMP_DEFAULT_VERSION
) {
296 vty_out(vty
, " ip igmp version %d\n", pim_ifp
->igmp_version
);
300 /* IF ip igmp query-max-response-time */
301 if (pim_ifp
->gm_query_max_response_time_dsec
!=
302 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC
) {
303 vty_out(vty
, " ip igmp query-max-response-time %d\n",
304 pim_ifp
->gm_query_max_response_time_dsec
);
308 /* IF ip igmp query-interval */
309 if (pim_ifp
->gm_default_query_interval
!= IGMP_GENERAL_QUERY_INTERVAL
) {
310 vty_out(vty
, " ip igmp query-interval %d\n",
311 pim_ifp
->gm_default_query_interval
);
315 /* IF ip igmp last-member_query-count */
316 if (pim_ifp
->gm_last_member_query_count
!=
317 IGMP_DEFAULT_ROBUSTNESS_VARIABLE
) {
318 vty_out(vty
, " ip igmp last-member-query-count %d\n",
319 pim_ifp
->gm_last_member_query_count
);
323 /* IF ip igmp last-member_query-interval */
324 if (pim_ifp
->gm_specific_query_max_response_time_dsec
!=
325 IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC
) {
326 vty_out(vty
, " ip igmp last-member-query-interval %d\n",
327 pim_ifp
->gm_specific_query_max_response_time_dsec
);
331 /* IF ip igmp join */
332 if (pim_ifp
->gm_join_list
) {
333 struct listnode
*node
;
335 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->gm_join_list
, node
, ij
)) {
336 char group_str
[INET_ADDRSTRLEN
];
337 char source_str
[INET_ADDRSTRLEN
];
338 pim_inet4_dump("<grp?>", ij
->group_addr
, group_str
,
340 if (ij
->source_addr
.s_addr
== INADDR_ANY
) {
341 vty_out(vty
, " ip igmp join %s\n", group_str
);
343 inet_ntop(AF_INET
, &ij
->source_addr
, source_str
,
345 vty_out(vty
, " ip igmp join %s %s\n", group_str
,
356 int pim_config_write(struct vty
*vty
, int writes
, struct interface
*ifp
,
357 struct pim_instance
*pim
)
359 struct pim_interface
*pim_ifp
= ifp
->info
;
361 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
362 vty_out(vty
, " " PIM_AF_NAME
" pim\n");
366 /* IF ip pim drpriority */
367 if (pim_ifp
->pim_dr_priority
!= PIM_DEFAULT_DR_PRIORITY
) {
368 vty_out(vty
, " " PIM_AF_NAME
" pim drpriority %u\n",
369 pim_ifp
->pim_dr_priority
);
373 /* IF ip pim hello */
374 if (pim_ifp
->pim_hello_period
!= PIM_DEFAULT_HELLO_PERIOD
) {
375 vty_out(vty
, " " PIM_AF_NAME
" pim hello %d", pim_ifp
->pim_hello_period
);
376 if (pim_ifp
->pim_default_holdtime
!= -1)
377 vty_out(vty
, " %d", pim_ifp
->pim_default_holdtime
);
383 writes
+= pim_igmp_config_write(vty
, writes
, pim_ifp
);
387 if (!pim_addr_is_any(pim_ifp
->update_source
)) {
388 vty_out(vty
, " " PIM_AF_NAME
" pim use-source %pPA\n",
389 &pim_ifp
->update_source
);
393 if (pim_ifp
->activeactive
)
394 vty_out(vty
, " " PIM_AF_NAME
" pim active-active\n");
397 if (pim_ifp
->boundary_oil_plist
) {
398 vty_out(vty
, " " PIM_AF_NAME
" multicast boundary oil %s\n",
399 pim_ifp
->boundary_oil_plist
);
403 writes
+= pim_static_write_mroute(pim
, vty
, ifp
);
404 pim_bsm_write_config(vty
, ifp
);
406 pim_bfd_write_config(vty
, ifp
);
412 int pim_interface_config_write(struct vty
*vty
)
414 struct pim_instance
*pim
;
415 struct interface
*ifp
;
419 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
424 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
425 /* pim is enabled internally/implicitly on the vxlan
426 * termination device ipmr-lo. skip displaying that
427 * config to avoid confusion
429 if (pim_vxlan_is_term_dev_cfg(pim
, ifp
))
433 if_vty_config_start(vty
, ifp
);
438 vty_out(vty
, " description %s\n", ifp
->desc
);
443 pim_config_write(vty
, writes
, ifp
, pim
);
445 if_vty_config_end(vty
);