From d78854f438e0b46ceec2b8dde1e168e4b6072f08 Mon Sep 17 00:00:00 2001 From: Francois Dumontet Date: Wed, 23 Aug 2023 10:34:13 +0200 Subject: [PATCH] bgpd: add snmp traps for bgp4-mibv2 This commit add the support of traps for bgp4-mibv2. It is conformant to draft-ietf-idr-bgp4-mibv2-11. The following traps are supported: - bgp4V2EstablishedNotification - bgp4V2BackwardTransitionNotification Signed-off-by: Francois Dumontet --- bgpd/bgp_snmp.c | 28 +++++++++-- bgpd/bgp_snmp.h | 3 ++ bgpd/bgp_snmp_bgp4.c | 4 +- bgpd/bgp_snmp_bgp4.h | 4 +- bgpd/bgp_snmp_bgp4v2.c | 103 +++++++++++++++++++++++++++++++++++++++++ bgpd/bgp_snmp_bgp4v2.h | 10 ++++ 6 files changed, 145 insertions(+), 7 deletions(-) diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c index 0d26b5c64c..22495ca0ac 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -59,9 +59,31 @@ static void bgp_snmp_traps_init(void) int bgp_cli_snmp_traps_config_write(struct vty *vty) { - if (CHECK_FLAG(bgp_snmp_traps_flags, BGP_SNMP_TRAPS_RFC4273_ENABLED)) - return 0; - vty_out(vty, "traps rfc4273 disable\n"); + int write = 0; + + if (!CHECK_FLAG(bm->options, BGP_OPT_TRAPS_RFC4273)) { + vty_out(vty, "no bgp snmp traps rfc4273\n"); + write++; + } + if (CHECK_FLAG(bm->options, BGP_OPT_TRAPS_BGP4MIBV2)) { + vty_out(vty, "bgp snmp traps bgp4-mibv2\n"); + write++; + } + + return write; +} + +int bgpTrapEstablished(struct peer *peer) +{ + bgp4TrapEstablished(peer); + bgpv2TrapEstablished(peer); + return 0; +} + +int bgpTrapBackwardTransition(struct peer *peer) +{ + bgp4TrapBackwardTransition(peer); + bgpv2TrapBackwardTransition(peer); return 0; } diff --git a/bgpd/bgp_snmp.h b/bgpd/bgp_snmp.h index 36ee4d6162..642352d853 100644 --- a/bgpd/bgp_snmp.h +++ b/bgpd/bgp_snmp.h @@ -19,4 +19,7 @@ extern uint32_t bgp_snmp_traps_flags; #define BGP_SNMP_TRAPS_RFC4273_ENABLED (1 << 0) +extern int bgpTrapEstablished(struct peer *peer); +extern int bgpTrapBackwardTransition(struct peer *peer); + #endif /* _FRR_BGP_SNMP_H_ */ diff --git a/bgpd/bgp_snmp_bgp4.c b/bgpd/bgp_snmp_bgp4.c index 6da16057d1..d1dcb0eb93 100644 --- a/bgpd/bgp_snmp_bgp4.c +++ b/bgpd/bgp_snmp_bgp4.c @@ -757,7 +757,7 @@ static struct variable bgp_variables[] = { {6, 1, 14}}, }; -int bgpTrapEstablished(struct peer *peer) +int bgp4TrapEstablished(struct peer *peer) { int ret; struct in_addr addr; @@ -785,7 +785,7 @@ int bgpTrapEstablished(struct peer *peer) return 0; } -int bgpTrapBackwardTransition(struct peer *peer) +int bgp4TrapBackwardTransition(struct peer *peer) { int ret; struct in_addr addr; diff --git a/bgpd/bgp_snmp_bgp4.h b/bgpd/bgp_snmp_bgp4.h index ccf00d6b7c..67f7cc640b 100644 --- a/bgpd/bgp_snmp_bgp4.h +++ b/bgpd/bgp_snmp_bgp4.h @@ -69,8 +69,8 @@ #define BGP4PATHATTRBEST 13 #define BGP4PATHATTRUNKNOWN 14 -extern int bgpTrapEstablished(struct peer *peer); -extern int bgpTrapBackwardTransition(struct peer *peer); +extern int bgp4TrapEstablished(struct peer *peer); +extern int bgp4TrapBackwardTransition(struct peer *peer); extern int bgp_snmp_bgp4_init(struct event_loop *tm); #endif /* _FRR_BGP_SNMP_BGP4_H_ */ diff --git a/bgpd/bgp_snmp_bgp4v2.c b/bgpd/bgp_snmp_bgp4v2.c index fb6f13a6ca..768cd3a039 100644 --- a/bgpd/bgp_snmp_bgp4v2.c +++ b/bgpd/bgp_snmp_bgp4v2.c @@ -32,6 +32,7 @@ SNMP_LOCAL_VARIABLES static oid bgpv2_oid[] = {BGP4V2MIB}; +static oid bgpv2_trap_oid[] = { BGP4V2MIB, 0 }; static struct in_addr bgp_empty_addr = {}; static struct peer *peer_lookup_all_vrf(struct ipaddr *addr) @@ -793,6 +794,38 @@ static uint8_t *bgp4v2PathAttrTable(struct variable *v, oid name[], return NULL; } +/* BGP V2 Traps. */ +static struct trap_object bgpv2TrapEstListv4[] = { + { 6, { 1, 2, 1, BGP4V2_PEER_STATE, 1, 1 } }, + { 6, { 1, 2, 1, BGP4V2_PEER_LOCAL_PORT, 1, 1 } }, + { 6, { 1, 2, 1, BGP4V2_PEER_REMOTE_PORT, 1, 1 } } +}; + +static struct trap_object bgpv2TrapEstListv6[] = { + { 6, { 1, 2, 1, BGP4V2_PEER_STATE, 1, 2 } }, + { 6, { 1, 2, 1, BGP4V2_PEER_LOCAL_PORT, 1, 2 } }, + { 6, { 1, 2, 1, BGP4V2_PEER_REMOTE_PORT, 1, 2 } } +}; + +static struct trap_object bgpv2TrapBackListv4[] = { + { 6, { 1, 2, 1, BGP4V2_PEER_STATE, 1, 1 } }, + { 6, { 1, 2, 1, BGP4V2_PEER_LOCAL_PORT, 1, 1 } }, + { 6, { 1, 2, 1, BGP4V2_PEER_REMOTE_PORT, 1, 1 } }, + { 6, { 1, 3, 1, BGP4V2_PEER_LAST_ERROR_CODE_RECEIVED, 1, 1 } }, + { 6, { 1, 3, 1, BGP4V2_PEER_LAST_ERROR_SUBCODE_RECEIVED, 1, 1 } }, + { 6, { 1, 3, 1, BGP4V2_PEER_LAST_ERROR_RECEIVED_TEXT, 1, 1 } } +}; + +static struct trap_object bgpv2TrapBackListv6[] = { + { 6, { 1, 2, 1, BGP4V2_PEER_STATE, 1, 2 } }, + { 6, { 1, 2, 1, BGP4V2_PEER_LOCAL_PORT, 1, 2 } }, + { 6, { 1, 2, 1, BGP4V2_PEER_REMOTE_PORT, 1, 2 } }, + { 6, { 1, 3, 1, BGP4V2_PEER_LAST_ERROR_CODE_RECEIVED, 1, 2 } }, + { 6, { 1, 3, 1, BGP4V2_PEER_LAST_ERROR_SUBCODE_RECEIVED, 1, 2 } }, + { 6, { 1, 3, 1, BGP4V2_PEER_LAST_ERROR_RECEIVED_TEXT, 1, 2 } } +}; + + static struct variable bgpv2_variables[] = { /* bgp4V2PeerEntry */ {BGP4V2_PEER_INSTANCE, @@ -1412,6 +1445,76 @@ static struct variable bgpv2_variables[] = { {1, 9, 1, BGP4V2_NLRI_PATH_ATTR_UNKNOWN, 1, 2}}, }; +int bgpv2TrapEstablished(struct peer *peer) +{ + oid index[sizeof(oid) * IN6_ADDR_SIZE]; + size_t length; + + /* Check if this peer just went to Established */ + if ((peer->connection->ostatus != OpenConfirm) || + !(peer_established(peer->connection))) + return 0; + + switch (sockunion_family(&peer->connection->su)) { + case AF_INET: + oid_copy_in_addr(index, &peer->connection->su.sin.sin_addr); + length = IN_ADDR_SIZE; + smux_trap(bgpv2_variables, array_size(bgpv2_variables), + bgpv2_trap_oid, array_size(bgpv2_trap_oid), bgpv2_oid, + sizeof(bgpv2_oid) / sizeof(oid), index, length, + bgpv2TrapEstListv4, array_size(bgpv2TrapEstListv4), + BGP4V2ESTABLISHED); + break; + case AF_INET6: + oid_copy_in6_addr(index, &peer->connection->su.sin6.sin6_addr); + length = IN6_ADDR_SIZE; + smux_trap(bgpv2_variables, array_size(bgpv2_variables), + bgpv2_trap_oid, array_size(bgpv2_trap_oid), bgpv2_oid, + sizeof(bgpv2_oid) / sizeof(oid), index, length, + bgpv2TrapEstListv6, array_size(bgpv2TrapEstListv6), + BGP4V2ESTABLISHED); + break; + default: + return 0; + ; + } + + return 0; +} + +int bgpv2TrapBackwardTransition(struct peer *peer) +{ + oid index[sizeof(oid) * IN6_ADDR_SIZE]; + size_t length; + + switch (sockunion_family(&peer->connection->su)) { + case AF_INET: + oid_copy_in_addr(index, &peer->connection->su.sin.sin_addr); + length = IN_ADDR_SIZE; + smux_trap(bgpv2_variables, array_size(bgpv2_variables), + bgpv2_trap_oid, array_size(bgpv2_trap_oid), bgpv2_oid, + sizeof(bgpv2_oid) / sizeof(oid), index, length, + bgpv2TrapBackListv4, array_size(bgpv2TrapBackListv4), + BGP4V2BACKWARDTRANSITION); + break; + case AF_INET6: + oid_copy_in6_addr(index, &peer->connection->su.sin6.sin6_addr); + length = IN6_ADDR_SIZE; + smux_trap(bgpv2_variables, array_size(bgpv2_variables), + bgpv2_trap_oid, array_size(bgpv2_trap_oid), bgpv2_oid, + sizeof(bgpv2_oid) / sizeof(oid), index, length, + bgpv2TrapBackListv6, array_size(bgpv2TrapBackListv6), + BGP4V2BACKWARDTRANSITION); + break; + default: + return 0; + ; + } + + return 0; +} + + int bgp_snmp_bgp4v2_init(struct event_loop *tm) { REGISTER_MIB("mibII/bgpv2", bgpv2_variables, variable, bgpv2_oid); diff --git a/bgpd/bgp_snmp_bgp4v2.h b/bgpd/bgp_snmp_bgp4v2.h index 6587a825c5..ca355338a6 100644 --- a/bgpd/bgp_snmp_bgp4v2.h +++ b/bgpd/bgp_snmp_bgp4v2.h @@ -16,6 +16,14 @@ * offset 1.3.6.1.3.5.1.1.2.1.x.(1|2).(4|16) = 13 * offset 1.3.6.1.4.1.7336.3.2.1.1.2.1.x.1.(1|2) = 16 */ + + +/* bgpTraps */ +#define BGP4V2ESTABLISHED 1 +#define BGP4V2BACKWARDTRANSITION 2 + +/* bgpPeerTable */ + #define BGP4V2_PEER_ENTRY_OFFSET 13 #define BGP4V2_PEER_INSTANCE 1 #define BGP4V2_PEER_LOCAL_ADDR_TYPE 2 @@ -84,5 +92,7 @@ #define BGP4V2_BACKWARD_TRANSITION_NOTIFICATION 2 extern int bgp_snmp_bgp4v2_init(struct event_loop *tm); +extern int bgpv2TrapEstablished(struct peer *peer); +extern int bgpv2TrapBackwardTransition(struct peer *peer); #endif /* _FRR_BGP_SNMP_BGP4V2_H_ */