Skip to content

Commit

Permalink
Merge pull request #14333 from fdumontet6WIND/bgp4v2_snmp
Browse files Browse the repository at this point in the history
bgpd: add support of traps for bgp4-mibv2
  • Loading branch information
ton31337 authored Oct 24, 2023
2 parents b6b0001 + ccef545 commit 26373fb
Show file tree
Hide file tree
Showing 16 changed files with 395 additions and 23 deletions.
85 changes: 85 additions & 0 deletions bgpd/bgp_snmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,93 @@
#include "bgpd/bgp_snmp_bgp4.h"
#include "bgpd/bgp_snmp_bgp4v2.h"
#include "bgpd/bgp_mplsvpn_snmp.h"
#include "bgpd/bgp_snmp_clippy.c"



static int bgp_cli_snmp_traps_config_write(struct vty *vty);

DEFPY(bgp_snmp_traps_rfc4273, bgp_snmp_traps_rfc4273_cmd,
"[no$no] bgp snmp traps rfc4273",
NO_STR BGP_STR
"Configure BGP SNMP\n"
"Configure SNMP traps for BGP\n"
"Configure use of rfc4273 SNMP traps for BGP\n")
{
if (no) {
UNSET_FLAG(bm->options, BGP_OPT_TRAPS_RFC4273);
return CMD_SUCCESS;
}
SET_FLAG(bm->options, BGP_OPT_TRAPS_RFC4273);
return CMD_SUCCESS;
}

DEFPY(bgp_snmp_traps_bgp4_mibv2, bgp_snmp_traps_bgp4_mibv2_cmd,
"[no$no] bgp snmp traps bgp4-mibv2",
NO_STR BGP_STR
"Configure BGP SNMP\n"
"Configure SNMP traps for BGP\n"
"Configure use of BGP4-MIBv2 SNMP traps for BGP\n")
{
if (no) {
UNSET_FLAG(bm->options, BGP_OPT_TRAPS_BGP4MIBV2);
return CMD_SUCCESS;
}
SET_FLAG(bm->options, BGP_OPT_TRAPS_BGP4MIBV2);
return CMD_SUCCESS;
}

static void bgp_snmp_traps_init(void)
{
install_element(CONFIG_NODE, &bgp_snmp_traps_rfc4273_cmd);
install_element(CONFIG_NODE, &bgp_snmp_traps_bgp4_mibv2_cmd);

SET_FLAG(bm->options, BGP_OPT_TRAPS_RFC4273);
/* BGP4MIBv2 traps are disabled by default */
}

int bgp_cli_snmp_traps_config_write(struct vty *vty)
{
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)
{
if (CHECK_FLAG(bm->options, BGP_OPT_TRAPS_RFC4273))
bgp4TrapEstablished(peer);

if (CHECK_FLAG(bm->options, BGP_OPT_TRAPS_BGP4MIBV2))
bgpv2TrapEstablished(peer);

return 0;
}

int bgpTrapBackwardTransition(struct peer *peer)
{
if (CHECK_FLAG(bm->options, BGP_OPT_TRAPS_RFC4273))
bgp4TrapBackwardTransition(peer);

if (CHECK_FLAG(bm->options, BGP_OPT_TRAPS_BGP4MIBV2))
bgpv2TrapBackwardTransition(peer);

return 0;
}

static int bgp_snmp_init(struct event_loop *tm)
{
smux_init(tm);
bgp_snmp_traps_init();
bgp_snmp_bgp4_init(tm);
bgp_snmp_bgp4v2_init(tm);
bgp_mpls_l3vpn_module_init();
Expand All @@ -44,6 +127,8 @@ static int bgp_snmp_module_init(void)
hook_register(peer_status_changed, bgpTrapEstablished);
hook_register(peer_backward_transition, bgpTrapBackwardTransition);
hook_register(frr_late_init, bgp_snmp_init);
hook_register(bgp_snmp_traps_config_write,
bgp_cli_snmp_traps_config_write);
return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions bgpd/bgp_snmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@
#define IPADDRESS ASN_IPADDRESS
#define GAUGE32 ASN_UNSIGNED

extern int bgpTrapEstablished(struct peer *peer);
extern int bgpTrapBackwardTransition(struct peer *peer);

#endif /* _FRR_BGP_SNMP_H_ */
4 changes: 2 additions & 2 deletions bgpd/bgp_snmp_bgp4.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -782,7 +782,7 @@ int bgpTrapEstablished(struct peer *peer)
return 0;
}

int bgpTrapBackwardTransition(struct peer *peer)
int bgp4TrapBackwardTransition(struct peer *peer)
{
int ret;
struct in_addr addr;
Expand Down
4 changes: 2 additions & 2 deletions bgpd/bgp_snmp_bgp4.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */
105 changes: 105 additions & 0 deletions bgpd/bgp_snmp_bgp4v2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -793,6 +794,37 @@ 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,
Expand Down Expand Up @@ -1412,6 +1444,79 @@ 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;

if (!CHECK_FLAG(bm->options, BGP_OPT_TRAPS_BGP4MIBV2))
return 0;

/* 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:
break;
}

return 0;
}

int bgpv2TrapBackwardTransition(struct peer *peer)
{
oid index[sizeof(oid) * IN6_ADDR_SIZE];
size_t length;

if (!CHECK_FLAG(bm->options, BGP_OPT_TRAPS_BGP4MIBV2))
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,
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:
break;
}

return 0;
}

int bgp_snmp_bgp4v2_init(struct event_loop *tm)
{
REGISTER_MIB("mibII/bgpv2", bgpv2_variables, variable, bgpv2_oid);
Expand Down
10 changes: 10 additions & 0 deletions bgpd/bgp_snmp_bgp4v2.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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_ */
3 changes: 3 additions & 0 deletions bgpd/bgp_vty.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ DEFINE_HOOK(bgp_inst_config_write,
(bgp, vty));
DEFINE_HOOK(bgp_snmp_update_last_changed, (struct bgp *bgp), (bgp));
DEFINE_HOOK(bgp_snmp_init_stats, (struct bgp *bgp), (bgp));
DEFINE_HOOK(bgp_snmp_traps_config_write, (struct vty * vty), (vty));

static struct peer_group *listen_range_exists(struct bgp *bgp,
struct prefix *range, int exact);
Expand Down Expand Up @@ -18506,6 +18507,8 @@ int bgp_config_write(struct vty *vty)
safi_t safi;
uint32_t tovpn_sid_index = 0;

hook_call(bgp_snmp_traps_config_write, vty);

if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
vty_out(vty, "bgp route-map delay-timer %u\n",
bm->rmap_update_timer);
Expand Down
3 changes: 3 additions & 0 deletions bgpd/bgpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ struct bgp_master {
#define BGP_OPT_NO_FIB (1 << 0)
#define BGP_OPT_NO_LISTEN (1 << 1)
#define BGP_OPT_NO_ZEBRA (1 << 2)
#define BGP_OPT_TRAPS_RFC4273 (1 << 3)
#define BGP_OPT_TRAPS_BGP4MIBV2 (1 << 4)

uint64_t updgrp_idspace;
uint64_t subgrp_idspace;
Expand Down Expand Up @@ -832,6 +834,7 @@ DECLARE_HOOK(bgp_inst_delete, (struct bgp *bgp), (bgp));
DECLARE_HOOK(bgp_inst_config_write,
(struct bgp *bgp, struct vty *vty),
(bgp, vty));
DECLARE_HOOK(bgp_snmp_traps_config_write, (struct vty *vty), (vty));
DECLARE_HOOK(bgp_config_end, (struct bgp *bgp), (bgp));

/* Thread callback information */
Expand Down
1 change: 1 addition & 0 deletions bgpd/subdir.am
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ clippy_scan += \
bgpd/bgp_rpki.c \
bgpd/bgp_vty.c \
bgpd/bgp_nexthop.c \
bgpd/bgp_snmp.c \
# end

nodist_bgpd_bgpd_SOURCES = \
Expand Down
20 changes: 18 additions & 2 deletions doc/user/snmptrap.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ Handling SNMP Traps
To handle snmp traps make sure your snmp setup of frr works correctly as
described in the frr documentation in :ref:`snmp-support`.

The BGP4 mib will send traps on peer up/down events. These should be visible in
your snmp logs with a message similar to:
BGP handles both :rfc:`4273` and [Draft-IETF-idr-bgp4-mibv2-11]_ MIBs.
The BGP4 MIBs will send traps on peer up/down events. These should be
visible in your snmp logs with a message similar to:

::

Expand Down Expand Up @@ -199,3 +200,18 @@ a siren, have your display flash, etc., be creative ;).
# mail the notification
echo "$MAIL" | mail -s "$SUBJECT" $EMAILADDR
.. _traps-mib-selection:
Traps Mib Selection in BGP
--------------------------
Both :rfc:`4273` and [Draft-IETF-idr-bgp4-mibv2-11]_ MIBs define traps for
dealing with up/down events and state transition. The user has the
possibility to select the MIB he wants to receive traps from:
.. clicmd:: bgp snmp traps <rfc4273|bgp4-mibv2>
By default, only rfc4273 traps are enabled and sent.
.. [Draft-IETF-idr-bgp4-mibv2-11] <https://tools.ietf.org/id/draft-ietf-idr-bgp4-mibv2-11.txt>
9 changes: 9 additions & 0 deletions tests/topotests/bgp_snmp_bgp4v2mib/r2/snmpd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ access public_group "" any noauth prefix all all none

rocommunity public default

trapsess -v2c -c public 127.0.0.1

notificationEvent linkUpTrap linkUp ifIndex ifAdminStatus ifOperStatus
notificationEvent linkDownTrap linkDown ifIndex ifAdminStatus ifOperStatus

monitor -r 2 -e linkUpTrap "Generate linkUp" ifOperStatus != 2
monitor -r 2 -e linkDownTrap "Generate linkDown" ifOperStatus == 2


view all included .1

iquerySecName frr
Expand Down
2 changes: 2 additions & 0 deletions tests/topotests/bgp_snmp_bgp4v2mib/r2/snmptrapd.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
authCommunity net,log public
disableAuthorization yes
Loading

0 comments on commit 26373fb

Please sign in to comment.