0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-09-19 20:05:21 +00:00

BGP: Statistics

Count message rx/tx, enqueued buckets/prefixes and recoverable
error conditions. Show them in 'show protocol all'
This commit is contained in:
Ondrej Zajicek (work) 2018-11-30 22:10:14 +01:00
parent 80a4c23b1e
commit 8972a08fab
4 changed files with 54 additions and 10 deletions

View File

@ -1094,8 +1094,10 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
ADVANCE(pos, len, alen);
}
#define FAIL(KEY) ({ STATS(KEY); goto fail; })
if (s->err_withdraw)
goto withdraw;
FAIL(bad_attribute);
/* If there is no reachability NLRI, we are finished */
if (!s->ip_reach_len && !s->mp_reach_len)
@ -1104,10 +1106,10 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
/* Handle missing mandatory attributes; RFC 7606 3 (d) */
if (!BIT32_TEST(s->attrs_seen, BA_ORIGIN))
{ REPORT(NO_MANDATORY, "ORIGIN"); goto withdraw; }
{ REPORT(NO_MANDATORY, "ORIGIN"); FAIL(no_mandatory); }
if (!BIT32_TEST(s->attrs_seen, BA_AS_PATH))
{ REPORT(NO_MANDATORY, "AS_PATH"); goto withdraw; }
{ REPORT(NO_MANDATORY, "AS_PATH"); FAIL(no_mandatory); }
/* When receiving attributes from non-AS4-aware BGP speaker, we have to
reconstruct AS_PATH and AGGREGATOR attributes; RFC 6793 4.2.3 */
@ -1116,19 +1118,19 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
/* Reject routes with our ASN in AS_PATH attribute */
if (bgp_as_path_loopy(p, attrs, p->local_as))
goto withdraw;
FAIL(loopy);
/* Reject routes with our Confederation ID in AS_PATH attribute; RFC 5065 4.0 */
if ((p->public_as != p->local_as) && bgp_as_path_loopy(p, attrs, p->public_as))
goto withdraw;
FAIL(loopy);
/* Reject routes with our Router ID in ORIGINATOR_ID attribute; RFC 4456 8 */
if (p->is_internal && bgp_originator_id_loopy(p, attrs))
goto withdraw;
FAIL(loopy);
/* Reject routes with our Cluster ID in CLUSTER_LIST attribute; RFC 4456 8 */
if (p->rr_client && bgp_cluster_list_loopy(p, attrs))
goto withdraw;
FAIL(loopy);
/* If there is no local preference, define one */
if (!BIT32_TEST(s->attrs_seen, BA_LOCAL_PREF))
@ -1141,8 +1143,11 @@ framing_error:
/* RFC 7606 4 - handle attribute framing errors */
REPORT("Malformed attribute list - framing error (%u/%u) at %d",
alen, len, (int) (pos - s->attrs));
FAIL(bad_alist);
withdraw:
#undef FAIL
fail:
/* RFC 7606 5.2 - handle missing NLRI during errors */
if (!s->ip_reach_len && !s->mp_reach_len)
bgp_parse_error(s, 1);

View File

@ -1328,6 +1328,8 @@ bgp_start(struct proto *P)
p->source_addr = p->cf->local_ip;
p->link_addr = IPA_NONE;
memset(&(p->stats), 0, sizeof(struct bgp_stats));
/* Lock all channels when in GR recovery mode */
if (p->p.gr_recovery && p->cf->gr_mode)
{
@ -2104,6 +2106,15 @@ bgp_show_proto_info(struct proto *P)
tm_remains(p->conn->keepalive_timer), p->conn->keepalive_time);
}
struct bgp_stats *s = &p->stats;
cli_msg(-1006, " Statistics:");
cli_msg(-1006, " rx-open %u rx-update %u rx-notify %u rx-keepalive %u rx-refresh %u",
s->rx_pkts[0], s->rx_pkts[1], s->rx_pkts[2], s->rx_pkts[3], s->rx_pkts[4]);
cli_msg(-1006, " tx-open %u tx-update %u tx-notify %u tx-keepalive %u tx-refresh %u",
s->tx_pkts[0], s->tx_pkts[1], s->tx_pkts[2], s->tx_pkts[3], s->tx_pkts[4]);
cli_msg(-1006, " bad-alist %u bad-attribute %u bad-next-hop %u no-mandatory %u loopy %u",
s->bad_alist, s->bad_attribute, s->bad_next_hop, s->no_mandatory, s->loopy);
if ((p->last_error_class != BE_NONE) &&
(p->last_error_class != BE_MAN_DOWN))
{
@ -2120,6 +2131,9 @@ bgp_show_proto_info(struct proto *P)
if (c->c.channel_state == CS_UP)
{
cli_msg(-1006, " Enqueued updates: %u", c->bucket_hash.count);
cli_msg(-1006, " Enqueued prefixes: %u", c->prefix_hash.count);
if (ipa_zero(c->link_addr))
cli_msg(-1006, " BGP Next hop: %I", c->next_hop_addr);
else

View File

@ -55,6 +55,8 @@ struct eattr;
#define BGP_AF_FLOW4 BGP_AF( BGP_AFI_IPV4, BGP_SAFI_FLOW )
#define BGP_AF_FLOW6 BGP_AF( BGP_AFI_IPV6, BGP_SAFI_FLOW )
#define BGP_PKT_TYPES 5 /* PKT_OPEN .. PKT_ROUTE_REFRESH */
struct bgp_write_state;
struct bgp_parse_state;
@ -196,6 +198,14 @@ struct bgp_caps {
#define WALK_AF_CAPS(caps,ac) \
for (ac = caps->af_data; ac < &caps->af_data[caps->af_count]; ac++)
struct bgp_stats {
uint rx_pkts[BGP_PKT_TYPES], tx_pkts[BGP_PKT_TYPES];
uint bad_alist, bad_attribute, bad_next_hop, no_mandatory, loopy;
};
#ifndef PARSER
#define STATS(KEY) ({ p->stats.KEY++; })
#endif
struct bgp_socket {
node n; /* Node in global bgp_sockets */
@ -254,6 +264,7 @@ struct bgp_proto {
struct neighbor *neigh; /* Neighbor entry corresponding to remote ip, NULL if multihop */
struct bgp_socket *sock; /* Shared listening socket */
struct bfd_request *bfd_req; /* BFD request, if BFD is used */
struct bgp_stats stats; /* Packet statistics */
ip_addr source_addr; /* Local address used as an advertised next hop */
ip_addr link_addr; /* Link-local version of source_addr */
event *event; /* Event for respawning and shutting process */

View File

@ -2174,6 +2174,7 @@ bgp_rx_end_mark(struct bgp_parse_state *s, u32 afi)
static inline void
bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_list *ea, byte *nh, uint nh_len)
{
struct bgp_proto *p = s->proto;
struct bgp_channel *c = bgp_get_channel(s->proto, afi);
rta *a = NULL;
@ -2207,7 +2208,10 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis
/* Handle withdraw during next hop decoding */
if (s->err_withdraw)
{
STATS(bad_next_hop);
a = NULL;
}
}
c->desc->decode_nlri(s, nlri, len, a);
@ -2446,6 +2450,7 @@ found:
static inline int
bgp_send(struct bgp_conn *conn, uint type, uint len)
{
struct bgp_proto *p = conn->bgp;
sock *sk = conn->sk;
byte *buf = sk->tbuf;
@ -2453,6 +2458,7 @@ bgp_send(struct bgp_conn *conn, uint type, uint len)
put_u16(buf+16, len);
buf[18] = type;
STATS(tx_pkts[type - 1]);
return sk_send(sk, len);
}
@ -2812,13 +2818,22 @@ bgp_rx_keepalive(struct bgp_conn *conn)
static void
bgp_rx_packet(struct bgp_conn *conn, byte *pkt, uint len)
{
struct bgp_proto *p = conn->bgp;
byte type = pkt[18];
DBG("BGP: Got packet %02x (%d bytes)\n", type, len);
if (conn->bgp->p.mrtdump & MD_MESSAGES)
if (p->p.mrtdump & MD_MESSAGES)
mrt_dump_bgp_packet(conn, pkt, len);
if (type < PKT_OPEN || type > PKT_ROUTE_REFRESH)
{
bgp_error(conn, 1, 3, pkt+18, 1);
return;
}
STATS(rx_pkts[type - 1]);
switch (type)
{
case PKT_OPEN: return bgp_rx_open(conn, pkt, len);
@ -2826,7 +2841,6 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, uint len)
case PKT_NOTIFICATION: return bgp_rx_notification(conn, pkt, len);
case PKT_KEEPALIVE: return bgp_rx_keepalive(conn);
case PKT_ROUTE_REFRESH: return bgp_rx_route_refresh(conn, pkt, len);
default: bgp_error(conn, 1, 3, pkt+18, 1);
}
}