1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2020 Volta Networks Inc
8 #include <net-snmp/net-snmp-config.h>
9 #include <net-snmp/net-snmp-includes.h>
20 #include "lib/version.h"
22 #include "bgpd/bgpd.h"
23 #include "bgpd/bgp_route.h"
24 #include "bgpd/bgp_attr.h"
25 #include "bgpd/bgp_ecommunity.h"
26 #include "bgpd/bgp_mplsvpn.h"
27 #include "bgpd/bgp_mplsvpn_snmp.h"
29 #define BGP_mplsvpn_notif_enable_true 1
30 #define BGP_mplsvpn_notif_enable_false 2
32 /* MPLSL3VPN MIB described in RFC4382 */
33 #define MPLSL3VPNMIB 1, 3, 6, 1, 2, 1, 10, 166, 11
35 /* MPLSL3VPN Scalars */
36 #define MPLSL3VPNCONFIGUREDVRFS 1
37 #define MPLSL3VPNACTIVEVRFS 2
38 #define MPLSL3VPNCONNECTEDINTERFACES 3
39 #define MPLSL3VPNNOTIFICATIONENABLE 4
40 #define MPLSL3VPNCONFMAXPOSSRTS 5
41 #define MPLSL3VPNVRFCONFRTEMXTHRSHTIME 6
42 #define MPLSL3VPNILLLBLRCVTHRSH 7
44 /* MPLSL3VPN IFConf Table */
45 #define MPLSL3VPNIFVPNCLASSIFICATION 1
46 #define MPLSL3VPNIFCONFSTORAGETYPE 2
47 #define MPLSL3VPNIFCONFROWSTATUS 3
49 /* MPLSL3VPN VRF Table */
50 #define MPLSL3VPNVRFVPNID 1
51 #define MPLSL3VPNVRFDESC 2
52 #define MPLSL3VPNVRFRD 3
53 #define MPLSL3VPNVRFCREATIONTIME 4
54 #define MPLSL3VPNVRFOPERSTATUS 5
55 #define MPLSL3VPNVRFACTIVEINTERFACES 6
56 #define MPLSL3VPNVRFASSOCIATEDINTERFACES 7
57 #define MPLSL3VPNVRFCONFMIDRTETHRESH 8
58 #define MPLSL3VPNVRFCONFHIGHRTETHRSH 9
59 #define MPLSL3VPNVRFCONFMAXROUTES 10
60 #define MPLSL3VPNVRFCONFLASTCHANGED 11
61 #define MPLSL3VPNVRFCONFROWSTATUS 12
62 #define MPLSL3VPNVRFCONFADMINSTATUS 13
63 #define MPLSL3VPNVRFCONFSTORAGETYPE 14
65 /* MPLSL3VPN RT Table */
66 #define MPLSL3VPNVRFRT 1
67 #define MPLSL3VPNVRFRTDESCR 2
68 #define MPLSL3VPNVRFRTROWSTATUS 3
69 #define MPLSL3VPNVRFRTSTORAGETYPE 4
71 /* MPLSL3VPN PERF Table */
72 #define MPLSL3VPNVRFPERFROUTESADDED 1
73 #define MPLSL3VPNVRFPERFROUTESDELETED 2
74 #define MPLSL3VPNVRFPERFCURRNUMROUTES 3
76 /* MPLSL3VPN RTE Table */
77 #define MPLSL3VPNVRFRTEINETCIDRDESTTYPE 1
78 #define MPLSL3VPNVRFRTEINETCIDRDEST 2
79 #define MPLSL3VPNVRFRTEINETCIDRPFXLEN 3
80 #define MPLSL3VPNVRFRTEINETCIDRPOLICY 4
81 #define MPLSL3VPNVRFRTEINETCIDRNHOPTYPE 5
82 #define MPLSL3VPNVRFRTEINETCIDRNEXTHOP 6
83 #define MPLSL3VPNVRFRTEINETCIDRIFINDEX 7
84 #define MPLSL3VPNVRFRTEINETCIDRTYPE 8
85 #define MPLSL3VPNVRFRTEINETCIDRPROTO 9
86 #define MPLSL3VPNVRFRTEINETCIDRAGE 10
87 #define MPLSL3VPNVRFRTEINETCIDRNEXTHOPAS 11
88 #define MPLSL3VPNVRFRTEINETCIDRMETRIC1 12
89 #define MPLSL3VPNVRFRTEINETCIDRMETRIC2 13
90 #define MPLSL3VPNVRFRTEINETCIDRMETRIC3 14
91 #define MPLSL3VPNVRFRTEINETCIDRMETRIC4 15
92 #define MPLSL3VPNVRFRTEINETCIDRMETRIC5 16
93 #define MPLSL3VPNVRFRTEINETCIDRXCPOINTER 17
94 #define MPLSL3VPNVRFRTEINETCIDRSTATUS 18
97 #define MPLSL3VPNVRFUP 1
98 #define MPLSL3VPNDOWN 2
100 /* SNMP value hack. */
101 #define INTEGER ASN_INTEGER
102 #define INTEGER32 ASN_INTEGER
103 #define COUNTER32 ASN_COUNTER
104 #define OCTET_STRING ASN_OCTET_STR
105 #define IPADDRESS ASN_IPADDRESS
106 #define GAUGE32 ASN_UNSIGNED
107 #define TIMETICKS ASN_TIMETICKS
108 #define OID ASN_OBJECT_ID
110 /* Declare static local variables for convenience. */
113 #define RT_PREAMBLE_SIZE 20
115 /* BGP-MPLS-MIB instances */
116 static oid mpls_l3vpn_oid
[] = {MPLSL3VPNMIB
};
117 static oid mpls_l3vpn_trap_oid
[] = {MPLSL3VPNMIB
, 0};
118 static char rd_buf
[RD_ADDRSTRLEN
];
119 /* Notifications enabled by default */
120 static uint8_t bgp_mplsvpn_notif_enable
= SNMP_TRUE
;
121 static oid mpls_l3vpn_policy_oid
[2] = {0, 0};
122 static const char *empty_nhop
= "";
123 char rt_description
[VRF_NAMSIZ
+ RT_PREAMBLE_SIZE
];
125 static uint8_t *mplsL3vpnConfiguredVrfs(struct variable
*, oid
[], size_t *, int,
126 size_t *, WriteMethod
**);
128 static uint8_t *mplsL3vpnActiveVrfs(struct variable
*, oid
[], size_t *, int,
129 size_t *, WriteMethod
**);
131 static uint8_t *mplsL3vpnConnectedInterfaces(struct variable
*, oid
[], size_t *,
132 int, size_t *, WriteMethod
**);
134 static uint8_t *mplsL3vpnNotificationEnable(struct variable
*, oid
[], size_t *,
135 int, size_t *, WriteMethod
**);
137 static uint8_t *mplsL3vpnVrfConfMaxPossRts(struct variable
*, oid
[], size_t *,
138 int, size_t *, WriteMethod
**);
140 static uint8_t *mplsL3vpnVrfConfRteMxThrshTime(struct variable
*, oid
[],
141 size_t *, int, size_t *,
144 static uint8_t *mplsL3vpnIllLblRcvThrsh(struct variable
*, oid
[], size_t *, int,
145 size_t *, WriteMethod
**);
147 static uint8_t *mplsL3vpnVrfTable(struct variable
*, oid
[], size_t *, int,
148 size_t *, WriteMethod
**);
150 static uint8_t *mplsL3vpnVrfRtTable(struct variable
*, oid
[], size_t *, int,
151 size_t *, WriteMethod
**);
153 static uint8_t *mplsL3vpnIfConfTable(struct variable
*, oid
[], size_t *, int,
154 size_t *, WriteMethod
**);
156 static uint8_t *mplsL3vpnPerfTable(struct variable
*, oid
[], size_t *, int,
157 size_t *, WriteMethod
**);
159 static uint8_t *mplsL3vpnRteTable(struct variable
*, oid
[], size_t *, int,
160 size_t *, WriteMethod
**);
163 static struct variable mpls_l3vpn_variables
[] = {
165 {MPLSL3VPNCONFIGUREDVRFS
,
168 mplsL3vpnConfiguredVrfs
,
171 {MPLSL3VPNACTIVEVRFS
,
177 {MPLSL3VPNCONNECTEDINTERFACES
,
180 mplsL3vpnConnectedInterfaces
,
183 {MPLSL3VPNNOTIFICATIONENABLE
,
186 mplsL3vpnNotificationEnable
,
189 {MPLSL3VPNCONFMAXPOSSRTS
,
192 mplsL3vpnVrfConfMaxPossRts
,
195 {MPLSL3VPNVRFCONFRTEMXTHRSHTIME
,
198 mplsL3vpnVrfConfRteMxThrshTime
,
201 {MPLSL3VPNILLLBLRCVTHRSH
,
204 mplsL3vpnIllLblRcvThrsh
,
209 {MPLSL3VPNIFVPNCLASSIFICATION
,
212 mplsL3vpnIfConfTable
,
215 {MPLSL3VPNIFCONFSTORAGETYPE
,
218 mplsL3vpnIfConfTable
,
221 {MPLSL3VPNIFCONFROWSTATUS
,
224 mplsL3vpnIfConfTable
,
228 /* mplsL3VpnVrf Table */
247 {MPLSL3VPNVRFCREATIONTIME
,
253 {MPLSL3VPNVRFOPERSTATUS
,
259 {MPLSL3VPNVRFACTIVEINTERFACES
,
265 {MPLSL3VPNVRFASSOCIATEDINTERFACES
,
271 {MPLSL3VPNVRFCONFMIDRTETHRESH
,
277 {MPLSL3VPNVRFCONFHIGHRTETHRSH
,
283 {MPLSL3VPNVRFCONFMAXROUTES
,
289 {MPLSL3VPNVRFCONFLASTCHANGED
,
295 {MPLSL3VPNVRFCONFROWSTATUS
,
301 {MPLSL3VPNVRFCONFADMINSTATUS
,
307 {MPLSL3VPNVRFCONFSTORAGETYPE
,
314 /* mplsL3vpnVrfRt Table */
321 {MPLSL3VPNVRFRTDESCR
,
327 {MPLSL3VPNVRFRTROWSTATUS
,
333 {MPLSL3VPNVRFRTSTORAGETYPE
,
340 /* mplsL3VpnPerfTable */
341 {MPLSL3VPNVRFPERFROUTESADDED
,
347 {MPLSL3VPNVRFPERFROUTESDELETED
,
353 {MPLSL3VPNVRFPERFCURRNUMROUTES
,
360 /* mplsVpnRteTable */
361 {MPLSL3VPNVRFRTEINETCIDRDESTTYPE
,
367 {MPLSL3VPNVRFRTEINETCIDRDEST
,
373 {MPLSL3VPNVRFRTEINETCIDRPFXLEN
,
379 {MPLSL3VPNVRFRTEINETCIDRPOLICY
,
385 {MPLSL3VPNVRFRTEINETCIDRNHOPTYPE
,
391 {MPLSL3VPNVRFRTEINETCIDRNEXTHOP
,
397 {MPLSL3VPNVRFRTEINETCIDRIFINDEX
,
403 {MPLSL3VPNVRFRTEINETCIDRTYPE
,
409 {MPLSL3VPNVRFRTEINETCIDRPROTO
,
415 {MPLSL3VPNVRFRTEINETCIDRAGE
,
421 {MPLSL3VPNVRFRTEINETCIDRNEXTHOPAS
,
427 {MPLSL3VPNVRFRTEINETCIDRMETRIC1
,
433 {MPLSL3VPNVRFRTEINETCIDRMETRIC2
,
439 {MPLSL3VPNVRFRTEINETCIDRMETRIC3
,
445 {MPLSL3VPNVRFRTEINETCIDRMETRIC4
,
451 {MPLSL3VPNVRFRTEINETCIDRMETRIC5
,
457 {MPLSL3VPNVRFRTEINETCIDRXCPOINTER
,
463 {MPLSL3VPNVRFRTEINETCIDRSTATUS
,
471 /* timeticks are in hundredths of a second */
472 static void bgp_mpls_l3vpn_update_timeticks(time_t *counter
)
477 *counter
= (tv
.tv_sec
* 100) + (tv
.tv_usec
/ 10000);
480 static int bgp_mpls_l3vpn_update_last_changed(struct bgp
*bgp
)
483 bgp_mpls_l3vpn_update_timeticks(
484 &(bgp
->snmp_stats
->modify_time
));
488 static uint32_t bgp_mpls_l3vpn_current_routes(struct bgp
*l3vpn_bgp
)
491 struct bgp_table
*table
;
492 struct bgp_dest
*dest
;
493 struct bgp_path_info
*pi
;
495 table
= l3vpn_bgp
->rib
[AFI_IP
][SAFI_UNICAST
];
496 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
497 pi
= bgp_dest_get_bgp_path_info(dest
);
498 for (; pi
; pi
= pi
->next
)
501 table
= l3vpn_bgp
->rib
[AFI_IP6
][SAFI_UNICAST
];
502 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
503 pi
= bgp_dest_get_bgp_path_info(dest
);
504 for (; pi
; pi
= pi
->next
)
510 static int bgp_init_snmp_stats(struct bgp
*bgp
)
512 if (is_bgp_vrf_mplsvpn(bgp
)) {
513 if (bgp
->snmp_stats
== NULL
) {
514 bgp
->snmp_stats
= XCALLOC(
515 MTYPE_BGP
, sizeof(struct bgp_snmp_stats
));
516 /* fix up added routes */
517 if (bgp
->snmp_stats
) {
518 bgp
->snmp_stats
->routes_added
=
519 bgp_mpls_l3vpn_current_routes(bgp
);
520 bgp_mpls_l3vpn_update_timeticks(
521 &(bgp
->snmp_stats
->creation_time
));
525 if (bgp
->snmp_stats
) {
526 XFREE(MTYPE_BGP
, bgp
->snmp_stats
);
527 bgp
->snmp_stats
= NULL
;
530 /* Something changed - update the timestamp */
531 bgp_mpls_l3vpn_update_last_changed(bgp
);
535 static int bgp_snmp_update_route_stats(struct bgp_dest
*dest
,
536 struct bgp_path_info
*pi
, bool added
)
538 struct bgp_table
*table
;
541 table
= bgp_dest_table(dest
);
542 /* only update if we have a stats block - MPLSVPN vrfs for now*/
543 if (table
&& table
->bgp
&& table
->bgp
->snmp_stats
) {
545 table
->bgp
->snmp_stats
->routes_added
++;
547 table
->bgp
->snmp_stats
->routes_deleted
++;
553 static bool is_bgp_vrf_active(struct bgp
*bgp
)
556 struct interface
*ifp
;
558 /* if there is one interface in the vrf which is up then it is deemed
561 vrf
= vrf_lookup_by_id(bgp
->vrf_id
);
564 RB_FOREACH (ifp
, if_name_head
, &vrf
->ifaces_by_name
) {
565 /* if we are in a vrf skip the l3mdev */
566 if (bgp
->name
&& strncmp(ifp
->name
, bgp
->name
, VRF_NAMSIZ
) == 0)
576 static struct trap_object l3vpn_trap_list
[] = {{5, {1, 2, 1, 1, 5} },
577 {5, {1, 2, 2, 1, 6} } };
579 static int bgp_vrf_check_update_active(struct bgp
*bgp
, struct interface
*ifp
)
581 bool new_active
= false;
583 struct index_oid trap_index
[2];
585 if (!is_bgp_vrf_mplsvpn(bgp
) || bgp
->snmp_stats
== NULL
586 || !bgp_mplsvpn_notif_enable
)
588 new_active
= is_bgp_vrf_active(bgp
);
589 if (bgp
->snmp_stats
->active
!= new_active
) {
590 /* add trap in here */
591 bgp
->snmp_stats
->active
= new_active
;
593 /* send relevent trap */
594 if (bgp
->snmp_stats
->active
)
595 trap
= MPLSL3VPNVRFUP
;
597 trap
= MPLSL3VPNDOWN
;
600 * first index vrf_name + ifindex
601 * second index vrf_name
603 trap_index
[1].indexlen
= strnlen(bgp
->name
, VRF_NAMSIZ
);
604 oid_copy_str(trap_index
[0].indexname
, bgp
->name
,
605 trap_index
[1].indexlen
);
606 oid_copy_str(trap_index
[1].indexname
, bgp
->name
,
607 trap_index
[1].indexlen
);
608 trap_index
[0].indexlen
=
609 trap_index
[1].indexlen
+ sizeof(ifindex_t
);
610 oid_copy_int(trap_index
[0].indexname
+ trap_index
[1].indexlen
,
611 (int *)&(ifp
->ifindex
));
613 smux_trap_multi_index(
614 mpls_l3vpn_variables
, array_size(mpls_l3vpn_variables
),
615 mpls_l3vpn_trap_oid
, array_size(mpls_l3vpn_trap_oid
),
616 mpls_l3vpn_oid
, sizeof(mpls_l3vpn_oid
) / sizeof(oid
),
617 trap_index
, array_size(trap_index
), l3vpn_trap_list
,
618 array_size(l3vpn_trap_list
), trap
);
620 bgp_mpls_l3vpn_update_last_changed(bgp
);
624 static uint8_t *mplsL3vpnConfiguredVrfs(struct variable
*v
, oid name
[],
625 size_t *length
, int exact
,
627 WriteMethod
**write_method
)
629 struct listnode
*node
, *nnode
;
633 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
637 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
638 if (is_bgp_vrf_mplsvpn(bgp
))
641 return SNMP_INTEGER(count
);
644 static uint8_t *mplsL3vpnActiveVrfs(struct variable
*v
, oid name
[],
645 size_t *length
, int exact
, size_t *var_len
,
646 WriteMethod
**write_method
)
648 struct listnode
*node
, *nnode
;
652 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
656 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
657 if (is_bgp_vrf_mplsvpn(bgp
) && is_bgp_vrf_active(bgp
))
660 return SNMP_INTEGER(count
);
663 static uint8_t *mplsL3vpnConnectedInterfaces(struct variable
*v
, oid name
[],
664 size_t *length
, int exact
,
666 WriteMethod
**write_method
)
668 struct listnode
*node
, *nnode
;
673 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
677 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
678 if (is_bgp_vrf_mplsvpn(bgp
)) {
679 vrf
= vrf_lookup_by_name(bgp
->name
);
683 count
+= vrf_interface_count(vrf
);
687 return SNMP_INTEGER(count
);
690 static int write_mplsL3vpnNotificationEnable(int action
, uint8_t *var_val
,
691 uint8_t var_val_type
,
692 size_t var_val_len
, uint8_t *statP
,
693 oid
*name
, size_t length
)
697 if (var_val_type
!= ASN_INTEGER
)
698 return SNMP_ERR_WRONGTYPE
;
700 if (var_val_len
!= sizeof(long))
701 return SNMP_ERR_WRONGLENGTH
;
703 intval
= *(long *)var_val
;
704 bgp_mplsvpn_notif_enable
= intval
;
705 return SNMP_ERR_NOERROR
;
708 static uint8_t *mplsL3vpnNotificationEnable(struct variable
*v
, oid name
[],
709 size_t *length
, int exact
,
711 WriteMethod
**write_method
)
713 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
717 *write_method
= write_mplsL3vpnNotificationEnable
;
718 return SNMP_INTEGER(bgp_mplsvpn_notif_enable
);
721 static uint8_t *mplsL3vpnVrfConfMaxPossRts(struct variable
*v
, oid name
[],
722 size_t *length
, int exact
,
724 WriteMethod
**write_method
)
726 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
730 return SNMP_INTEGER(0);
733 static uint8_t *mplsL3vpnVrfConfRteMxThrshTime(struct variable
*v
, oid name
[],
734 size_t *length
, int exact
,
736 WriteMethod
**write_method
)
738 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
742 return SNMP_INTEGER(0);
745 static uint8_t *mplsL3vpnIllLblRcvThrsh(struct variable
*v
, oid name
[],
746 size_t *length
, int exact
,
748 WriteMethod
**write_method
)
750 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
754 return SNMP_INTEGER(0);
758 static struct bgp
*bgp_lookup_by_name_next(char *vrf_name
)
760 struct bgp
*bgp
, *bgp_next
= NULL
;
761 struct listnode
*node
, *nnode
;
765 * the vrfs are not stored alphabetically but since we are using the
766 * vrf name as an index we need the getnext function to return them
767 * in a atrict order. Thus run through and find the best next one.
769 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
770 if (!is_bgp_vrf_mplsvpn(bgp
))
772 if (strnlen(vrf_name
, VRF_NAMSIZ
) == 0 && bgp_next
== NULL
) {
777 if (first
|| strncmp(bgp
->name
, vrf_name
, VRF_NAMSIZ
) > 0) {
778 if (bgp_next
== NULL
)
780 else if (strncmp(bgp
->name
, bgp_next
->name
, VRF_NAMSIZ
)
788 /* 1.3.6.1.2.1.10.166.11.1.2.1.1.x = 14*/
789 #define IFCONFTAB_NAMELEN 14
790 static struct bgp
*bgpL3vpnIfConf_lookup(struct variable
*v
, oid name
[],
791 size_t *length
, char *vrf_name
,
792 ifindex_t
*ifindex
, int exact
)
794 struct bgp
*bgp
= NULL
;
795 size_t namelen
= v
? v
->namelen
: IFCONFTAB_NAMELEN
;
796 struct interface
*ifp
;
797 int vrf_name_len
, len
;
800 if (*length
- namelen
> (VRF_NAMSIZ
+ sizeof(uint32_t)))
802 /* do we have index info in the oid ? */
803 if (*length
- namelen
!= 0 && *length
- namelen
>= sizeof(uint32_t)) {
804 /* copy the info from the oid */
805 vrf_name_len
= *length
- (namelen
+ sizeof(ifindex_t
));
806 oid2string(name
+ namelen
, vrf_name_len
, vrf_name
);
807 oid2int(name
+ namelen
+ vrf_name_len
, ifindex
);
811 /* Check the length. */
812 bgp
= bgp_lookup_by_name(vrf_name
);
813 if (bgp
&& !is_bgp_vrf_mplsvpn(bgp
))
817 ifp
= if_lookup_by_index(*ifindex
, bgp
->vrf_id
);
821 if (strnlen(vrf_name
, VRF_NAMSIZ
) == 0)
822 bgp
= bgp_lookup_by_name_next(vrf_name
);
824 bgp
= bgp_lookup_by_name(vrf_name
);
827 ifp
= if_vrf_lookup_by_index_next(*ifindex
,
830 vrf_name_len
= strnlen(bgp
->name
, VRF_NAMSIZ
);
831 *ifindex
= ifp
->ifindex
;
832 len
= vrf_name_len
+ sizeof(ifindex_t
);
833 oid_copy_str(name
+ namelen
, bgp
->name
,
835 oid_copy_int(name
+ namelen
+ vrf_name_len
,
837 *length
= len
+ namelen
;
842 bgp
= bgp_lookup_by_name_next(bgp
->name
);
850 static uint8_t *mplsL3vpnIfConfTable(struct variable
*v
, oid name
[],
851 size_t *length
, int exact
, size_t *var_len
,
852 WriteMethod
**write_method
)
854 char vrf_name
[VRF_NAMSIZ
];
855 ifindex_t ifindex
= 0;
856 struct bgp
*l3vpn_bgp
;
858 if (smux_header_table(v
, name
, length
, exact
, var_len
, write_method
)
862 memset(vrf_name
, 0, VRF_NAMSIZ
);
863 l3vpn_bgp
= bgpL3vpnIfConf_lookup(v
, name
, length
, vrf_name
, &ifindex
,
869 case MPLSL3VPNIFVPNCLASSIFICATION
:
870 return SNMP_INTEGER(2);
871 case MPLSL3VPNIFCONFSTORAGETYPE
:
872 return SNMP_INTEGER(2);
873 case MPLSL3VPNIFCONFROWSTATUS
:
874 return SNMP_INTEGER(1);
879 /* 1.3.6.1.2.1.10.166.11.1.2.2.1.x = 14*/
880 #define VRFTAB_NAMELEN 14
882 static struct bgp
*bgpL3vpnVrf_lookup(struct variable
*v
, oid name
[],
883 size_t *length
, char *vrf_name
, int exact
)
885 struct bgp
*bgp
= NULL
;
886 size_t namelen
= v
? v
->namelen
: VRFTAB_NAMELEN
;
889 if (*length
- namelen
> VRF_NAMSIZ
)
891 oid2string(name
+ namelen
, *length
- namelen
, vrf_name
);
893 /* Check the length. */
894 bgp
= bgp_lookup_by_name(vrf_name
);
895 if (bgp
&& !is_bgp_vrf_mplsvpn(bgp
))
898 bgp
= bgp_lookup_by_name_next(vrf_name
);
903 len
= strnlen(bgp
->name
, VRF_NAMSIZ
);
904 oid_copy_str(name
+ namelen
, bgp
->name
, len
);
905 *length
= len
+ namelen
;
910 static uint8_t *mplsL3vpnVrfTable(struct variable
*v
, oid name
[],
911 size_t *length
, int exact
, size_t *var_len
,
912 WriteMethod
**write_method
)
914 char vrf_name
[VRF_NAMSIZ
];
915 struct bgp
*l3vpn_bgp
;
917 if (smux_header_table(v
, name
, length
, exact
, var_len
, write_method
)
921 memset(vrf_name
, 0, VRF_NAMSIZ
);
922 l3vpn_bgp
= bgpL3vpnVrf_lookup(v
, name
, length
, vrf_name
, exact
);
928 case MPLSL3VPNVRFVPNID
:
931 case MPLSL3VPNVRFDESC
:
932 *var_len
= strnlen(l3vpn_bgp
->name
, VRF_NAMSIZ
);
933 return (uint8_t *)l3vpn_bgp
->name
;
936 * this is a horror show but the MIB dicates one RD per vrf
937 * and not one RD per AFI as we (FRR) have. So this little gem
938 * returns the V4 one if it's set OR the v6 one if it's set or
939 * zero-length string id neither are set
941 memset(rd_buf
, 0, RD_ADDRSTRLEN
);
942 if (CHECK_FLAG(l3vpn_bgp
->vpn_policy
[AFI_IP
].flags
,
943 BGP_VPN_POLICY_TOVPN_RD_SET
))
944 prefix_rd2str(&l3vpn_bgp
->vpn_policy
[AFI_IP
].tovpn_rd
,
945 rd_buf
, sizeof(rd_buf
),
946 bgp_get_asnotation(l3vpn_bgp
));
947 else if (CHECK_FLAG(l3vpn_bgp
->vpn_policy
[AFI_IP6
].flags
,
948 BGP_VPN_POLICY_TOVPN_RD_SET
))
949 prefix_rd2str(&l3vpn_bgp
->vpn_policy
[AFI_IP6
].tovpn_rd
,
950 rd_buf
, sizeof(rd_buf
),
951 bgp_get_asnotation(l3vpn_bgp
));
953 *var_len
= strnlen(rd_buf
, RD_ADDRSTRLEN
);
954 return (uint8_t *)rd_buf
;
955 case MPLSL3VPNVRFCREATIONTIME
:
957 (uint32_t)l3vpn_bgp
->snmp_stats
->creation_time
);
958 case MPLSL3VPNVRFOPERSTATUS
:
959 if (l3vpn_bgp
->snmp_stats
->active
)
960 return SNMP_INTEGER(1);
962 return SNMP_INTEGER(2);
963 case MPLSL3VPNVRFACTIVEINTERFACES
:
964 return SNMP_INTEGER(bgp_vrf_interfaces(l3vpn_bgp
, true));
965 case MPLSL3VPNVRFASSOCIATEDINTERFACES
:
966 return SNMP_INTEGER(bgp_vrf_interfaces(l3vpn_bgp
, false));
967 case MPLSL3VPNVRFCONFMIDRTETHRESH
:
968 return SNMP_INTEGER(0);
969 case MPLSL3VPNVRFCONFHIGHRTETHRSH
:
970 return SNMP_INTEGER(0);
971 case MPLSL3VPNVRFCONFMAXROUTES
:
972 return SNMP_INTEGER(0);
973 case MPLSL3VPNVRFCONFLASTCHANGED
:
975 (uint32_t)l3vpn_bgp
->snmp_stats
->modify_time
);
976 case MPLSL3VPNVRFCONFROWSTATUS
:
977 return SNMP_INTEGER(1);
978 case MPLSL3VPNVRFCONFADMINSTATUS
:
979 return SNMP_INTEGER(1);
980 case MPLSL3VPNVRFCONFSTORAGETYPE
:
981 return SNMP_INTEGER(2);
986 /* 1.3.6.1.2.1.10.166.11.1.2.3.1.x = 14*/
987 #define VRFRTTAB_NAMELEN 14
988 static struct bgp
*bgpL3vpnVrfRt_lookup(struct variable
*v
, oid name
[],
989 size_t *length
, char *vrf_name
,
990 uint32_t *rt_index
, uint8_t *rt_type
,
993 uint32_t type_index_size
;
994 struct bgp
*l3vpn_bgp
;
995 size_t namelen
= v
? v
->namelen
: VRFRTTAB_NAMELEN
;
996 int vrf_name_len
, len
;
999 if (*length
- namelen
1000 > (VRF_NAMSIZ
+ sizeof(uint32_t)) + sizeof(uint8_t))
1003 type_index_size
= sizeof(uint32_t) + sizeof(uint8_t);
1004 /* do we have index info in the oid ? */
1005 if (*length
- namelen
!= 0 && *length
- namelen
>= type_index_size
) {
1006 /* copy the info from the oid */
1007 vrf_name_len
= *length
- (namelen
+ type_index_size
);
1008 oid2string(name
+ namelen
, vrf_name_len
, vrf_name
);
1009 oid2int(name
+ namelen
+ vrf_name_len
, (int *)rt_index
);
1010 *rt_type
= name
[namelen
+ vrf_name_len
+ sizeof(uint32_t)];
1013 /* validate the RT index is in range */
1014 if (*rt_index
> AFI_IP6
)
1018 l3vpn_bgp
= bgp_lookup_by_name(vrf_name
);
1019 if (l3vpn_bgp
&& !is_bgp_vrf_mplsvpn(l3vpn_bgp
))
1023 if ((*rt_index
!= AFI_IP
) && (*rt_index
!= AFI_IP6
))
1025 /* do we have RT config */
1026 if (!(l3vpn_bgp
->vpn_policy
[*rt_index
]
1027 .rtlist
[BGP_VPN_POLICY_DIR_FROMVPN
]
1028 || l3vpn_bgp
->vpn_policy
[*rt_index
]
1029 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
]))
1033 if (strnlen(vrf_name
, VRF_NAMSIZ
) == 0)
1034 l3vpn_bgp
= bgp_lookup_by_name_next(vrf_name
);
1036 l3vpn_bgp
= bgp_lookup_by_name(vrf_name
);
1038 switch (*rt_index
) {
1043 *rt_index
= AFI_IP6
;
1052 *rt_type
= MPLSVPNVRFRTTYPEIMPORT
;
1054 case MPLSVPNVRFRTTYPEIMPORT
:
1055 *rt_type
= MPLSVPNVRFRTTYPEEXPORT
;
1057 case MPLSVPNVRFRTTYPEEXPORT
:
1058 case MPLSVPNVRFRTTYPEBOTH
:
1063 bool import
, export
;
1066 (!!l3vpn_bgp
->vpn_policy
[*rt_index
].rtlist
1067 [BGP_VPN_POLICY_DIR_FROMVPN
]);
1069 (!!l3vpn_bgp
->vpn_policy
[*rt_index
].rtlist
1070 [BGP_VPN_POLICY_DIR_TOVPN
]);
1071 if (*rt_type
== MPLSVPNVRFRTTYPEIMPORT
1074 if (*rt_type
== MPLSVPNVRFRTTYPEEXPORT
1077 /* ckeck for both */
1078 if (*rt_type
== MPLSVPNVRFRTTYPEIMPORT
&& import
1081 l3vpn_bgp
->vpn_policy
[*rt_index
].rtlist
1082 [BGP_VPN_POLICY_DIR_FROMVPN
],
1083 l3vpn_bgp
->vpn_policy
[*rt_index
].rtlist
1084 [BGP_VPN_POLICY_DIR_TOVPN
]))
1085 *rt_type
= MPLSVPNVRFRTTYPEBOTH
;
1087 /* we have a match copy the oid info */
1089 strnlen(l3vpn_bgp
->name
, VRF_NAMSIZ
);
1090 len
= vrf_name_len
+ sizeof(uint32_t)
1092 oid_copy_str(name
+ namelen
, l3vpn_bgp
->name
,
1094 oid_copy_int(name
+ namelen
+ vrf_name_len
,
1096 name
[(namelen
+ len
) - 1] = *rt_type
;
1097 *length
= len
+ namelen
;
1100 l3vpn_bgp
= bgp_lookup_by_name_next(l3vpn_bgp
->name
);
1106 static const char *rt_type2str(uint8_t rt_type
)
1109 case MPLSVPNVRFRTTYPEIMPORT
:
1111 case MPLSVPNVRFRTTYPEEXPORT
:
1113 case MPLSVPNVRFRTTYPEBOTH
:
1119 static uint8_t *mplsL3vpnVrfRtTable(struct variable
*v
, oid name
[],
1120 size_t *length
, int exact
, size_t *var_len
,
1121 WriteMethod
**write_method
)
1123 char vrf_name
[VRF_NAMSIZ
];
1124 struct bgp
*l3vpn_bgp
;
1125 uint32_t rt_index
= 0;
1126 uint8_t rt_type
= 0;
1128 static char rt_b_str
[BUFSIZ
] = {};
1130 if (smux_header_table(v
, name
, length
, exact
, var_len
, write_method
)
1134 memset(vrf_name
, 0, VRF_NAMSIZ
);
1135 l3vpn_bgp
= bgpL3vpnVrfRt_lookup(v
, name
, length
, vrf_name
, &rt_index
,
1142 case MPLSL3VPNVRFRT
:
1144 case MPLSVPNVRFRTTYPEIMPORT
:
1145 rt_b
= ecommunity_ecom2str(
1146 l3vpn_bgp
->vpn_policy
[rt_index
]
1147 .rtlist
[BGP_VPN_POLICY_DIR_FROMVPN
],
1148 ECOMMUNITY_FORMAT_ROUTE_MAP
,
1149 ECOMMUNITY_ROUTE_TARGET
);
1151 case MPLSVPNVRFRTTYPEEXPORT
:
1152 case MPLSVPNVRFRTTYPEBOTH
:
1153 rt_b
= ecommunity_ecom2str(
1154 l3vpn_bgp
->vpn_policy
[rt_index
]
1155 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
1156 ECOMMUNITY_FORMAT_ROUTE_MAP
,
1157 ECOMMUNITY_ROUTE_TARGET
);
1163 *var_len
= strnlen(rt_b
, ECOMMUNITY_STRLEN
);
1164 strlcpy(rt_b_str
, rt_b
, sizeof(rt_b_str
));
1165 XFREE(MTYPE_ECOMMUNITY_STR
, rt_b
);
1169 return (uint8_t *)rt_b_str
;
1170 case MPLSL3VPNVRFRTDESCR
:
1171 /* since we dont have a description generate one */
1172 memset(rt_description
, 0, VRF_NAMSIZ
+ RT_PREAMBLE_SIZE
);
1173 snprintf(rt_description
, VRF_NAMSIZ
+ RT_PREAMBLE_SIZE
,
1174 "RT %s for VRF %s", rt_type2str(rt_type
),
1177 strnlen(rt_description
, VRF_NAMSIZ
+ RT_PREAMBLE_SIZE
);
1178 return (uint8_t *)rt_description
;
1179 case MPLSL3VPNVRFRTROWSTATUS
:
1180 return SNMP_INTEGER(1);
1181 case MPLSL3VPNVRFRTSTORAGETYPE
:
1182 return SNMP_INTEGER(2);
1187 /* 1.3.6.1.2.1.10.166.11.1.3.1.1.x = 14*/
1188 #define PERFTAB_NAMELEN 14
1190 static uint8_t *mplsL3vpnPerfTable(struct variable
*v
, oid name
[],
1191 size_t *length
, int exact
, size_t *var_len
,
1192 WriteMethod
**write_method
)
1194 char vrf_name
[VRF_NAMSIZ
];
1195 struct bgp
*l3vpn_bgp
;
1197 if (smux_header_table(v
, name
, length
, exact
, var_len
, write_method
)
1201 memset(vrf_name
, 0, VRF_NAMSIZ
);
1202 l3vpn_bgp
= bgpL3vpnVrf_lookup(v
, name
, length
, vrf_name
, exact
);
1208 case MPLSL3VPNVRFPERFROUTESADDED
:
1209 return SNMP_INTEGER(l3vpn_bgp
->snmp_stats
->routes_added
);
1210 case MPLSL3VPNVRFPERFROUTESDELETED
:
1211 return SNMP_INTEGER(l3vpn_bgp
->snmp_stats
->routes_deleted
);
1212 case MPLSL3VPNVRFPERFCURRNUMROUTES
:
1213 return SNMP_INTEGER(bgp_mpls_l3vpn_current_routes(l3vpn_bgp
));
1218 static struct bgp_path_info
*
1219 bgp_lookup_route(struct bgp
*l3vpn_bgp
, struct bgp_dest
**dest
,
1220 struct prefix
*prefix
, uint16_t policy
, struct ipaddr
*nexthop
)
1222 struct bgp_path_info
*pi
= NULL
;
1223 struct bgp_table
*table
;
1225 switch (prefix
->family
) {
1227 table
= l3vpn_bgp
->rib
[AFI_IP
][SAFI_UNICAST
];
1230 table
= l3vpn_bgp
->rib
[AFI_IP6
][SAFI_UNICAST
];
1237 *dest
= bgp_node_lookup(table
, prefix
);
1241 /* now find the right path */
1242 pi
= bgp_dest_get_bgp_path_info(*dest
);
1243 for (; pi
; pi
= pi
->next
) {
1244 switch (nexthop
->ipa_type
) {
1246 if (nexthop
->ip
._v4_addr
.s_addr
1247 == pi
->attr
->nexthop
.s_addr
)
1251 if (memcmp(&nexthop
->ip
._v6_addr
,
1252 &pi
->attr
->mp_nexthop_global
,
1253 sizeof(struct in6_addr
))
1264 static struct bgp_path_info
*bgp_lookup_route_next(struct bgp
**l3vpn_bgp
,
1265 struct bgp_dest
**dest
,
1266 struct prefix
*prefix
,
1268 struct ipaddr
*nexthop
)
1270 struct bgp_path_info
*pi
= NULL
;
1271 struct bgp_table
*table
;
1272 const struct prefix
*p
;
1276 if (prefix
->prefixlen
== 0) {
1278 table
= (*l3vpn_bgp
)->rib
[AFI_IP
][SAFI_UNICAST
];
1279 for (*dest
= bgp_table_top(table
); *dest
;
1280 *dest
= bgp_route_next(*dest
)) {
1281 pi
= bgp_dest_get_bgp_path_info(*dest
);
1288 table
= (*l3vpn_bgp
)->rib
[AFI_IP6
][SAFI_UNICAST
];
1289 for (*dest
= bgp_table_top(table
); *dest
;
1290 *dest
= bgp_route_next(*dest
)) {
1291 pi
= bgp_dest_get_bgp_path_info(*dest
);
1298 /* real next search for the entry first use exact lookup */
1299 pi
= bgp_lookup_route(*l3vpn_bgp
, dest
, prefix
, *policy
, nexthop
);
1304 p
= bgp_dest_get_prefix(*dest
);
1307 /* We have found the input path let's find the next one in the list */
1309 /* ensure OID is always higher for multipath routes by
1310 * incrementing opaque policy oid
1316 /* No more paths in the input route so find the next route */
1318 *l3vpn_bgp
= bgp_lookup_by_name_next((*l3vpn_bgp
)->name
)) {
1321 table
= (*l3vpn_bgp
)->rib
[AFI_IP
][SAFI_UNICAST
];
1322 *dest
= bgp_table_top(table
);
1325 *dest
= bgp_route_next(*dest
);
1328 for (; *dest
; *dest
= bgp_route_next(*dest
)) {
1329 pi
= bgp_dest_get_bgp_path_info(*dest
);
1334 if (family
== AF_INET
) {
1335 table
= (*l3vpn_bgp
)
1336 ->rib
[AFI_IP6
][SAFI_UNICAST
];
1337 *dest
= bgp_table_top(table
);
1348 static bool is_addr_type(oid id
)
1351 case INETADDRESSTYPEUNKNOWN
:
1352 case INETADDRESSTYPEIPV4
:
1353 case INETADDRESSTYPEIPV6
:
1359 /* 1.3.6.1.2.1.10.166.11.1.4.1.1.x = 14*/
1360 #define PERFTAB_NAMELEN 14
1362 static struct bgp_path_info
*bgpL3vpnRte_lookup(struct variable
*v
, oid name
[],
1363 size_t *length
, char *vrf_name
,
1364 struct bgp
**l3vpn_bgp
,
1365 struct bgp_dest
**dest
,
1366 uint16_t *policy
, int exact
)
1369 uint8_t vrf_name_len
= 0;
1370 struct bgp_path_info
*pi
= NULL
;
1371 size_t namelen
= v
? v
->namelen
: IFCONFTAB_NAMELEN
;
1372 struct prefix prefix
= {0};
1373 struct ipaddr nexthop
= {0};
1374 uint8_t prefix_type
;
1375 uint8_t nexthop_type
;
1377 if ((uint32_t)(*length
- namelen
) > (VRF_NAMSIZ
+ 37))
1380 if (*length
- namelen
!= 0) {
1381 /* parse incoming OID */
1382 for (i
= namelen
; i
< (*length
); i
++) {
1383 if (is_addr_type(name
[i
]))
1387 if (vrf_name_len
> VRF_NAMSIZ
)
1390 oid2string(name
+ namelen
, vrf_name_len
, vrf_name
);
1391 prefix_type
= name
[i
++];
1392 switch (prefix_type
) {
1393 case INETADDRESSTYPEUNKNOWN
:
1394 prefix
.family
= AF_UNSPEC
;
1396 case INETADDRESSTYPEIPV4
:
1397 prefix
.family
= AF_INET
;
1398 oid2in_addr(&name
[i
], sizeof(struct in_addr
),
1400 i
+= sizeof(struct in_addr
);
1402 case INETADDRESSTYPEIPV6
:
1403 prefix
.family
= AF_INET6
;
1404 oid2in6_addr(&name
[i
], &prefix
.u
.prefix6
);
1405 i
+= sizeof(struct in6_addr
);
1408 prefix
.prefixlen
= (uint8_t)name
[i
++];
1409 *policy
|= name
[i
++] << 8;
1410 *policy
|= name
[i
++];
1411 nexthop_type
= name
[i
++];
1412 switch (nexthop_type
) {
1413 case INETADDRESSTYPEUNKNOWN
:
1414 nexthop
.ipa_type
= (prefix
.family
== AF_INET
)
1418 case INETADDRESSTYPEIPV4
:
1419 nexthop
.ipa_type
= IPADDR_V4
;
1420 oid2in_addr(&name
[i
], sizeof(struct in_addr
),
1421 &nexthop
.ip
._v4_addr
);
1422 /* i += sizeof(struct in_addr); */
1424 case INETADDRESSTYPEIPV6
:
1425 nexthop
.ipa_type
= IPADDR_V6
;
1426 oid2in6_addr(&name
[i
], &nexthop
.ip
._v6_addr
);
1427 /* i += sizeof(struct in6_addr); */
1433 *l3vpn_bgp
= bgp_lookup_by_name(vrf_name
);
1434 if (*l3vpn_bgp
&& !is_bgp_vrf_mplsvpn(*l3vpn_bgp
))
1436 if (*l3vpn_bgp
== NULL
)
1439 /* now lookup the route in this bgp table */
1440 pi
= bgp_lookup_route(*l3vpn_bgp
, dest
, &prefix
, *policy
,
1445 str_len
= strnlen(vrf_name
, VRF_NAMSIZ
);
1447 *l3vpn_bgp
= bgp_lookup_by_name_next(vrf_name
);
1449 /* otherwise lookup the one we have */
1450 *l3vpn_bgp
= bgp_lookup_by_name(vrf_name
);
1452 if (*l3vpn_bgp
== NULL
)
1455 pi
= bgp_lookup_route_next(l3vpn_bgp
, dest
, &prefix
, policy
,
1458 uint8_t vrf_name_len
=
1459 strnlen((*l3vpn_bgp
)->name
, VRF_NAMSIZ
);
1460 const struct prefix
*p
= bgp_dest_get_prefix(*dest
);
1462 bool v4
= (p
->family
== AF_INET
);
1463 uint8_t addr_len
= v4
? sizeof(struct in_addr
)
1464 : sizeof(struct in6_addr
);
1465 struct attr
*attr
= pi
->attr
;
1467 /* copy the index parameters */
1468 oid_copy_str(&name
[namelen
], (*l3vpn_bgp
)->name
,
1470 oid_index
= namelen
+ vrf_name_len
;
1472 name
[oid_index
++] = INETADDRESSTYPEIPV4
;
1473 oid_copy_in_addr(&name
[oid_index
],
1476 name
[oid_index
++] = INETADDRESSTYPEIPV6
;
1477 oid_copy_in6_addr(&name
[oid_index
],
1481 oid_index
+= addr_len
;
1482 name
[oid_index
++] = p
->prefixlen
;
1483 name
[oid_index
++] = *policy
>> 8;
1484 name
[oid_index
++] = *policy
& 0xff;
1486 if (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
1487 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
1489 INETADDRESSTYPEUNKNOWN
;
1491 name
[oid_index
++] = INETADDRESSTYPEIPV4
;
1492 oid_copy_in_addr(&name
[oid_index
],
1494 oid_index
+= sizeof(struct in_addr
);
1497 if (IN6_IS_ADDR_UNSPECIFIED(
1498 &attr
->mp_nexthop_global
))
1500 INETADDRESSTYPEUNKNOWN
;
1502 name
[oid_index
++] = INETADDRESSTYPEIPV6
;
1505 &attr
->mp_nexthop_global
);
1506 oid_index
+= sizeof(struct in6_addr
);
1509 *length
= oid_index
;
1515 static uint8_t *mplsL3vpnRteTable(struct variable
*v
, oid name
[],
1516 size_t *length
, int exact
, size_t *var_len
,
1517 WriteMethod
**write_method
)
1519 char vrf_name
[VRF_NAMSIZ
];
1520 struct bgp
*l3vpn_bgp
;
1521 struct bgp_dest
*dest
;
1522 struct bgp_path_info
*pi
, *bpi_ultimate
;
1523 const struct prefix
*p
;
1524 uint16_t policy
= 0;
1526 if (smux_header_table(v
, name
, length
, exact
, var_len
, write_method
)
1530 memset(vrf_name
, 0, VRF_NAMSIZ
);
1531 pi
= bgpL3vpnRte_lookup(v
, name
, length
, vrf_name
, &l3vpn_bgp
, &dest
,
1538 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pi
);
1540 p
= bgp_dest_get_prefix(dest
);
1546 case MPLSL3VPNVRFRTEINETCIDRDESTTYPE
:
1547 switch (p
->family
) {
1549 return SNMP_INTEGER(INETADDRESSTYPEIPV4
);
1551 return SNMP_INTEGER(INETADDRESSTYPEIPV6
);
1553 return SNMP_INTEGER(INETADDRESSTYPEUNKNOWN
);
1555 case MPLSL3VPNVRFRTEINETCIDRDEST
:
1556 switch (p
->family
) {
1558 return SNMP_IPADDRESS(p
->u
.prefix4
);
1560 return SNMP_IP6ADDRESS(p
->u
.prefix6
);
1565 case MPLSL3VPNVRFRTEINETCIDRPFXLEN
:
1566 return SNMP_INTEGER(p
->prefixlen
);
1567 case MPLSL3VPNVRFRTEINETCIDRPOLICY
:
1568 *var_len
= sizeof(mpls_l3vpn_policy_oid
);
1569 mpls_l3vpn_policy_oid
[0] = policy
>> 8;
1570 mpls_l3vpn_policy_oid
[1] = policy
& 0xff;
1571 return (uint8_t *)mpls_l3vpn_policy_oid
;
1572 case MPLSL3VPNVRFRTEINETCIDRNHOPTYPE
:
1573 if (!BGP_ATTR_NEXTHOP_AFI_IP6(pi
->attr
)) {
1574 if (pi
->attr
->nexthop
.s_addr
== INADDR_ANY
)
1575 return SNMP_INTEGER(INETADDRESSTYPEUNKNOWN
);
1577 return SNMP_INTEGER(INETADDRESSTYPEIPV4
);
1578 } else if (IN6_IS_ADDR_UNSPECIFIED(
1579 &pi
->attr
->mp_nexthop_global
))
1580 return SNMP_INTEGER(INETADDRESSTYPEUNKNOWN
);
1582 return SNMP_INTEGER(INETADDRESSTYPEIPV6
);
1584 case MPLSL3VPNVRFRTEINETCIDRNEXTHOP
:
1585 if (!BGP_ATTR_NEXTHOP_AFI_IP6(pi
->attr
))
1586 if (pi
->attr
->nexthop
.s_addr
== INADDR_ANY
) {
1588 return (uint8_t *)empty_nhop
;
1590 return SNMP_IPADDRESS(pi
->attr
->nexthop
);
1591 else if (IN6_IS_ADDR_UNSPECIFIED(
1592 &pi
->attr
->mp_nexthop_global
)) {
1594 return (uint8_t *)empty_nhop
;
1596 return SNMP_IP6ADDRESS(pi
->attr
->mp_nexthop_global
);
1598 case MPLSL3VPNVRFRTEINETCIDRIFINDEX
:
1599 if (pi
->nexthop
&& pi
->nexthop
->nexthop
)
1600 return SNMP_INTEGER(pi
->nexthop
->nexthop
->ifindex
);
1602 return SNMP_INTEGER(0);
1603 case MPLSL3VPNVRFRTEINETCIDRTYPE
:
1604 if (pi
->nexthop
&& pi
->nexthop
->nexthop
) {
1605 switch (pi
->nexthop
->nexthop
->type
) {
1606 case NEXTHOP_TYPE_IFINDEX
:
1607 return SNMP_INTEGER(
1608 MPLSL3VPNVRFRTECIDRTYPELOCAL
);
1609 case NEXTHOP_TYPE_IPV4
:
1610 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1611 case NEXTHOP_TYPE_IPV6
:
1612 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1613 return SNMP_INTEGER(
1614 MPLSL3VPNVRFRTECIDRTYPEREMOTE
);
1615 case NEXTHOP_TYPE_BLACKHOLE
:
1616 switch (pi
->nexthop
->nexthop
->bh_type
) {
1617 case BLACKHOLE_REJECT
:
1618 return SNMP_INTEGER(
1619 MPLSL3VPNVRFRTECIDRTYPEREJECT
);
1620 case BLACKHOLE_UNSPEC
:
1621 case BLACKHOLE_NULL
:
1622 case BLACKHOLE_ADMINPROHIB
:
1623 return SNMP_INTEGER(
1624 MPLSL3VPNVRFRTECIDRTYPEBLACKHOLE
);
1629 return SNMP_INTEGER(MPLSL3VPNVRFRTECIDRTYPEOTHER
);
1630 case MPLSL3VPNVRFRTEINETCIDRPROTO
:
1632 case ZEBRA_ROUTE_CONNECT
:
1633 return SNMP_INTEGER(IANAIPROUTEPROTOCOLLOCAL
);
1634 case ZEBRA_ROUTE_STATIC
:
1635 return SNMP_INTEGER(IANAIPROUTEPROTOCOLNETMGMT
);
1636 case ZEBRA_ROUTE_RIP
:
1637 case ZEBRA_ROUTE_RIPNG
:
1638 return SNMP_INTEGER(IANAIPROUTEPROTOCOLRIP
);
1639 case ZEBRA_ROUTE_OSPF
:
1640 case ZEBRA_ROUTE_OSPF6
:
1641 return SNMP_INTEGER(IANAIPROUTEPROTOCOLOSPF
);
1642 case ZEBRA_ROUTE_ISIS
:
1643 return SNMP_INTEGER(IANAIPROUTEPROTOCOLISIS
);
1644 case ZEBRA_ROUTE_BGP
:
1645 return SNMP_INTEGER(IANAIPROUTEPROTOCOLBGP
);
1646 case ZEBRA_ROUTE_EIGRP
:
1647 return SNMP_INTEGER(IANAIPROUTEPROTOCOLCISCOEIGRP
);
1649 return SNMP_INTEGER(IANAIPROUTEPROTOCOLOTHER
);
1651 case MPLSL3VPNVRFRTEINETCIDRAGE
:
1652 return SNMP_INTEGER(pi
->uptime
);
1653 case MPLSL3VPNVRFRTEINETCIDRNEXTHOPAS
:
1654 return SNMP_INTEGER(pi
->peer
? pi
->peer
->as
: 0);
1655 case MPLSL3VPNVRFRTEINETCIDRMETRIC1
:
1656 if (bpi_ultimate
->extra
)
1657 return SNMP_INTEGER(bpi_ultimate
->extra
->igpmetric
);
1659 return SNMP_INTEGER(0);
1660 case MPLSL3VPNVRFRTEINETCIDRMETRIC2
:
1661 return SNMP_INTEGER(-1);
1662 case MPLSL3VPNVRFRTEINETCIDRMETRIC3
:
1663 return SNMP_INTEGER(-1);
1664 case MPLSL3VPNVRFRTEINETCIDRMETRIC4
:
1665 return SNMP_INTEGER(-1);
1666 case MPLSL3VPNVRFRTEINETCIDRMETRIC5
:
1667 return SNMP_INTEGER(-1);
1668 case MPLSL3VPNVRFRTEINETCIDRXCPOINTER
:
1669 return SNMP_OCTET(0);
1670 case MPLSL3VPNVRFRTEINETCIDRSTATUS
:
1671 return SNMP_INTEGER(1);
1676 void bgp_mpls_l3vpn_module_init(void)
1678 hook_register(bgp_vrf_status_changed
, bgp_vrf_check_update_active
);
1679 hook_register(bgp_snmp_init_stats
, bgp_init_snmp_stats
);
1680 hook_register(bgp_snmp_update_last_changed
,
1681 bgp_mpls_l3vpn_update_last_changed
);
1682 hook_register(bgp_snmp_update_stats
, bgp_snmp_update_route_stats
);
1683 REGISTER_MIB("mplsL3VpnMIB", mpls_l3vpn_variables
, variable
,