forked from Mirror/frr
bgpd, lib: add mplsL3VpnVrf table
Add SNMP support for L3vpn Vrf table as defined in [RFC4382] Keep track of vrf status for the table and for future traps. Signed-off-by: Pat Ruddy <pat@voltanet.io>
This commit is contained in:
parent
aa53f69348
commit
0d020cd6d9
|
@ -41,8 +41,6 @@
|
|||
#define BGP_mplsvpn_notif_enable_true 1
|
||||
#define BGP_mplsvpn_notif_enable_false 2
|
||||
|
||||
static uint8_t bgp_mplsvpn_notif_enable = SNMP_FALSE;
|
||||
|
||||
/* MPLSL3VPN MIB described in RFC4382 */
|
||||
#define MPLSL3VPNMIB 1, 3, 6, 1, 2, 1, 10, 166, 11
|
||||
|
||||
|
@ -55,6 +53,22 @@ static uint8_t bgp_mplsvpn_notif_enable = SNMP_FALSE;
|
|||
#define MPLSL3VPNVRFCONFRTEMXTHRSHTIME 6
|
||||
#define MPLSL3VPNILLLBLRCVTHRSH 7
|
||||
|
||||
/* MPLSL3VPN VRF Table */
|
||||
#define MPLSL3VPNVRFVPNID 1
|
||||
#define MPLSL3VPNVRFDESC 2
|
||||
#define MPLSL3VPNVRFRD 3
|
||||
#define MPLSL3VPNVRFCREATIONTIME 4
|
||||
#define MPLSL3VPNVRFOPERSTATUS 5
|
||||
#define MPLSL3VPNVRFACTIVEINTERFACES 6
|
||||
#define MPLSL3VPNVRFASSOCIATEDINTERFACES 7
|
||||
#define MPLSL3VPNVRFCONFMIDRTETHRESH 8
|
||||
#define MPLSL3VPNVRFCONFHIGHRTETHRSH 9
|
||||
#define MPLSL3VPNVRFCONFMAXROUTES 10
|
||||
#define MPLSL3VPNVRFCONFLASTCHANGED 11
|
||||
#define MPLSL3VPNVRFCONFROWSTATUS 12
|
||||
#define MPLSL3VPNVRFCONFADMINSTATUS 13
|
||||
#define MPLSL3VPNVRFCONFSTORAGETYPE 14
|
||||
|
||||
/* SNMP value hack. */
|
||||
#define INTEGER ASN_INTEGER
|
||||
#define INTEGER32 ASN_INTEGER
|
||||
|
@ -62,12 +76,15 @@ static uint8_t bgp_mplsvpn_notif_enable = SNMP_FALSE;
|
|||
#define OCTET_STRING ASN_OCTET_STR
|
||||
#define IPADDRESS ASN_IPADDRESS
|
||||
#define GAUGE32 ASN_UNSIGNED
|
||||
#define TIMETICKS ASN_TIMETICKS
|
||||
|
||||
/* Declare static local variables for convenience. */
|
||||
SNMP_LOCAL_VARIABLES
|
||||
|
||||
/* BGP-MPLS-MIB innstances */
|
||||
static oid mpls_l3vpn_oid[] = {MPLSL3VPNMIB};
|
||||
static char rd_buf[RD_ADDRSTRLEN];
|
||||
static uint8_t bgp_mplsvpn_notif_enable = SNMP_FALSE;
|
||||
|
||||
static uint8_t *mplsL3vpnConfiguredVrfs(struct variable *, oid[], size_t *, int,
|
||||
size_t *, WriteMethod **);
|
||||
|
@ -91,6 +108,10 @@ static uint8_t *mplsL3vpnVrfConfRteMxThrshTime(struct variable *, oid[],
|
|||
static uint8_t *mplsL3vpnIllLblRcvThrsh(struct variable *, oid[], size_t *, int,
|
||||
size_t *, WriteMethod **);
|
||||
|
||||
static uint8_t *mplsL3vpnVrfTable(struct variable *, oid[], size_t *, int,
|
||||
size_t *, WriteMethod **);
|
||||
|
||||
|
||||
static struct variable mpls_l3vpn_variables[] = {
|
||||
/* BGP version. */
|
||||
{MPLSL3VPNCONFIGUREDVRFS,
|
||||
|
@ -136,8 +157,168 @@ static struct variable mpls_l3vpn_variables[] = {
|
|||
3,
|
||||
{1, 1, 7} },
|
||||
|
||||
/* Vrf Table */
|
||||
{MPLSL3VPNVRFVPNID,
|
||||
OCTET_STRING,
|
||||
RONLY,
|
||||
mplsL3vpnVrfTable,
|
||||
5,
|
||||
{1, 2, 2, 1, 2} },
|
||||
{MPLSL3VPNVRFDESC,
|
||||
OCTET_STRING,
|
||||
RONLY,
|
||||
mplsL3vpnVrfTable,
|
||||
5,
|
||||
{1, 2, 2, 1, 3} },
|
||||
{MPLSL3VPNVRFRD,
|
||||
OCTET_STRING,
|
||||
RONLY,
|
||||
mplsL3vpnVrfTable,
|
||||
5,
|
||||
{1, 2, 2, 1, 4} },
|
||||
{MPLSL3VPNVRFCREATIONTIME,
|
||||
TIMETICKS,
|
||||
RONLY,
|
||||
mplsL3vpnVrfTable,
|
||||
5,
|
||||
{1, 2, 2, 1, 5} },
|
||||
{MPLSL3VPNVRFOPERSTATUS,
|
||||
INTEGER,
|
||||
RONLY,
|
||||
mplsL3vpnVrfTable,
|
||||
5,
|
||||
{1, 2, 2, 1, 6} },
|
||||
{MPLSL3VPNVRFACTIVEINTERFACES,
|
||||
GAUGE32,
|
||||
RONLY,
|
||||
mplsL3vpnVrfTable,
|
||||
5,
|
||||
{1, 2, 2, 1, 7} },
|
||||
{MPLSL3VPNVRFASSOCIATEDINTERFACES,
|
||||
GAUGE32,
|
||||
RONLY,
|
||||
mplsL3vpnVrfTable,
|
||||
5,
|
||||
{1, 2, 2, 1, 8} },
|
||||
{MPLSL3VPNVRFCONFMIDRTETHRESH,
|
||||
GAUGE32,
|
||||
RONLY,
|
||||
mplsL3vpnVrfTable,
|
||||
5,
|
||||
{1, 2, 2, 1, 9} },
|
||||
{MPLSL3VPNVRFCONFHIGHRTETHRSH,
|
||||
GAUGE32,
|
||||
RONLY,
|
||||
mplsL3vpnVrfTable,
|
||||
5,
|
||||
{1, 2, 2, 1, 10} },
|
||||
{MPLSL3VPNVRFCONFMAXROUTES,
|
||||
GAUGE32,
|
||||
RONLY,
|
||||
mplsL3vpnVrfTable,
|
||||
5,
|
||||
{1, 2, 2, 1, 11} },
|
||||
{MPLSL3VPNVRFCONFLASTCHANGED,
|
||||
TIMETICKS,
|
||||
RONLY,
|
||||
mplsL3vpnVrfTable,
|
||||
5,
|
||||
{1, 2, 2, 1, 12} },
|
||||
{MPLSL3VPNVRFCONFROWSTATUS,
|
||||
INTEGER,
|
||||
RONLY,
|
||||
mplsL3vpnVrfTable,
|
||||
5,
|
||||
{1, 2, 2, 1, 13} },
|
||||
{MPLSL3VPNVRFCONFADMINSTATUS,
|
||||
INTEGER,
|
||||
RONLY,
|
||||
mplsL3vpnVrfTable,
|
||||
5,
|
||||
{1, 2, 2, 1, 14} },
|
||||
{MPLSL3VPNVRFCONFSTORAGETYPE,
|
||||
INTEGER,
|
||||
RONLY,
|
||||
mplsL3vpnVrfTable,
|
||||
5,
|
||||
{1, 2, 2, 1, 15} },
|
||||
};
|
||||
|
||||
/* timeticks are in hundredths of a second */
|
||||
static void bgp_mpls_l3vpn_update_timeticks(time_t *counter)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
monotime(&tv);
|
||||
*counter = (tv.tv_sec * 100) + (tv.tv_usec / 10000);
|
||||
}
|
||||
|
||||
static int bgp_mpls_l3vpn_update_last_changed(struct bgp *bgp)
|
||||
{
|
||||
if (bgp->snmp_stats)
|
||||
bgp_mpls_l3vpn_update_timeticks(
|
||||
&(bgp->snmp_stats->modify_time));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bgp_init_snmp_stats(struct bgp *bgp)
|
||||
{
|
||||
if (is_bgp_vrf_mplsvpn(bgp)) {
|
||||
if (bgp->snmp_stats == NULL) {
|
||||
bgp->snmp_stats = XCALLOC(
|
||||
MTYPE_BGP, sizeof(struct bgp_snmp_stats));
|
||||
/* fix up added routes */
|
||||
if (bgp->snmp_stats)
|
||||
bgp_mpls_l3vpn_update_timeticks(
|
||||
&(bgp->snmp_stats->creation_time));
|
||||
}
|
||||
} else {
|
||||
if (bgp->snmp_stats) {
|
||||
XFREE(MTYPE_BGP, bgp->snmp_stats);
|
||||
bgp->snmp_stats = NULL;
|
||||
}
|
||||
}
|
||||
/* Something changed - update the timestamp */
|
||||
bgp_mpls_l3vpn_update_last_changed(bgp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_bgp_vrf_active(struct bgp *bgp)
|
||||
{
|
||||
struct vrf *vrf;
|
||||
struct interface *ifp;
|
||||
|
||||
/* if there is one interface in the vrf which is up then it is deemed
|
||||
* active
|
||||
*/
|
||||
vrf = vrf_lookup_by_id(bgp->vrf_id);
|
||||
if (vrf == NULL)
|
||||
return false;
|
||||
RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name) {
|
||||
/* if we are in a vrf skip the l3mdev */
|
||||
if (bgp->name && strncmp(ifp->name, bgp->name, VRF_NAMSIZ) == 0)
|
||||
continue;
|
||||
|
||||
if (if_is_up(ifp))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int bgp_vrf_check_update_active(struct bgp *bgp, struct interface *ifp)
|
||||
{
|
||||
bool new_active = false;
|
||||
|
||||
if (!is_bgp_vrf_mplsvpn(bgp) || bgp->snmp_stats == NULL)
|
||||
return 0;
|
||||
new_active = is_bgp_vrf_active(bgp);
|
||||
if (bgp->snmp_stats->active != new_active) {
|
||||
/* add trap in here */
|
||||
bgp->snmp_stats->active = new_active;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t *mplsL3vpnConfiguredVrfs(struct variable *v, oid name[],
|
||||
size_t *length, int exact,
|
||||
size_t *var_len,
|
||||
|
@ -211,7 +392,6 @@ static int write_mplsL3vpnNotificationEnable(int action, uint8_t *var_val,
|
|||
{
|
||||
uint32_t intval;
|
||||
|
||||
zlog_debug("PJDR: %s", __func__);
|
||||
if (var_val_type != ASN_INTEGER) {
|
||||
return SNMP_ERR_WRONGTYPE;
|
||||
}
|
||||
|
@ -234,7 +414,6 @@ static uint8_t *mplsL3vpnNotificationEnable(struct variable *v, oid name[],
|
|||
== MATCH_FAILED)
|
||||
return NULL;
|
||||
|
||||
zlog_debug("PJDR: %s", __func__);
|
||||
*write_method = write_mplsL3vpnNotificationEnable;
|
||||
return SNMP_INTEGER(bgp_mplsvpn_notif_enable);
|
||||
}
|
||||
|
@ -276,8 +455,149 @@ static uint8_t *mplsL3vpnIllLblRcvThrsh(struct variable *v, oid name[],
|
|||
}
|
||||
|
||||
|
||||
/* 1.3.6.1.2.1.10.166.11.1.2.2.1.x = 14*/
|
||||
#define VRFTAB_NAMELEN 14
|
||||
|
||||
static struct bgp *bgp_lookup_by_name_next(const char *vrf_name)
|
||||
{
|
||||
struct bgp *bgp, *bgp_next = NULL;
|
||||
struct listnode *node, *nnode;
|
||||
bool first = false;
|
||||
|
||||
/*
|
||||
* the vrfs are not stored alphabetically but since we are using the
|
||||
* vrf name as an index we need the getnext function to return them
|
||||
* in a atrict order. Thus run through and find the best next one.
|
||||
*/
|
||||
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
|
||||
if (!is_bgp_vrf_mplsvpn(bgp))
|
||||
continue;
|
||||
if (strnlen(vrf_name, VRF_NAMSIZ) == 0 && bgp_next == NULL) {
|
||||
first = true;
|
||||
bgp_next = bgp;
|
||||
continue;
|
||||
}
|
||||
if (first || strncmp(bgp->name, vrf_name, VRF_NAMSIZ) > 0) {
|
||||
if (bgp_next == NULL)
|
||||
bgp_next = bgp;
|
||||
else if (strncmp(bgp->name, bgp_next->name, VRF_NAMSIZ)
|
||||
< 0)
|
||||
bgp_next = bgp;
|
||||
}
|
||||
}
|
||||
return bgp_next;
|
||||
}
|
||||
|
||||
static struct bgp *bgpL3vpnTable_lookup(struct variable *v, oid name[],
|
||||
size_t *length, char *vrf_name,
|
||||
int exact)
|
||||
{
|
||||
struct bgp *bgp = NULL;
|
||||
size_t namelen = v ? v->namelen : VRFTAB_NAMELEN;
|
||||
int len;
|
||||
|
||||
if (*length - namelen > VRF_NAMSIZ)
|
||||
return NULL;
|
||||
oid2string(name + namelen, *length - namelen, vrf_name);
|
||||
if (exact) {
|
||||
/* Check the length. */
|
||||
bgp = bgp_lookup_by_name(vrf_name);
|
||||
if (bgp && !is_bgp_vrf_mplsvpn(bgp))
|
||||
return NULL;
|
||||
} else {
|
||||
bgp = bgp_lookup_by_name_next(vrf_name);
|
||||
|
||||
if (bgp == NULL)
|
||||
return NULL;
|
||||
|
||||
len = strnlen(bgp->name, VRF_NAMSIZ);
|
||||
oid_copy_str(name + namelen, bgp->name, len);
|
||||
*length = len + namelen;
|
||||
}
|
||||
return bgp;
|
||||
}
|
||||
|
||||
static uint8_t *mplsL3vpnVrfTable(struct variable *v, oid name[],
|
||||
size_t *length, int exact, size_t *var_len,
|
||||
WriteMethod **write_method)
|
||||
{
|
||||
char vrf_name[VRF_NAMSIZ];
|
||||
struct bgp *l3vpn_bgp;
|
||||
|
||||
if (smux_header_table(v, name, length, exact, var_len, write_method)
|
||||
== MATCH_FAILED)
|
||||
return NULL;
|
||||
|
||||
memset(vrf_name, 0, VRF_NAMSIZ);
|
||||
l3vpn_bgp = bgpL3vpnTable_lookup(v, name, length, vrf_name, exact);
|
||||
|
||||
if (!l3vpn_bgp)
|
||||
return NULL;
|
||||
|
||||
switch (v->magic) {
|
||||
case MPLSL3VPNVRFVPNID:
|
||||
*var_len = 0;
|
||||
return NULL;
|
||||
case MPLSL3VPNVRFDESC:
|
||||
*var_len = strnlen(l3vpn_bgp->name, VRF_NAMSIZ);
|
||||
return (uint8_t *)l3vpn_bgp->name;
|
||||
case MPLSL3VPNVRFRD:
|
||||
/*
|
||||
* this is a horror show but the MIB dicates one RD per vrf
|
||||
* and not one RD per AFI as we (FRR) have. So this little gem
|
||||
* returns the V4 one if it's set OR the v6 one if it's set or
|
||||
* zero-length string id neither are set
|
||||
*/
|
||||
memset(rd_buf, 0, RD_ADDRSTRLEN);
|
||||
if (CHECK_FLAG(l3vpn_bgp->vpn_policy[AFI_IP].flags,
|
||||
BGP_VPN_POLICY_TOVPN_RD_SET))
|
||||
prefix_rd2str(&l3vpn_bgp->vpn_policy[AFI_IP].tovpn_rd,
|
||||
rd_buf, sizeof(rd_buf));
|
||||
else if (CHECK_FLAG(l3vpn_bgp->vpn_policy[AFI_IP6].flags,
|
||||
BGP_VPN_POLICY_TOVPN_RD_SET))
|
||||
prefix_rd2str(&l3vpn_bgp->vpn_policy[AFI_IP6].tovpn_rd,
|
||||
rd_buf, sizeof(rd_buf));
|
||||
|
||||
*var_len = strnlen(rd_buf, RD_ADDRSTRLEN);
|
||||
return (uint8_t *)rd_buf;
|
||||
case MPLSL3VPNVRFCREATIONTIME:
|
||||
return SNMP_INTEGER(
|
||||
(uint32_t)l3vpn_bgp->snmp_stats->creation_time);
|
||||
case MPLSL3VPNVRFOPERSTATUS:
|
||||
if (l3vpn_bgp->snmp_stats->active)
|
||||
return SNMP_INTEGER(1);
|
||||
else
|
||||
return SNMP_INTEGER(2);
|
||||
case MPLSL3VPNVRFACTIVEINTERFACES:
|
||||
return SNMP_INTEGER(bgp_vrf_interfaces(l3vpn_bgp, true));
|
||||
case MPLSL3VPNVRFASSOCIATEDINTERFACES:
|
||||
return SNMP_INTEGER(bgp_vrf_interfaces(l3vpn_bgp, false));
|
||||
case MPLSL3VPNVRFCONFMIDRTETHRESH:
|
||||
return SNMP_INTEGER(0);
|
||||
case MPLSL3VPNVRFCONFHIGHRTETHRSH:
|
||||
return SNMP_INTEGER(0);
|
||||
case MPLSL3VPNVRFCONFMAXROUTES:
|
||||
return SNMP_INTEGER(0);
|
||||
case MPLSL3VPNVRFCONFLASTCHANGED:
|
||||
return SNMP_INTEGER(
|
||||
(uint32_t)l3vpn_bgp->snmp_stats->modify_time);
|
||||
case MPLSL3VPNVRFCONFROWSTATUS:
|
||||
return SNMP_INTEGER(1);
|
||||
case MPLSL3VPNVRFCONFADMINSTATUS:
|
||||
return SNMP_INTEGER(1);
|
||||
case MPLSL3VPNVRFCONFSTORAGETYPE:
|
||||
return SNMP_INTEGER(2);
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bgp_mpls_l3vpn_module_init(void)
|
||||
{
|
||||
hook_register(bgp_vrf_status_changed, bgp_vrf_check_update_active);
|
||||
hook_register(bgp_snmp_init_stats, bgp_init_snmp_stats);
|
||||
hook_register(bgp_snmp_update_last_changed,
|
||||
bgp_mpls_l3vpn_update_last_changed);
|
||||
REGISTER_MIB("mplsL3VpnMIB", mpls_l3vpn_variables, variable,
|
||||
mpls_l3vpn_oid);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include "bgpd/bgp_io.h"
|
||||
#include "bgpd/bgp_damp.h"
|
||||
|
||||
DEFINE_HOOK(bgp_snmp_init_stats, (struct bgp *bgp), (bgp))
|
||||
|
||||
FRR_CFG_DEFAULT_ULONG(BGP_CONNECT_RETRY,
|
||||
{ .val_ulong = 10, .match_profile = "datacenter", },
|
||||
{ .val_ulong = 120 },
|
||||
|
@ -9862,6 +9864,7 @@ static int bgp_global_afi_safi_ip_unicast_vpn_config_import_export_vpn_modify(
|
|||
UNSET_FLAG(bgp->af_flags[afi][safi], flag);
|
||||
}
|
||||
|
||||
hook_call(bgp_snmp_init_stats, bgp);
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -127,6 +127,7 @@ FRR_CFG_DEFAULT_BOOL(BGP_SUPPRESS_DUPLICATES,
|
|||
DEFINE_HOOK(bgp_inst_config_write,
|
||||
(struct bgp *bgp, struct vty *vty),
|
||||
(bgp, vty))
|
||||
DEFINE_HOOK(bgp_snmp_update_last_changed, (struct bgp *bgp), (bgp))
|
||||
|
||||
#define GR_NO_OPER \
|
||||
"The Graceful Restart No Operation was executed as cmd same as previous one."
|
||||
|
@ -9141,6 +9142,7 @@ DEFPY (af_label_vpn_export,
|
|||
vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||
bgp_get_default(), bgp);
|
||||
|
||||
hook_call(bgp_snmp_update_last_changed, bgp);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,10 @@
|
|||
/* All information about zebra. */
|
||||
struct zclient *zclient = NULL;
|
||||
|
||||
/* hook to indicate vrf status change for SNMP */
|
||||
DEFINE_HOOK(bgp_vrf_status_changed, (struct bgp *bgp, struct interface *ifp),
|
||||
(bgp, ifp))
|
||||
|
||||
/* Can we install into zebra? */
|
||||
static inline bool bgp_install_info_to_zebra(struct bgp *bgp)
|
||||
{
|
||||
|
@ -212,8 +216,10 @@ static int bgp_ifp_destroy(struct interface *ifp)
|
|||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_debug("Rx Intf del VRF %u IF %s", ifp->vrf_id, ifp->name);
|
||||
|
||||
if (bgp)
|
||||
if (bgp) {
|
||||
bgp_update_interface_nbrs(bgp, ifp, NULL);
|
||||
hook_call(bgp_vrf_status_changed, bgp, ifp);
|
||||
}
|
||||
|
||||
bgp_mac_del_mac_entry(ifp);
|
||||
|
||||
|
@ -243,6 +249,7 @@ static int bgp_ifp_up(struct interface *ifp)
|
|||
for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc))
|
||||
bgp_nbr_connected_add(bgp, nc);
|
||||
|
||||
hook_call(bgp_vrf_status_changed, bgp, ifp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -297,6 +304,7 @@ static int bgp_ifp_down(struct interface *ifp)
|
|||
}
|
||||
}
|
||||
|
||||
hook_call(bgp_vrf_status_changed, bgp, ifp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -461,6 +469,8 @@ static int bgp_interface_vrf_update(ZAPI_CALLBACK_ARGS)
|
|||
|
||||
for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc))
|
||||
bgp_nbr_connected_add(bgp, nc);
|
||||
|
||||
hook_call(bgp_vrf_status_changed, bgp, ifp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2963,6 +2973,7 @@ static int bgp_ifp_create(struct interface *ifp)
|
|||
bgp_mac_add_mac_entry(ifp);
|
||||
|
||||
bgp_update_interface_nbrs(bgp, ifp, ifp);
|
||||
hook_call(bgp_vrf_status_changed, bgp, ifp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -3704,6 +3704,7 @@ void bgp_free(struct bgp *bgp)
|
|||
|
||||
XFREE(MTYPE_BGP, bgp->name);
|
||||
XFREE(MTYPE_BGP, bgp->name_pretty);
|
||||
XFREE(MTYPE_BGP, bgp->snmp_stats);
|
||||
|
||||
XFREE(MTYPE_BGP, bgp);
|
||||
}
|
||||
|
|
53
bgpd/bgpd.h
53
bgpd/bgpd.h
|
@ -310,6 +310,13 @@ enum bgp_link_bw_handling {
|
|||
RB_HEAD(bgp_es_vrf_rb_head, bgp_evpn_es_vrf);
|
||||
RB_PROTOTYPE(bgp_es_vrf_rb_head, bgp_evpn_es_vrf, rb_node, bgp_es_vrf_rb_cmp);
|
||||
|
||||
struct bgp_snmp_stats {
|
||||
/* SNMP variables for mplsL3Vpn*/
|
||||
time_t creation_time;
|
||||
time_t modify_time;
|
||||
bool active;
|
||||
};
|
||||
|
||||
/* BGP instance structure. */
|
||||
struct bgp {
|
||||
/* AS number of this BGP instance. */
|
||||
|
@ -363,6 +370,8 @@ struct bgp {
|
|||
uint32_t subgrps_deleted;
|
||||
} update_group_stats;
|
||||
|
||||
struct bgp_snmp_stats *snmp_stats;
|
||||
|
||||
/* BGP configuration. */
|
||||
uint16_t config;
|
||||
#define BGP_CONFIG_CLUSTER_ID (1 << 0)
|
||||
|
@ -2165,23 +2174,6 @@ static inline int afindex(afi_t afi, safi_t safi)
|
|||
}
|
||||
}
|
||||
|
||||
static inline bool is_bgp_vrf_active(struct bgp *bgp)
|
||||
{
|
||||
struct vrf *vrf;
|
||||
struct interface *ifp;
|
||||
|
||||
/* if there is one interface in the vrf which is up then it is deemed
|
||||
* active
|
||||
*/
|
||||
vrf = vrf_lookup_by_name(bgp->name);
|
||||
if (vrf == NULL)
|
||||
return false;
|
||||
RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name)
|
||||
if (if_is_up(ifp))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the peer is not a peer-group but is bound to a peer-group return 1 */
|
||||
static inline int peer_group_active(struct peer *peer)
|
||||
{
|
||||
|
@ -2263,6 +2255,27 @@ static inline struct vrf *bgp_vrf_lookup_by_instance_type(struct bgp *bgp)
|
|||
return vrf;
|
||||
}
|
||||
|
||||
static inline uint32_t bgp_vrf_interfaces(struct bgp *bgp, bool active)
|
||||
{
|
||||
struct vrf *vrf;
|
||||
struct interface *ifp;
|
||||
uint32_t count = 0;
|
||||
|
||||
/* if there is one interface in the vrf which is up then it is deemed
|
||||
* active
|
||||
*/
|
||||
vrf = bgp_vrf_lookup_by_instance_type(bgp);
|
||||
if (vrf == NULL)
|
||||
return 0;
|
||||
RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name) {
|
||||
if (strncmp(ifp->name, bgp->name, VRF_NAMSIZ) == 0)
|
||||
continue;
|
||||
if (!active || if_is_up(ifp))
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Link BGP instance to VRF. */
|
||||
static inline void bgp_vrf_link(struct bgp *bgp, struct vrf *vrf)
|
||||
{
|
||||
|
@ -2300,7 +2313,11 @@ extern int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as,
|
|||
enum bgp_instance_type inst_type);
|
||||
|
||||
/* Hooks */
|
||||
DECLARE_HOOK(peer_status_changed, (struct peer * peer), (peer))
|
||||
DECLARE_HOOK(bgp_vrf_status_changed, (struct bgp *bgp, struct interface *ifp),
|
||||
(bgp, ifp))
|
||||
DECLARE_HOOK(peer_status_changed, (struct peer *peer), (peer))
|
||||
DECLARE_HOOK(bgp_snmp_init_stats, (struct bgp *bgp), (bgp))
|
||||
DECLARE_HOOK(bgp_snmp_update_last_changed, (struct bgp *bgp), (bgp))
|
||||
void peer_nsf_stop(struct peer *peer);
|
||||
|
||||
#endif /* _QUAGGA_BGPD_H */
|
||||
|
|
|
@ -106,6 +106,8 @@ extern int oid_compare(const oid *, int, const oid *, int);
|
|||
extern void oid2in_addr(oid[], int, struct in_addr *);
|
||||
extern void *oid_copy(void *, const void *, size_t);
|
||||
extern void oid_copy_addr(oid[], const struct in_addr *, int);
|
||||
extern void oid2string(oid oid[], int len, char *string);
|
||||
extern void oid_copy_str(oid oid[], const char *string, int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
28
lib/snmp.c
28
lib/snmp.c
|
@ -78,6 +78,34 @@ void oid_copy_addr(oid oid[], const struct in_addr *addr, int len)
|
|||
oid[i] = *pnt++;
|
||||
}
|
||||
|
||||
void oid2string(oid oid[], int len, char *string)
|
||||
{
|
||||
int i;
|
||||
uint8_t *pnt;
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
pnt = (uint8_t *)string;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
*pnt++ = oid[i];
|
||||
}
|
||||
|
||||
void oid_copy_str(oid oid[], const char *string, int len)
|
||||
{
|
||||
int i;
|
||||
const uint8_t *pnt;
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
pnt = (uint8_t *)string;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
oid[i] = *pnt++;
|
||||
}
|
||||
|
||||
int smux_header_generic(struct variable *v, oid *name, size_t *length,
|
||||
int exact, size_t *var_len, WriteMethod **write_method)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue