2 * Copyright (C) 2020 Volta Networks Inc
4 * This file is part of FRR.
6 * FRRouting is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * FRRouting is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <net-snmp/net-snmp-config.h>
24 #include <net-snmp/net-snmp-includes.h>
35 #include "lib/version.h"
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_attr.h"
40 #include "bgpd/bgp_ecommunity.h"
41 #include "bgpd/bgp_mplsvpn.h"
42 #include "bgpd/bgp_mplsvpn_snmp.h"
44 #define BGP_mplsvpn_notif_enable_true 1
45 #define BGP_mplsvpn_notif_enable_false 2
47 /* MPLSL3VPN MIB described in RFC4382 */
48 #define MPLSL3VPNMIB 1, 3, 6, 1, 2, 1, 10, 166, 11
50 /* MPLSL3VPN Scalars */
51 #define MPLSL3VPNCONFIGUREDVRFS 1
52 #define MPLSL3VPNACTIVEVRFS 2
53 #define MPLSL3VPNCONNECTEDINTERFACES 3
54 #define MPLSL3VPNNOTIFICATIONENABLE 4
55 #define MPLSL3VPNCONFMAXPOSSRTS 5
56 #define MPLSL3VPNVRFCONFRTEMXTHRSHTIME 6
57 #define MPLSL3VPNILLLBLRCVTHRSH 7
59 /* MPLSL3VPN IFConf Table */
60 #define MPLSL3VPNIFVPNCLASSIFICATION 1
61 #define MPLSL3VPNIFCONFSTORAGETYPE 2
62 #define MPLSL3VPNIFCONFROWSTATUS 3
64 /* MPLSL3VPN VRF Table */
65 #define MPLSL3VPNVRFVPNID 1
66 #define MPLSL3VPNVRFDESC 2
67 #define MPLSL3VPNVRFRD 3
68 #define MPLSL3VPNVRFCREATIONTIME 4
69 #define MPLSL3VPNVRFOPERSTATUS 5
70 #define MPLSL3VPNVRFACTIVEINTERFACES 6
71 #define MPLSL3VPNVRFASSOCIATEDINTERFACES 7
72 #define MPLSL3VPNVRFCONFMIDRTETHRESH 8
73 #define MPLSL3VPNVRFCONFHIGHRTETHRSH 9
74 #define MPLSL3VPNVRFCONFMAXROUTES 10
75 #define MPLSL3VPNVRFCONFLASTCHANGED 11
76 #define MPLSL3VPNVRFCONFROWSTATUS 12
77 #define MPLSL3VPNVRFCONFADMINSTATUS 13
78 #define MPLSL3VPNVRFCONFSTORAGETYPE 14
80 /* MPLSL3VPN RT Table */
81 #define MPLSL3VPNVRFRT 1
82 #define MPLSL3VPNVRFRTDESCR 2
83 #define MPLSL3VPNVRFRTROWSTATUS 3
84 #define MPLSL3VPNVRFRTSTORAGETYPE 4
86 /* MPLSL3VPN PERF Table */
87 #define MPLSL3VPNVRFPERFROUTESADDED 1
88 #define MPLSL3VPNVRFPERFROUTESDELETED 2
89 #define MPLSL3VPNVRFPERFCURRNUMROUTES 3
91 /* MPLSL3VPN RTE Table */
92 #define MPLSL3VPNVRFRTEINETCIDRDESTTYPE 1
93 #define MPLSL3VPNVRFRTEINETCIDRDEST 2
94 #define MPLSL3VPNVRFRTEINETCIDRPFXLEN 3
95 #define MPLSL3VPNVRFRTEINETCIDRPOLICY 4
96 #define MPLSL3VPNVRFRTEINETCIDRNHOPTYPE 5
97 #define MPLSL3VPNVRFRTEINETCIDRNEXTHOP 6
98 #define MPLSL3VPNVRFRTEINETCIDRIFINDEX 7
99 #define MPLSL3VPNVRFRTEINETCIDRTYPE 8
100 #define MPLSL3VPNVRFRTEINETCIDRPROTO 9
101 #define MPLSL3VPNVRFRTEINETCIDRAGE 10
102 #define MPLSL3VPNVRFRTEINETCIDRNEXTHOPAS 11
103 #define MPLSL3VPNVRFRTEINETCIDRMETRIC1 12
104 #define MPLSL3VPNVRFRTEINETCIDRMETRIC2 13
105 #define MPLSL3VPNVRFRTEINETCIDRMETRIC3 14
106 #define MPLSL3VPNVRFRTEINETCIDRMETRIC4 15
107 #define MPLSL3VPNVRFRTEINETCIDRMETRIC5 16
108 #define MPLSL3VPNVRFRTEINETCIDRXCPOINTER 17
109 #define MPLSL3VPNVRFRTEINETCIDRSTATUS 18
112 #define MPLSL3VPNVRFUP 1
113 #define MPLSL3VPNDOWN 2
115 /* SNMP value hack. */
116 #define INTEGER ASN_INTEGER
117 #define INTEGER32 ASN_INTEGER
118 #define COUNTER32 ASN_COUNTER
119 #define OCTET_STRING ASN_OCTET_STR
120 #define IPADDRESS ASN_IPADDRESS
121 #define GAUGE32 ASN_UNSIGNED
122 #define TIMETICKS ASN_TIMETICKS
123 #define OID ASN_OBJECT_ID
125 /* Declare static local variables for convenience. */
128 #define RT_PREAMBLE_SIZE 20
130 /* BGP-MPLS-MIB instances */
131 static oid mpls_l3vpn_oid
[] = {MPLSL3VPNMIB
};
132 static oid mpls_l3vpn_trap_oid
[] = {MPLSL3VPNMIB
, 0};
133 static char rd_buf
[RD_ADDRSTRLEN
];
134 /* Notifications enabled by default */
135 static uint8_t bgp_mplsvpn_notif_enable
= SNMP_TRUE
;
136 static oid mpls_l3vpn_policy_oid
[2] = {0, 0};
137 static const char *empty_nhop
= "";
138 char rt_description
[VRF_NAMSIZ
+ RT_PREAMBLE_SIZE
];
140 static uint8_t *mplsL3vpnConfiguredVrfs(struct variable
*, oid
[], size_t *, int,
141 size_t *, WriteMethod
**);
143 static uint8_t *mplsL3vpnActiveVrfs(struct variable
*, oid
[], size_t *, int,
144 size_t *, WriteMethod
**);
146 static uint8_t *mplsL3vpnConnectedInterfaces(struct variable
*, oid
[], size_t *,
147 int, size_t *, WriteMethod
**);
149 static uint8_t *mplsL3vpnNotificationEnable(struct variable
*, oid
[], size_t *,
150 int, size_t *, WriteMethod
**);
152 static uint8_t *mplsL3vpnVrfConfMaxPossRts(struct variable
*, oid
[], size_t *,
153 int, size_t *, WriteMethod
**);
155 static uint8_t *mplsL3vpnVrfConfRteMxThrshTime(struct variable
*, oid
[],
156 size_t *, int, size_t *,
159 static uint8_t *mplsL3vpnIllLblRcvThrsh(struct variable
*, oid
[], size_t *, int,
160 size_t *, WriteMethod
**);
162 static uint8_t *mplsL3vpnVrfTable(struct variable
*, oid
[], size_t *, int,
163 size_t *, WriteMethod
**);
165 static uint8_t *mplsL3vpnVrfRtTable(struct variable
*, oid
[], size_t *, int,
166 size_t *, WriteMethod
**);
168 static uint8_t *mplsL3vpnIfConfTable(struct variable
*, oid
[], size_t *, int,
169 size_t *, WriteMethod
**);
171 static uint8_t *mplsL3vpnPerfTable(struct variable
*, oid
[], size_t *, int,
172 size_t *, WriteMethod
**);
174 static uint8_t *mplsL3vpnRteTable(struct variable
*, oid
[], size_t *, int,
175 size_t *, WriteMethod
**);
178 static struct variable mpls_l3vpn_variables
[] = {
180 {MPLSL3VPNCONFIGUREDVRFS
,
183 mplsL3vpnConfiguredVrfs
,
186 {MPLSL3VPNACTIVEVRFS
,
192 {MPLSL3VPNCONNECTEDINTERFACES
,
195 mplsL3vpnConnectedInterfaces
,
198 {MPLSL3VPNNOTIFICATIONENABLE
,
201 mplsL3vpnNotificationEnable
,
204 {MPLSL3VPNCONFMAXPOSSRTS
,
207 mplsL3vpnVrfConfMaxPossRts
,
210 {MPLSL3VPNVRFCONFRTEMXTHRSHTIME
,
213 mplsL3vpnVrfConfRteMxThrshTime
,
216 {MPLSL3VPNILLLBLRCVTHRSH
,
219 mplsL3vpnIllLblRcvThrsh
,
224 {MPLSL3VPNIFVPNCLASSIFICATION
,
227 mplsL3vpnIfConfTable
,
230 {MPLSL3VPNIFCONFSTORAGETYPE
,
233 mplsL3vpnIfConfTable
,
236 {MPLSL3VPNIFCONFROWSTATUS
,
239 mplsL3vpnIfConfTable
,
243 /* mplsL3VpnVrf Table */
262 {MPLSL3VPNVRFCREATIONTIME
,
268 {MPLSL3VPNVRFOPERSTATUS
,
274 {MPLSL3VPNVRFACTIVEINTERFACES
,
280 {MPLSL3VPNVRFASSOCIATEDINTERFACES
,
286 {MPLSL3VPNVRFCONFMIDRTETHRESH
,
292 {MPLSL3VPNVRFCONFHIGHRTETHRSH
,
298 {MPLSL3VPNVRFCONFMAXROUTES
,
304 {MPLSL3VPNVRFCONFLASTCHANGED
,
310 {MPLSL3VPNVRFCONFROWSTATUS
,
316 {MPLSL3VPNVRFCONFADMINSTATUS
,
322 {MPLSL3VPNVRFCONFSTORAGETYPE
,
329 /* mplsL3vpnVrfRt Table */
336 {MPLSL3VPNVRFRTDESCR
,
342 {MPLSL3VPNVRFRTROWSTATUS
,
348 {MPLSL3VPNVRFRTSTORAGETYPE
,
355 /* mplsL3VpnPerfTable */
356 {MPLSL3VPNVRFPERFROUTESADDED
,
362 {MPLSL3VPNVRFPERFROUTESDELETED
,
368 {MPLSL3VPNVRFPERFCURRNUMROUTES
,
375 /* mplsVpnRteTable */
376 {MPLSL3VPNVRFRTEINETCIDRDESTTYPE
,
382 {MPLSL3VPNVRFRTEINETCIDRDEST
,
388 {MPLSL3VPNVRFRTEINETCIDRPFXLEN
,
394 {MPLSL3VPNVRFRTEINETCIDRPOLICY
,
400 {MPLSL3VPNVRFRTEINETCIDRNHOPTYPE
,
406 {MPLSL3VPNVRFRTEINETCIDRNEXTHOP
,
412 {MPLSL3VPNVRFRTEINETCIDRIFINDEX
,
418 {MPLSL3VPNVRFRTEINETCIDRTYPE
,
424 {MPLSL3VPNVRFRTEINETCIDRPROTO
,
430 {MPLSL3VPNVRFRTEINETCIDRAGE
,
436 {MPLSL3VPNVRFRTEINETCIDRNEXTHOPAS
,
442 {MPLSL3VPNVRFRTEINETCIDRMETRIC1
,
448 {MPLSL3VPNVRFRTEINETCIDRMETRIC2
,
454 {MPLSL3VPNVRFRTEINETCIDRMETRIC3
,
460 {MPLSL3VPNVRFRTEINETCIDRMETRIC4
,
466 {MPLSL3VPNVRFRTEINETCIDRMETRIC5
,
472 {MPLSL3VPNVRFRTEINETCIDRXCPOINTER
,
478 {MPLSL3VPNVRFRTEINETCIDRSTATUS
,
486 /* timeticks are in hundredths of a second */
487 static void bgp_mpls_l3vpn_update_timeticks(time_t *counter
)
492 *counter
= (tv
.tv_sec
* 100) + (tv
.tv_usec
/ 10000);
495 static int bgp_mpls_l3vpn_update_last_changed(struct bgp
*bgp
)
498 bgp_mpls_l3vpn_update_timeticks(
499 &(bgp
->snmp_stats
->modify_time
));
503 static uint32_t bgp_mpls_l3vpn_current_routes(struct bgp
*l3vpn_bgp
)
506 struct bgp_table
*table
;
507 struct bgp_dest
*dest
;
508 struct bgp_path_info
*pi
;
510 table
= l3vpn_bgp
->rib
[AFI_IP
][SAFI_UNICAST
];
511 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
512 pi
= bgp_dest_get_bgp_path_info(dest
);
513 for (; pi
; pi
= pi
->next
)
516 table
= l3vpn_bgp
->rib
[AFI_IP6
][SAFI_UNICAST
];
517 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
518 pi
= bgp_dest_get_bgp_path_info(dest
);
519 for (; pi
; pi
= pi
->next
)
525 static int bgp_init_snmp_stats(struct bgp
*bgp
)
527 if (is_bgp_vrf_mplsvpn(bgp
)) {
528 if (bgp
->snmp_stats
== NULL
) {
529 bgp
->snmp_stats
= XCALLOC(
530 MTYPE_BGP
, sizeof(struct bgp_snmp_stats
));
531 /* fix up added routes */
532 if (bgp
->snmp_stats
) {
533 bgp
->snmp_stats
->routes_added
=
534 bgp_mpls_l3vpn_current_routes(bgp
);
535 bgp_mpls_l3vpn_update_timeticks(
536 &(bgp
->snmp_stats
->creation_time
));
540 if (bgp
->snmp_stats
) {
541 XFREE(MTYPE_BGP
, bgp
->snmp_stats
);
542 bgp
->snmp_stats
= NULL
;
545 /* Something changed - update the timestamp */
546 bgp_mpls_l3vpn_update_last_changed(bgp
);
550 static int bgp_snmp_update_route_stats(struct bgp_dest
*dest
,
551 struct bgp_path_info
*pi
, bool added
)
553 struct bgp_table
*table
;
556 table
= bgp_dest_table(dest
);
557 /* only update if we have a stats block - MPLSVPN vrfs for now*/
558 if (table
&& table
->bgp
&& table
->bgp
->snmp_stats
) {
560 table
->bgp
->snmp_stats
->routes_added
++;
562 table
->bgp
->snmp_stats
->routes_deleted
++;
568 static bool is_bgp_vrf_active(struct bgp
*bgp
)
571 struct interface
*ifp
;
573 /* if there is one interface in the vrf which is up then it is deemed
576 vrf
= vrf_lookup_by_id(bgp
->vrf_id
);
579 RB_FOREACH (ifp
, if_name_head
, &vrf
->ifaces_by_name
) {
580 /* if we are in a vrf skip the l3mdev */
581 if (bgp
->name
&& strncmp(ifp
->name
, bgp
->name
, VRF_NAMSIZ
) == 0)
591 static struct trap_object l3vpn_trap_list
[] = {{5, {1, 2, 1, 1, 5} },
592 {5, {1, 2, 2, 1, 6} } };
594 static int bgp_vrf_check_update_active(struct bgp
*bgp
, struct interface
*ifp
)
596 bool new_active
= false;
598 struct index_oid trap_index
[2];
600 if (!is_bgp_vrf_mplsvpn(bgp
) || bgp
->snmp_stats
== NULL
601 || !bgp_mplsvpn_notif_enable
)
603 new_active
= is_bgp_vrf_active(bgp
);
604 if (bgp
->snmp_stats
->active
!= new_active
) {
605 /* add trap in here */
606 bgp
->snmp_stats
->active
= new_active
;
608 /* send relevent trap */
609 if (bgp
->snmp_stats
->active
)
610 trap
= MPLSL3VPNVRFUP
;
612 trap
= MPLSL3VPNDOWN
;
615 * first index vrf_name + ifindex
616 * second index vrf_name
618 trap_index
[1].indexlen
= strnlen(bgp
->name
, VRF_NAMSIZ
);
619 oid_copy_str(trap_index
[0].indexname
, bgp
->name
,
620 trap_index
[1].indexlen
);
621 oid_copy_str(trap_index
[1].indexname
, bgp
->name
,
622 trap_index
[1].indexlen
);
623 trap_index
[0].indexlen
=
624 trap_index
[1].indexlen
+ sizeof(ifindex_t
);
625 oid_copy_int(trap_index
[0].indexname
+ trap_index
[1].indexlen
,
626 (int *)&(ifp
->ifindex
));
628 smux_trap_multi_index(
629 mpls_l3vpn_variables
, array_size(mpls_l3vpn_variables
),
630 mpls_l3vpn_trap_oid
, array_size(mpls_l3vpn_trap_oid
),
631 mpls_l3vpn_oid
, sizeof(mpls_l3vpn_oid
) / sizeof(oid
),
632 trap_index
, array_size(trap_index
), l3vpn_trap_list
,
633 array_size(l3vpn_trap_list
), trap
);
635 bgp_mpls_l3vpn_update_last_changed(bgp
);
639 static uint8_t *mplsL3vpnConfiguredVrfs(struct variable
*v
, oid name
[],
640 size_t *length
, int exact
,
642 WriteMethod
**write_method
)
644 struct listnode
*node
, *nnode
;
648 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
652 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
653 if (is_bgp_vrf_mplsvpn(bgp
))
656 return SNMP_INTEGER(count
);
659 static uint8_t *mplsL3vpnActiveVrfs(struct variable
*v
, oid name
[],
660 size_t *length
, int exact
, size_t *var_len
,
661 WriteMethod
**write_method
)
663 struct listnode
*node
, *nnode
;
667 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
671 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
672 if (is_bgp_vrf_mplsvpn(bgp
) && is_bgp_vrf_active(bgp
))
675 return SNMP_INTEGER(count
);
678 static uint8_t *mplsL3vpnConnectedInterfaces(struct variable
*v
, oid name
[],
679 size_t *length
, int exact
,
681 WriteMethod
**write_method
)
683 struct listnode
*node
, *nnode
;
688 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
692 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
693 if (is_bgp_vrf_mplsvpn(bgp
)) {
694 vrf
= vrf_lookup_by_name(bgp
->name
);
698 count
+= vrf_interface_count(vrf
);
702 return SNMP_INTEGER(count
);
705 static int write_mplsL3vpnNotificationEnable(int action
, uint8_t *var_val
,
706 uint8_t var_val_type
,
707 size_t var_val_len
, uint8_t *statP
,
708 oid
*name
, size_t length
)
712 if (var_val_type
!= ASN_INTEGER
)
713 return SNMP_ERR_WRONGTYPE
;
715 if (var_val_len
!= sizeof(long))
716 return SNMP_ERR_WRONGLENGTH
;
718 intval
= *(long *)var_val
;
719 bgp_mplsvpn_notif_enable
= intval
;
720 return SNMP_ERR_NOERROR
;
723 static uint8_t *mplsL3vpnNotificationEnable(struct variable
*v
, oid name
[],
724 size_t *length
, int exact
,
726 WriteMethod
**write_method
)
728 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
732 *write_method
= write_mplsL3vpnNotificationEnable
;
733 return SNMP_INTEGER(bgp_mplsvpn_notif_enable
);
736 static uint8_t *mplsL3vpnVrfConfMaxPossRts(struct variable
*v
, oid name
[],
737 size_t *length
, int exact
,
739 WriteMethod
**write_method
)
741 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
745 return SNMP_INTEGER(0);
748 static uint8_t *mplsL3vpnVrfConfRteMxThrshTime(struct variable
*v
, oid name
[],
749 size_t *length
, int exact
,
751 WriteMethod
**write_method
)
753 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
757 return SNMP_INTEGER(0);
760 static uint8_t *mplsL3vpnIllLblRcvThrsh(struct variable
*v
, oid name
[],
761 size_t *length
, int exact
,
763 WriteMethod
**write_method
)
765 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
769 return SNMP_INTEGER(0);
773 static struct bgp
*bgp_lookup_by_name_next(char *vrf_name
)
775 struct bgp
*bgp
, *bgp_next
= NULL
;
776 struct listnode
*node
, *nnode
;
780 * the vrfs are not stored alphabetically but since we are using the
781 * vrf name as an index we need the getnext function to return them
782 * in a atrict order. Thus run through and find the best next one.
784 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
785 if (!is_bgp_vrf_mplsvpn(bgp
))
787 if (strnlen(vrf_name
, VRF_NAMSIZ
) == 0 && bgp_next
== NULL
) {
792 if (first
|| strncmp(bgp
->name
, vrf_name
, VRF_NAMSIZ
) > 0) {
793 if (bgp_next
== NULL
)
795 else if (strncmp(bgp
->name
, bgp_next
->name
, VRF_NAMSIZ
)
803 /* 1.3.6.1.2.1.10.166.11.1.2.1.1.x = 14*/
804 #define IFCONFTAB_NAMELEN 14
805 static struct bgp
*bgpL3vpnIfConf_lookup(struct variable
*v
, oid name
[],
806 size_t *length
, char *vrf_name
,
807 ifindex_t
*ifindex
, int exact
)
809 struct bgp
*bgp
= NULL
;
810 size_t namelen
= v
? v
->namelen
: IFCONFTAB_NAMELEN
;
811 struct interface
*ifp
;
812 int vrf_name_len
, len
;
815 if (*length
- namelen
> (VRF_NAMSIZ
+ sizeof(uint32_t)))
817 /* do we have index info in the oid ? */
818 if (*length
- namelen
!= 0 && *length
- namelen
>= sizeof(uint32_t)) {
819 /* copy the info from the oid */
820 vrf_name_len
= *length
- (namelen
+ sizeof(ifindex_t
));
821 oid2string(name
+ namelen
, vrf_name_len
, vrf_name
);
822 oid2int(name
+ namelen
+ vrf_name_len
, ifindex
);
826 /* Check the length. */
827 bgp
= bgp_lookup_by_name(vrf_name
);
828 if (bgp
&& !is_bgp_vrf_mplsvpn(bgp
))
832 ifp
= if_lookup_by_index(*ifindex
, bgp
->vrf_id
);
836 if (strnlen(vrf_name
, VRF_NAMSIZ
) == 0)
837 bgp
= bgp_lookup_by_name_next(vrf_name
);
839 bgp
= bgp_lookup_by_name(vrf_name
);
842 ifp
= if_vrf_lookup_by_index_next(*ifindex
,
845 vrf_name_len
= strnlen(bgp
->name
, VRF_NAMSIZ
);
846 *ifindex
= ifp
->ifindex
;
847 len
= vrf_name_len
+ sizeof(ifindex_t
);
848 oid_copy_str(name
+ namelen
, bgp
->name
,
850 oid_copy_int(name
+ namelen
+ vrf_name_len
,
852 *length
= len
+ namelen
;
857 bgp
= bgp_lookup_by_name_next(bgp
->name
);
865 static uint8_t *mplsL3vpnIfConfTable(struct variable
*v
, oid name
[],
866 size_t *length
, int exact
, size_t *var_len
,
867 WriteMethod
**write_method
)
869 char vrf_name
[VRF_NAMSIZ
];
870 ifindex_t ifindex
= 0;
871 struct bgp
*l3vpn_bgp
;
873 if (smux_header_table(v
, name
, length
, exact
, var_len
, write_method
)
877 memset(vrf_name
, 0, VRF_NAMSIZ
);
878 l3vpn_bgp
= bgpL3vpnIfConf_lookup(v
, name
, length
, vrf_name
, &ifindex
,
884 case MPLSL3VPNIFVPNCLASSIFICATION
:
885 return SNMP_INTEGER(2);
886 case MPLSL3VPNIFCONFSTORAGETYPE
:
887 return SNMP_INTEGER(2);
888 case MPLSL3VPNIFCONFROWSTATUS
:
889 return SNMP_INTEGER(1);
894 /* 1.3.6.1.2.1.10.166.11.1.2.2.1.x = 14*/
895 #define VRFTAB_NAMELEN 14
897 static struct bgp
*bgpL3vpnVrf_lookup(struct variable
*v
, oid name
[],
898 size_t *length
, char *vrf_name
, int exact
)
900 struct bgp
*bgp
= NULL
;
901 size_t namelen
= v
? v
->namelen
: VRFTAB_NAMELEN
;
904 if (*length
- namelen
> VRF_NAMSIZ
)
906 oid2string(name
+ namelen
, *length
- namelen
, vrf_name
);
908 /* Check the length. */
909 bgp
= bgp_lookup_by_name(vrf_name
);
910 if (bgp
&& !is_bgp_vrf_mplsvpn(bgp
))
913 bgp
= bgp_lookup_by_name_next(vrf_name
);
918 len
= strnlen(bgp
->name
, VRF_NAMSIZ
);
919 oid_copy_str(name
+ namelen
, bgp
->name
, len
);
920 *length
= len
+ namelen
;
925 static uint8_t *mplsL3vpnVrfTable(struct variable
*v
, oid name
[],
926 size_t *length
, int exact
, size_t *var_len
,
927 WriteMethod
**write_method
)
929 char vrf_name
[VRF_NAMSIZ
];
930 struct bgp
*l3vpn_bgp
;
932 if (smux_header_table(v
, name
, length
, exact
, var_len
, write_method
)
936 memset(vrf_name
, 0, VRF_NAMSIZ
);
937 l3vpn_bgp
= bgpL3vpnVrf_lookup(v
, name
, length
, vrf_name
, exact
);
943 case MPLSL3VPNVRFVPNID
:
946 case MPLSL3VPNVRFDESC
:
947 *var_len
= strnlen(l3vpn_bgp
->name
, VRF_NAMSIZ
);
948 return (uint8_t *)l3vpn_bgp
->name
;
951 * this is a horror show but the MIB dicates one RD per vrf
952 * and not one RD per AFI as we (FRR) have. So this little gem
953 * returns the V4 one if it's set OR the v6 one if it's set or
954 * zero-length string id neither are set
956 memset(rd_buf
, 0, RD_ADDRSTRLEN
);
957 if (CHECK_FLAG(l3vpn_bgp
->vpn_policy
[AFI_IP
].flags
,
958 BGP_VPN_POLICY_TOVPN_RD_SET
))
959 prefix_rd2str(&l3vpn_bgp
->vpn_policy
[AFI_IP
].tovpn_rd
,
960 rd_buf
, sizeof(rd_buf
));
961 else if (CHECK_FLAG(l3vpn_bgp
->vpn_policy
[AFI_IP6
].flags
,
962 BGP_VPN_POLICY_TOVPN_RD_SET
))
963 prefix_rd2str(&l3vpn_bgp
->vpn_policy
[AFI_IP6
].tovpn_rd
,
964 rd_buf
, sizeof(rd_buf
));
966 *var_len
= strnlen(rd_buf
, RD_ADDRSTRLEN
);
967 return (uint8_t *)rd_buf
;
968 case MPLSL3VPNVRFCREATIONTIME
:
970 (uint32_t)l3vpn_bgp
->snmp_stats
->creation_time
);
971 case MPLSL3VPNVRFOPERSTATUS
:
972 if (l3vpn_bgp
->snmp_stats
->active
)
973 return SNMP_INTEGER(1);
975 return SNMP_INTEGER(2);
976 case MPLSL3VPNVRFACTIVEINTERFACES
:
977 return SNMP_INTEGER(bgp_vrf_interfaces(l3vpn_bgp
, true));
978 case MPLSL3VPNVRFASSOCIATEDINTERFACES
:
979 return SNMP_INTEGER(bgp_vrf_interfaces(l3vpn_bgp
, false));
980 case MPLSL3VPNVRFCONFMIDRTETHRESH
:
981 return SNMP_INTEGER(0);
982 case MPLSL3VPNVRFCONFHIGHRTETHRSH
:
983 return SNMP_INTEGER(0);
984 case MPLSL3VPNVRFCONFMAXROUTES
:
985 return SNMP_INTEGER(0);
986 case MPLSL3VPNVRFCONFLASTCHANGED
:
988 (uint32_t)l3vpn_bgp
->snmp_stats
->modify_time
);
989 case MPLSL3VPNVRFCONFROWSTATUS
:
990 return SNMP_INTEGER(1);
991 case MPLSL3VPNVRFCONFADMINSTATUS
:
992 return SNMP_INTEGER(1);
993 case MPLSL3VPNVRFCONFSTORAGETYPE
:
994 return SNMP_INTEGER(2);
999 /* 1.3.6.1.2.1.10.166.11.1.2.3.1.x = 14*/
1000 #define VRFRTTAB_NAMELEN 14
1001 static struct bgp
*bgpL3vpnVrfRt_lookup(struct variable
*v
, oid name
[],
1002 size_t *length
, char *vrf_name
,
1003 uint32_t *rt_index
, uint8_t *rt_type
,
1006 uint32_t type_index_size
;
1007 struct bgp
*l3vpn_bgp
;
1008 size_t namelen
= v
? v
->namelen
: VRFRTTAB_NAMELEN
;
1009 int vrf_name_len
, len
;
1012 if (*length
- namelen
1013 > (VRF_NAMSIZ
+ sizeof(uint32_t)) + sizeof(uint8_t))
1016 type_index_size
= sizeof(uint32_t) + sizeof(uint8_t);
1017 /* do we have index info in the oid ? */
1018 if (*length
- namelen
!= 0 && *length
- namelen
>= type_index_size
) {
1019 /* copy the info from the oid */
1020 vrf_name_len
= *length
- (namelen
+ type_index_size
);
1021 oid2string(name
+ namelen
, vrf_name_len
, vrf_name
);
1022 oid2int(name
+ namelen
+ vrf_name_len
, (int *)rt_index
);
1023 *rt_type
= name
[namelen
+ vrf_name_len
+ sizeof(uint32_t)];
1026 /* validate the RT index is in range */
1027 if (*rt_index
> AFI_IP6
)
1031 l3vpn_bgp
= bgp_lookup_by_name(vrf_name
);
1032 if (l3vpn_bgp
&& !is_bgp_vrf_mplsvpn(l3vpn_bgp
))
1036 if ((*rt_index
!= AFI_IP
) && (*rt_index
!= AFI_IP6
))
1038 /* do we have RT config */
1039 if (!(l3vpn_bgp
->vpn_policy
[*rt_index
]
1040 .rtlist
[BGP_VPN_POLICY_DIR_FROMVPN
]
1041 || l3vpn_bgp
->vpn_policy
[*rt_index
]
1042 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
]))
1046 if (strnlen(vrf_name
, VRF_NAMSIZ
) == 0)
1047 l3vpn_bgp
= bgp_lookup_by_name_next(vrf_name
);
1049 l3vpn_bgp
= bgp_lookup_by_name(vrf_name
);
1051 switch (*rt_index
) {
1056 *rt_index
= AFI_IP6
;
1065 *rt_type
= MPLSVPNVRFRTTYPEIMPORT
;
1067 case MPLSVPNVRFRTTYPEIMPORT
:
1068 *rt_type
= MPLSVPNVRFRTTYPEEXPORT
;
1070 case MPLSVPNVRFRTTYPEEXPORT
:
1071 case MPLSVPNVRFRTTYPEBOTH
:
1076 bool import
, export
;
1079 (!!l3vpn_bgp
->vpn_policy
[*rt_index
].rtlist
1080 [BGP_VPN_POLICY_DIR_FROMVPN
]);
1082 (!!l3vpn_bgp
->vpn_policy
[*rt_index
].rtlist
1083 [BGP_VPN_POLICY_DIR_TOVPN
]);
1084 if (*rt_type
== MPLSVPNVRFRTTYPEIMPORT
1087 if (*rt_type
== MPLSVPNVRFRTTYPEEXPORT
1090 /* ckeck for both */
1091 if (*rt_type
== MPLSVPNVRFRTTYPEIMPORT
&& import
1094 l3vpn_bgp
->vpn_policy
[*rt_index
].rtlist
1095 [BGP_VPN_POLICY_DIR_FROMVPN
],
1096 l3vpn_bgp
->vpn_policy
[*rt_index
].rtlist
1097 [BGP_VPN_POLICY_DIR_TOVPN
]))
1098 *rt_type
= MPLSVPNVRFRTTYPEBOTH
;
1100 /* we have a match copy the oid info */
1102 strnlen(l3vpn_bgp
->name
, VRF_NAMSIZ
);
1103 len
= vrf_name_len
+ sizeof(uint32_t)
1105 oid_copy_str(name
+ namelen
, l3vpn_bgp
->name
,
1107 oid_copy_int(name
+ namelen
+ vrf_name_len
,
1109 name
[(namelen
+ len
) - 1] = *rt_type
;
1110 *length
= len
+ namelen
;
1113 l3vpn_bgp
= bgp_lookup_by_name_next(l3vpn_bgp
->name
);
1119 static const char *rt_type2str(uint8_t rt_type
)
1122 case MPLSVPNVRFRTTYPEIMPORT
:
1124 case MPLSVPNVRFRTTYPEEXPORT
:
1126 case MPLSVPNVRFRTTYPEBOTH
:
1132 static uint8_t *mplsL3vpnVrfRtTable(struct variable
*v
, oid name
[],
1133 size_t *length
, int exact
, size_t *var_len
,
1134 WriteMethod
**write_method
)
1136 char vrf_name
[VRF_NAMSIZ
];
1137 struct bgp
*l3vpn_bgp
;
1138 uint32_t rt_index
= 0;
1139 uint8_t rt_type
= 0;
1142 if (smux_header_table(v
, name
, length
, exact
, var_len
, write_method
)
1146 memset(vrf_name
, 0, VRF_NAMSIZ
);
1147 l3vpn_bgp
= bgpL3vpnVrfRt_lookup(v
, name
, length
, vrf_name
, &rt_index
,
1154 case MPLSL3VPNVRFRT
:
1156 case MPLSVPNVRFRTTYPEIMPORT
:
1157 rt_b
= ecommunity_ecom2str(
1158 l3vpn_bgp
->vpn_policy
[rt_index
]
1159 .rtlist
[BGP_VPN_POLICY_DIR_FROMVPN
],
1160 ECOMMUNITY_FORMAT_ROUTE_MAP
,
1161 ECOMMUNITY_ROUTE_TARGET
);
1163 case MPLSVPNVRFRTTYPEEXPORT
:
1164 case MPLSVPNVRFRTTYPEBOTH
:
1165 rt_b
= ecommunity_ecom2str(
1166 l3vpn_bgp
->vpn_policy
[rt_index
]
1167 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
1168 ECOMMUNITY_FORMAT_ROUTE_MAP
,
1169 ECOMMUNITY_ROUTE_TARGET
);
1176 *var_len
= strnlen(rt_b
, ECOMMUNITY_STRLEN
);
1179 return (uint8_t *)rt_b
;
1180 case MPLSL3VPNVRFRTDESCR
:
1181 /* since we dont have a description generate one */
1182 memset(rt_description
, 0, VRF_NAMSIZ
+ RT_PREAMBLE_SIZE
);
1183 snprintf(rt_description
, VRF_NAMSIZ
+ RT_PREAMBLE_SIZE
,
1184 "RT %s for VRF %s", rt_type2str(rt_type
),
1187 strnlen(rt_description
, VRF_NAMSIZ
+ RT_PREAMBLE_SIZE
);
1188 return (uint8_t *)rt_description
;
1189 case MPLSL3VPNVRFRTROWSTATUS
:
1190 return SNMP_INTEGER(1);
1191 case MPLSL3VPNVRFRTSTORAGETYPE
:
1192 return SNMP_INTEGER(2);
1197 /* 1.3.6.1.2.1.10.166.11.1.3.1.1.x = 14*/
1198 #define PERFTAB_NAMELEN 14
1200 static uint8_t *mplsL3vpnPerfTable(struct variable
*v
, oid name
[],
1201 size_t *length
, int exact
, size_t *var_len
,
1202 WriteMethod
**write_method
)
1204 char vrf_name
[VRF_NAMSIZ
];
1205 struct bgp
*l3vpn_bgp
;
1207 if (smux_header_table(v
, name
, length
, exact
, var_len
, write_method
)
1211 memset(vrf_name
, 0, VRF_NAMSIZ
);
1212 l3vpn_bgp
= bgpL3vpnVrf_lookup(v
, name
, length
, vrf_name
, exact
);
1218 case MPLSL3VPNVRFPERFROUTESADDED
:
1219 return SNMP_INTEGER(l3vpn_bgp
->snmp_stats
->routes_added
);
1220 case MPLSL3VPNVRFPERFROUTESDELETED
:
1221 return SNMP_INTEGER(l3vpn_bgp
->snmp_stats
->routes_deleted
);
1222 case MPLSL3VPNVRFPERFCURRNUMROUTES
:
1223 return SNMP_INTEGER(bgp_mpls_l3vpn_current_routes(l3vpn_bgp
));
1228 static struct bgp_path_info
*
1229 bgp_lookup_route(struct bgp
*l3vpn_bgp
, struct bgp_dest
**dest
,
1230 struct prefix
*prefix
, uint16_t policy
, struct ipaddr
*nexthop
)
1232 struct bgp_path_info
*pi
= NULL
;
1233 struct bgp_table
*table
;
1235 switch (prefix
->family
) {
1237 table
= l3vpn_bgp
->rib
[AFI_IP
][SAFI_UNICAST
];
1240 table
= l3vpn_bgp
->rib
[AFI_IP6
][SAFI_UNICAST
];
1247 *dest
= bgp_node_lookup(table
, prefix
);
1251 /* now find the right path */
1252 pi
= bgp_dest_get_bgp_path_info(*dest
);
1253 for (; pi
; pi
= pi
->next
) {
1254 switch (nexthop
->ipa_type
) {
1256 if (nexthop
->ip
._v4_addr
.s_addr
1257 == pi
->attr
->nexthop
.s_addr
)
1261 if (memcmp(&nexthop
->ip
._v6_addr
,
1262 &pi
->attr
->mp_nexthop_global
,
1263 sizeof(struct in6_addr
))
1274 static struct bgp_path_info
*bgp_lookup_route_next(struct bgp
**l3vpn_bgp
,
1275 struct bgp_dest
**dest
,
1276 struct prefix
*prefix
,
1278 struct ipaddr
*nexthop
)
1280 struct bgp_path_info
*pi
= NULL
;
1281 struct bgp_table
*table
;
1282 const struct prefix
*p
;
1286 if (prefix
->prefixlen
== 0) {
1288 table
= (*l3vpn_bgp
)->rib
[AFI_IP
][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 table
= (*l3vpn_bgp
)->rib
[AFI_IP6
][SAFI_UNICAST
];
1299 for (*dest
= bgp_table_top(table
); *dest
;
1300 *dest
= bgp_route_next(*dest
)) {
1301 pi
= bgp_dest_get_bgp_path_info(*dest
);
1308 /* real next search for the entry first use exact lookup */
1309 pi
= bgp_lookup_route(*l3vpn_bgp
, dest
, prefix
, *policy
, nexthop
);
1314 p
= bgp_dest_get_prefix(*dest
);
1317 /* We have found the input path let's find the next one in the list */
1319 /* ensure OID is always higher for multipath routes by
1320 * incrementing opaque policy oid
1326 /* No more paths in the input route so find the next route */
1328 *l3vpn_bgp
= bgp_lookup_by_name_next((*l3vpn_bgp
)->name
)) {
1331 table
= (*l3vpn_bgp
)->rib
[AFI_IP
][SAFI_UNICAST
];
1332 *dest
= bgp_table_top(table
);
1335 *dest
= bgp_route_next(*dest
);
1338 for (; *dest
; *dest
= bgp_route_next(*dest
)) {
1339 pi
= bgp_dest_get_bgp_path_info(*dest
);
1344 if (family
== AF_INET
) {
1345 table
= (*l3vpn_bgp
)
1346 ->rib
[AFI_IP6
][SAFI_UNICAST
];
1347 *dest
= bgp_table_top(table
);
1358 static bool is_addr_type(oid id
)
1361 case INETADDRESSTYPEUNKNOWN
:
1362 case INETADDRESSTYPEIPV4
:
1363 case INETADDRESSTYPEIPV6
:
1369 /* 1.3.6.1.2.1.10.166.11.1.4.1.1.x = 14*/
1370 #define PERFTAB_NAMELEN 14
1372 static struct bgp_path_info
*bgpL3vpnRte_lookup(struct variable
*v
, oid name
[],
1373 size_t *length
, char *vrf_name
,
1374 struct bgp
**l3vpn_bgp
,
1375 struct bgp_dest
**dest
,
1376 uint16_t *policy
, int exact
)
1379 uint8_t vrf_name_len
= 0;
1380 struct bgp_path_info
*pi
= NULL
;
1381 size_t namelen
= v
? v
->namelen
: IFCONFTAB_NAMELEN
;
1382 struct prefix prefix
= {0};
1383 struct ipaddr nexthop
= {0};
1384 uint8_t prefix_type
;
1385 uint8_t nexthop_type
;
1387 if ((uint32_t)(*length
- namelen
) > (VRF_NAMSIZ
+ 37))
1390 if (*length
- namelen
!= 0) {
1391 /* parse incoming OID */
1392 for (i
= namelen
; i
< (*length
); i
++) {
1393 if (is_addr_type(name
[i
]))
1397 if (vrf_name_len
> VRF_NAMSIZ
)
1400 oid2string(name
+ namelen
, vrf_name_len
, vrf_name
);
1401 prefix_type
= name
[i
++];
1402 switch (prefix_type
) {
1403 case INETADDRESSTYPEUNKNOWN
:
1404 prefix
.family
= AF_UNSPEC
;
1406 case INETADDRESSTYPEIPV4
:
1407 prefix
.family
= AF_INET
;
1408 oid2in_addr(&name
[i
], sizeof(struct in_addr
),
1410 i
+= sizeof(struct in_addr
);
1412 case INETADDRESSTYPEIPV6
:
1413 prefix
.family
= AF_INET6
;
1414 oid2in6_addr(&name
[i
], &prefix
.u
.prefix6
);
1415 i
+= sizeof(struct in6_addr
);
1418 prefix
.prefixlen
= (uint8_t)name
[i
++];
1419 *policy
|= name
[i
++] << 8;
1420 *policy
|= name
[i
++];
1421 nexthop_type
= name
[i
++];
1422 switch (nexthop_type
) {
1423 case INETADDRESSTYPEUNKNOWN
:
1424 nexthop
.ipa_type
= (prefix
.family
== AF_INET
)
1428 case INETADDRESSTYPEIPV4
:
1429 nexthop
.ipa_type
= IPADDR_V4
;
1430 oid2in_addr(&name
[i
], sizeof(struct in_addr
),
1431 &nexthop
.ip
._v4_addr
);
1432 /* i += sizeof(struct in_addr); */
1434 case INETADDRESSTYPEIPV6
:
1435 nexthop
.ipa_type
= IPADDR_V6
;
1436 oid2in6_addr(&name
[i
], &nexthop
.ip
._v6_addr
);
1437 /* i += sizeof(struct in6_addr); */
1443 *l3vpn_bgp
= bgp_lookup_by_name(vrf_name
);
1444 if (*l3vpn_bgp
&& !is_bgp_vrf_mplsvpn(*l3vpn_bgp
))
1446 if (*l3vpn_bgp
== NULL
)
1449 /* now lookup the route in this bgp table */
1450 pi
= bgp_lookup_route(*l3vpn_bgp
, dest
, &prefix
, *policy
,
1455 str_len
= strnlen(vrf_name
, VRF_NAMSIZ
);
1457 *l3vpn_bgp
= bgp_lookup_by_name_next(vrf_name
);
1459 /* otherwise lookup the one we have */
1460 *l3vpn_bgp
= bgp_lookup_by_name(vrf_name
);
1462 if (*l3vpn_bgp
== NULL
)
1465 pi
= bgp_lookup_route_next(l3vpn_bgp
, dest
, &prefix
, policy
,
1468 uint8_t vrf_name_len
=
1469 strnlen((*l3vpn_bgp
)->name
, VRF_NAMSIZ
);
1470 const struct prefix
*p
= bgp_dest_get_prefix(*dest
);
1472 bool v4
= (p
->family
== AF_INET
);
1473 uint8_t addr_len
= v4
? sizeof(struct in_addr
)
1474 : sizeof(struct in6_addr
);
1475 struct attr
*attr
= pi
->attr
;
1477 /* copy the index parameters */
1478 oid_copy_str(&name
[namelen
], (*l3vpn_bgp
)->name
,
1480 oid_index
= namelen
+ vrf_name_len
;
1482 name
[oid_index
++] = INETADDRESSTYPEIPV4
;
1483 oid_copy_in_addr(&name
[oid_index
],
1486 name
[oid_index
++] = INETADDRESSTYPEIPV6
;
1487 oid_copy_in6_addr(&name
[oid_index
],
1491 oid_index
+= addr_len
;
1492 name
[oid_index
++] = p
->prefixlen
;
1493 name
[oid_index
++] = *policy
>> 8;
1494 name
[oid_index
++] = *policy
& 0xff;
1496 if (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
1497 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
1499 INETADDRESSTYPEUNKNOWN
;
1501 name
[oid_index
++] = INETADDRESSTYPEIPV4
;
1502 oid_copy_in_addr(&name
[oid_index
],
1504 oid_index
+= sizeof(struct in_addr
);
1507 if (IN6_IS_ADDR_UNSPECIFIED(
1508 &attr
->mp_nexthop_global
))
1510 INETADDRESSTYPEUNKNOWN
;
1512 name
[oid_index
++] = INETADDRESSTYPEIPV6
;
1515 &attr
->mp_nexthop_global
);
1516 oid_index
+= sizeof(struct in6_addr
);
1519 *length
= oid_index
;
1525 static uint8_t *mplsL3vpnRteTable(struct variable
*v
, oid name
[],
1526 size_t *length
, int exact
, size_t *var_len
,
1527 WriteMethod
**write_method
)
1529 char vrf_name
[VRF_NAMSIZ
];
1530 struct bgp
*l3vpn_bgp
;
1531 struct bgp_dest
*dest
;
1532 struct bgp_path_info
*pi
;
1533 const struct prefix
*p
;
1534 uint16_t policy
= 0;
1536 if (smux_header_table(v
, name
, length
, exact
, var_len
, write_method
)
1540 memset(vrf_name
, 0, VRF_NAMSIZ
);
1541 pi
= bgpL3vpnRte_lookup(v
, name
, length
, vrf_name
, &l3vpn_bgp
, &dest
,
1548 p
= bgp_dest_get_prefix(dest
);
1554 case MPLSL3VPNVRFRTEINETCIDRDESTTYPE
:
1555 switch (p
->family
) {
1557 return SNMP_INTEGER(INETADDRESSTYPEIPV4
);
1559 return SNMP_INTEGER(INETADDRESSTYPEIPV6
);
1561 return SNMP_INTEGER(INETADDRESSTYPEUNKNOWN
);
1563 case MPLSL3VPNVRFRTEINETCIDRDEST
:
1564 switch (p
->family
) {
1566 return SNMP_IPADDRESS(p
->u
.prefix4
);
1568 return SNMP_IP6ADDRESS(p
->u
.prefix6
);
1573 case MPLSL3VPNVRFRTEINETCIDRPFXLEN
:
1574 return SNMP_INTEGER(p
->prefixlen
);
1575 case MPLSL3VPNVRFRTEINETCIDRPOLICY
:
1576 *var_len
= sizeof(mpls_l3vpn_policy_oid
);
1577 mpls_l3vpn_policy_oid
[0] = policy
>> 8;
1578 mpls_l3vpn_policy_oid
[1] = policy
& 0xff;
1579 return (uint8_t *)mpls_l3vpn_policy_oid
;
1580 case MPLSL3VPNVRFRTEINETCIDRNHOPTYPE
:
1581 if (!BGP_ATTR_NEXTHOP_AFI_IP6(pi
->attr
)) {
1582 if (pi
->attr
->nexthop
.s_addr
== INADDR_ANY
)
1583 return SNMP_INTEGER(INETADDRESSTYPEUNKNOWN
);
1585 return SNMP_INTEGER(INETADDRESSTYPEIPV4
);
1586 } else if (IN6_IS_ADDR_UNSPECIFIED(
1587 &pi
->attr
->mp_nexthop_global
))
1588 return SNMP_INTEGER(INETADDRESSTYPEUNKNOWN
);
1590 return SNMP_INTEGER(INETADDRESSTYPEIPV6
);
1592 case MPLSL3VPNVRFRTEINETCIDRNEXTHOP
:
1593 if (!BGP_ATTR_NEXTHOP_AFI_IP6(pi
->attr
))
1594 if (pi
->attr
->nexthop
.s_addr
== INADDR_ANY
) {
1596 return (uint8_t *)empty_nhop
;
1598 return SNMP_IPADDRESS(pi
->attr
->nexthop
);
1599 else if (IN6_IS_ADDR_UNSPECIFIED(
1600 &pi
->attr
->mp_nexthop_global
)) {
1602 return (uint8_t *)empty_nhop
;
1604 return SNMP_IP6ADDRESS(pi
->attr
->mp_nexthop_global
);
1606 case MPLSL3VPNVRFRTEINETCIDRIFINDEX
:
1607 if (pi
->nexthop
&& pi
->nexthop
->nexthop
)
1608 return SNMP_INTEGER(pi
->nexthop
->nexthop
->ifindex
);
1610 return SNMP_INTEGER(0);
1611 case MPLSL3VPNVRFRTEINETCIDRTYPE
:
1612 if (pi
->nexthop
&& pi
->nexthop
->nexthop
) {
1613 switch (pi
->nexthop
->nexthop
->type
) {
1614 case NEXTHOP_TYPE_IFINDEX
:
1615 return SNMP_INTEGER(
1616 MPLSL3VPNVRFRTECIDRTYPELOCAL
);
1617 case NEXTHOP_TYPE_IPV4
:
1618 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1619 case NEXTHOP_TYPE_IPV6
:
1620 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1621 return SNMP_INTEGER(
1622 MPLSL3VPNVRFRTECIDRTYPEREMOTE
);
1623 case NEXTHOP_TYPE_BLACKHOLE
:
1624 switch (pi
->nexthop
->nexthop
->bh_type
) {
1625 case BLACKHOLE_REJECT
:
1626 return SNMP_INTEGER(
1627 MPLSL3VPNVRFRTECIDRTYPEREJECT
);
1629 return SNMP_INTEGER(
1630 MPLSL3VPNVRFRTECIDRTYPEBLACKHOLE
);
1633 return SNMP_INTEGER(
1634 MPLSL3VPNVRFRTECIDRTYPEOTHER
);
1637 return SNMP_INTEGER(MPLSL3VPNVRFRTECIDRTYPEOTHER
);
1638 case MPLSL3VPNVRFRTEINETCIDRPROTO
:
1640 case ZEBRA_ROUTE_CONNECT
:
1641 return SNMP_INTEGER(IANAIPROUTEPROTOCOLLOCAL
);
1642 case ZEBRA_ROUTE_STATIC
:
1643 return SNMP_INTEGER(IANAIPROUTEPROTOCOLNETMGMT
);
1644 case ZEBRA_ROUTE_RIP
:
1645 case ZEBRA_ROUTE_RIPNG
:
1646 return SNMP_INTEGER(IANAIPROUTEPROTOCOLRIP
);
1647 case ZEBRA_ROUTE_OSPF
:
1648 case ZEBRA_ROUTE_OSPF6
:
1649 return SNMP_INTEGER(IANAIPROUTEPROTOCOLOSPF
);
1650 case ZEBRA_ROUTE_ISIS
:
1651 return SNMP_INTEGER(IANAIPROUTEPROTOCOLISIS
);
1652 case ZEBRA_ROUTE_BGP
:
1653 return SNMP_INTEGER(IANAIPROUTEPROTOCOLBGP
);
1654 case ZEBRA_ROUTE_EIGRP
:
1655 return SNMP_INTEGER(IANAIPROUTEPROTOCOLCISCOEIGRP
);
1657 return SNMP_INTEGER(IANAIPROUTEPROTOCOLOTHER
);
1659 case MPLSL3VPNVRFRTEINETCIDRAGE
:
1660 return SNMP_INTEGER(pi
->uptime
);
1661 case MPLSL3VPNVRFRTEINETCIDRNEXTHOPAS
:
1662 return SNMP_INTEGER(pi
->peer
? pi
->peer
->as
: 0);
1663 case MPLSL3VPNVRFRTEINETCIDRMETRIC1
:
1665 return SNMP_INTEGER(pi
->extra
->igpmetric
);
1667 return SNMP_INTEGER(0);
1668 case MPLSL3VPNVRFRTEINETCIDRMETRIC2
:
1669 return SNMP_INTEGER(-1);
1670 case MPLSL3VPNVRFRTEINETCIDRMETRIC3
:
1671 return SNMP_INTEGER(-1);
1672 case MPLSL3VPNVRFRTEINETCIDRMETRIC4
:
1673 return SNMP_INTEGER(-1);
1674 case MPLSL3VPNVRFRTEINETCIDRMETRIC5
:
1675 return SNMP_INTEGER(-1);
1676 case MPLSL3VPNVRFRTEINETCIDRXCPOINTER
:
1677 return SNMP_OCTET(0);
1678 case MPLSL3VPNVRFRTEINETCIDRSTATUS
:
1679 return SNMP_INTEGER(1);
1684 void bgp_mpls_l3vpn_module_init(void)
1686 hook_register(bgp_vrf_status_changed
, bgp_vrf_check_update_active
);
1687 hook_register(bgp_snmp_init_stats
, bgp_init_snmp_stats
);
1688 hook_register(bgp_snmp_update_last_changed
,
1689 bgp_mpls_l3vpn_update_last_changed
);
1690 hook_register(bgp_snmp_update_stats
, bgp_snmp_update_route_stats
);
1691 REGISTER_MIB("mplsL3VpnMIB", mpls_l3vpn_variables
, variable
,