Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bgpd: add support of traps for bgp4-mibv2 #14333

Merged
merged 8 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"

ton31337 marked this conversation as resolved.
Show resolved Hide resolved


static int bgp_cli_snmp_traps_config_write(struct vty *vty);

ton31337 marked this conversation as resolved.
Show resolved Hide resolved
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");
ton31337 marked this conversation as resolved.
Show resolved Hide resolved
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);

ton31337 marked this conversation as resolved.
Show resolved Hide resolved
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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why even have a return value for this function? And the following one? I don't ever see anything but a return of 0? What is the goal here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only coherency with previously existing function
int bgp4TrapEstablished(struct peer *peer)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

void?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have already
int bgp4TrapEstablished(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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

void?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have already
int bgp4TrapBackwardTransition(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 @@ -18477,6 +18478,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
Loading