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 else if (CHECK_FLAG(l3vpn_bgp
->vpn_policy
[AFI_IP6
].flags
,
947 BGP_VPN_POLICY_TOVPN_RD_SET
))
948 prefix_rd2str(&l3vpn_bgp
->vpn_policy
[AFI_IP6
].tovpn_rd
,
949 rd_buf
, sizeof(rd_buf
));
951 *var_len
= strnlen(rd_buf
, RD_ADDRSTRLEN
);
952 return (uint8_t *)rd_buf
;
953 case MPLSL3VPNVRFCREATIONTIME
:
955 (uint32_t)l3vpn_bgp
->snmp_stats
->creation_time
);
956 case MPLSL3VPNVRFOPERSTATUS
:
957 if (l3vpn_bgp
->snmp_stats
->active
)
958 return SNMP_INTEGER(1);
960 return SNMP_INTEGER(2);
961 case MPLSL3VPNVRFACTIVEINTERFACES
:
962 return SNMP_INTEGER(bgp_vrf_interfaces(l3vpn_bgp
, true));
963 case MPLSL3VPNVRFASSOCIATEDINTERFACES
:
964 return SNMP_INTEGER(bgp_vrf_interfaces(l3vpn_bgp
, false));
965 case MPLSL3VPNVRFCONFMIDRTETHRESH
:
966 return SNMP_INTEGER(0);
967 case MPLSL3VPNVRFCONFHIGHRTETHRSH
:
968 return SNMP_INTEGER(0);
969 case MPLSL3VPNVRFCONFMAXROUTES
:
970 return SNMP_INTEGER(0);
971 case MPLSL3VPNVRFCONFLASTCHANGED
:
973 (uint32_t)l3vpn_bgp
->snmp_stats
->modify_time
);
974 case MPLSL3VPNVRFCONFROWSTATUS
:
975 return SNMP_INTEGER(1);
976 case MPLSL3VPNVRFCONFADMINSTATUS
:
977 return SNMP_INTEGER(1);
978 case MPLSL3VPNVRFCONFSTORAGETYPE
:
979 return SNMP_INTEGER(2);
984 /* 1.3.6.1.2.1.10.166.11.1.2.3.1.x = 14*/
985 #define VRFRTTAB_NAMELEN 14
986 static struct bgp
*bgpL3vpnVrfRt_lookup(struct variable
*v
, oid name
[],
987 size_t *length
, char *vrf_name
,
988 uint32_t *rt_index
, uint8_t *rt_type
,
991 uint32_t type_index_size
;
992 struct bgp
*l3vpn_bgp
;
993 size_t namelen
= v
? v
->namelen
: VRFRTTAB_NAMELEN
;
994 int vrf_name_len
, len
;
997 if (*length
- namelen
998 > (VRF_NAMSIZ
+ sizeof(uint32_t)) + sizeof(uint8_t))
1001 type_index_size
= sizeof(uint32_t) + sizeof(uint8_t);
1002 /* do we have index info in the oid ? */
1003 if (*length
- namelen
!= 0 && *length
- namelen
>= type_index_size
) {
1004 /* copy the info from the oid */
1005 vrf_name_len
= *length
- (namelen
+ type_index_size
);
1006 oid2string(name
+ namelen
, vrf_name_len
, vrf_name
);
1007 oid2int(name
+ namelen
+ vrf_name_len
, (int *)rt_index
);
1008 *rt_type
= name
[namelen
+ vrf_name_len
+ sizeof(uint32_t)];
1011 /* validate the RT index is in range */
1012 if (*rt_index
> AFI_IP6
)
1016 l3vpn_bgp
= bgp_lookup_by_name(vrf_name
);
1017 if (l3vpn_bgp
&& !is_bgp_vrf_mplsvpn(l3vpn_bgp
))
1021 if ((*rt_index
!= AFI_IP
) && (*rt_index
!= AFI_IP6
))
1023 /* do we have RT config */
1024 if (!(l3vpn_bgp
->vpn_policy
[*rt_index
]
1025 .rtlist
[BGP_VPN_POLICY_DIR_FROMVPN
]
1026 || l3vpn_bgp
->vpn_policy
[*rt_index
]
1027 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
]))
1031 if (strnlen(vrf_name
, VRF_NAMSIZ
) == 0)
1032 l3vpn_bgp
= bgp_lookup_by_name_next(vrf_name
);
1034 l3vpn_bgp
= bgp_lookup_by_name(vrf_name
);
1036 switch (*rt_index
) {
1041 *rt_index
= AFI_IP6
;
1050 *rt_type
= MPLSVPNVRFRTTYPEIMPORT
;
1052 case MPLSVPNVRFRTTYPEIMPORT
:
1053 *rt_type
= MPLSVPNVRFRTTYPEEXPORT
;
1055 case MPLSVPNVRFRTTYPEEXPORT
:
1056 case MPLSVPNVRFRTTYPEBOTH
:
1061 bool import
, export
;
1064 (!!l3vpn_bgp
->vpn_policy
[*rt_index
].rtlist
1065 [BGP_VPN_POLICY_DIR_FROMVPN
]);
1067 (!!l3vpn_bgp
->vpn_policy
[*rt_index
].rtlist
1068 [BGP_VPN_POLICY_DIR_TOVPN
]);
1069 if (*rt_type
== MPLSVPNVRFRTTYPEIMPORT
1072 if (*rt_type
== MPLSVPNVRFRTTYPEEXPORT
1075 /* ckeck for both */
1076 if (*rt_type
== MPLSVPNVRFRTTYPEIMPORT
&& import
1079 l3vpn_bgp
->vpn_policy
[*rt_index
].rtlist
1080 [BGP_VPN_POLICY_DIR_FROMVPN
],
1081 l3vpn_bgp
->vpn_policy
[*rt_index
].rtlist
1082 [BGP_VPN_POLICY_DIR_TOVPN
]))
1083 *rt_type
= MPLSVPNVRFRTTYPEBOTH
;
1085 /* we have a match copy the oid info */
1087 strnlen(l3vpn_bgp
->name
, VRF_NAMSIZ
);
1088 len
= vrf_name_len
+ sizeof(uint32_t)
1090 oid_copy_str(name
+ namelen
, l3vpn_bgp
->name
,
1092 oid_copy_int(name
+ namelen
+ vrf_name_len
,
1094 name
[(namelen
+ len
) - 1] = *rt_type
;
1095 *length
= len
+ namelen
;
1098 l3vpn_bgp
= bgp_lookup_by_name_next(l3vpn_bgp
->name
);
1104 static const char *rt_type2str(uint8_t rt_type
)
1107 case MPLSVPNVRFRTTYPEIMPORT
:
1109 case MPLSVPNVRFRTTYPEEXPORT
:
1111 case MPLSVPNVRFRTTYPEBOTH
:
1117 static uint8_t *mplsL3vpnVrfRtTable(struct variable
*v
, oid name
[],
1118 size_t *length
, int exact
, size_t *var_len
,
1119 WriteMethod
**write_method
)
1121 char vrf_name
[VRF_NAMSIZ
];
1122 struct bgp
*l3vpn_bgp
;
1123 uint32_t rt_index
= 0;
1124 uint8_t rt_type
= 0;
1127 if (smux_header_table(v
, name
, length
, exact
, var_len
, write_method
)
1131 memset(vrf_name
, 0, VRF_NAMSIZ
);
1132 l3vpn_bgp
= bgpL3vpnVrfRt_lookup(v
, name
, length
, vrf_name
, &rt_index
,
1139 case MPLSL3VPNVRFRT
:
1141 case MPLSVPNVRFRTTYPEIMPORT
:
1142 rt_b
= ecommunity_ecom2str(
1143 l3vpn_bgp
->vpn_policy
[rt_index
]
1144 .rtlist
[BGP_VPN_POLICY_DIR_FROMVPN
],
1145 ECOMMUNITY_FORMAT_ROUTE_MAP
,
1146 ECOMMUNITY_ROUTE_TARGET
);
1148 case MPLSVPNVRFRTTYPEEXPORT
:
1149 case MPLSVPNVRFRTTYPEBOTH
:
1150 rt_b
= ecommunity_ecom2str(
1151 l3vpn_bgp
->vpn_policy
[rt_index
]
1152 .rtlist
[BGP_VPN_POLICY_DIR_TOVPN
],
1153 ECOMMUNITY_FORMAT_ROUTE_MAP
,
1154 ECOMMUNITY_ROUTE_TARGET
);
1161 *var_len
= strnlen(rt_b
, ECOMMUNITY_STRLEN
);
1164 return (uint8_t *)rt_b
;
1165 case MPLSL3VPNVRFRTDESCR
:
1166 /* since we dont have a description generate one */
1167 memset(rt_description
, 0, VRF_NAMSIZ
+ RT_PREAMBLE_SIZE
);
1168 snprintf(rt_description
, VRF_NAMSIZ
+ RT_PREAMBLE_SIZE
,
1169 "RT %s for VRF %s", rt_type2str(rt_type
),
1172 strnlen(rt_description
, VRF_NAMSIZ
+ RT_PREAMBLE_SIZE
);
1173 return (uint8_t *)rt_description
;
1174 case MPLSL3VPNVRFRTROWSTATUS
:
1175 return SNMP_INTEGER(1);
1176 case MPLSL3VPNVRFRTSTORAGETYPE
:
1177 return SNMP_INTEGER(2);
1182 /* 1.3.6.1.2.1.10.166.11.1.3.1.1.x = 14*/
1183 #define PERFTAB_NAMELEN 14
1185 static uint8_t *mplsL3vpnPerfTable(struct variable
*v
, oid name
[],
1186 size_t *length
, int exact
, size_t *var_len
,
1187 WriteMethod
**write_method
)
1189 char vrf_name
[VRF_NAMSIZ
];
1190 struct bgp
*l3vpn_bgp
;
1192 if (smux_header_table(v
, name
, length
, exact
, var_len
, write_method
)
1196 memset(vrf_name
, 0, VRF_NAMSIZ
);
1197 l3vpn_bgp
= bgpL3vpnVrf_lookup(v
, name
, length
, vrf_name
, exact
);
1203 case MPLSL3VPNVRFPERFROUTESADDED
:
1204 return SNMP_INTEGER(l3vpn_bgp
->snmp_stats
->routes_added
);
1205 case MPLSL3VPNVRFPERFROUTESDELETED
:
1206 return SNMP_INTEGER(l3vpn_bgp
->snmp_stats
->routes_deleted
);
1207 case MPLSL3VPNVRFPERFCURRNUMROUTES
:
1208 return SNMP_INTEGER(bgp_mpls_l3vpn_current_routes(l3vpn_bgp
));
1213 static struct bgp_path_info
*
1214 bgp_lookup_route(struct bgp
*l3vpn_bgp
, struct bgp_dest
**dest
,
1215 struct prefix
*prefix
, uint16_t policy
, struct ipaddr
*nexthop
)
1217 struct bgp_path_info
*pi
= NULL
;
1218 struct bgp_table
*table
;
1220 switch (prefix
->family
) {
1222 table
= l3vpn_bgp
->rib
[AFI_IP
][SAFI_UNICAST
];
1225 table
= l3vpn_bgp
->rib
[AFI_IP6
][SAFI_UNICAST
];
1232 *dest
= bgp_node_lookup(table
, prefix
);
1236 /* now find the right path */
1237 pi
= bgp_dest_get_bgp_path_info(*dest
);
1238 for (; pi
; pi
= pi
->next
) {
1239 switch (nexthop
->ipa_type
) {
1241 if (nexthop
->ip
._v4_addr
.s_addr
1242 == pi
->attr
->nexthop
.s_addr
)
1246 if (memcmp(&nexthop
->ip
._v6_addr
,
1247 &pi
->attr
->mp_nexthop_global
,
1248 sizeof(struct in6_addr
))
1259 static struct bgp_path_info
*bgp_lookup_route_next(struct bgp
**l3vpn_bgp
,
1260 struct bgp_dest
**dest
,
1261 struct prefix
*prefix
,
1263 struct ipaddr
*nexthop
)
1265 struct bgp_path_info
*pi
= NULL
;
1266 struct bgp_table
*table
;
1267 const struct prefix
*p
;
1271 if (prefix
->prefixlen
== 0) {
1273 table
= (*l3vpn_bgp
)->rib
[AFI_IP
][SAFI_UNICAST
];
1274 for (*dest
= bgp_table_top(table
); *dest
;
1275 *dest
= bgp_route_next(*dest
)) {
1276 pi
= bgp_dest_get_bgp_path_info(*dest
);
1283 table
= (*l3vpn_bgp
)->rib
[AFI_IP6
][SAFI_UNICAST
];
1284 for (*dest
= bgp_table_top(table
); *dest
;
1285 *dest
= bgp_route_next(*dest
)) {
1286 pi
= bgp_dest_get_bgp_path_info(*dest
);
1293 /* real next search for the entry first use exact lookup */
1294 pi
= bgp_lookup_route(*l3vpn_bgp
, dest
, prefix
, *policy
, nexthop
);
1299 p
= bgp_dest_get_prefix(*dest
);
1302 /* We have found the input path let's find the next one in the list */
1304 /* ensure OID is always higher for multipath routes by
1305 * incrementing opaque policy oid
1311 /* No more paths in the input route so find the next route */
1313 *l3vpn_bgp
= bgp_lookup_by_name_next((*l3vpn_bgp
)->name
)) {
1316 table
= (*l3vpn_bgp
)->rib
[AFI_IP
][SAFI_UNICAST
];
1317 *dest
= bgp_table_top(table
);
1320 *dest
= bgp_route_next(*dest
);
1323 for (; *dest
; *dest
= bgp_route_next(*dest
)) {
1324 pi
= bgp_dest_get_bgp_path_info(*dest
);
1329 if (family
== AF_INET
) {
1330 table
= (*l3vpn_bgp
)
1331 ->rib
[AFI_IP6
][SAFI_UNICAST
];
1332 *dest
= bgp_table_top(table
);
1343 static bool is_addr_type(oid id
)
1346 case INETADDRESSTYPEUNKNOWN
:
1347 case INETADDRESSTYPEIPV4
:
1348 case INETADDRESSTYPEIPV6
:
1354 /* 1.3.6.1.2.1.10.166.11.1.4.1.1.x = 14*/
1355 #define PERFTAB_NAMELEN 14
1357 static struct bgp_path_info
*bgpL3vpnRte_lookup(struct variable
*v
, oid name
[],
1358 size_t *length
, char *vrf_name
,
1359 struct bgp
**l3vpn_bgp
,
1360 struct bgp_dest
**dest
,
1361 uint16_t *policy
, int exact
)
1364 uint8_t vrf_name_len
= 0;
1365 struct bgp_path_info
*pi
= NULL
;
1366 size_t namelen
= v
? v
->namelen
: IFCONFTAB_NAMELEN
;
1367 struct prefix prefix
= {0};
1368 struct ipaddr nexthop
= {0};
1369 uint8_t prefix_type
;
1370 uint8_t nexthop_type
;
1372 if ((uint32_t)(*length
- namelen
) > (VRF_NAMSIZ
+ 37))
1375 if (*length
- namelen
!= 0) {
1376 /* parse incoming OID */
1377 for (i
= namelen
; i
< (*length
); i
++) {
1378 if (is_addr_type(name
[i
]))
1382 if (vrf_name_len
> VRF_NAMSIZ
)
1385 oid2string(name
+ namelen
, vrf_name_len
, vrf_name
);
1386 prefix_type
= name
[i
++];
1387 switch (prefix_type
) {
1388 case INETADDRESSTYPEUNKNOWN
:
1389 prefix
.family
= AF_UNSPEC
;
1391 case INETADDRESSTYPEIPV4
:
1392 prefix
.family
= AF_INET
;
1393 oid2in_addr(&name
[i
], sizeof(struct in_addr
),
1395 i
+= sizeof(struct in_addr
);
1397 case INETADDRESSTYPEIPV6
:
1398 prefix
.family
= AF_INET6
;
1399 oid2in6_addr(&name
[i
], &prefix
.u
.prefix6
);
1400 i
+= sizeof(struct in6_addr
);
1403 prefix
.prefixlen
= (uint8_t)name
[i
++];
1404 *policy
|= name
[i
++] << 8;
1405 *policy
|= name
[i
++];
1406 nexthop_type
= name
[i
++];
1407 switch (nexthop_type
) {
1408 case INETADDRESSTYPEUNKNOWN
:
1409 nexthop
.ipa_type
= (prefix
.family
== AF_INET
)
1413 case INETADDRESSTYPEIPV4
:
1414 nexthop
.ipa_type
= IPADDR_V4
;
1415 oid2in_addr(&name
[i
], sizeof(struct in_addr
),
1416 &nexthop
.ip
._v4_addr
);
1417 /* i += sizeof(struct in_addr); */
1419 case INETADDRESSTYPEIPV6
:
1420 nexthop
.ipa_type
= IPADDR_V6
;
1421 oid2in6_addr(&name
[i
], &nexthop
.ip
._v6_addr
);
1422 /* i += sizeof(struct in6_addr); */
1428 *l3vpn_bgp
= bgp_lookup_by_name(vrf_name
);
1429 if (*l3vpn_bgp
&& !is_bgp_vrf_mplsvpn(*l3vpn_bgp
))
1431 if (*l3vpn_bgp
== NULL
)
1434 /* now lookup the route in this bgp table */
1435 pi
= bgp_lookup_route(*l3vpn_bgp
, dest
, &prefix
, *policy
,
1440 str_len
= strnlen(vrf_name
, VRF_NAMSIZ
);
1442 *l3vpn_bgp
= bgp_lookup_by_name_next(vrf_name
);
1444 /* otherwise lookup the one we have */
1445 *l3vpn_bgp
= bgp_lookup_by_name(vrf_name
);
1447 if (*l3vpn_bgp
== NULL
)
1450 pi
= bgp_lookup_route_next(l3vpn_bgp
, dest
, &prefix
, policy
,
1453 uint8_t vrf_name_len
=
1454 strnlen((*l3vpn_bgp
)->name
, VRF_NAMSIZ
);
1455 const struct prefix
*p
= bgp_dest_get_prefix(*dest
);
1457 bool v4
= (p
->family
== AF_INET
);
1458 uint8_t addr_len
= v4
? sizeof(struct in_addr
)
1459 : sizeof(struct in6_addr
);
1460 struct attr
*attr
= pi
->attr
;
1462 /* copy the index parameters */
1463 oid_copy_str(&name
[namelen
], (*l3vpn_bgp
)->name
,
1465 oid_index
= namelen
+ vrf_name_len
;
1467 name
[oid_index
++] = INETADDRESSTYPEIPV4
;
1468 oid_copy_in_addr(&name
[oid_index
],
1471 name
[oid_index
++] = INETADDRESSTYPEIPV6
;
1472 oid_copy_in6_addr(&name
[oid_index
],
1476 oid_index
+= addr_len
;
1477 name
[oid_index
++] = p
->prefixlen
;
1478 name
[oid_index
++] = *policy
>> 8;
1479 name
[oid_index
++] = *policy
& 0xff;
1481 if (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
1482 if (attr
->nexthop
.s_addr
== INADDR_ANY
)
1484 INETADDRESSTYPEUNKNOWN
;
1486 name
[oid_index
++] = INETADDRESSTYPEIPV4
;
1487 oid_copy_in_addr(&name
[oid_index
],
1489 oid_index
+= sizeof(struct in_addr
);
1492 if (IN6_IS_ADDR_UNSPECIFIED(
1493 &attr
->mp_nexthop_global
))
1495 INETADDRESSTYPEUNKNOWN
;
1497 name
[oid_index
++] = INETADDRESSTYPEIPV6
;
1500 &attr
->mp_nexthop_global
);
1501 oid_index
+= sizeof(struct in6_addr
);
1504 *length
= oid_index
;
1510 static uint8_t *mplsL3vpnRteTable(struct variable
*v
, oid name
[],
1511 size_t *length
, int exact
, size_t *var_len
,
1512 WriteMethod
**write_method
)
1514 char vrf_name
[VRF_NAMSIZ
];
1515 struct bgp
*l3vpn_bgp
;
1516 struct bgp_dest
*dest
;
1517 struct bgp_path_info
*pi
, *bpi_ultimate
;
1518 const struct prefix
*p
;
1519 uint16_t policy
= 0;
1521 if (smux_header_table(v
, name
, length
, exact
, var_len
, write_method
)
1525 memset(vrf_name
, 0, VRF_NAMSIZ
);
1526 pi
= bgpL3vpnRte_lookup(v
, name
, length
, vrf_name
, &l3vpn_bgp
, &dest
,
1533 bpi_ultimate
= bgp_get_imported_bpi_ultimate(pi
);
1535 p
= bgp_dest_get_prefix(dest
);
1541 case MPLSL3VPNVRFRTEINETCIDRDESTTYPE
:
1542 switch (p
->family
) {
1544 return SNMP_INTEGER(INETADDRESSTYPEIPV4
);
1546 return SNMP_INTEGER(INETADDRESSTYPEIPV6
);
1548 return SNMP_INTEGER(INETADDRESSTYPEUNKNOWN
);
1550 case MPLSL3VPNVRFRTEINETCIDRDEST
:
1551 switch (p
->family
) {
1553 return SNMP_IPADDRESS(p
->u
.prefix4
);
1555 return SNMP_IP6ADDRESS(p
->u
.prefix6
);
1560 case MPLSL3VPNVRFRTEINETCIDRPFXLEN
:
1561 return SNMP_INTEGER(p
->prefixlen
);
1562 case MPLSL3VPNVRFRTEINETCIDRPOLICY
:
1563 *var_len
= sizeof(mpls_l3vpn_policy_oid
);
1564 mpls_l3vpn_policy_oid
[0] = policy
>> 8;
1565 mpls_l3vpn_policy_oid
[1] = policy
& 0xff;
1566 return (uint8_t *)mpls_l3vpn_policy_oid
;
1567 case MPLSL3VPNVRFRTEINETCIDRNHOPTYPE
:
1568 if (!BGP_ATTR_NEXTHOP_AFI_IP6(pi
->attr
)) {
1569 if (pi
->attr
->nexthop
.s_addr
== INADDR_ANY
)
1570 return SNMP_INTEGER(INETADDRESSTYPEUNKNOWN
);
1572 return SNMP_INTEGER(INETADDRESSTYPEIPV4
);
1573 } else if (IN6_IS_ADDR_UNSPECIFIED(
1574 &pi
->attr
->mp_nexthop_global
))
1575 return SNMP_INTEGER(INETADDRESSTYPEUNKNOWN
);
1577 return SNMP_INTEGER(INETADDRESSTYPEIPV6
);
1579 case MPLSL3VPNVRFRTEINETCIDRNEXTHOP
:
1580 if (!BGP_ATTR_NEXTHOP_AFI_IP6(pi
->attr
))
1581 if (pi
->attr
->nexthop
.s_addr
== INADDR_ANY
) {
1583 return (uint8_t *)empty_nhop
;
1585 return SNMP_IPADDRESS(pi
->attr
->nexthop
);
1586 else if (IN6_IS_ADDR_UNSPECIFIED(
1587 &pi
->attr
->mp_nexthop_global
)) {
1589 return (uint8_t *)empty_nhop
;
1591 return SNMP_IP6ADDRESS(pi
->attr
->mp_nexthop_global
);
1593 case MPLSL3VPNVRFRTEINETCIDRIFINDEX
:
1594 if (pi
->nexthop
&& pi
->nexthop
->nexthop
)
1595 return SNMP_INTEGER(pi
->nexthop
->nexthop
->ifindex
);
1597 return SNMP_INTEGER(0);
1598 case MPLSL3VPNVRFRTEINETCIDRTYPE
:
1599 if (pi
->nexthop
&& pi
->nexthop
->nexthop
) {
1600 switch (pi
->nexthop
->nexthop
->type
) {
1601 case NEXTHOP_TYPE_IFINDEX
:
1602 return SNMP_INTEGER(
1603 MPLSL3VPNVRFRTECIDRTYPELOCAL
);
1604 case NEXTHOP_TYPE_IPV4
:
1605 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1606 case NEXTHOP_TYPE_IPV6
:
1607 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1608 return SNMP_INTEGER(
1609 MPLSL3VPNVRFRTECIDRTYPEREMOTE
);
1610 case NEXTHOP_TYPE_BLACKHOLE
:
1611 switch (pi
->nexthop
->nexthop
->bh_type
) {
1612 case BLACKHOLE_REJECT
:
1613 return SNMP_INTEGER(
1614 MPLSL3VPNVRFRTECIDRTYPEREJECT
);
1615 case BLACKHOLE_UNSPEC
:
1616 case BLACKHOLE_NULL
:
1617 case BLACKHOLE_ADMINPROHIB
:
1618 return SNMP_INTEGER(
1619 MPLSL3VPNVRFRTECIDRTYPEBLACKHOLE
);
1624 return SNMP_INTEGER(MPLSL3VPNVRFRTECIDRTYPEOTHER
);
1625 case MPLSL3VPNVRFRTEINETCIDRPROTO
:
1627 case ZEBRA_ROUTE_CONNECT
:
1628 return SNMP_INTEGER(IANAIPROUTEPROTOCOLLOCAL
);
1629 case ZEBRA_ROUTE_STATIC
:
1630 return SNMP_INTEGER(IANAIPROUTEPROTOCOLNETMGMT
);
1631 case ZEBRA_ROUTE_RIP
:
1632 case ZEBRA_ROUTE_RIPNG
:
1633 return SNMP_INTEGER(IANAIPROUTEPROTOCOLRIP
);
1634 case ZEBRA_ROUTE_OSPF
:
1635 case ZEBRA_ROUTE_OSPF6
:
1636 return SNMP_INTEGER(IANAIPROUTEPROTOCOLOSPF
);
1637 case ZEBRA_ROUTE_ISIS
:
1638 return SNMP_INTEGER(IANAIPROUTEPROTOCOLISIS
);
1639 case ZEBRA_ROUTE_BGP
:
1640 return SNMP_INTEGER(IANAIPROUTEPROTOCOLBGP
);
1641 case ZEBRA_ROUTE_EIGRP
:
1642 return SNMP_INTEGER(IANAIPROUTEPROTOCOLCISCOEIGRP
);
1644 return SNMP_INTEGER(IANAIPROUTEPROTOCOLOTHER
);
1646 case MPLSL3VPNVRFRTEINETCIDRAGE
:
1647 return SNMP_INTEGER(pi
->uptime
);
1648 case MPLSL3VPNVRFRTEINETCIDRNEXTHOPAS
:
1649 return SNMP_INTEGER(pi
->peer
? pi
->peer
->as
: 0);
1650 case MPLSL3VPNVRFRTEINETCIDRMETRIC1
:
1651 if (bpi_ultimate
->extra
)
1652 return SNMP_INTEGER(bpi_ultimate
->extra
->igpmetric
);
1654 return SNMP_INTEGER(0);
1655 case MPLSL3VPNVRFRTEINETCIDRMETRIC2
:
1656 return SNMP_INTEGER(-1);
1657 case MPLSL3VPNVRFRTEINETCIDRMETRIC3
:
1658 return SNMP_INTEGER(-1);
1659 case MPLSL3VPNVRFRTEINETCIDRMETRIC4
:
1660 return SNMP_INTEGER(-1);
1661 case MPLSL3VPNVRFRTEINETCIDRMETRIC5
:
1662 return SNMP_INTEGER(-1);
1663 case MPLSL3VPNVRFRTEINETCIDRXCPOINTER
:
1664 return SNMP_OCTET(0);
1665 case MPLSL3VPNVRFRTEINETCIDRSTATUS
:
1666 return SNMP_INTEGER(1);
1671 void bgp_mpls_l3vpn_module_init(void)
1673 hook_register(bgp_vrf_status_changed
, bgp_vrf_check_update_active
);
1674 hook_register(bgp_snmp_init_stats
, bgp_init_snmp_stats
);
1675 hook_register(bgp_snmp_update_last_changed
,
1676 bgp_mpls_l3vpn_update_last_changed
);
1677 hook_register(bgp_snmp_update_stats
, bgp_snmp_update_route_stats
);
1678 REGISTER_MIB("mplsL3VpnMIB", mpls_l3vpn_variables
, variable
,