BGP: Update dump to allow Extended Time Format

Allow the bgp dump functionality to handle the Extended Time format
as specified in RFC 6396.

Fixes a segmentation fault with multiple dump rules as well.

Signed-off-by: Alexis Fasquel <alexis@pch.net>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Alexis Fasquel 2015-11-16 13:55:16 -05:00 committed by Donald Sharp
parent 9da3a1a191
commit 4db5d90acf
5 changed files with 184 additions and 166 deletions

View File

@ -192,6 +192,8 @@ main (int argc, char **argv)
if (type == MSG_PROTOCOL_BGP4MP) if (type == MSG_PROTOCOL_BGP4MP)
printf ("TYPE: BGP4MP"); printf ("TYPE: BGP4MP");
else if (type == MSG_PROTOCOL_BGP4MP_ET)
printf ("TYPE: BGP4MP_ET");
else if (type == MSG_TABLE_DUMP) else if (type == MSG_TABLE_DUMP)
printf ("TYPE: MSG_TABLE_DUMP"); printf ("TYPE: MSG_TABLE_DUMP");
else else

View File

@ -40,10 +40,25 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
enum bgp_dump_type enum bgp_dump_type
{ {
BGP_DUMP_ALL, BGP_DUMP_ALL,
BGP_DUMP_ALL_ET,
BGP_DUMP_UPDATES, BGP_DUMP_UPDATES,
BGP_DUMP_UPDATES_ET,
BGP_DUMP_ROUTES BGP_DUMP_ROUTES
}; };
static const struct bgp_dump_type_map {
enum bgp_dump_type type;
const char *str;
} bgp_dump_type_map[] =
{
{BGP_DUMP_ALL, "all"},
{BGP_DUMP_ALL_ET, "all-et"},
{BGP_DUMP_UPDATES, "updates"},
{BGP_DUMP_UPDATES_ET, "updates-et"},
{BGP_DUMP_ROUTES, "routes-mrt"},
{0, NULL},
};
enum MRT_MSG_TYPES { enum MRT_MSG_TYPES {
MSG_NULL, MSG_NULL,
MSG_START, /* sender is starting up */ MSG_START, /* sender is starting up */
@ -61,8 +76,6 @@ enum MRT_MSG_TYPES {
MSG_TABLE_DUMP_V2 /* routing table dump, version 2 */ MSG_TABLE_DUMP_V2 /* routing table dump, version 2 */
}; };
static int bgp_dump_interval_func (struct thread *);
struct bgp_dump struct bgp_dump
{ {
enum bgp_dump_type type; enum bgp_dump_type type;
@ -78,6 +91,9 @@ struct bgp_dump
struct thread *t_interval; struct thread *t_interval;
}; };
static int bgp_dump_unset (struct vty *vty, struct bgp_dump *bgp_dump);
static int bgp_dump_interval_func (struct thread *);
/* BGP packet dump output buffer. */ /* BGP packet dump output buffer. */
struct stream *bgp_dump_obuf; struct stream *bgp_dump_obuf;
@ -90,10 +106,6 @@ struct bgp_dump bgp_dump_updates;
/* BGP dump structure for 'dump bgp routes' */ /* BGP dump structure for 'dump bgp routes' */
struct bgp_dump bgp_dump_routes; struct bgp_dump bgp_dump_routes;
/* Dump whole BGP table is very heavy process. */
struct thread *t_bgp_dump_routes;
/* Some define for BGP packet dump. */
static FILE * static FILE *
bgp_dump_open_file (struct bgp_dump *bgp_dump) bgp_dump_open_file (struct bgp_dump *bgp_dump)
{ {
@ -174,24 +186,40 @@ bgp_dump_interval_add (struct bgp_dump *bgp_dump, int interval)
/* Dump common header. */ /* Dump common header. */
static void static void
bgp_dump_header (struct stream *obuf, int type, int subtype) bgp_dump_header (struct stream *obuf, int type, int subtype, int dump_type)
{ {
time_t now; struct timeval clock;
long msecs;
time_t secs;
/* Set header. */ if ((dump_type == BGP_DUMP_ALL_ET || dump_type == BGP_DUMP_UPDATES_ET)
time (&now); && type == MSG_PROTOCOL_BGP4MP)
type = MSG_PROTOCOL_BGP4MP_ET;
gettimeofday(&clock, NULL);
secs = clock.tv_sec;
msecs = clock.tv_usec;
/* Put dump packet header. */ /* Put dump packet header. */
stream_putl (obuf, now); stream_putl (obuf, secs);
stream_putw (obuf, type); stream_putw (obuf, type);
stream_putw (obuf, subtype); stream_putw (obuf, subtype);
stream_putl (obuf, 0); /* len */ stream_putl (obuf, 0); /* len */
/* Adding microseconds for the MRT Extended Header */
if (type == MSG_PROTOCOL_BGP4MP_ET)
stream_putl (obuf, msecs);
} }
static void static void
bgp_dump_set_size (struct stream *s, int type) bgp_dump_set_size (struct stream *s, int type)
{ {
/*
* The BGP_DUMP_HEADER_SIZE stay at 12 event when ET:
* "The Microsecond Timestamp is included in the computation
* of the Length field value." (RFC6396 2011)
*/
stream_putl_at (s, 8, stream_get_endp (s) - BGP_DUMP_HEADER_SIZE); stream_putl_at (s, 8, stream_get_endp (s) - BGP_DUMP_HEADER_SIZE);
} }
@ -207,7 +235,8 @@ bgp_dump_routes_index_table(struct bgp *bgp)
stream_reset (obuf); stream_reset (obuf);
/* MRT header */ /* MRT header */
bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_PEER_INDEX_TABLE); bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_PEER_INDEX_TABLE,
BGP_DUMP_ROUTES);
/* Collector BGP ID */ /* Collector BGP ID */
stream_put_in_addr (obuf, &bgp->router_id); stream_put_in_addr (obuf, &bgp->router_id);
@ -235,12 +264,10 @@ bgp_dump_routes_index_table(struct bgp *bgp)
{ {
stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP); stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP);
} }
#ifdef HAVE_IPV6
else if (sockunion_family(&peer->su) == AF_INET6) else if (sockunion_family(&peer->su) == AF_INET6)
{ {
stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6); stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6);
} }
#endif /* HAVE_IPV6 */
/* Peer's BGP ID */ /* Peer's BGP ID */
stream_put_in_addr (obuf, &peer->remote_id); stream_put_in_addr (obuf, &peer->remote_id);
@ -250,13 +277,11 @@ bgp_dump_routes_index_table(struct bgp *bgp)
{ {
stream_put_in_addr (obuf, &peer->su.sin.sin_addr); stream_put_in_addr (obuf, &peer->su.sin.sin_addr);
} }
#ifdef HAVE_IPV6
else if (sockunion_family(&peer->su) == AF_INET6) else if (sockunion_family(&peer->su) == AF_INET6)
{ {
stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr, stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr,
IPV6_MAX_BYTELEN); IPV6_MAX_BYTELEN);
} }
#endif /* HAVE_IPV6 */
/* Peer's AS number. */ /* Peer's AS number. */
/* Note that, as this is an AS4 compliant quagga, the RIB is always AS4 */ /* Note that, as this is an AS4 compliant quagga, the RIB is always AS4 */
@ -312,15 +337,11 @@ bgp_dump_routes_func (int afi, int first_run, unsigned int seq)
/* MRT header */ /* MRT header */
if (afi == AFI_IP) if (afi == AFI_IP)
{ bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST,
bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST); BGP_DUMP_ROUTES);
}
#ifdef HAVE_IPV6
else if (afi == AFI_IP6) else if (afi == AFI_IP6)
{ bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST,
bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST); BGP_DUMP_ROUTES);
}
#endif /* HAVE_IPV6 */
/* Sequence number */ /* Sequence number */
stream_putl(obuf, seq); stream_putl(obuf, seq);
@ -334,13 +355,11 @@ bgp_dump_routes_func (int afi, int first_run, unsigned int seq)
/* We'll dump only the useful bits (those not 0), but have to align on 8 bits */ /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
stream_write(obuf, (u_char *)&rn->p.u.prefix4, (rn->p.prefixlen+7)/8); stream_write(obuf, (u_char *)&rn->p.u.prefix4, (rn->p.prefixlen+7)/8);
} }
#ifdef HAVE_IPV6
else if (afi == AFI_IP6) else if (afi == AFI_IP6)
{ {
/* We'll dump only the useful bits (those not 0), but have to align on 8 bits */ /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
stream_write (obuf, (u_char *)&rn->p.u.prefix6, (rn->p.prefixlen+7)/8); stream_write (obuf, (u_char *)&rn->p.u.prefix6, (rn->p.prefixlen+7)/8);
} }
#endif /* HAVE_IPV6 */
/* Save where we are now, so we can overwride the entry count later */ /* Save where we are now, so we can overwride the entry count later */
int sizep = stream_get_endp(obuf); int sizep = stream_get_endp(obuf);
@ -399,9 +418,7 @@ bgp_dump_interval_func (struct thread *t)
if (bgp_dump->type == BGP_DUMP_ROUTES) if (bgp_dump->type == BGP_DUMP_ROUTES)
{ {
unsigned int seq = bgp_dump_routes_func (AFI_IP, 1, 0); unsigned int seq = bgp_dump_routes_func (AFI_IP, 1, 0);
#ifdef HAVE_IPV6
bgp_dump_routes_func (AFI_IP6, 0, seq); bgp_dump_routes_func (AFI_IP6, 0, seq);
#endif /* HAVE_IPV6 */
/* Close the file now. For a RIB dump there's no point in leaving /* Close the file now. For a RIB dump there's no point in leaving
* it open until the next scheduled dump starts. */ * it open until the next scheduled dump starts. */
fclose(bgp_dump->fp); bgp_dump->fp = NULL; fclose(bgp_dump->fp); bgp_dump->fp = NULL;
@ -445,7 +462,6 @@ bgp_dump_common (struct stream *obuf, struct peer *peer, int forceas4)
else else
stream_put (obuf, empty, IPV4_MAX_BYTELEN); stream_put (obuf, empty, IPV4_MAX_BYTELEN);
} }
#ifdef HAVE_IPV6
else if (peer->su.sa.sa_family == AF_INET6) else if (peer->su.sa.sa_family == AF_INET6)
{ {
/* Interface Index and Address family. */ /* Interface Index and Address family. */
@ -460,7 +476,6 @@ bgp_dump_common (struct stream *obuf, struct peer *peer, int forceas4)
else else
stream_put (obuf, empty, IPV6_MAX_BYTELEN); stream_put (obuf, empty, IPV6_MAX_BYTELEN);
} }
#endif /* HAVE_IPV6 */
} }
/* Dump BGP status change. */ /* Dump BGP status change. */
@ -477,7 +492,8 @@ bgp_dump_state (struct peer *peer, int status_old, int status_new)
obuf = bgp_dump_obuf; obuf = bgp_dump_obuf;
stream_reset (obuf); stream_reset (obuf);
bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4); bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4,
bgp_dump_all.type);
bgp_dump_common (obuf, peer, 1);/* force this in as4speak*/ bgp_dump_common (obuf, peer, 1);/* force this in as4speak*/
stream_putw (obuf, status_old); stream_putw (obuf, status_old);
@ -508,11 +524,13 @@ bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer,
/* Dump header and common part. */ /* Dump header and common part. */
if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) ) if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
{ {
bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE_AS4); bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE_AS4,
bgp_dump->type);
} }
else else
{ {
bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE); bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE,
bgp_dump->type);
} }
bgp_dump_common (obuf, peer, 0); bgp_dump_common (obuf, peer, 0);
@ -593,9 +611,28 @@ bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump,
{ {
unsigned int interval; unsigned int interval;
/* Don't schedule duplicate dumps if the dump command is given twice */
if (bgp_dump->filename && strcmp(path, bgp_dump->filename) == 0
&& type == bgp_dump->type)
{
if (interval_str) if (interval_str)
{ {
if (bgp_dump->interval_str &&
strcmp(bgp_dump->interval_str, interval_str) == 0)
return CMD_SUCCESS;
}
else
{
if (!bgp_dump->interval_str)
return CMD_SUCCESS;
}
}
/* Removing previous config */
bgp_dump_unset(vty, bgp_dump);
if (interval_str)
{
/* Check interval string. */ /* Check interval string. */
interval = bgp_dump_parse_time (interval_str); interval = bgp_dump_parse_time (interval_str);
if (interval == 0) if (interval == 0)
@ -604,37 +641,26 @@ bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump,
return CMD_WARNING; return CMD_WARNING;
} }
/* Don't schedule duplicate dumps if the dump command is given twice */ /* Setting interval string */
if (interval == bgp_dump->interval &&
type == bgp_dump->type &&
path && bgp_dump->filename && !strcmp (path, bgp_dump->filename))
{
return CMD_SUCCESS;
}
/* Set interval. */
bgp_dump->interval = interval;
if (bgp_dump->interval_str)
XFREE(MTYPE_BGP_DUMP_STR, bgp_dump->interval_str);
bgp_dump->interval_str = XSTRDUP(MTYPE_BGP_DUMP_STR, interval_str); bgp_dump->interval_str = XSTRDUP(MTYPE_BGP_DUMP_STR, interval_str);
} }
else else
{ {
interval = 0; interval = 0;
} }
/* Create interval thread. */
bgp_dump_interval_add (bgp_dump, interval);
/* Set type. */ /* Set type. */
bgp_dump->type = type; bgp_dump->type = type;
/* Set interval */
bgp_dump->interval = interval;
/* Set file name. */ /* Set file name. */
if (bgp_dump->filename)
XFREE(MTYPE_BGP_DUMP_STR, bgp_dump->filename);
bgp_dump->filename = XSTRDUP (MTYPE_BGP_DUMP_STR, path); bgp_dump->filename = XSTRDUP (MTYPE_BGP_DUMP_STR, path);
/* Create interval thread. */
bgp_dump_interval_add (bgp_dump, interval);
/* This should be called when interval is expired. */ /* This should be called when interval is expired. */
bgp_dump_open_file (bgp_dump); bgp_dump_open_file (bgp_dump);
@ -644,21 +670,21 @@ bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump,
static int static int
bgp_dump_unset (struct vty *vty, struct bgp_dump *bgp_dump) bgp_dump_unset (struct vty *vty, struct bgp_dump *bgp_dump)
{ {
/* Set file name. */ /* Removing file name. */
if (bgp_dump->filename) if (bgp_dump->filename)
{ {
XFREE(MTYPE_BGP_DUMP_STR, bgp_dump->filename); XFREE(MTYPE_BGP_DUMP_STR, bgp_dump->filename);
bgp_dump->filename = NULL; bgp_dump->filename = NULL;
} }
/* This should be called when interval is expired. */ /* Closing file. */
if (bgp_dump->fp) if (bgp_dump->fp)
{ {
fclose (bgp_dump->fp); fclose (bgp_dump->fp);
bgp_dump->fp = NULL; bgp_dump->fp = NULL;
} }
/* Create interval thread. */ /* Removing interval thread. */
if (bgp_dump->t_interval) if (bgp_dump->t_interval)
{ {
thread_cancel (bgp_dump->t_interval); thread_cancel (bgp_dump->t_interval);
@ -667,118 +693,73 @@ bgp_dump_unset (struct vty *vty, struct bgp_dump *bgp_dump)
bgp_dump->interval = 0; bgp_dump->interval = 0;
/* Removing interval string. */
if (bgp_dump->interval_str) if (bgp_dump->interval_str)
{ {
XFREE(MTYPE_BGP_DUMP_STR, bgp_dump->interval_str); XFREE(MTYPE_BGP_DUMP_STR, bgp_dump->interval_str);
bgp_dump->interval_str = NULL; bgp_dump->interval_str = NULL;
} }
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (dump_bgp_all, DEFUN (dump_bgp_all,
dump_bgp_all_cmd, dump_bgp_all_cmd,
"dump bgp all PATH", "dump bgp (all|all-et|updates|updates-et|routes-mrt) PATH [INTERVAL]",
"Dump packet\n" "Dump packet\n"
"BGP packet dump\n" "BGP packet dump\n"
"Dump all BGP packets\n" "Dump all BGP packets\nDump all BGP packets (Extended Tiemstamp Header)\n"
"Output filename\n") "Dump BGP updates only\nDump BGP updates only (Extended Tiemstamp Header)\n"
{ "Dump whole BGP routing table\n"
return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], NULL);
}
DEFUN (dump_bgp_all_interval,
dump_bgp_all_interval_cmd,
"dump bgp all PATH INTERVAL",
"Dump packet\n"
"BGP packet dump\n"
"Dump all BGP packets\n"
"Output filename\n" "Output filename\n"
"Interval of output\n") "Interval of output\n")
{ {
return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], argv[1]); int bgp_dump_type = 0;
const char *interval = NULL;
struct bgp_dump *bgp_dump_struct = NULL;
const struct bgp_dump_type_map *map = NULL;
for (map = bgp_dump_type_map; map->str; map++)
if (strcmp(argv[0], map->str) == 0)
bgp_dump_type = map->type;
switch (bgp_dump_type)
{
case BGP_DUMP_ALL:
case BGP_DUMP_ALL_ET:
bgp_dump_struct = &bgp_dump_all;
break;
case BGP_DUMP_UPDATES:
case BGP_DUMP_UPDATES_ET:
bgp_dump_struct = &bgp_dump_updates;
break;
case BGP_DUMP_ROUTES:
default:
bgp_dump_struct = &bgp_dump_routes;
break;
}
/* When an interval is given */
if (argc == 3)
interval = argv[2];
return bgp_dump_set (vty, bgp_dump_struct, bgp_dump_type,
argv[1], interval);
} }
DEFUN (no_dump_bgp_all, DEFUN (no_dump_bgp_all,
no_dump_bgp_all_cmd, no_dump_bgp_all_cmd,
"no dump bgp all [PATH] [INTERVAL]", "no dump bgp (all|updates|routes-mrt) [PATH] [INTERVAL]",
NO_STR NO_STR
"Dump packet\n" "Stop dump packet\n"
"BGP packet dump\n" "Stop BGP packet dump\n"
"Dump all BGP packets\n") "Stop dump process all/all-et\n"
"Stop dump process updates/updates-et\n"
"Stop dump process route-mrt\n")
{ {
return bgp_dump_unset (vty, &bgp_dump_all); return bgp_dump_unset (vty, &bgp_dump_all);
} }
DEFUN (dump_bgp_updates,
dump_bgp_updates_cmd,
"dump bgp updates PATH",
"Dump packet\n"
"BGP packet dump\n"
"Dump BGP updates only\n"
"Output filename\n")
{
return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], NULL);
}
DEFUN (dump_bgp_updates_interval,
dump_bgp_updates_interval_cmd,
"dump bgp updates PATH INTERVAL",
"Dump packet\n"
"BGP packet dump\n"
"Dump BGP updates only\n"
"Output filename\n"
"Interval of output\n")
{
return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], argv[1]);
}
DEFUN (no_dump_bgp_updates,
no_dump_bgp_updates_cmd,
"no dump bgp updates [PATH] [INTERVAL]",
NO_STR
"Dump packet\n"
"BGP packet dump\n"
"Dump BGP updates only\n")
{
return bgp_dump_unset (vty, &bgp_dump_updates);
}
DEFUN (dump_bgp_routes,
dump_bgp_routes_cmd,
"dump bgp routes-mrt PATH",
"Dump packet\n"
"BGP packet dump\n"
"Dump whole BGP routing table\n"
"Output filename\n")
{
return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], NULL);
}
DEFUN (dump_bgp_routes_interval,
dump_bgp_routes_interval_cmd,
"dump bgp routes-mrt PATH INTERVAL",
"Dump packet\n"
"BGP packet dump\n"
"Dump whole BGP routing table\n"
"Output filename\n"
"Interval of output\n")
{
return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], argv[1]);
}
DEFUN (no_dump_bgp_routes,
no_dump_bgp_routes_cmd,
"no dump bgp routes-mrt [PATH] [INTERVAL]",
NO_STR
"Dump packet\n"
"BGP packet dump\n"
"Dump whole BGP routing table\n")
{
return bgp_dump_unset (vty, &bgp_dump_routes);
}
/* BGP node structure. */ /* BGP node structure. */
static struct cmd_node bgp_dump_node = static struct cmd_node bgp_dump_node =
{ {
@ -818,18 +799,26 @@ config_write_bgp_dump (struct vty *vty)
{ {
if (bgp_dump_all.filename) if (bgp_dump_all.filename)
{ {
const char *type_str = "all";
if (bgp_dump_all.type == BGP_DUMP_ALL_ET)
type_str = "all-et";
if (bgp_dump_all.interval_str) if (bgp_dump_all.interval_str)
vty_out (vty, "dump bgp all %s %s%s", vty_out (vty, "dump bgp %s %s %s%s", type_str,
bgp_dump_all.filename, bgp_dump_all.interval_str, bgp_dump_all.filename, bgp_dump_all.interval_str,
VTY_NEWLINE); VTY_NEWLINE);
else else
vty_out (vty, "dump bgp all %s%s", vty_out (vty, "dump bgp %s %s%s", type_str,
bgp_dump_all.filename, VTY_NEWLINE); bgp_dump_all.filename, VTY_NEWLINE);
} }
if (bgp_dump_updates.filename) if (bgp_dump_updates.filename)
{ {
const char *type_str = "updates";
if (bgp_dump_updates.type == BGP_DUMP_UPDATES_ET)
type_str = "updates-et";
if (bgp_dump_updates.interval_str) if (bgp_dump_updates.interval_str)
vty_out (vty, "dump bgp updates %s %s%s", vty_out (vty, "dump bgp %s %s %s%s", type_str,
bgp_dump_updates.filename, bgp_dump_updates.interval_str, bgp_dump_updates.filename, bgp_dump_updates.interval_str,
VTY_NEWLINE); VTY_NEWLINE);
else else
@ -842,9 +831,6 @@ config_write_bgp_dump (struct vty *vty)
vty_out (vty, "dump bgp routes-mrt %s %s%s", vty_out (vty, "dump bgp routes-mrt %s %s%s",
bgp_dump_routes.filename, bgp_dump_routes.interval_str, bgp_dump_routes.filename, bgp_dump_routes.interval_str,
VTY_NEWLINE); VTY_NEWLINE);
else
vty_out (vty, "dump bgp routes-mrt %s%s",
bgp_dump_routes.filename, VTY_NEWLINE);
} }
return 0; return 0;
} }
@ -863,14 +849,7 @@ bgp_dump_init (void)
install_node (&bgp_dump_node, config_write_bgp_dump); install_node (&bgp_dump_node, config_write_bgp_dump);
install_element (CONFIG_NODE, &dump_bgp_all_cmd); install_element (CONFIG_NODE, &dump_bgp_all_cmd);
install_element (CONFIG_NODE, &dump_bgp_all_interval_cmd);
install_element (CONFIG_NODE, &no_dump_bgp_all_cmd); install_element (CONFIG_NODE, &no_dump_bgp_all_cmd);
install_element (CONFIG_NODE, &dump_bgp_updates_cmd);
install_element (CONFIG_NODE, &dump_bgp_updates_interval_cmd);
install_element (CONFIG_NODE, &no_dump_bgp_updates_cmd);
install_element (CONFIG_NODE, &dump_bgp_routes_cmd);
install_element (CONFIG_NODE, &dump_bgp_routes_interval_cmd);
install_element (CONFIG_NODE, &no_dump_bgp_routes_cmd);
} }
void void

View File

@ -24,6 +24,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
/* MRT compatible packet dump values. */ /* MRT compatible packet dump values. */
/* type value */ /* type value */
#define MSG_PROTOCOL_BGP4MP 16 #define MSG_PROTOCOL_BGP4MP 16
#define MSG_PROTOCOL_BGP4MP_ET 17
/* subtype value */ /* subtype value */
#define BGP4MP_STATE_CHANGE 0 #define BGP4MP_STATE_CHANGE 0
#define BGP4MP_MESSAGE 1 #define BGP4MP_MESSAGE 1

View File

@ -28,6 +28,25 @@ don't need to change header format.
| Length | | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@end group @end group
@end example
If `type' is PROTOCOL_BGP4MP_ET, the common header format will
contain an additional microsecond field (RFC6396 2011).
@example
@group
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Subtype |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Microsecond |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@end group
@end example @end example
If `type' is PROTOCOL_BGP4MP, `subtype' is BGP4MP_STATE_CHANGE, and If `type' is PROTOCOL_BGP4MP, `subtype' is BGP4MP_STATE_CHANGE, and
@ -228,6 +247,7 @@ If `type' is PROTOCOL_BGP4MP and `subtype' is BGP4MP_SNAPSHOT,
Constants: Constants:
/* type value */ /* type value */
#define MSG_PROTOCOL_BGP4MP 16 #define MSG_PROTOCOL_BGP4MP 16
#define MSG_PROTOCOL_BGP4MP_ET 17
/* subtype value */ /* subtype value */
#define BGP4MP_STATE_CHANGE 0 #define BGP4MP_STATE_CHANGE 0
#define BGP4MP_MESSAGE 1 #define BGP4MP_MESSAGE 1

View File

@ -1362,21 +1362,36 @@ log file bgpd.log
@node Dump BGP packets and table @node Dump BGP packets and table
@section Dump BGP packets and table @section Dump BGP packets and table
@deffn Command {dump bgp all @var{path}} {} @deffn Command {dump bgp all @var{path} [@var{interval}]} {}
@deffnx Command {dump bgp all @var{path} @var{interval}} {} @deffnx Command {dump bgp all-et @var{path} [@var{interval}]} {}
@deffnx Command {no dump bgp all [@var{path}] [@var{interval}]} {}
Dump all BGP packet and events to @var{path} file. Dump all BGP packet and events to @var{path} file.
If @var{interval} is set, a new file will be created for echo @var{interval} of seconds.
The path @var{path} can be set with date and time formatting (strftime).
The type all-et enables support for Extended Timestamp Header (@pxref{Packet Binary Dump Format}).
(@pxref{Packet Binary Dump Format})
@end deffn @end deffn
@deffn Command {dump bgp updates @var{path}} {} @deffn Command {dump bgp updates @var{path} [@var{interval}]} {}
@deffnx Command {dump bgp updates @var{path} @var{interval}} {} @deffnx Command {dump bgp updates-et @var{path} [@var{interval}]} {}
Dump BGP updates to @var{path} file. @deffnx Command {no dump bgp updates [@var{path}] [@var{interval}]} {}
Dump only BGP updates messages to @var{path} file.
If @var{interval} is set, a new file will be created for echo @var{interval} of seconds.
The path @var{path} can be set with date and time formatting (strftime).
The type updates-et enables support for Extended Timestamp Header (@pxref{Packet Binary Dump Format}).
@end deffn @end deffn
@deffn Command {dump bgp routes @var{path}} {} @deffn Command {dump bgp routes-mrt @var{path}} {}
@deffnx Command {dump bgp routes @var{path}} {} @deffnx Command {dump bgp routes-mrt @var{path} @var{interval}} {}
@deffnx Command {no dump bgp route-mrt [@var{path}] [@var{interval}]} {}
Dump whole BGP routing table to @var{path}. This is heavy process. Dump whole BGP routing table to @var{path}. This is heavy process.
The path @var{path} can be set with date and time formatting (strftime).
If @var{interval} is set, a new file will be created for echo @var{interval} of seconds.
@end deffn @end deffn
Note: the interval variable can also be set using hours and minutes: 04h20m00.
@node BGP Configuration Examples @node BGP Configuration Examples
@section BGP Configuration Examples @section BGP Configuration Examples