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
17 along with GNU Zebra; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
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 vty
*vty
, 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
= thread_add_timer (bm
->master
, bgp_dump_interval_func
,
179 /* One-off dump: execute immediately, don't affect any scheduled dumps */
180 bgp_dump
->t_interval
= thread_add_event (bm
->master
, bgp_dump_interval_func
,
187 /* Dump common header. */
189 bgp_dump_header (struct stream
*obuf
, int type
, int subtype
, int dump_type
)
191 struct timeval clock
;
195 if ((dump_type
== BGP_DUMP_ALL_ET
|| dump_type
== BGP_DUMP_UPDATES_ET
)
196 && type
== MSG_PROTOCOL_BGP4MP
)
197 type
= MSG_PROTOCOL_BGP4MP_ET
;
199 gettimeofday(&clock
, NULL
);
202 msecs
= clock
.tv_usec
;
204 /* Put dump packet header. */
205 stream_putl (obuf
, secs
);
206 stream_putw (obuf
, type
);
207 stream_putw (obuf
, subtype
);
208 stream_putl (obuf
, 0); /* len */
210 /* Adding microseconds for the MRT Extended Header */
211 if (type
== MSG_PROTOCOL_BGP4MP_ET
)
212 stream_putl (obuf
, msecs
);
216 bgp_dump_set_size (struct stream
*s
, int type
)
219 * The BGP_DUMP_HEADER_SIZE stay at 12 event when ET:
220 * "The Microsecond Timestamp is included in the computation
221 * of the Length field value." (RFC6396 2011)
223 stream_putl_at (s
, 8, stream_get_endp (s
) - BGP_DUMP_HEADER_SIZE
);
227 bgp_dump_routes_index_table(struct bgp
*bgp
)
230 struct listnode
*node
;
234 obuf
= bgp_dump_obuf
;
238 bgp_dump_header (obuf
, MSG_TABLE_DUMP_V2
, TABLE_DUMP_V2_PEER_INDEX_TABLE
,
241 /* Collector BGP ID */
242 stream_put_in_addr (obuf
, &bgp
->router_id
);
247 stream_putw (obuf
, strlen(bgp
->name
));
248 stream_put(obuf
, bgp
->name
, strlen(bgp
->name
));
252 stream_putw(obuf
, 0);
255 /* Peer count ( plus one extra internal peer ) */
256 stream_putw (obuf
, listcount(bgp
->peer
) + 1);
258 /* Populate fake peer at index 0, for locally originated routes */
259 /* Peer type (IPv4) */
260 stream_putc (obuf
, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4
+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP
);
261 /* Peer BGP ID (0.0.0.0) */
262 stream_putl (obuf
, 0);
263 /* Peer IP address (0.0.0.0) */
264 stream_putl (obuf
, 0);
266 stream_putl (obuf
, 0);
268 /* Walk down all peers */
269 for(ALL_LIST_ELEMENTS_RO (bgp
->peer
, node
, peer
))
273 if (sockunion_family(&peer
->su
) == AF_INET
)
275 stream_putc (obuf
, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4
+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP
);
277 else if (sockunion_family(&peer
->su
) == AF_INET6
)
279 stream_putc (obuf
, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4
+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6
);
283 stream_put_in_addr (obuf
, &peer
->remote_id
);
285 /* Peer's IP address */
286 if (sockunion_family(&peer
->su
) == AF_INET
)
288 stream_put_in_addr (obuf
, &peer
->su
.sin
.sin_addr
);
290 else if (sockunion_family(&peer
->su
) == AF_INET6
)
292 stream_write (obuf
, (u_char
*)&peer
->su
.sin6
.sin6_addr
,
296 /* Peer's AS number. */
297 /* Note that, as this is an AS4 compliant quagga, the RIB is always AS4 */
298 stream_putl (obuf
, peer
->as
);
300 /* Store the peer number for this peer */
301 peer
->table_dump_index
= peerno
;
305 bgp_dump_set_size(obuf
, MSG_TABLE_DUMP_V2
);
307 fwrite (STREAM_DATA (obuf
), stream_get_endp (obuf
), 1, bgp_dump_routes
.fp
);
308 fflush (bgp_dump_routes
.fp
);
312 static struct bgp_info
*
313 bgp_dump_route_node_record (int afi
, struct bgp_node
*rn
,
314 struct bgp_info
*info
, unsigned int seq
)
320 obuf
= bgp_dump_obuf
;
325 bgp_dump_header (obuf
, MSG_TABLE_DUMP_V2
, TABLE_DUMP_V2_RIB_IPV4_UNICAST
,
327 else if (afi
== AFI_IP6
)
328 bgp_dump_header (obuf
, MSG_TABLE_DUMP_V2
, TABLE_DUMP_V2_RIB_IPV6_UNICAST
,
331 /* Sequence number */
332 stream_putl (obuf
, seq
);
335 stream_putc (obuf
, rn
->p
.prefixlen
);
340 /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
341 stream_write (obuf
, (u_char
*)&rn
->p
.u
.prefix4
, (rn
->p
.prefixlen
+7)/8);
343 else if (afi
== AFI_IP6
)
345 /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
346 stream_write (obuf
, (u_char
*)&rn
->p
.u
.prefix6
, (rn
->p
.prefixlen
+7)/8);
349 /* Save where we are now, so we can overwride the entry count later */
350 sizep
= stream_get_endp (obuf
);
353 uint16_t entry_count
= 0;
355 /* Entry count, note that this is overwritten later */
356 stream_putw (obuf
, 0);
358 endp
= stream_get_endp (obuf
);
359 for (; info
; info
= info
->next
)
364 stream_putw (obuf
, info
->peer
->table_dump_index
);
367 #ifdef HAVE_CLOCK_MONOTONIC
368 stream_putl (obuf
, time(NULL
) - (bgp_clock() - info
->uptime
));
370 stream_putl (obuf
, info
->uptime
);
371 #endif /* HAVE_CLOCK_MONOTONIC */
373 /* Dump attribute. */
374 /* Skip prefix & AFI/SAFI for MP_NLRI */
375 bgp_dump_routes_attr (obuf
, info
->attr
, &rn
->p
);
377 cur_endp
= stream_get_endp (obuf
);
378 if (cur_endp
> BGP_MAX_PACKET_SIZE
+ BGP_DUMP_MSG_HEADER
379 + BGP_DUMP_HEADER_SIZE
)
381 stream_set_endp (obuf
, endp
);
389 /* Overwrite the entry count, now that we know the right number */
390 stream_putw_at (obuf
, sizep
, entry_count
);
392 bgp_dump_set_size (obuf
, MSG_TABLE_DUMP_V2
);
393 fwrite (STREAM_DATA (obuf
), stream_get_endp (obuf
), 1, bgp_dump_routes
.fp
);
399 /* Runs under child process. */
401 bgp_dump_routes_func (int afi
, int first_run
, unsigned int seq
)
403 struct bgp_info
*info
;
406 struct bgp_table
*table
;
408 bgp
= bgp_get_default ();
412 if (bgp_dump_routes
.fp
== NULL
)
415 /* Note that bgp_dump_routes_index_table will do ipv4 and ipv6 peers,
416 so this should only be done on the first call to bgp_dump_routes_func.
417 ( this function will be called once for ipv4 and once for ipv6 ) */
419 bgp_dump_routes_index_table(bgp
);
421 /* Walk down each BGP route. */
422 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
424 for (rn
= bgp_table_top (table
); rn
; rn
= bgp_route_next (rn
))
429 info
= bgp_dump_route_node_record (afi
, rn
, info
, seq
);
434 fflush (bgp_dump_routes
.fp
);
440 bgp_dump_interval_func (struct thread
*t
)
442 struct bgp_dump
*bgp_dump
;
443 bgp_dump
= THREAD_ARG (t
);
444 bgp_dump
->t_interval
= NULL
;
446 /* Reschedule dump even if file couldn't be opened this time... */
447 if (bgp_dump_open_file (bgp_dump
) != NULL
)
449 /* In case of bgp_dump_routes, we need special route dump function. */
450 if (bgp_dump
->type
== BGP_DUMP_ROUTES
)
452 unsigned int seq
= bgp_dump_routes_func (AFI_IP
, 1, 0);
453 bgp_dump_routes_func (AFI_IP6
, 0, seq
);
454 /* Close the file now. For a RIB dump there's no point in leaving
455 * it open until the next scheduled dump starts. */
456 fclose(bgp_dump
->fp
); bgp_dump
->fp
= NULL
;
460 /* if interval is set reschedule */
461 if (bgp_dump
->interval
> 0)
462 bgp_dump_interval_add (bgp_dump
, bgp_dump
->interval
);
467 /* Dump common information. */
469 bgp_dump_common (struct stream
*obuf
, struct peer
*peer
, int forceas4
)
471 char empty
[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
473 /* Source AS number and Destination AS number. */
474 if (forceas4
|| CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
476 stream_putl (obuf
, peer
->as
);
477 stream_putl (obuf
, peer
->local_as
);
481 stream_putw (obuf
, peer
->as
);
482 stream_putw (obuf
, peer
->local_as
);
485 if (peer
->su
.sa
.sa_family
== AF_INET
)
487 stream_putw (obuf
, peer
->ifindex
);
488 stream_putw (obuf
, AFI_IP
);
490 stream_put (obuf
, &peer
->su
.sin
.sin_addr
, IPV4_MAX_BYTELEN
);
493 stream_put (obuf
, &peer
->su_local
->sin
.sin_addr
, IPV4_MAX_BYTELEN
);
495 stream_put (obuf
, empty
, IPV4_MAX_BYTELEN
);
497 else if (peer
->su
.sa
.sa_family
== AF_INET6
)
499 /* Interface Index and Address family. */
500 stream_putw (obuf
, peer
->ifindex
);
501 stream_putw (obuf
, AFI_IP6
);
503 /* Source IP Address and Destination IP Address. */
504 stream_put (obuf
, &peer
->su
.sin6
.sin6_addr
, IPV6_MAX_BYTELEN
);
507 stream_put (obuf
, &peer
->su_local
->sin6
.sin6_addr
, IPV6_MAX_BYTELEN
);
509 stream_put (obuf
, empty
, IPV6_MAX_BYTELEN
);
513 /* Dump BGP status change. */
515 bgp_dump_state (struct peer
*peer
, int status_old
, int status_new
)
519 /* If dump file pointer is disabled return immediately. */
520 if (bgp_dump_all
.fp
== NULL
)
523 /* Make dump stream. */
524 obuf
= bgp_dump_obuf
;
527 bgp_dump_header (obuf
, MSG_PROTOCOL_BGP4MP
, BGP4MP_STATE_CHANGE_AS4
,
529 bgp_dump_common (obuf
, peer
, 1);/* force this in as4speak*/
531 stream_putw (obuf
, status_old
);
532 stream_putw (obuf
, status_new
);
535 bgp_dump_set_size (obuf
, MSG_PROTOCOL_BGP4MP
);
537 /* Write to the stream. */
538 fwrite (STREAM_DATA (obuf
), stream_get_endp (obuf
), 1, bgp_dump_all
.fp
);
539 fflush (bgp_dump_all
.fp
);
543 bgp_dump_packet_func (struct bgp_dump
*bgp_dump
, struct peer
*peer
,
544 struct stream
*packet
)
548 /* If dump file pointer is disabled return immediately. */
549 if (bgp_dump
->fp
== NULL
)
552 /* Make dump stream. */
553 obuf
= bgp_dump_obuf
;
556 /* Dump header and common part. */
557 if (CHECK_FLAG (peer
->cap
, PEER_CAP_AS4_RCV
) )
559 bgp_dump_header (obuf
, MSG_PROTOCOL_BGP4MP
, BGP4MP_MESSAGE_AS4
,
564 bgp_dump_header (obuf
, MSG_PROTOCOL_BGP4MP
, BGP4MP_MESSAGE
,
567 bgp_dump_common (obuf
, peer
, 0);
569 /* Packet contents. */
570 stream_put (obuf
, STREAM_DATA (packet
), stream_get_endp (packet
));
573 bgp_dump_set_size (obuf
, MSG_PROTOCOL_BGP4MP
);
575 /* Write to the stream. */
576 fwrite (STREAM_DATA (obuf
), stream_get_endp (obuf
), 1, bgp_dump
->fp
);
577 fflush (bgp_dump
->fp
);
580 /* Called from bgp_packet.c when BGP packet is received. */
582 bgp_dump_packet (struct peer
*peer
, int type
, struct stream
*packet
)
585 bgp_dump_packet_func (&bgp_dump_all
, peer
, packet
);
587 /* bgp_dump_updates. */
588 if (type
== BGP_MSG_UPDATE
)
589 bgp_dump_packet_func (&bgp_dump_updates
, peer
, packet
);
593 bgp_dump_parse_time (const char *str
)
608 for (i
= 0; i
< len
; i
++)
610 if (isdigit ((int) str
[i
]))
613 time
+= str
[i
] - '0';
615 else if (str
[i
] == 'H' || str
[i
] == 'h')
621 total
+= time
* 60 *60;
625 else if (str
[i
] == 'M' || str
[i
] == 'm')
640 bgp_dump_set (struct vty
*vty
, struct bgp_dump
*bgp_dump
,
641 enum bgp_dump_type type
, const char *path
,
642 const char *interval_str
)
644 unsigned int interval
;
646 /* Don't schedule duplicate dumps if the dump command is given twice */
647 if (bgp_dump
->filename
&& strcmp(path
, bgp_dump
->filename
) == 0
648 && type
== bgp_dump
->type
)
652 if (bgp_dump
->interval_str
&&
653 strcmp(bgp_dump
->interval_str
, interval_str
) == 0)
658 if (!bgp_dump
->interval_str
)
663 /* Removing previous config */
664 bgp_dump_unset(vty
, bgp_dump
);
668 /* Check interval string. */
669 interval
= bgp_dump_parse_time (interval_str
);
672 vty_out (vty
, "Malformed interval string%s", VTY_NEWLINE
);
676 /* Setting interval string */
677 bgp_dump
->interval_str
= XSTRDUP(MTYPE_BGP_DUMP_STR
, interval_str
);
685 bgp_dump
->type
= type
;
688 bgp_dump
->interval
= interval
;
691 bgp_dump
->filename
= XSTRDUP (MTYPE_BGP_DUMP_STR
, path
);
693 /* Create interval thread. */
694 bgp_dump_interval_add (bgp_dump
, interval
);
696 /* This should be called when interval is expired. */
697 bgp_dump_open_file (bgp_dump
);
703 bgp_dump_unset (struct vty
*vty
, struct bgp_dump
*bgp_dump
)
705 /* Removing file name. */
706 if (bgp_dump
->filename
)
708 XFREE(MTYPE_BGP_DUMP_STR
, bgp_dump
->filename
);
709 bgp_dump
->filename
= NULL
;
715 fclose (bgp_dump
->fp
);
719 /* Removing interval thread. */
720 if (bgp_dump
->t_interval
)
722 thread_cancel (bgp_dump
->t_interval
);
723 bgp_dump
->t_interval
= NULL
;
726 bgp_dump
->interval
= 0;
728 /* Removing interval string. */
729 if (bgp_dump
->interval_str
)
731 XFREE(MTYPE_BGP_DUMP_STR
, bgp_dump
->interval_str
);
732 bgp_dump
->interval_str
= NULL
;
740 "dump bgp (all|all-et|updates|updates-et|routes-mrt) PATH [INTERVAL]",
743 "Dump all BGP packets\nDump all BGP packets (Extended Timestamp Header)\n"
744 "Dump BGP updates only\nDump BGP updates only (Extended Timestamp Header)\n"
745 "Dump whole BGP routing table\n"
747 "Interval of output\n")
749 int bgp_dump_type
= 0;
750 const char *interval
= NULL
;
751 struct bgp_dump
*bgp_dump_struct
= NULL
;
752 const struct bgp_dump_type_map
*map
= NULL
;
754 for (map
= bgp_dump_type_map
; map
->str
; map
++)
755 if (strcmp(argv
[0], map
->str
) == 0)
756 bgp_dump_type
= map
->type
;
758 switch (bgp_dump_type
)
761 case BGP_DUMP_ALL_ET
:
762 bgp_dump_struct
= &bgp_dump_all
;
764 case BGP_DUMP_UPDATES
:
765 case BGP_DUMP_UPDATES_ET
:
766 bgp_dump_struct
= &bgp_dump_updates
;
768 case BGP_DUMP_ROUTES
:
770 bgp_dump_struct
= &bgp_dump_routes
;
774 /* When an interval is given */
778 return bgp_dump_set (vty
, bgp_dump_struct
, bgp_dump_type
,
782 DEFUN (no_dump_bgp_all
,
784 "no dump bgp (all|all-et|updates|updates-et|routes-mrt) [PATH] [INTERVAL]",
787 "Stop BGP packet dump\n"
788 "Stop dump process all\n"
789 "Stop dump process all-et\n"
790 "Stop dump process updates\n"
791 "Stop dump process updates-et\n"
792 "Stop dump process route-mrt\n")
794 int bgp_dump_type
= 0;
795 const struct bgp_dump_type_map
*map
= NULL
;
796 struct bgp_dump
*bgp_dump_struct
= NULL
;
798 for (map
= bgp_dump_type_map
; map
->str
; map
++)
799 if (strcmp(argv
[0], map
->str
) == 0)
800 bgp_dump_type
= map
->type
;
802 switch (bgp_dump_type
)
805 case BGP_DUMP_ALL_ET
:
806 bgp_dump_struct
= &bgp_dump_all
;
808 case BGP_DUMP_UPDATES
:
809 case BGP_DUMP_UPDATES_ET
:
810 bgp_dump_struct
= &bgp_dump_updates
;
812 case BGP_DUMP_ROUTES
:
814 bgp_dump_struct
= &bgp_dump_routes
;
818 return bgp_dump_unset (vty
, bgp_dump_struct
);
821 /* BGP node structure. */
822 static struct cmd_node bgp_dump_node
=
831 config_time2str (unsigned int interval
)
833 static char buf
[BUFSIZ
];
839 sprintf (buf
, "%dh", interval
/ 3600);
844 sprintf (buf
+ strlen (buf
), "%dm", interval
/60);
849 sprintf (buf
+ strlen (buf
), "%d", interval
);
856 config_write_bgp_dump (struct vty
*vty
)
858 if (bgp_dump_all
.filename
)
860 const char *type_str
= "all";
861 if (bgp_dump_all
.type
== BGP_DUMP_ALL_ET
)
864 if (bgp_dump_all
.interval_str
)
865 vty_out (vty
, "dump bgp %s %s %s%s", type_str
,
866 bgp_dump_all
.filename
, bgp_dump_all
.interval_str
,
869 vty_out (vty
, "dump bgp %s %s%s", type_str
,
870 bgp_dump_all
.filename
, VTY_NEWLINE
);
872 if (bgp_dump_updates
.filename
)
874 const char *type_str
= "updates";
875 if (bgp_dump_updates
.type
== BGP_DUMP_UPDATES_ET
)
876 type_str
= "updates-et";
878 if (bgp_dump_updates
.interval_str
)
879 vty_out (vty
, "dump bgp %s %s %s%s", type_str
,
880 bgp_dump_updates
.filename
, bgp_dump_updates
.interval_str
,
883 vty_out (vty
, "dump bgp updates %s%s",
884 bgp_dump_updates
.filename
, VTY_NEWLINE
);
886 if (bgp_dump_routes
.filename
)
888 if (bgp_dump_routes
.interval_str
)
889 vty_out (vty
, "dump bgp routes-mrt %s %s%s",
890 bgp_dump_routes
.filename
, bgp_dump_routes
.interval_str
,
896 /* Initialize BGP packet dump functionality. */
900 memset (&bgp_dump_all
, 0, sizeof (struct bgp_dump
));
901 memset (&bgp_dump_updates
, 0, sizeof (struct bgp_dump
));
902 memset (&bgp_dump_routes
, 0, sizeof (struct bgp_dump
));
904 bgp_dump_obuf
= stream_new ((BGP_MAX_PACKET_SIZE
<< 1)
905 + BGP_DUMP_MSG_HEADER
+ BGP_DUMP_HEADER_SIZE
);
907 install_node (&bgp_dump_node
, config_write_bgp_dump
);
909 install_element (CONFIG_NODE
, &dump_bgp_all_cmd
);
910 install_element (CONFIG_NODE
, &no_dump_bgp_all_cmd
);
914 bgp_dump_finish (void)
916 stream_free (bgp_dump_obuf
);
917 bgp_dump_obuf
= NULL
;