diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 2a64958a..83105a68 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -545,6 +545,8 @@ bgp_conn_enter_established_state(struct bgp_conn *conn) struct bgp_channel *c; BGP_TRACE(D_EVENTS, "BGP session established"); + p->last_established = current_time(); + p->stats.fsm_established_transitions++; /* For multi-hop BGP sessions */ if (ipa_zero(p->local_ip)) @@ -685,6 +687,7 @@ static void bgp_conn_leave_established_state(struct bgp_proto *p) { BGP_TRACE(D_EVENTS, "BGP session closed"); + p->last_established = current_time(); p->conn = NULL; if (p->p.proto_state == PS_UP) @@ -1520,6 +1523,12 @@ bgp_start(struct proto *P) p->gr_ready = 0; p->gr_active_num = 0; + /* Reset some stats */ + p->stats.rx_messages = p->stats.tx_messages = 0; + p->stats.rx_updates = p->stats.tx_updates = 0; + p->stats.rx_bytes = p->stats.tx_bytes = 0; + p->last_rx_update = 0; + p->event = ev_new_init(p->p.pool, bgp_decision, p); p->startup_timer = tm_new_init(p->p.pool, bgp_startup_timeout, p, 0, 0); p->gr_timer = tm_new_init(p->p.pool, bgp_graceful_restart_timeout, p, 0, 0); @@ -2448,6 +2457,16 @@ 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, " FSM established transitions: %u", + s->fsm_established_transitions); + cli_msg(-1006, " Rcvd messages: %u total / %u updates / %lu bytes", + s->rx_messages, s->rx_updates, s->rx_bytes); + cli_msg(-1006, " Sent messages: %u total / %u updates / %lu bytes", + s->tx_messages, s->tx_updates, s->tx_bytes); + cli_msg(-1006, " Last rcvd update elapsed time: %t s", + p->last_rx_update ? (current_time() - p->last_rx_update) : 0); + if ((p->last_error_class != BE_NONE) && (p->last_error_class != BE_MAN_DOWN)) { diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index d336132b..03b92bd8 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -245,6 +245,14 @@ struct bgp_socket { u32 uc; /* Use count */ }; +struct bgp_stats { + uint rx_messages, tx_messages; + uint rx_updates, tx_updates; + u64 rx_bytes, tx_bytes; + + uint fsm_established_transitions; +}; + struct bgp_conn { struct bgp_proto *bgp; struct birdsock *sk; @@ -303,6 +311,9 @@ struct bgp_proto { struct bgp_socket *sock; /* Shared listening socket */ struct bfd_request *bfd_req; /* BFD request, if BFD is used */ struct birdsock *postponed_sk; /* Postponed incoming socket for dynamic BGP */ + struct bgp_stats stats; /* BGP statistics */ + btime last_established; /* Last time of enter/leave of established state */ + btime last_rx_update; /* Last time of RX update */ ip_addr link_addr; /* Link-local version of local_ip */ event *event; /* Event for respawning and shutting process */ timer *startup_timer; /* Timer used to delay protocol startup due to previous errors (startup_delay) */ diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 0bc63c55..ed878e41 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -2300,6 +2300,7 @@ again: ; done: BGP_TRACE_RL(&rl_snd_update, D_PACKETS, "Sending UPDATE"); + p->stats.tx_updates++; lp_flush(s.pool); return res; @@ -2335,6 +2336,7 @@ bgp_create_end_mark(struct bgp_channel *c, byte *buf) struct bgp_proto *p = (void *) c->c.proto; BGP_TRACE(D_PACKETS, "Sending END-OF-RIB"); + p->stats.tx_updates++; return (c->afi == BGP_AF_IPV4) ? bgp_create_ip_end_mark(c, buf): @@ -2415,6 +2417,8 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len) ea_list *ea = NULL; BGP_TRACE_RL(&rl_rcv_update, D_PACKETS, "Got UPDATE"); + p->last_rx_update = current_time(); + p->stats.rx_updates++; /* Workaround for some BGP implementations that skip initial KEEPALIVE */ if (conn->state == BS_OPENCONFIRM) @@ -2702,6 +2706,9 @@ bgp_send(struct bgp_conn *conn, uint type, uint len) sock *sk = conn->sk; byte *buf = sk->tbuf; + conn->bgp->stats.tx_messages++; + conn->bgp->stats.tx_bytes += len; + memset(buf, 0xff, 16); /* Marker */ put_u16(buf+16, len); buf[18] = type; @@ -3075,6 +3082,8 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, uint len) byte type = pkt[18]; DBG("BGP: Got packet %02x (%d bytes)\n", type, len); + conn->bgp->stats.rx_messages++; + conn->bgp->stats.rx_bytes += len; if (conn->bgp->p.mrtdump & MD_MESSAGES) bgp_dump_message(conn, pkt, len);