mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-03-11 17:08:46 +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:
parent
80a4c23b1e
commit
8972a08fab
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user