2 * Copyright (C) 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "sockunion.h"
34 #include "bgpd/bgp_table.h"
35 #include "bgpd/bgpd.h"
36 #include "bgpd/bgp_route.h"
37 #include "bgpd/bgp_attr.h"
38 #include "bgpd/bgp_dump.h"
49 static const struct bgp_dump_type_map
{
50 enum bgp_dump_type type
;
52 } bgp_dump_type_map
[] =
54 {BGP_DUMP_ALL
, "all"},
55 {BGP_DUMP_ALL_ET
, "all-et"},
56 {BGP_DUMP_UPDATES
, "updates"},
57 {BGP_DUMP_UPDATES_ET
, "updates-et"},
58 {BGP_DUMP_ROUTES
, "routes-mrt"},
64 MSG_START
, /* sender is starting up */
65 MSG_DIE
, /* receiver should shut down */
66 MSG_I_AM_DEAD
, /* sender is shutting down */
67 MSG_PEER_DOWN
, /* sender's peer is down */
68 MSG_PROTOCOL_BGP
, /* msg is a BGP packet */
69 MSG_PROTOCOL_RIP
, /* msg is a RIP packet */
70 MSG_PROTOCOL_IDRP
, /* msg is an IDRP packet */
71 MSG_PROTOCOL_RIPNG
, /* msg is a RIPNG packet */
72 MSG_PROTOCOL_BGP4PLUS
, /* msg is a BGP4+ packet */
73 MSG_PROTOCOL_BGP4PLUS_01
, /* msg is a BGP4+ (draft 01) packet */
74 MSG_PROTOCOL_OSPF
, /* msg is an OSPF packet */
75 MSG_TABLE_DUMP
, /* routing table dump */
76 MSG_TABLE_DUMP_V2
/* routing table dump, version 2 */
81 enum bgp_dump_type type
;
87 unsigned int interval
;
91 struct thread
*t_interval
;
94 static int bgp_dump_unset (struct bgp_dump
*bgp_dump
);
95 static int bgp_dump_interval_func (struct thread
*);
97 /* BGP packet dump output buffer. */
98 struct stream
*bgp_dump_obuf
;
100 /* BGP dump strucuture for 'dump bgp all' */
101 struct bgp_dump bgp_dump_all
;
103 /* BGP dump structure for 'dump bgp updates' */
104 struct bgp_dump bgp_dump_updates
;
106 /* BGP dump structure for 'dump bgp routes' */
107 struct bgp_dump bgp_dump_routes
;
110 bgp_dump_open_file (struct bgp_dump
*bgp_dump
)
115 char fullpath
[MAXPATHLEN
];
116 char realpath
[MAXPATHLEN
];
120 tm
= localtime (&clock
);
122 if (bgp_dump
->filename
[0] != DIRECTORY_SEP
)
124 sprintf (fullpath
, "%s/%s", vty_get_cwd (), bgp_dump
->filename
);
125 ret
= strftime (realpath
, MAXPATHLEN
, fullpath
, tm
);
128 ret
= strftime (realpath
, MAXPATHLEN
, bgp_dump
->filename
, tm
);
132 zlog_warn ("bgp_dump_open_file: strftime error");
137 fclose (bgp_dump
->fp
);
140 oldumask
= umask(0777 & ~LOGFILE_MASK
);
141 bgp_dump
->fp
= fopen (realpath
, "w");
143 if (bgp_dump
->fp
== NULL
)
145 zlog_warn ("bgp_dump_open_file: %s: %s", realpath
, strerror (errno
));
155 bgp_dump_interval_add (struct bgp_dump
*bgp_dump
, int interval
)
163 /* Periodic dump every interval seconds */
164 if ((interval
< 86400) && ((86400 % interval
) == 0))
166 /* Dump at predictable times: if a day has a whole number of
167 * intervals, dump every interval seconds starting from midnight
171 secs_into_day
= tm
->tm_sec
+ 60*tm
->tm_min
+ 60*60*tm
->tm_hour
;
172 interval
= interval
- secs_into_day
% interval
; /* always > 0 */
174 bgp_dump
->t_interval
= NULL
;
175 thread_add_timer(bm
->master
, bgp_dump_interval_func
, bgp_dump
, interval
,
176 &bgp_dump
->t_interval
);
180 /* One-off dump: execute immediately, don't affect any scheduled dumps */
181 bgp_dump
->t_interval
= NULL
;
182 thread_add_event(bm
->master
, bgp_dump_interval_func
, bgp_dump
, 0,
183 &bgp_dump
->t_interval
);
189 /* Dump common header. */
191 bgp_dump_header (struct stream
*obuf
, int type
, int subtype
, int dump_type
)
193 struct timeval clock
;
197 if ((dump_type
== BGP_DUMP_ALL_ET
|| dump_type
== BGP_DUMP_UPDATES_ET
)
198 && type
== MSG_PROTOCOL_BGP4MP
)
199 type
= MSG_PROTOCOL_BGP4MP_ET
;
201 gettimeofday(&clock
, NULL
);
204 msecs
= clock
.tv_usec
;
206 /* Put dump packet header. */
207 stream_putl (obuf
, secs
);
208 stream_putw (obuf
, type
);
209 stream_putw (obuf
, subtype
);
210 stream_putl (obuf
, 0); /* len */
212 /* Adding microseconds for the MRT Extended Header */
213 if (type
== MSG_PROTOCOL_BGP4MP_ET
)
214 stream_putl (obuf
, msecs
);
218 bgp_dump_set_size (struct stream
*s
, int type
)
221 * The BGP_DUMP_HEADER_SIZE stay at 12 event when ET:
222 * "The Microsecond Timestamp is included in the computation
223 * of the Length field value." (RFC6396 2011)
225 stream_putl_at (s
, 8, stream_get_endp (s
) - BGP_DUMP_HEADER_SIZE
);
229 bgp_dump_routes_index_table(struct bgp
*bgp
)
232 struct listnode
*node
;
236 obuf
= bgp_dump_obuf
;
240 bgp_dump_header (obuf
, MSG_TABLE_DUMP_V2
, TABLE_DUMP_V2_PEER_INDEX_TABLE
,
243 /* Collector BGP ID */
244 stream_put_in_addr (obuf
, &bgp
->router_id
);
249 stream_putw (obuf
, strlen(bgp
->name
));
250 stream_put(obuf
, bgp
->name
, strlen(bgp
->name
));
254 stream_putw(obuf
, 0);
257 /* Peer count ( plus one extra internal peer ) */
258 stream_putw (obuf
, listcount(bgp
->peer
) + 1);
260 /* Populate fake peer at index 0, for locally originated routes */
261 /* Peer type (IPv4) */
262 stream_putc (obuf
, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4
+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP
);
263 /* Peer BGP ID (0.0.0.0) */
264 stream_putl (obuf
, 0);
265 /* Peer IP address (0.0.0.0) */
266 stream_putl (obuf
, 0);
268 stream_putl (obuf
, 0);
270 /* Walk down all peers */
271 for(ALL_LIST_ELEMENTS_RO (bgp
->peer
, node
, peer
))
275 if (sockunion_family(&peer
->su
) == AF_INET
)
277 stream_putc (obuf
, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4
+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP
);
279 else if (sockunion_family(&peer
->su
) == AF_INET6
)
281 stream_putc (obuf
, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4
+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6
);
285 stream_put_in_addr (obuf
, &peer
->remote_id
);
287 /* Peer's IP address */
288 if (sockunion_family(&peer
->su
) == AF_INET
)
290 stream_put_in_addr (obuf
, &peer
->su
.sin
.sin_addr
);
292 else if (sockunion_family(&peer
->su
) == AF_INET6
)
294 stream_write (obuf
, (u_char
*)&peer
->su
.sin6
.sin6_addr
,
298 /* Peer's AS number. */
299 /* Note that, as this is an AS4 compliant quagga, the RIB is always AS4 */
300 stream_putl (obuf
, peer
->as
);
302 /* Store the peer number for this peer */
303 peer
->table_dump_index
= peerno
;
307 bgp_dump_set_size(obuf
, MSG_TABLE_DUMP_V2
);
309 fwrite (STREAM_DATA (obuf
), stream_get_endp (obuf
), 1, bgp_dump_routes
.fp
);
310 fflush (bgp_dump_routes
.fp
);
314 static struct bgp_info
*
315 bgp_dump_route_node_record (int afi
, struct bgp_node
*rn
,
316 struct bgp_info
*info
, unsigned int seq
)
322 obuf
= bgp_dump_obuf
;
327 bgp_dump_header (obuf
, MSG_TABLE_DUMP_V2
, TABLE_DUMP_V2_RIB_IPV4_UNICAST
,
329 else if (afi
== AFI_IP6
)
330 bgp_dump_header (obuf
, MSG_TABLE_DUMP_V2
, TABLE_DUMP_V2_RIB_IPV6_UNICAST
,
333 /* Sequence number */
334 stream_putl (obuf
, seq
);
337 stream_putc (obuf
, rn
->p
.prefixlen
);
342 /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
343 stream_write (obuf
, (u_char
*)&rn
->p
.u
.prefix4
, (rn
->p
.prefixlen
+7)/8);
345 else if (afi
== AFI_IP6
)
347 /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
348 stream_write (obuf
, (u_char
*)&rn
->p
.u
.prefix6
, (rn
->p
.prefixlen
+7)/8);
351 /* Save where we are now, so we can overwride the entry count later */
352 sizep
= stream_get_endp (obuf
);
355 uint16_t entry_count
= 0;
357 /* Entry count, note that this is overwritten later */
358 stream_putw (obuf
, 0);
360 endp
= stream_get_endp (obuf
);
361 for (; info
; info
= info
->next
)
366 stream_putw (obuf
, info
->peer
->table_dump_index
);
369 stream_putl (obuf
, time(NULL
) - (bgp_clock() - info
->uptime
));
371 /* Dump attribute. */
372 /* Skip prefix & AFI/SAFI for MP_NLRI */
373 bgp_dump_routes_attr (obuf
, info
->attr
, &rn
->p
);
375 cur_endp
= stream_get_endp (obuf
);
376 if (cur_endp
> BGP_MAX_PACKET_SIZE
+ BGP_DUMP_MSG_HEADER
377 + BGP_DUMP_HEADER_SIZE
)
379 stream_set_endp (obuf
, endp
);
387 /* Overwrite the entry count, now that we know the right number */
388 stream_putw_at (obuf
, sizep
, entry_count
);
390 bgp_dump_set_size (obuf
, MSG_TABLE_DUMP_V2
);
391 fwrite (STREAM_DATA (obuf
), stream_get_endp (obuf
), 1, bgp_dump_routes
.fp
);
397 /* Runs under child process. */
399 bgp_dump_routes_func (int afi
, int first_run
, unsigned int seq
)
401 struct bgp_info
*info
;
404 struct bgp_table
*table
;
406 bgp
= bgp_get_default ();
410 if (bgp_dump_routes
.fp
== NULL
)
413 /* Note that bgp_dump_routes_index_table will do ipv4 and ipv6 peers,
414 so this should only be done on the first call to bgp_dump_routes_func.
415 ( this function will be called once for ipv4 and once for ipv6 ) */
417 bgp_dump_routes_index_table(bgp
);
419 /* Walk down each BGP route. */
420 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
422 for (rn
= bgp_table_top (table
); rn
; rn
= bgp_route_next (rn
))
427 info
= bgp_dump_route_node_record (afi
, rn
, info
, seq
);
432 fflush (bgp_dump_routes
.fp
);
438 bgp_dump_interval_func (struct thread
*t
)
440 struct bgp_dump
*bgp_dump
;
441 bgp_dump
= THREAD_ARG (t
);
442 bgp_dump
->t_interval
= NULL
;
444 /* Reschedule dump even if file couldn't be opened this time... */
445 if (bgp_dump_open_file (bgp_dump
) != NULL
)
447 /* In case of bgp_dump_routes, we need special route dump function. */
448 if (bgp_dump
->type
== BGP_DUMP_ROUTES
)
450 unsigned int seq
= bgp_dump_routes_func (AFI_IP
, 1, 0);
451 bgp_dump_routes_func (AFI_IP6
, 0, seq
);
452 /* Close the file now. For a RIB dump there's no point in leaving
453 * it open until the next scheduled dump starts. */
454 fclose(bgp_dump
->fp
); bgp_dump
->fp
= NULL
;
458 /* if interval is set reschedule */
459 if (bgp_dump
->interval
> 0)
460 bgp_dump_interval_add (bgp_dump
, bgp_dump
->interval
);
465 /* Dump common information. */
467 bgp_dump_common (struct stream
*obuf
, struct peer
*peer
, int forceas4
)
469 char empty
[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
471 /* Source AS number and Destination AS number. */
472 if (forceas4
|| CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
474 stream_putl (obuf
, peer
->as
);
475 stream_putl (obuf
, peer
->local_as
);
479 stream_putw (obuf
, peer
->as
);
480 stream_putw (obuf
, peer
->local_as
);
483 if (peer
->su
.sa
.sa_family
== AF_INET
)
485 stream_putw (obuf
, peer
->ifindex
);
486 stream_putw (obuf
, AFI_IP
);
488 stream_put (obuf
, &peer
->su
.sin
.sin_addr
, IPV4_MAX_BYTELEN
);
491 stream_put (obuf
, &peer
->su_local
->sin
.sin_addr
, IPV4_MAX_BYTELEN
);
493 stream_put (obuf
, empty
, IPV4_MAX_BYTELEN
);
495 else if (peer
->su
.sa
.sa_family
== AF_INET6
)
497 /* Interface Index and Address family. */
498 stream_putw (obuf
, peer
->ifindex
);
499 stream_putw (obuf
, AFI_IP6
);
501 /* Source IP Address and Destination IP Address. */
502 stream_put (obuf
, &peer
->su
.sin6
.sin6_addr
, IPV6_MAX_BYTELEN
);
505 stream_put (obuf
, &peer
->su_local
->sin6
.sin6_addr
, IPV6_MAX_BYTELEN
);
507 stream_put (obuf
, empty
, IPV6_MAX_BYTELEN
);
511 /* Dump BGP status change. */
513 bgp_dump_state (struct peer
*peer
, int status_old
, int status_new
)
517 /* If dump file pointer is disabled return immediately. */
518 if (bgp_dump_all
.fp
== NULL
)
521 /* Make dump stream. */
522 obuf
= bgp_dump_obuf
;
525 bgp_dump_header (obuf
, MSG_PROTOCOL_BGP4MP
, BGP4MP_STATE_CHANGE_AS4
,
527 bgp_dump_common (obuf
, peer
, 1);/* force this in as4speak*/
529 stream_putw (obuf
, status_old
);
530 stream_putw (obuf
, status_new
);
533 bgp_dump_set_size (obuf
, MSG_PROTOCOL_BGP4MP
);
535 /* Write to the stream. */
536 fwrite (STREAM_DATA (obuf
), stream_get_endp (obuf
), 1, bgp_dump_all
.fp
);
537 fflush (bgp_dump_all
.fp
);
541 bgp_dump_packet_func (struct bgp_dump
*bgp_dump
, struct peer
*peer
,
542 struct stream
*packet
)
546 /* If dump file pointer is disabled return immediately. */
547 if (bgp_dump
->fp
== NULL
)
550 /* Make dump stream. */
551 obuf
= bgp_dump_obuf
;
554 /* Dump header and common part. */
555 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
557 bgp_dump_header (obuf
, MSG_PROTOCOL_BGP4MP
, BGP4MP_MESSAGE_AS4
,
562 bgp_dump_header (obuf
, MSG_PROTOCOL_BGP4MP
, BGP4MP_MESSAGE
,
565 bgp_dump_common (obuf
, peer
, 0);
567 /* Packet contents. */
568 stream_put (obuf
, STREAM_DATA (packet
), stream_get_endp (packet
));
571 bgp_dump_set_size (obuf
, MSG_PROTOCOL_BGP4MP
);
573 /* Write to the stream. */
574 fwrite (STREAM_DATA (obuf
), stream_get_endp (obuf
), 1, bgp_dump
->fp
);
575 fflush (bgp_dump
->fp
);
578 /* Called from bgp_packet.c when BGP packet is received. */
580 bgp_dump_packet (struct peer
*peer
, int type
, struct stream
*packet
)
583 bgp_dump_packet_func (&bgp_dump_all
, peer
, packet
);
585 /* bgp_dump_updates. */
586 if (type
== BGP_MSG_UPDATE
)
587 bgp_dump_packet_func (&bgp_dump_updates
, peer
, packet
);
591 bgp_dump_parse_time (const char *str
)
606 for (i
= 0; i
< len
; i
++)
608 if (isdigit ((int) str
[i
]))
611 time
+= str
[i
] - '0';
613 else if (str
[i
] == 'H' || str
[i
] == 'h')
619 total
+= time
* 60 *60;
623 else if (str
[i
] == 'M' || str
[i
] == 'm')
638 bgp_dump_set (struct vty
*vty
, struct bgp_dump
*bgp_dump
,
639 enum bgp_dump_type type
, const char *path
,
640 const char *interval_str
)
642 unsigned int interval
;
644 /* Don't schedule duplicate dumps if the dump command is given twice */
645 if (bgp_dump
->filename
&& strcmp(path
, bgp_dump
->filename
) == 0
646 && type
== bgp_dump
->type
)
650 if (bgp_dump
->interval_str
&&
651 strcmp(bgp_dump
->interval_str
, interval_str
) == 0)
656 if (!bgp_dump
->interval_str
)
661 /* Removing previous config */
662 bgp_dump_unset(bgp_dump
);
666 /* Check interval string. */
667 interval
= bgp_dump_parse_time (interval_str
);
670 vty_out (vty
, "Malformed interval string%s", VTY_NEWLINE
);
674 /* Setting interval string */
675 bgp_dump
->interval_str
= XSTRDUP(MTYPE_BGP_DUMP_STR
, interval_str
);
683 bgp_dump
->type
= type
;
686 bgp_dump
->interval
= interval
;
689 bgp_dump
->filename
= XSTRDUP (MTYPE_BGP_DUMP_STR
, path
);
691 /* Create interval thread. */
692 bgp_dump_interval_add (bgp_dump
, interval
);
694 /* This should be called when interval is expired. */
695 bgp_dump_open_file (bgp_dump
);
701 bgp_dump_unset (struct bgp_dump
*bgp_dump
)
703 /* Removing file name. */
704 if (bgp_dump
->filename
)
706 XFREE(MTYPE_BGP_DUMP_STR
, bgp_dump
->filename
);
707 bgp_dump
->filename
= NULL
;
713 fclose (bgp_dump
->fp
);
717 /* Removing interval thread. */
718 if (bgp_dump
->t_interval
)
720 thread_cancel (bgp_dump
->t_interval
);
721 bgp_dump
->t_interval
= NULL
;
724 bgp_dump
->interval
= 0;
726 /* Removing interval string. */
727 if (bgp_dump
->interval_str
)
729 XFREE(MTYPE_BGP_DUMP_STR
, bgp_dump
->interval_str
);
730 bgp_dump
->interval_str
= NULL
;
738 "dump bgp <all|all-et|updates|updates-et|routes-mrt> PATH [INTERVAL]",
741 "Dump all BGP packets\nDump all BGP packets (Extended Timestamp Header)\n"
742 "Dump BGP updates only\nDump BGP updates only (Extended Timestamp Header)\n"
743 "Dump whole BGP routing table\n"
745 "Interval of output\n")
747 int idx_dump_routes
= 2;
749 int idx_interval
= 4;
750 int bgp_dump_type
= 0;
751 const char *interval
= NULL
;
752 struct bgp_dump
*bgp_dump_struct
= NULL
;
753 const struct bgp_dump_type_map
*map
= NULL
;
755 for (map
= bgp_dump_type_map
; map
->str
; map
++)
756 if (strcmp(argv
[idx_dump_routes
]->arg
, map
->str
) == 0)
757 bgp_dump_type
= map
->type
;
759 switch (bgp_dump_type
)
762 case BGP_DUMP_ALL_ET
:
763 bgp_dump_struct
= &bgp_dump_all
;
765 case BGP_DUMP_UPDATES
:
766 case BGP_DUMP_UPDATES_ET
:
767 bgp_dump_struct
= &bgp_dump_updates
;
769 case BGP_DUMP_ROUTES
:
771 bgp_dump_struct
= &bgp_dump_routes
;
775 /* When an interval is given */
776 if (argc
== idx_interval
+ 1)
777 interval
= argv
[idx_interval
]->arg
;
779 return bgp_dump_set (vty
, bgp_dump_struct
, bgp_dump_type
,
780 argv
[idx_path
]->arg
, interval
);
783 DEFUN (no_dump_bgp_all
,
785 "no dump bgp <all|all-et|updates|updates-et|routes-mrt> [PATH [INTERVAL]]",
788 "Stop BGP packet dump\n"
789 "Stop dump process all\n"
790 "Stop dump process all-et\n"
791 "Stop dump process updates\n"
792 "Stop dump process updates-et\n"
793 "Stop dump process route-mrt\n"
795 "Interval of output\n")
797 int idx_dump_routes
= 3;
798 int bgp_dump_type
= 0;
799 const struct bgp_dump_type_map
*map
= NULL
;
800 struct bgp_dump
*bgp_dump_struct
= NULL
;
802 for (map
= bgp_dump_type_map
; map
->str
; map
++)
803 if (strcmp(argv
[idx_dump_routes
]->arg
, map
->str
) == 0)
804 bgp_dump_type
= map
->type
;
806 switch (bgp_dump_type
)
809 case BGP_DUMP_ALL_ET
:
810 bgp_dump_struct
= &bgp_dump_all
;
812 case BGP_DUMP_UPDATES
:
813 case BGP_DUMP_UPDATES_ET
:
814 bgp_dump_struct
= &bgp_dump_updates
;
816 case BGP_DUMP_ROUTES
:
818 bgp_dump_struct
= &bgp_dump_routes
;
822 return bgp_dump_unset (bgp_dump_struct
);
825 /* BGP node structure. */
826 static struct cmd_node bgp_dump_node
=
835 config_time2str (unsigned int interval
)
837 static char buf
[BUFSIZ
];
843 sprintf (buf
, "%dh", interval
/ 3600);
848 sprintf (buf
+ strlen (buf
), "%dm", interval
/60);
853 sprintf (buf
+ strlen (buf
), "%d", interval
);
860 config_write_bgp_dump (struct vty
*vty
)
862 if (bgp_dump_all
.filename
)
864 const char *type_str
= "all";
865 if (bgp_dump_all
.type
== BGP_DUMP_ALL_ET
)
868 if (bgp_dump_all
.interval_str
)
869 vty_out (vty
, "dump bgp %s %s %s%s", type_str
,
870 bgp_dump_all
.filename
, bgp_dump_all
.interval_str
,
873 vty_out (vty
, "dump bgp %s %s%s", type_str
,
874 bgp_dump_all
.filename
, VTY_NEWLINE
);
876 if (bgp_dump_updates
.filename
)
878 const char *type_str
= "updates";
879 if (bgp_dump_updates
.type
== BGP_DUMP_UPDATES_ET
)
880 type_str
= "updates-et";
882 if (bgp_dump_updates
.interval_str
)
883 vty_out (vty
, "dump bgp %s %s %s%s", type_str
,
884 bgp_dump_updates
.filename
, bgp_dump_updates
.interval_str
,
887 vty_out (vty
, "dump bgp %s %s%s", type_str
,
888 bgp_dump_updates
.filename
, VTY_NEWLINE
);
890 if (bgp_dump_routes
.filename
)
892 if (bgp_dump_routes
.interval_str
)
893 vty_out (vty
, "dump bgp routes-mrt %s %s%s",
894 bgp_dump_routes
.filename
, bgp_dump_routes
.interval_str
,
897 vty_out (vty
, "dump bgp routes-mrt %s%s",
898 bgp_dump_routes
.filename
, VTY_NEWLINE
);
904 /* Initialize BGP packet dump functionality. */
908 memset (&bgp_dump_all
, 0, sizeof (struct bgp_dump
));
909 memset (&bgp_dump_updates
, 0, sizeof (struct bgp_dump
));
910 memset (&bgp_dump_routes
, 0, sizeof (struct bgp_dump
));
912 bgp_dump_obuf
= stream_new ((BGP_MAX_PACKET_SIZE
<< 1)
913 + BGP_DUMP_MSG_HEADER
+ BGP_DUMP_HEADER_SIZE
);
915 install_node (&bgp_dump_node
, config_write_bgp_dump
);
917 install_element (CONFIG_NODE
, &dump_bgp_all_cmd
);
918 install_element (CONFIG_NODE
, &no_dump_bgp_all_cmd
);
922 bgp_dump_finish (void)
924 bgp_dump_unset (&bgp_dump_all
);
925 bgp_dump_unset (&bgp_dump_updates
);
926 bgp_dump_unset (&bgp_dump_routes
);
928 stream_free (bgp_dump_obuf
);
929 bgp_dump_obuf
= NULL
;