Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | /* |
3 | | * PIM for Quagga |
4 | | * Copyright (C) 2008 Everton da Silva Marques |
5 | | */ |
6 | | |
7 | | #include <zebra.h> |
8 | | |
9 | | #include "if.h" |
10 | | #include "linklist.h" |
11 | | #include "prefix.h" |
12 | | #include "vty.h" |
13 | | #include "vrf.h" |
14 | | #include "plist.h" |
15 | | |
16 | | #include "pimd.h" |
17 | | #include "pim_vty.h" |
18 | | #include "pim_iface.h" |
19 | | #include "pim_str.h" |
20 | | #include "pim_ssmpingd.h" |
21 | | #include "pim_pim.h" |
22 | | #include "pim_oil.h" |
23 | | #include "pim_static.h" |
24 | | #include "pim_rp.h" |
25 | | #include "pim_msdp.h" |
26 | | #include "pim_ssm.h" |
27 | | #include "pim_bfd.h" |
28 | | #include "pim_bsm.h" |
29 | | #include "pim_vxlan.h" |
30 | | #include "pim6_mld.h" |
31 | | |
32 | | int pim_debug_config_write(struct vty *vty) |
33 | 0 | { |
34 | 0 | int writes = 0; |
35 | |
|
36 | 0 | if (PIM_DEBUG_MSDP_EVENTS) { |
37 | 0 | vty_out(vty, "debug msdp events\n"); |
38 | 0 | ++writes; |
39 | 0 | } |
40 | 0 | if (PIM_DEBUG_MSDP_PACKETS) { |
41 | 0 | vty_out(vty, "debug msdp packets\n"); |
42 | 0 | ++writes; |
43 | 0 | } |
44 | 0 | if (PIM_DEBUG_MSDP_INTERNAL) { |
45 | 0 | vty_out(vty, "debug msdp internal\n"); |
46 | 0 | ++writes; |
47 | 0 | } |
48 | 0 | if (PIM_DEBUG_GM_EVENTS) { |
49 | 0 | vty_out(vty, "debug " GM_AF_DBG " events\n"); |
50 | 0 | ++writes; |
51 | 0 | } |
52 | 0 | if (PIM_DEBUG_GM_PACKETS) { |
53 | 0 | vty_out(vty, "debug " GM_AF_DBG " packets\n"); |
54 | 0 | ++writes; |
55 | 0 | } |
56 | | /* PIM_DEBUG_GM_TRACE catches _DETAIL too */ |
57 | 0 | if (router->debugs & PIM_MASK_GM_TRACE) { |
58 | 0 | vty_out(vty, "debug " GM_AF_DBG " trace\n"); |
59 | 0 | ++writes; |
60 | 0 | } |
61 | 0 | if (PIM_DEBUG_GM_TRACE_DETAIL) { |
62 | 0 | vty_out(vty, "debug " GM_AF_DBG " trace detail\n"); |
63 | 0 | ++writes; |
64 | 0 | } |
65 | | |
66 | | /* PIM_DEBUG_MROUTE catches _DETAIL too */ |
67 | 0 | if (router->debugs & PIM_MASK_MROUTE) { |
68 | 0 | vty_out(vty, "debug " PIM_MROUTE_DBG "\n"); |
69 | 0 | ++writes; |
70 | 0 | } |
71 | 0 | if (PIM_DEBUG_MROUTE_DETAIL) { |
72 | 0 | vty_out(vty, "debug " PIM_MROUTE_DBG " detail\n"); |
73 | 0 | ++writes; |
74 | 0 | } |
75 | |
|
76 | 0 | if (PIM_DEBUG_MTRACE) { |
77 | 0 | vty_out(vty, "debug mtrace\n"); |
78 | 0 | ++writes; |
79 | 0 | } |
80 | |
|
81 | 0 | if (PIM_DEBUG_PIM_EVENTS) { |
82 | 0 | vty_out(vty, "debug " PIM_AF_DBG " events\n"); |
83 | 0 | ++writes; |
84 | 0 | } |
85 | 0 | if (PIM_DEBUG_PIM_PACKETS) { |
86 | 0 | vty_out(vty, "debug " PIM_AF_DBG " packets\n"); |
87 | 0 | ++writes; |
88 | 0 | } |
89 | 0 | if (PIM_DEBUG_PIM_PACKETDUMP_SEND) { |
90 | 0 | vty_out(vty, "debug " PIM_AF_DBG " packet-dump send\n"); |
91 | 0 | ++writes; |
92 | 0 | } |
93 | 0 | if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { |
94 | 0 | vty_out(vty, "debug " PIM_AF_DBG " packet-dump receive\n"); |
95 | 0 | ++writes; |
96 | 0 | } |
97 | | |
98 | | /* PIM_DEBUG_PIM_TRACE catches _DETAIL too */ |
99 | 0 | if (router->debugs & PIM_MASK_PIM_TRACE) { |
100 | 0 | vty_out(vty, "debug " PIM_AF_DBG " trace\n"); |
101 | 0 | ++writes; |
102 | 0 | } |
103 | 0 | if (PIM_DEBUG_PIM_TRACE_DETAIL) { |
104 | 0 | vty_out(vty, "debug " PIM_AF_DBG " trace detail\n"); |
105 | 0 | ++writes; |
106 | 0 | } |
107 | |
|
108 | 0 | if (PIM_DEBUG_ZEBRA) { |
109 | 0 | vty_out(vty, "debug " PIM_AF_DBG " zebra\n"); |
110 | 0 | ++writes; |
111 | 0 | } |
112 | |
|
113 | 0 | if (PIM_DEBUG_MLAG) { |
114 | 0 | vty_out(vty, "debug pim mlag\n"); |
115 | 0 | ++writes; |
116 | 0 | } |
117 | |
|
118 | 0 | if (PIM_DEBUG_BSM) { |
119 | 0 | vty_out(vty, "debug " PIM_AF_DBG " bsm\n"); |
120 | 0 | ++writes; |
121 | 0 | } |
122 | |
|
123 | 0 | if (PIM_DEBUG_VXLAN) { |
124 | 0 | vty_out(vty, "debug " PIM_AF_DBG " vxlan\n"); |
125 | 0 | ++writes; |
126 | 0 | } |
127 | |
|
128 | 0 | if (PIM_DEBUG_SSMPINGD) { |
129 | 0 | vty_out(vty, "debug ssmpingd\n"); |
130 | 0 | ++writes; |
131 | 0 | } |
132 | |
|
133 | 0 | if (PIM_DEBUG_PIM_HELLO) { |
134 | 0 | vty_out(vty, "debug " PIM_AF_DBG " packets hello\n"); |
135 | 0 | ++writes; |
136 | 0 | } |
137 | |
|
138 | 0 | if (PIM_DEBUG_PIM_J_P) { |
139 | 0 | vty_out(vty, "debug " PIM_AF_DBG " packets joins\n"); |
140 | 0 | ++writes; |
141 | 0 | } |
142 | |
|
143 | 0 | if (PIM_DEBUG_PIM_REG) { |
144 | 0 | vty_out(vty, "debug " PIM_AF_DBG " packets register\n"); |
145 | 0 | ++writes; |
146 | 0 | } |
147 | |
|
148 | 0 | if (PIM_DEBUG_STATIC) { |
149 | 0 | vty_out(vty, "debug pim static\n"); |
150 | 0 | ++writes; |
151 | 0 | } |
152 | |
|
153 | 0 | if (PIM_DEBUG_PIM_NHT) { |
154 | 0 | vty_out(vty, "debug " PIM_AF_DBG " nht\n"); |
155 | 0 | ++writes; |
156 | 0 | } |
157 | |
|
158 | 0 | if (PIM_DEBUG_PIM_NHT_RP) { |
159 | 0 | vty_out(vty, "debug pim nht rp\n"); |
160 | 0 | ++writes; |
161 | 0 | } |
162 | |
|
163 | 0 | if (PIM_DEBUG_PIM_NHT_DETAIL) { |
164 | 0 | vty_out(vty, "debug " PIM_AF_DBG " nht detail\n"); |
165 | 0 | ++writes; |
166 | 0 | } |
167 | |
|
168 | 0 | return writes; |
169 | 0 | } |
170 | | |
171 | | int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty) |
172 | 0 | { |
173 | 0 | int writes = 0; |
174 | 0 | struct pim_ssm *ssm = pim->ssm_info; |
175 | 0 | char spaces[10]; |
176 | |
|
177 | 0 | if (pim->vrf->vrf_id == VRF_DEFAULT) |
178 | 0 | snprintf(spaces, sizeof(spaces), "%s", ""); |
179 | 0 | else |
180 | 0 | snprintf(spaces, sizeof(spaces), "%s", " "); |
181 | |
|
182 | 0 | writes += pim_msdp_peer_config_write(vty, pim, spaces); |
183 | 0 | writes += pim_msdp_config_write(pim, vty, spaces); |
184 | |
|
185 | 0 | if (!pim->send_v6_secondary) { |
186 | 0 | vty_out(vty, "%sno ip pim send-v6-secondary\n", spaces); |
187 | 0 | ++writes; |
188 | 0 | } |
189 | |
|
190 | 0 | writes += pim_rp_config_write(pim, vty, spaces); |
191 | |
|
192 | 0 | if (pim->vrf->vrf_id == VRF_DEFAULT) { |
193 | 0 | if (router->register_suppress_time |
194 | 0 | != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) { |
195 | 0 | vty_out(vty, "%s" PIM_AF_NAME " pim register-suppress-time %d\n", |
196 | 0 | spaces, router->register_suppress_time); |
197 | 0 | ++writes; |
198 | 0 | } |
199 | 0 | if (router->t_periodic != PIM_DEFAULT_T_PERIODIC) { |
200 | 0 | vty_out(vty, "%s" PIM_AF_NAME " pim join-prune-interval %d\n", |
201 | 0 | spaces, router->t_periodic); |
202 | 0 | ++writes; |
203 | 0 | } |
204 | |
|
205 | 0 | if (router->packet_process != PIM_DEFAULT_PACKET_PROCESS) { |
206 | 0 | vty_out(vty, "%s" PIM_AF_NAME " pim packets %d\n", spaces, |
207 | 0 | router->packet_process); |
208 | 0 | ++writes; |
209 | 0 | } |
210 | 0 | } |
211 | 0 | if (pim->keep_alive_time != PIM_KEEPALIVE_PERIOD) { |
212 | 0 | vty_out(vty, "%s" PIM_AF_NAME " pim keep-alive-timer %d\n", |
213 | 0 | spaces, pim->keep_alive_time); |
214 | 0 | ++writes; |
215 | 0 | } |
216 | 0 | if (pim->rp_keep_alive_time != (unsigned int)PIM_RP_KEEPALIVE_PERIOD) { |
217 | 0 | vty_out(vty, "%s" PIM_AF_NAME " pim rp keep-alive-timer %d\n", |
218 | 0 | spaces, pim->rp_keep_alive_time); |
219 | 0 | ++writes; |
220 | 0 | } |
221 | 0 | if (ssm->plist_name) { |
222 | 0 | vty_out(vty, "%sip pim ssm prefix-list %s\n", spaces, |
223 | 0 | ssm->plist_name); |
224 | 0 | ++writes; |
225 | 0 | } |
226 | 0 | if (pim->register_plist) { |
227 | 0 | vty_out(vty, "%sip pim register-accept-list %s\n", spaces, |
228 | 0 | pim->register_plist); |
229 | 0 | ++writes; |
230 | 0 | } |
231 | 0 | if (pim->spt.switchover == PIM_SPT_INFINITY) { |
232 | 0 | if (pim->spt.plist) |
233 | 0 | vty_out(vty, |
234 | 0 | "%s" PIM_AF_NAME " pim spt-switchover infinity-and-beyond prefix-list %s\n", |
235 | 0 | spaces, pim->spt.plist); |
236 | 0 | else |
237 | 0 | vty_out(vty, |
238 | 0 | "%s" PIM_AF_NAME " pim spt-switchover infinity-and-beyond\n", |
239 | 0 | spaces); |
240 | 0 | ++writes; |
241 | 0 | } |
242 | 0 | if (pim->ecmp_rebalance_enable) { |
243 | 0 | vty_out(vty, "%sip pim ecmp rebalance\n", spaces); |
244 | 0 | ++writes; |
245 | 0 | } else if (pim->ecmp_enable) { |
246 | 0 | vty_out(vty, "%sip pim ecmp\n", spaces); |
247 | 0 | ++writes; |
248 | 0 | } |
249 | |
|
250 | 0 | if (pim->gm_watermark_limit != 0) { |
251 | 0 | #if PIM_IPV == 4 |
252 | 0 | vty_out(vty, "%s" PIM_AF_NAME " igmp watermark-warn %u\n", |
253 | 0 | spaces, pim->gm_watermark_limit); |
254 | | #else |
255 | | vty_out(vty, "%s" PIM_AF_NAME " mld watermark-warn %u\n", |
256 | | spaces, pim->gm_watermark_limit); |
257 | | #endif |
258 | 0 | ++writes; |
259 | 0 | } |
260 | |
|
261 | 0 | if (pim->ssmpingd_list) { |
262 | 0 | struct listnode *node; |
263 | 0 | struct ssmpingd_sock *ss; |
264 | 0 | ++writes; |
265 | 0 | for (ALL_LIST_ELEMENTS_RO(pim->ssmpingd_list, node, ss)) { |
266 | 0 | vty_out(vty, "%s" PIM_AF_NAME " ssmpingd %pPA\n", |
267 | 0 | spaces, &ss->source_addr); |
268 | 0 | ++writes; |
269 | 0 | } |
270 | 0 | } |
271 | |
|
272 | 0 | if (pim->msdp.hold_time != PIM_MSDP_PEER_HOLD_TIME |
273 | 0 | || pim->msdp.keep_alive != PIM_MSDP_PEER_KA_TIME |
274 | 0 | || pim->msdp.connection_retry != PIM_MSDP_PEER_CONNECT_RETRY_TIME) { |
275 | 0 | vty_out(vty, "%sip msdp timers %u %u", spaces, |
276 | 0 | pim->msdp.hold_time, pim->msdp.keep_alive); |
277 | 0 | if (pim->msdp.connection_retry |
278 | 0 | != PIM_MSDP_PEER_CONNECT_RETRY_TIME) |
279 | 0 | vty_out(vty, " %u", pim->msdp.connection_retry); |
280 | 0 | vty_out(vty, "\n"); |
281 | 0 | } |
282 | |
|
283 | 0 | return writes; |
284 | 0 | } |
285 | | |
286 | | #if PIM_IPV == 4 |
287 | | static int gm_config_write(struct vty *vty, int writes, |
288 | | struct pim_interface *pim_ifp) |
289 | 0 | { |
290 | | /* IF ip igmp */ |
291 | 0 | if (pim_ifp->gm_enable) { |
292 | 0 | vty_out(vty, " ip igmp\n"); |
293 | 0 | ++writes; |
294 | 0 | } |
295 | | |
296 | | /* ip igmp version */ |
297 | 0 | if (pim_ifp->igmp_version != IGMP_DEFAULT_VERSION) { |
298 | 0 | vty_out(vty, " ip igmp version %d\n", pim_ifp->igmp_version); |
299 | 0 | ++writes; |
300 | 0 | } |
301 | | |
302 | | /* IF ip igmp query-max-response-time */ |
303 | 0 | if (pim_ifp->gm_query_max_response_time_dsec != |
304 | 0 | GM_QUERY_MAX_RESPONSE_TIME_DSEC) { |
305 | 0 | vty_out(vty, " ip igmp query-max-response-time %d\n", |
306 | 0 | pim_ifp->gm_query_max_response_time_dsec); |
307 | 0 | ++writes; |
308 | 0 | } |
309 | | |
310 | | /* IF ip igmp query-interval */ |
311 | 0 | if (pim_ifp->gm_default_query_interval != GM_GENERAL_QUERY_INTERVAL) { |
312 | 0 | vty_out(vty, " ip igmp query-interval %d\n", |
313 | 0 | pim_ifp->gm_default_query_interval); |
314 | 0 | ++writes; |
315 | 0 | } |
316 | | |
317 | | /* IF ip igmp last-member_query-count */ |
318 | 0 | if (pim_ifp->gm_last_member_query_count != |
319 | 0 | GM_DEFAULT_ROBUSTNESS_VARIABLE) { |
320 | 0 | vty_out(vty, " ip igmp last-member-query-count %d\n", |
321 | 0 | pim_ifp->gm_last_member_query_count); |
322 | 0 | ++writes; |
323 | 0 | } |
324 | | |
325 | | /* IF ip igmp last-member_query-interval */ |
326 | 0 | if (pim_ifp->gm_specific_query_max_response_time_dsec != |
327 | 0 | GM_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC) { |
328 | 0 | vty_out(vty, " ip igmp last-member-query-interval %d\n", |
329 | 0 | pim_ifp->gm_specific_query_max_response_time_dsec); |
330 | 0 | ++writes; |
331 | 0 | } |
332 | | |
333 | | /* IF ip igmp join */ |
334 | 0 | if (pim_ifp->gm_join_list) { |
335 | 0 | struct listnode *node; |
336 | 0 | struct gm_join *ij; |
337 | 0 | for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_join_list, node, ij)) { |
338 | 0 | if (pim_addr_is_any(ij->source_addr)) |
339 | 0 | vty_out(vty, " ip igmp join %pPAs\n", |
340 | 0 | &ij->group_addr); |
341 | 0 | else |
342 | 0 | vty_out(vty, " ip igmp join %pPAs %pPAs\n", |
343 | 0 | &ij->group_addr, &ij->source_addr); |
344 | 0 | ++writes; |
345 | 0 | } |
346 | 0 | } |
347 | |
|
348 | 0 | return writes; |
349 | 0 | } |
350 | | #else |
351 | | static int gm_config_write(struct vty *vty, int writes, |
352 | | struct pim_interface *pim_ifp) |
353 | | { |
354 | | /* IF ipv6 mld */ |
355 | | if (pim_ifp->gm_enable) { |
356 | | vty_out(vty, " ipv6 mld\n"); |
357 | | ++writes; |
358 | | } |
359 | | |
360 | | if (pim_ifp->mld_version != MLD_DEFAULT_VERSION) |
361 | | vty_out(vty, " ipv6 mld version %d\n", pim_ifp->mld_version); |
362 | | |
363 | | /* IF ipv6 mld query-max-response-time */ |
364 | | if (pim_ifp->gm_query_max_response_time_dsec != |
365 | | GM_QUERY_MAX_RESPONSE_TIME_DSEC) |
366 | | vty_out(vty, " ipv6 mld query-max-response-time %d\n", |
367 | | pim_ifp->gm_query_max_response_time_dsec); |
368 | | |
369 | | if (pim_ifp->gm_default_query_interval != GM_GENERAL_QUERY_INTERVAL) |
370 | | vty_out(vty, " ipv6 mld query-interval %d\n", |
371 | | pim_ifp->gm_default_query_interval); |
372 | | |
373 | | /* IF ipv6 mld last-member_query-count */ |
374 | | if (pim_ifp->gm_last_member_query_count != |
375 | | GM_DEFAULT_ROBUSTNESS_VARIABLE) |
376 | | vty_out(vty, " ipv6 mld last-member-query-count %d\n", |
377 | | pim_ifp->gm_last_member_query_count); |
378 | | |
379 | | /* IF ipv6 mld last-member_query-interval */ |
380 | | if (pim_ifp->gm_specific_query_max_response_time_dsec != |
381 | | GM_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC) |
382 | | vty_out(vty, " ipv6 mld last-member-query-interval %d\n", |
383 | | pim_ifp->gm_specific_query_max_response_time_dsec); |
384 | | |
385 | | /* IF ipv6 mld join */ |
386 | | if (pim_ifp->gm_join_list) { |
387 | | struct listnode *node; |
388 | | struct gm_join *ij; |
389 | | for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_join_list, node, ij)) { |
390 | | if (pim_addr_is_any(ij->source_addr)) |
391 | | vty_out(vty, " ipv6 mld join %pPAs\n", |
392 | | &ij->group_addr); |
393 | | else |
394 | | vty_out(vty, " ipv6 mld join %pPAs %pPAs\n", |
395 | | &ij->group_addr, &ij->source_addr); |
396 | | ++writes; |
397 | | } |
398 | | } |
399 | | |
400 | | return writes; |
401 | | } |
402 | | #endif |
403 | | |
404 | | int pim_config_write(struct vty *vty, int writes, struct interface *ifp, |
405 | | struct pim_instance *pim) |
406 | 0 | { |
407 | 0 | struct pim_interface *pim_ifp = ifp->info; |
408 | |
|
409 | 0 | if (pim_ifp->pim_enable) { |
410 | 0 | vty_out(vty, " " PIM_AF_NAME " pim\n"); |
411 | 0 | ++writes; |
412 | 0 | } |
413 | | |
414 | | /* IF ip pim drpriority */ |
415 | 0 | if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) { |
416 | 0 | vty_out(vty, " " PIM_AF_NAME " pim drpriority %u\n", |
417 | 0 | pim_ifp->pim_dr_priority); |
418 | 0 | ++writes; |
419 | 0 | } |
420 | | |
421 | | /* IF ip pim hello */ |
422 | 0 | if (pim_ifp->pim_hello_period != PIM_DEFAULT_HELLO_PERIOD) { |
423 | 0 | vty_out(vty, " " PIM_AF_NAME " pim hello %d", pim_ifp->pim_hello_period); |
424 | 0 | if (pim_ifp->pim_default_holdtime != -1) |
425 | 0 | vty_out(vty, " %d", pim_ifp->pim_default_holdtime); |
426 | 0 | vty_out(vty, "\n"); |
427 | 0 | ++writes; |
428 | 0 | } |
429 | |
|
430 | 0 | writes += gm_config_write(vty, writes, pim_ifp); |
431 | | |
432 | | /* update source */ |
433 | 0 | if (!pim_addr_is_any(pim_ifp->update_source)) { |
434 | 0 | vty_out(vty, " " PIM_AF_NAME " pim use-source %pPA\n", |
435 | 0 | &pim_ifp->update_source); |
436 | 0 | ++writes; |
437 | 0 | } |
438 | |
|
439 | 0 | if (pim_ifp->activeactive) |
440 | 0 | vty_out(vty, " " PIM_AF_NAME " pim active-active\n"); |
441 | | |
442 | | /* boundary */ |
443 | 0 | if (pim_ifp->boundary_oil_plist) { |
444 | 0 | vty_out(vty, " " PIM_AF_NAME " multicast boundary oil %s\n", |
445 | 0 | pim_ifp->boundary_oil_plist); |
446 | 0 | ++writes; |
447 | 0 | } |
448 | |
|
449 | 0 | if (pim_ifp->pim_passive_enable) { |
450 | 0 | vty_out(vty, " " PIM_AF_NAME " pim passive\n"); |
451 | 0 | ++writes; |
452 | 0 | } |
453 | |
|
454 | 0 | writes += pim_static_write_mroute(pim, vty, ifp); |
455 | 0 | pim_bsm_write_config(vty, ifp); |
456 | 0 | ++writes; |
457 | 0 | pim_bfd_write_config(vty, ifp); |
458 | 0 | ++writes; |
459 | |
|
460 | 0 | return writes; |
461 | 0 | } |
462 | | |
463 | | int pim_interface_config_write(struct vty *vty) |
464 | 0 | { |
465 | 0 | struct pim_instance *pim; |
466 | 0 | struct interface *ifp; |
467 | 0 | struct vrf *vrf; |
468 | 0 | int writes = 0; |
469 | |
|
470 | 0 | RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { |
471 | 0 | pim = vrf->info; |
472 | 0 | if (!pim) |
473 | 0 | continue; |
474 | | |
475 | 0 | FOR_ALL_INTERFACES (pim->vrf, ifp) { |
476 | | /* pim is enabled internally/implicitly on the vxlan |
477 | | * termination device ipmr-lo. skip displaying that |
478 | | * config to avoid confusion |
479 | | */ |
480 | 0 | if (pim_vxlan_is_term_dev_cfg(pim, ifp)) |
481 | 0 | continue; |
482 | | |
483 | | /* IF name */ |
484 | 0 | if_vty_config_start(vty, ifp); |
485 | |
|
486 | 0 | ++writes; |
487 | |
|
488 | 0 | if (ifp->desc) { |
489 | 0 | vty_out(vty, " description %s\n", ifp->desc); |
490 | 0 | ++writes; |
491 | 0 | } |
492 | |
|
493 | 0 | if (ifp->info) { |
494 | 0 | pim_config_write(vty, writes, ifp, pim); |
495 | 0 | } |
496 | 0 | if_vty_config_end(vty); |
497 | |
|
498 | 0 | ++writes; |
499 | 0 | } |
500 | 0 | } |
501 | |
|
502 | 0 | return writes; |
503 | 0 | } |