]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_mplsvpn_snmp.c
bgpd: expose ecommunity string length
[mirror_frr.git] / bgpd / bgp_mplsvpn_snmp.c
CommitLineData
aa53f693
PR
1/* MPLS/BGP L3VPN MIB
2 * Copyright (C) 2020 Volta Networks Inc
3 *
4 * This file is part of FRR.
5 *
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
9 * later version.
10 *
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.
15 *
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
19 */
20
21#include <zebra.h>
22
23#include <net-snmp/net-snmp-config.h>
24#include <net-snmp/net-snmp-includes.h>
25
26#include "if.h"
27#include "log.h"
28#include "prefix.h"
29#include "command.h"
30#include "thread.h"
31#include "smux.h"
32#include "filter.h"
33#include "hook.h"
34#include "libfrr.h"
35#include "version.h"
36
37#include "bgpd/bgpd.h"
7fd28dd2 38#include "bgpd/bgp_route.h"
62e66e55
PR
39#include "bgpd/bgp_attr.h"
40
aa53f693
PR
41#include "bgpd/bgp_mplsvpn.h"
42#include "bgpd/bgp_mplsvpn_snmp.h"
43
44#define BGP_mplsvpn_notif_enable_true 1
45#define BGP_mplsvpn_notif_enable_false 2
46
aa53f693
PR
47/* MPLSL3VPN MIB described in RFC4382 */
48#define MPLSL3VPNMIB 1, 3, 6, 1, 2, 1, 10, 166, 11
49
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
58
1ea16ac0
PR
59/* MPLSL3VPN IFConf Table */
60#define MPLSL3VPNIFVPNCLASSIFICATION 1
61#define MPLSL3VPNIFCONFSTORAGETYPE 2
62#define MPLSL3VPNIFCONFROWSTATUS 3
63
0d020cd6
PR
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
79
7fd28dd2
PR
80/* MPLSL3VPN PERF Table */
81#define MPLSL3VPNVRFPERFROUTESADDED 1
82#define MPLSL3VPNVRFPERFROUTESDELETED 2
83#define MPLSL3VPNVRFPERFCURRNUMROUTES 3
84
62e66e55
PR
85/* MPLSL3VPN RTE Table */
86#define MPLSL3VPNVRFRTEINETCIDRDESTTYPE 1
87#define MPLSL3VPNVRFRTEINETCIDRDEST 2
88#define MPLSL3VPNVRFRTEINETCIDRPFXLEN 3
89#define MPLSL3VPNVRFRTEINETCIDRPOLICY 4
90#define MPLSL3VPNVRFRTEINETCIDRNHOPTYPE 5
91#define MPLSL3VPNVRFRTEINETCIDRNEXTHOP 6
92#define MPLSL3VPNVRFRTEINETCIDRIFINDEX 7
93#define MPLSL3VPNVRFRTEINETCIDRTYPE 8
94#define MPLSL3VPNVRFRTEINETCIDRPROTO 9
95#define MPLSL3VPNVRFRTEINETCIDRAGE 10
96#define MPLSL3VPNVRFRTEINETCIDRNEXTHOPAS 11
97#define MPLSL3VPNVRFRTEINETCIDRMETRIC1 12
98#define MPLSL3VPNVRFRTEINETCIDRMETRIC2 13
99#define MPLSL3VPNVRFRTEINETCIDRMETRIC3 14
100#define MPLSL3VPNVRFRTEINETCIDRMETRIC4 15
101#define MPLSL3VPNVRFRTEINETCIDRMETRIC5 16
102#define MPLSL3VPNVRFRTEINETCIDRXCPOINTER 17
103#define MPLSL3VPNVRFRTEINETCIDRSTATUS 18
104
aa53f693
PR
105/* SNMP value hack. */
106#define INTEGER ASN_INTEGER
107#define INTEGER32 ASN_INTEGER
108#define COUNTER32 ASN_COUNTER
109#define OCTET_STRING ASN_OCTET_STR
110#define IPADDRESS ASN_IPADDRESS
111#define GAUGE32 ASN_UNSIGNED
0d020cd6 112#define TIMETICKS ASN_TIMETICKS
62e66e55 113#define OID ASN_OBJECT_ID
aa53f693
PR
114
115/* Declare static local variables for convenience. */
116SNMP_LOCAL_VARIABLES
117
62e66e55 118/* BGP-MPLS-MIB instances */
aa53f693 119static oid mpls_l3vpn_oid[] = {MPLSL3VPNMIB};
0d020cd6
PR
120static char rd_buf[RD_ADDRSTRLEN];
121static uint8_t bgp_mplsvpn_notif_enable = SNMP_FALSE;
62e66e55
PR
122static oid mpls_l3vpn_policy_oid[2] = {0, 0};
123static const char *empty_nhop = "";
aa53f693
PR
124
125static uint8_t *mplsL3vpnConfiguredVrfs(struct variable *, oid[], size_t *, int,
126 size_t *, WriteMethod **);
127
128static uint8_t *mplsL3vpnActiveVrfs(struct variable *, oid[], size_t *, int,
129 size_t *, WriteMethod **);
130
131static uint8_t *mplsL3vpnConnectedInterfaces(struct variable *, oid[], size_t *,
132 int, size_t *, WriteMethod **);
133
134static uint8_t *mplsL3vpnNotificationEnable(struct variable *, oid[], size_t *,
135 int, size_t *, WriteMethod **);
136
137static uint8_t *mplsL3vpnVrfConfMaxPossRts(struct variable *, oid[], size_t *,
138 int, size_t *, WriteMethod **);
139
140static uint8_t *mplsL3vpnVrfConfRteMxThrshTime(struct variable *, oid[],
141 size_t *, int, size_t *,
142 WriteMethod **);
143
144static uint8_t *mplsL3vpnIllLblRcvThrsh(struct variable *, oid[], size_t *, int,
145 size_t *, WriteMethod **);
146
0d020cd6
PR
147static uint8_t *mplsL3vpnVrfTable(struct variable *, oid[], size_t *, int,
148 size_t *, WriteMethod **);
149
1ea16ac0
PR
150static uint8_t *mplsL3vpnIfConfTable(struct variable *, oid[], size_t *, int,
151 size_t *, WriteMethod **);
152
7fd28dd2
PR
153static uint8_t *mplsL3vpnPerfTable(struct variable *, oid[], size_t *, int,
154 size_t *, WriteMethod **);
155
62e66e55
PR
156static uint8_t *mplsL3vpnRteTable(struct variable *, oid[], size_t *, int,
157 size_t *, WriteMethod **);
158
0d020cd6 159
aa53f693
PR
160static struct variable mpls_l3vpn_variables[] = {
161 /* BGP version. */
162 {MPLSL3VPNCONFIGUREDVRFS,
163 GAUGE32,
164 RONLY,
165 mplsL3vpnConfiguredVrfs,
166 3,
167 {1, 1, 1} },
168 {MPLSL3VPNACTIVEVRFS,
169 GAUGE32,
170 RONLY,
171 mplsL3vpnActiveVrfs,
172 3,
173 {1, 1, 2} },
174 {MPLSL3VPNCONNECTEDINTERFACES,
175 GAUGE32,
176 RONLY,
177 mplsL3vpnConnectedInterfaces,
178 3,
179 {1, 1, 3} },
180 {MPLSL3VPNNOTIFICATIONENABLE,
181 INTEGER,
182 RWRITE,
183 mplsL3vpnNotificationEnable,
184 3,
185 {1, 1, 4} },
186 {MPLSL3VPNCONFMAXPOSSRTS,
187 GAUGE32,
188 RONLY,
189 mplsL3vpnVrfConfMaxPossRts,
190 3,
191 {1, 1, 5} },
192 {MPLSL3VPNVRFCONFRTEMXTHRSHTIME,
193 GAUGE32,
194 RONLY,
195 mplsL3vpnVrfConfRteMxThrshTime,
196 3,
197 {1, 1, 6} },
198 {MPLSL3VPNILLLBLRCVTHRSH,
199 GAUGE32,
200 RONLY,
201 mplsL3vpnIllLblRcvThrsh,
202 3,
203 {1, 1, 7} },
204
1ea16ac0
PR
205 /* Ifconf Table */
206 {MPLSL3VPNIFVPNCLASSIFICATION,
207 INTEGER,
208 RONLY,
209 mplsL3vpnIfConfTable,
210 5,
211 {1, 2, 1, 1, 2} },
212 {MPLSL3VPNIFCONFSTORAGETYPE,
213 INTEGER,
214 RONLY,
215 mplsL3vpnIfConfTable,
216 5,
217 {1, 2, 1, 1, 4} },
218 {MPLSL3VPNIFCONFROWSTATUS,
219 INTEGER,
220 RONLY,
221 mplsL3vpnIfConfTable,
222 5,
223 {1, 2, 1, 1, 5} },
224
7fd28dd2 225 /* mplsL3VpnVrf Table */
0d020cd6
PR
226 {MPLSL3VPNVRFVPNID,
227 OCTET_STRING,
228 RONLY,
229 mplsL3vpnVrfTable,
230 5,
231 {1, 2, 2, 1, 2} },
232 {MPLSL3VPNVRFDESC,
233 OCTET_STRING,
234 RONLY,
235 mplsL3vpnVrfTable,
236 5,
237 {1, 2, 2, 1, 3} },
238 {MPLSL3VPNVRFRD,
239 OCTET_STRING,
240 RONLY,
241 mplsL3vpnVrfTable,
242 5,
243 {1, 2, 2, 1, 4} },
244 {MPLSL3VPNVRFCREATIONTIME,
245 TIMETICKS,
246 RONLY,
247 mplsL3vpnVrfTable,
248 5,
249 {1, 2, 2, 1, 5} },
250 {MPLSL3VPNVRFOPERSTATUS,
251 INTEGER,
252 RONLY,
253 mplsL3vpnVrfTable,
254 5,
255 {1, 2, 2, 1, 6} },
256 {MPLSL3VPNVRFACTIVEINTERFACES,
257 GAUGE32,
258 RONLY,
259 mplsL3vpnVrfTable,
260 5,
261 {1, 2, 2, 1, 7} },
262 {MPLSL3VPNVRFASSOCIATEDINTERFACES,
263 GAUGE32,
264 RONLY,
265 mplsL3vpnVrfTable,
266 5,
267 {1, 2, 2, 1, 8} },
268 {MPLSL3VPNVRFCONFMIDRTETHRESH,
269 GAUGE32,
270 RONLY,
271 mplsL3vpnVrfTable,
272 5,
273 {1, 2, 2, 1, 9} },
274 {MPLSL3VPNVRFCONFHIGHRTETHRSH,
275 GAUGE32,
276 RONLY,
277 mplsL3vpnVrfTable,
278 5,
279 {1, 2, 2, 1, 10} },
280 {MPLSL3VPNVRFCONFMAXROUTES,
281 GAUGE32,
282 RONLY,
283 mplsL3vpnVrfTable,
284 5,
285 {1, 2, 2, 1, 11} },
286 {MPLSL3VPNVRFCONFLASTCHANGED,
287 TIMETICKS,
288 RONLY,
289 mplsL3vpnVrfTable,
290 5,
291 {1, 2, 2, 1, 12} },
292 {MPLSL3VPNVRFCONFROWSTATUS,
293 INTEGER,
294 RONLY,
295 mplsL3vpnVrfTable,
296 5,
297 {1, 2, 2, 1, 13} },
298 {MPLSL3VPNVRFCONFADMINSTATUS,
299 INTEGER,
300 RONLY,
301 mplsL3vpnVrfTable,
302 5,
303 {1, 2, 2, 1, 14} },
304 {MPLSL3VPNVRFCONFSTORAGETYPE,
305 INTEGER,
306 RONLY,
307 mplsL3vpnVrfTable,
308 5,
309 {1, 2, 2, 1, 15} },
7fd28dd2
PR
310
311 /* mplsL3VpnPerfTable */
312 {MPLSL3VPNVRFPERFROUTESADDED,
313 COUNTER32,
314 RONLY,
315 mplsL3vpnPerfTable,
316 5,
317 {1, 3, 1, 1, 1} },
318 {MPLSL3VPNVRFPERFROUTESDELETED,
319 COUNTER32,
320 RONLY,
321 mplsL3vpnPerfTable,
322 5,
323 {1, 3, 1, 1, 2} },
324 {MPLSL3VPNVRFPERFCURRNUMROUTES,
325 GAUGE32,
326 RONLY,
327 mplsL3vpnPerfTable,
328 5,
329 {1, 3, 1, 1, 3} },
62e66e55
PR
330
331 /* mplsVpnRteTable */
332 {MPLSL3VPNVRFRTEINETCIDRDESTTYPE,
333 INTEGER,
334 RONLY,
335 mplsL3vpnRteTable,
336 5,
337 {1, 4, 1, 1, 1} },
338 {MPLSL3VPNVRFRTEINETCIDRDEST,
339 OCTET_STRING,
340 RONLY,
341 mplsL3vpnRteTable,
342 5,
343 {1, 4, 1, 1, 2} },
344 {MPLSL3VPNVRFRTEINETCIDRPFXLEN,
345 GAUGE32,
346 RONLY,
347 mplsL3vpnRteTable,
348 5,
349 {1, 4, 1, 1, 3} },
350 {MPLSL3VPNVRFRTEINETCIDRPOLICY,
351 OID,
352 RONLY,
353 mplsL3vpnRteTable,
354 5,
355 {1, 4, 1, 1, 4} },
356 {MPLSL3VPNVRFRTEINETCIDRNHOPTYPE,
357 INTEGER,
358 RONLY,
359 mplsL3vpnRteTable,
360 5,
361 {1, 4, 1, 1, 5} },
362 {MPLSL3VPNVRFRTEINETCIDRNEXTHOP,
363 OCTET_STRING,
364 RONLY,
365 mplsL3vpnRteTable,
366 5,
367 {1, 4, 1, 1, 6} },
368 {MPLSL3VPNVRFRTEINETCIDRIFINDEX,
369 INTEGER,
370 RONLY,
371 mplsL3vpnRteTable,
372 5,
373 {1, 4, 1, 1, 7} },
374 {MPLSL3VPNVRFRTEINETCIDRTYPE,
375 INTEGER,
376 RONLY,
377 mplsL3vpnRteTable,
378 5,
379 {1, 4, 1, 1, 8} },
380 {MPLSL3VPNVRFRTEINETCIDRPROTO,
381 INTEGER,
382 RONLY,
383 mplsL3vpnRteTable,
384 5,
385 {1, 4, 1, 1, 9} },
386 {MPLSL3VPNVRFRTEINETCIDRAGE,
387 GAUGE32,
388 RONLY,
389 mplsL3vpnRteTable,
390 5,
391 {1, 4, 1, 1, 10} },
392 {MPLSL3VPNVRFRTEINETCIDRNEXTHOPAS,
393 GAUGE32,
394 RONLY,
395 mplsL3vpnRteTable,
396 5,
397 {1, 4, 1, 1, 11} },
398 {MPLSL3VPNVRFRTEINETCIDRMETRIC1,
399 INTEGER,
400 RONLY,
401 mplsL3vpnRteTable,
402 5,
403 {1, 4, 1, 1, 12} },
404 {MPLSL3VPNVRFRTEINETCIDRMETRIC2,
405 INTEGER,
406 RONLY,
407 mplsL3vpnRteTable,
408 5,
409 {1, 4, 1, 1, 13} },
410 {MPLSL3VPNVRFRTEINETCIDRMETRIC3,
411 INTEGER,
412 RONLY,
413 mplsL3vpnRteTable,
414 5,
415 {1, 4, 1, 1, 14} },
416 {MPLSL3VPNVRFRTEINETCIDRMETRIC4,
417 INTEGER,
418 RONLY,
419 mplsL3vpnRteTable,
420 5,
421 {1, 4, 1, 1, 15} },
422 {MPLSL3VPNVRFRTEINETCIDRMETRIC5,
423 INTEGER,
424 RONLY,
425 mplsL3vpnRteTable,
426 5,
427 {1, 4, 1, 1, 16} },
428 {MPLSL3VPNVRFRTEINETCIDRXCPOINTER,
429 OCTET_STRING,
430 RONLY,
431 mplsL3vpnRteTable,
432 5,
433 {1, 4, 1, 1, 17} },
434 {MPLSL3VPNVRFRTEINETCIDRSTATUS,
435 INTEGER,
436 RONLY,
437 mplsL3vpnRteTable,
438 5,
439 {1, 4, 1, 1, 18} },
aa53f693
PR
440};
441
0d020cd6
PR
442/* timeticks are in hundredths of a second */
443static void bgp_mpls_l3vpn_update_timeticks(time_t *counter)
444{
445 struct timeval tv;
446
447 monotime(&tv);
448 *counter = (tv.tv_sec * 100) + (tv.tv_usec / 10000);
449}
450
451static int bgp_mpls_l3vpn_update_last_changed(struct bgp *bgp)
452{
453 if (bgp->snmp_stats)
454 bgp_mpls_l3vpn_update_timeticks(
455 &(bgp->snmp_stats->modify_time));
456 return 0;
457}
458
7fd28dd2
PR
459static uint32_t bgp_mpls_l3vpn_current_routes(struct bgp *l3vpn_bgp)
460{
461 uint32_t count = 0;
462 struct bgp_table *table;
463 struct bgp_dest *dest;
464 struct bgp_path_info *pi;
465
466 table = l3vpn_bgp->rib[AFI_IP][SAFI_UNICAST];
467 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
468 pi = bgp_dest_get_bgp_path_info(dest);
469 for (; pi; pi = pi->next)
470 count++;
471 }
472 table = l3vpn_bgp->rib[AFI_IP6][SAFI_UNICAST];
473 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
474 pi = bgp_dest_get_bgp_path_info(dest);
475 for (; pi; pi = pi->next)
476 count++;
477 }
478 return count;
479}
480
0d020cd6
PR
481static int bgp_init_snmp_stats(struct bgp *bgp)
482{
483 if (is_bgp_vrf_mplsvpn(bgp)) {
484 if (bgp->snmp_stats == NULL) {
485 bgp->snmp_stats = XCALLOC(
486 MTYPE_BGP, sizeof(struct bgp_snmp_stats));
487 /* fix up added routes */
7fd28dd2
PR
488 if (bgp->snmp_stats) {
489 bgp->snmp_stats->routes_added =
490 bgp_mpls_l3vpn_current_routes(bgp);
0d020cd6
PR
491 bgp_mpls_l3vpn_update_timeticks(
492 &(bgp->snmp_stats->creation_time));
7fd28dd2 493 }
0d020cd6
PR
494 }
495 } else {
496 if (bgp->snmp_stats) {
497 XFREE(MTYPE_BGP, bgp->snmp_stats);
498 bgp->snmp_stats = NULL;
499 }
500 }
501 /* Something changed - update the timestamp */
502 bgp_mpls_l3vpn_update_last_changed(bgp);
503 return 0;
504}
505
7fd28dd2
PR
506static int bgp_snmp_update_route_stats(struct bgp_dest *dest,
507 struct bgp_path_info *pi, bool added)
508{
509 struct bgp_table *table;
510
511 if (dest) {
512 table = bgp_dest_table(dest);
513 /* only update if we have a stats block - MPLSVPN vrfs for now*/
514 if (table && table->bgp && table->bgp->snmp_stats) {
515 if (added)
516 table->bgp->snmp_stats->routes_added++;
517 else
518 table->bgp->snmp_stats->routes_deleted++;
519 }
520 }
521 return 0;
522}
523
0d020cd6
PR
524static bool is_bgp_vrf_active(struct bgp *bgp)
525{
526 struct vrf *vrf;
527 struct interface *ifp;
528
529 /* if there is one interface in the vrf which is up then it is deemed
530 * active
531 */
532 vrf = vrf_lookup_by_id(bgp->vrf_id);
533 if (vrf == NULL)
534 return false;
535 RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name) {
536 /* if we are in a vrf skip the l3mdev */
537 if (bgp->name && strncmp(ifp->name, bgp->name, VRF_NAMSIZ) == 0)
538 continue;
539
540 if (if_is_up(ifp))
541 return true;
542 }
543 return false;
544}
545
546static int bgp_vrf_check_update_active(struct bgp *bgp, struct interface *ifp)
547{
548 bool new_active = false;
549
550 if (!is_bgp_vrf_mplsvpn(bgp) || bgp->snmp_stats == NULL)
551 return 0;
552 new_active = is_bgp_vrf_active(bgp);
553 if (bgp->snmp_stats->active != new_active) {
554 /* add trap in here */
555 bgp->snmp_stats->active = new_active;
556 }
557 return 0;
558}
559
aa53f693
PR
560static uint8_t *mplsL3vpnConfiguredVrfs(struct variable *v, oid name[],
561 size_t *length, int exact,
562 size_t *var_len,
563 WriteMethod **write_method)
564{
565 struct listnode *node, *nnode;
566 struct bgp *bgp;
567 uint32_t count = 0;
568
569 if (smux_header_generic(v, name, length, exact, var_len, write_method)
570 == MATCH_FAILED)
571 return NULL;
572
573 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
574 if (is_bgp_vrf_mplsvpn(bgp))
575 count++;
576 }
577 return SNMP_INTEGER(count);
578}
579
580static uint8_t *mplsL3vpnActiveVrfs(struct variable *v, oid name[],
581 size_t *length, int exact, size_t *var_len,
582 WriteMethod **write_method)
583{
584 struct listnode *node, *nnode;
585 struct bgp *bgp;
586 uint32_t count = 0;
587
588 if (smux_header_generic(v, name, length, exact, var_len, write_method)
589 == MATCH_FAILED)
590 return NULL;
591
592 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
593 if (is_bgp_vrf_mplsvpn(bgp) && is_bgp_vrf_active(bgp))
594 count++;
595 }
596 return SNMP_INTEGER(count);
597}
598
599static uint8_t *mplsL3vpnConnectedInterfaces(struct variable *v, oid name[],
600 size_t *length, int exact,
601 size_t *var_len,
602 WriteMethod **write_method)
603{
604 struct listnode *node, *nnode;
605 struct bgp *bgp;
606 uint32_t count = 0;
607 struct vrf *vrf;
608
609 if (smux_header_generic(v, name, length, exact, var_len, write_method)
610 == MATCH_FAILED)
611 return NULL;
612
613 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
614 if (is_bgp_vrf_mplsvpn(bgp)) {
615 vrf = vrf_lookup_by_name(bgp->name);
616 if (vrf == NULL)
617 continue;
618
619 count += vrf_interface_count(vrf);
620 }
621 }
622
623 return SNMP_INTEGER(count);
624}
625
626static int write_mplsL3vpnNotificationEnable(int action, uint8_t *var_val,
627 uint8_t var_val_type,
628 size_t var_val_len, uint8_t *statP,
629 oid *name, size_t length)
630{
631 uint32_t intval;
632
aa53f693
PR
633 if (var_val_type != ASN_INTEGER) {
634 return SNMP_ERR_WRONGTYPE;
635 }
636
637 if (var_val_len != sizeof(long)) {
638 return SNMP_ERR_WRONGLENGTH;
639 }
640
641 intval = *(long *)var_val;
642 bgp_mplsvpn_notif_enable = intval;
643 return SNMP_ERR_NOERROR;
644}
645
646static uint8_t *mplsL3vpnNotificationEnable(struct variable *v, oid name[],
647 size_t *length, int exact,
648 size_t *var_len,
649 WriteMethod **write_method)
650{
651 if (smux_header_generic(v, name, length, exact, var_len, write_method)
652 == MATCH_FAILED)
653 return NULL;
654
aa53f693
PR
655 *write_method = write_mplsL3vpnNotificationEnable;
656 return SNMP_INTEGER(bgp_mplsvpn_notif_enable);
657}
658
659static uint8_t *mplsL3vpnVrfConfMaxPossRts(struct variable *v, oid name[],
660 size_t *length, int exact,
661 size_t *var_len,
662 WriteMethod **write_method)
663{
664 if (smux_header_generic(v, name, length, exact, var_len, write_method)
665 == MATCH_FAILED)
666 return NULL;
667
668 return SNMP_INTEGER(0);
669}
670
671static uint8_t *mplsL3vpnVrfConfRteMxThrshTime(struct variable *v, oid name[],
672 size_t *length, int exact,
673 size_t *var_len,
674 WriteMethod **write_method)
675{
676 if (smux_header_generic(v, name, length, exact, var_len, write_method)
677 == MATCH_FAILED)
678 return NULL;
679
680 return SNMP_INTEGER(0);
681}
682
683static uint8_t *mplsL3vpnIllLblRcvThrsh(struct variable *v, oid name[],
684 size_t *length, int exact,
685 size_t *var_len,
686 WriteMethod **write_method)
687{
688 if (smux_header_generic(v, name, length, exact, var_len, write_method)
689 == MATCH_FAILED)
690 return NULL;
691
692 return SNMP_INTEGER(0);
693}
694
695
1ea16ac0 696static struct bgp *bgp_lookup_by_name_next(char *vrf_name)
0d020cd6
PR
697{
698 struct bgp *bgp, *bgp_next = NULL;
699 struct listnode *node, *nnode;
700 bool first = false;
701
702 /*
703 * the vrfs are not stored alphabetically but since we are using the
704 * vrf name as an index we need the getnext function to return them
705 * in a atrict order. Thus run through and find the best next one.
706 */
707 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
708 if (!is_bgp_vrf_mplsvpn(bgp))
709 continue;
710 if (strnlen(vrf_name, VRF_NAMSIZ) == 0 && bgp_next == NULL) {
711 first = true;
712 bgp_next = bgp;
713 continue;
714 }
715 if (first || strncmp(bgp->name, vrf_name, VRF_NAMSIZ) > 0) {
716 if (bgp_next == NULL)
717 bgp_next = bgp;
718 else if (strncmp(bgp->name, bgp_next->name, VRF_NAMSIZ)
719 < 0)
720 bgp_next = bgp;
721 }
722 }
723 return bgp_next;
724}
725
1ea16ac0
PR
726/* 1.3.6.1.2.1.10.166.11.1.2.1.1.x = 14*/
727#define IFCONFTAB_NAMELEN 14
728static struct bgp *bgpL3vpnIfConf_lookup(struct variable *v, oid name[],
729 size_t *length, char *vrf_name,
730 ifindex_t *ifindex, int exact)
731{
732 struct bgp *bgp = NULL;
733 size_t namelen = v ? v->namelen : IFCONFTAB_NAMELEN;
734 struct interface *ifp;
735 int vrf_name_len, len;
736
737 /* too long ? */
738 if (*length - namelen > (VRF_NAMSIZ + sizeof(uint32_t)))
739 return NULL;
740 /* do we have index info in the oid ? */
741 if (*length - namelen != 0 && *length - namelen >= sizeof(uint32_t)) {
742 /* copy the info from the oid */
743 vrf_name_len = *length - (namelen + sizeof(ifindex_t));
744 oid2string(name + namelen, vrf_name_len, vrf_name);
745 oid2int(name + namelen + vrf_name_len, ifindex);
746 }
747
748 if (exact) {
749 /* Check the length. */
750 bgp = bgp_lookup_by_name(vrf_name);
751 if (bgp && !is_bgp_vrf_mplsvpn(bgp))
752 return NULL;
753 if (!bgp)
754 return NULL;
755 ifp = if_lookup_by_index(*ifindex, bgp->vrf_id);
756 if (!ifp)
757 return NULL;
758 } else {
759 if (strnlen(vrf_name, VRF_NAMSIZ) == 0)
760 bgp = bgp_lookup_by_name_next(vrf_name);
761 else
762 bgp = bgp_lookup_by_name(vrf_name);
763
764 while (bgp) {
765 ifp = if_vrf_lookup_by_index_next(*ifindex,
766 bgp->vrf_id);
767 if (ifp) {
768 vrf_name_len = strnlen(bgp->name, VRF_NAMSIZ);
769 *ifindex = ifp->ifindex;
770 len = vrf_name_len + sizeof(ifindex_t);
771 oid_copy_str(name + namelen, bgp->name,
772 vrf_name_len);
773 oid_copy_int(name + namelen + vrf_name_len,
774 ifindex);
775 *length = len + namelen;
776
777 return bgp;
778 }
779 *ifindex = 0;
780 bgp = bgp_lookup_by_name_next(bgp->name);
781 }
782
783 return NULL;
784 }
785 return bgp;
786}
787
788static uint8_t *mplsL3vpnIfConfTable(struct variable *v, oid name[],
789 size_t *length, int exact, size_t *var_len,
790 WriteMethod **write_method)
791{
792 char vrf_name[VRF_NAMSIZ];
793 ifindex_t ifindex = 0;
794 struct bgp *l3vpn_bgp;
795
796 if (smux_header_table(v, name, length, exact, var_len, write_method)
797 == MATCH_FAILED)
798 return NULL;
799
800 memset(vrf_name, 0, VRF_NAMSIZ);
801 l3vpn_bgp = bgpL3vpnIfConf_lookup(v, name, length, vrf_name, &ifindex,
802 exact);
803 if (!l3vpn_bgp)
804 return NULL;
805
806 switch (v->magic) {
807 case MPLSL3VPNIFVPNCLASSIFICATION:
808 return SNMP_INTEGER(2);
809 case MPLSL3VPNIFCONFSTORAGETYPE:
810 return SNMP_INTEGER(2);
811 case MPLSL3VPNIFCONFROWSTATUS:
812 return SNMP_INTEGER(1);
813 }
814 return NULL;
815}
816
817/* 1.3.6.1.2.1.10.166.11.1.2.2.1.x = 14*/
818#define VRFTAB_NAMELEN 14
819
820static struct bgp *bgpL3vpnVrf_lookup(struct variable *v, oid name[],
821 size_t *length, char *vrf_name, int exact)
0d020cd6
PR
822{
823 struct bgp *bgp = NULL;
824 size_t namelen = v ? v->namelen : VRFTAB_NAMELEN;
825 int len;
826
827 if (*length - namelen > VRF_NAMSIZ)
828 return NULL;
829 oid2string(name + namelen, *length - namelen, vrf_name);
830 if (exact) {
831 /* Check the length. */
832 bgp = bgp_lookup_by_name(vrf_name);
833 if (bgp && !is_bgp_vrf_mplsvpn(bgp))
834 return NULL;
835 } else {
836 bgp = bgp_lookup_by_name_next(vrf_name);
837
838 if (bgp == NULL)
839 return NULL;
840
841 len = strnlen(bgp->name, VRF_NAMSIZ);
842 oid_copy_str(name + namelen, bgp->name, len);
843 *length = len + namelen;
844 }
845 return bgp;
846}
847
848static uint8_t *mplsL3vpnVrfTable(struct variable *v, oid name[],
849 size_t *length, int exact, size_t *var_len,
850 WriteMethod **write_method)
851{
852 char vrf_name[VRF_NAMSIZ];
853 struct bgp *l3vpn_bgp;
854
855 if (smux_header_table(v, name, length, exact, var_len, write_method)
856 == MATCH_FAILED)
857 return NULL;
858
859 memset(vrf_name, 0, VRF_NAMSIZ);
1ea16ac0 860 l3vpn_bgp = bgpL3vpnVrf_lookup(v, name, length, vrf_name, exact);
0d020cd6
PR
861
862 if (!l3vpn_bgp)
863 return NULL;
864
865 switch (v->magic) {
866 case MPLSL3VPNVRFVPNID:
867 *var_len = 0;
868 return NULL;
869 case MPLSL3VPNVRFDESC:
870 *var_len = strnlen(l3vpn_bgp->name, VRF_NAMSIZ);
871 return (uint8_t *)l3vpn_bgp->name;
872 case MPLSL3VPNVRFRD:
873 /*
874 * this is a horror show but the MIB dicates one RD per vrf
875 * and not one RD per AFI as we (FRR) have. So this little gem
876 * returns the V4 one if it's set OR the v6 one if it's set or
877 * zero-length string id neither are set
878 */
879 memset(rd_buf, 0, RD_ADDRSTRLEN);
880 if (CHECK_FLAG(l3vpn_bgp->vpn_policy[AFI_IP].flags,
881 BGP_VPN_POLICY_TOVPN_RD_SET))
882 prefix_rd2str(&l3vpn_bgp->vpn_policy[AFI_IP].tovpn_rd,
883 rd_buf, sizeof(rd_buf));
884 else if (CHECK_FLAG(l3vpn_bgp->vpn_policy[AFI_IP6].flags,
885 BGP_VPN_POLICY_TOVPN_RD_SET))
886 prefix_rd2str(&l3vpn_bgp->vpn_policy[AFI_IP6].tovpn_rd,
887 rd_buf, sizeof(rd_buf));
888
889 *var_len = strnlen(rd_buf, RD_ADDRSTRLEN);
890 return (uint8_t *)rd_buf;
891 case MPLSL3VPNVRFCREATIONTIME:
892 return SNMP_INTEGER(
893 (uint32_t)l3vpn_bgp->snmp_stats->creation_time);
894 case MPLSL3VPNVRFOPERSTATUS:
895 if (l3vpn_bgp->snmp_stats->active)
896 return SNMP_INTEGER(1);
897 else
898 return SNMP_INTEGER(2);
899 case MPLSL3VPNVRFACTIVEINTERFACES:
900 return SNMP_INTEGER(bgp_vrf_interfaces(l3vpn_bgp, true));
901 case MPLSL3VPNVRFASSOCIATEDINTERFACES:
902 return SNMP_INTEGER(bgp_vrf_interfaces(l3vpn_bgp, false));
903 case MPLSL3VPNVRFCONFMIDRTETHRESH:
904 return SNMP_INTEGER(0);
905 case MPLSL3VPNVRFCONFHIGHRTETHRSH:
906 return SNMP_INTEGER(0);
907 case MPLSL3VPNVRFCONFMAXROUTES:
908 return SNMP_INTEGER(0);
909 case MPLSL3VPNVRFCONFLASTCHANGED:
910 return SNMP_INTEGER(
911 (uint32_t)l3vpn_bgp->snmp_stats->modify_time);
912 case MPLSL3VPNVRFCONFROWSTATUS:
913 return SNMP_INTEGER(1);
914 case MPLSL3VPNVRFCONFADMINSTATUS:
915 return SNMP_INTEGER(1);
916 case MPLSL3VPNVRFCONFSTORAGETYPE:
917 return SNMP_INTEGER(2);
7fd28dd2
PR
918 }
919 return NULL;
920}
921
922/* 1.3.6.1.2.1.10.166.11.1.3.1.1.x = 14*/
923#define PERFTAB_NAMELEN 14
924
925static uint8_t *mplsL3vpnPerfTable(struct variable *v, oid name[],
926 size_t *length, int exact, size_t *var_len,
927 WriteMethod **write_method)
928{
929 char vrf_name[VRF_NAMSIZ];
930 struct bgp *l3vpn_bgp;
931
932 if (smux_header_table(v, name, length, exact, var_len, write_method)
933 == MATCH_FAILED)
0d020cd6 934 return NULL;
7fd28dd2
PR
935
936 memset(vrf_name, 0, VRF_NAMSIZ);
937 l3vpn_bgp = bgpL3vpnVrf_lookup(v, name, length, vrf_name, exact);
938
939 if (!l3vpn_bgp)
940 return NULL;
941
942 switch (v->magic) {
943 case MPLSL3VPNVRFPERFROUTESADDED:
944 return SNMP_INTEGER(l3vpn_bgp->snmp_stats->routes_added);
945 case MPLSL3VPNVRFPERFROUTESDELETED:
946 return SNMP_INTEGER(l3vpn_bgp->snmp_stats->routes_deleted);
947 case MPLSL3VPNVRFPERFCURRNUMROUTES:
948 return SNMP_INTEGER(bgp_mpls_l3vpn_current_routes(l3vpn_bgp));
0d020cd6
PR
949 }
950 return NULL;
951}
952
62e66e55
PR
953static struct bgp_path_info *
954bgp_lookup_route(struct bgp *l3vpn_bgp, struct bgp_dest **dest,
955 struct prefix *prefix, uint16_t policy, struct ipaddr *nexthop)
956{
957 struct bgp_path_info *pi = NULL;
958 struct bgp_table *table;
959
960 switch (prefix->family) {
961 case AF_INET:
962 table = l3vpn_bgp->rib[AFI_IP][SAFI_UNICAST];
963 break;
964 case AF_INET6:
965 table = l3vpn_bgp->rib[AFI_IP6][SAFI_UNICAST];
966 break;
967 default:
968 return NULL;
969 }
970
971 /*get the prefix */
972 *dest = bgp_node_lookup(table, prefix);
973 if (*dest == NULL)
974 return NULL;
975
976 /* now find the right path */
977 pi = bgp_dest_get_bgp_path_info(*dest);
978 for (; pi; pi = pi->next) {
979 switch (nexthop->ipa_type) {
980 case IPADDR_V4:
981 if (nexthop->ip._v4_addr.s_addr
982 == pi->attr->nexthop.s_addr)
983 return pi;
984 break;
985 case IPADDR_V6:
986 if (memcmp(&nexthop->ip._v6_addr,
987 &pi->attr->mp_nexthop_global,
988 sizeof(struct in6_addr))
989 == 0)
990 return pi;
991 break;
992 default:
993 return pi;
994 }
995 }
996 return NULL;
997}
998
999static struct bgp_path_info *bgp_lookup_route_next(struct bgp **l3vpn_bgp,
1000 struct bgp_dest **dest,
1001 struct prefix *prefix,
1002 uint16_t *policy,
1003 struct ipaddr *nexthop)
1004{
1005 struct bgp_path_info *pi = NULL;
1006 struct bgp_table *table;
1007 const struct prefix *p;
1008 uint8_t family;
1009
1010 /* First route?*/
1011 if (prefix->prefixlen == 0) {
1012 /* try V4 table */
1013 table = (*l3vpn_bgp)->rib[AFI_IP][SAFI_UNICAST];
1014 for (*dest = bgp_table_top(table); *dest;
1015 *dest = bgp_route_next(*dest)) {
1016 pi = bgp_dest_get_bgp_path_info(*dest);
1017 if (pi)
1018 break;
1019 }
1020
1021 if (!pi) {
1022 /* try V6 table */
1023 table = (*l3vpn_bgp)->rib[AFI_IP6][SAFI_UNICAST];
1024 for (*dest = bgp_table_top(table); *dest;
1025 *dest = bgp_route_next(*dest)) {
1026 pi = bgp_dest_get_bgp_path_info(*dest);
1027 if (pi)
1028 break;
1029 }
1030 }
1031 return pi;
1032 }
1033 /* real next search for the entry first use exact lookup */
1034 pi = bgp_lookup_route(*l3vpn_bgp, dest, prefix, *policy, nexthop);
1035
1036 if (pi == NULL)
1037 return NULL;
1038
1039 p = bgp_dest_get_prefix(*dest);
1040 family = p->family;
1041
1042 /* We have found the input path let's find the next one in the list */
1043 if (pi->next) {
1044 /* ensure OID is always higher for multipath routes by
1045 * incrementing opaque policy oid
1046 */
1047 *policy += 1;
1048 return pi->next;
1049 }
1050
1051 /* No more paths in the input route so find the next route */
1052 for (; *l3vpn_bgp;
1053 *l3vpn_bgp = bgp_lookup_by_name_next((*l3vpn_bgp)->name)) {
1054 *policy = 0;
1055 if (!*dest) {
1056 table = (*l3vpn_bgp)->rib[AFI_IP][SAFI_UNICAST];
1057 *dest = bgp_table_top(table);
1058 family = AF_INET;
1059 } else
1060 *dest = bgp_route_next(*dest);
1061
1062 while (true) {
1063 for (; *dest; *dest = bgp_route_next(*dest)) {
1064 pi = bgp_dest_get_bgp_path_info(*dest);
1065
1066 if (pi)
1067 return pi;
1068 }
1069 if (family == AF_INET) {
1070 table = (*l3vpn_bgp)
1071 ->rib[AFI_IP6][SAFI_UNICAST];
1072 *dest = bgp_table_top(table);
1073 family = AF_INET6;
1074 continue;
1075 }
1076 break;
1077 }
1078 }
1079
1080 return NULL;
1081}
1082
1083static bool is_addr_type(oid id)
1084{
1085 switch (id) {
1086 case INETADDRESSTYPEUNKNOWN:
1087 case INETADDRESSTYPEIPV4:
1088 case INETADDRESSTYPEIPV6:
1089 return true;
1090 }
1091 return false;
1092}
1093
1094/* 1.3.6.1.2.1.10.166.11.1.4.1.1.x = 14*/
1095#define PERFTAB_NAMELEN 14
1096
1097static struct bgp_path_info *bgpL3vpnRte_lookup(struct variable *v, oid name[],
1098 size_t *length, char *vrf_name,
1099 struct bgp **l3vpn_bgp,
1100 struct bgp_dest **dest,
1101 uint16_t *policy, int exact)
1102{
1103 uint8_t i;
1104 uint8_t vrf_name_len = 0;
1105 struct bgp_path_info *pi = NULL;
1106 size_t namelen = v ? v->namelen : IFCONFTAB_NAMELEN;
1107 struct prefix prefix = {0};
1108 struct ipaddr nexthop = {0};
1109 uint8_t prefix_type;
1110 uint8_t nexthop_type;
1111
1112 if ((uint32_t)(*length - namelen) > (VRF_NAMSIZ + 37))
1113 return NULL;
1114
1115 if (*length - namelen != 0) {
1116 /* parse incoming OID */
1117 for (i = namelen; i < (*length); i++) {
1118 if (is_addr_type(name[i]))
1119 break;
1120 vrf_name_len++;
1121 }
1122 if (vrf_name_len > VRF_NAMSIZ)
1123 return NULL;
1124
1125 oid2string(name + namelen, vrf_name_len, vrf_name);
1126 prefix_type = name[i++];
1127 switch (prefix_type) {
1128 case INETADDRESSTYPEUNKNOWN:
1129 prefix.family = AF_UNSPEC;
1130 break;
1131 case INETADDRESSTYPEIPV4:
1132 prefix.family = AF_INET;
1133 oid2in_addr(&name[i], sizeof(struct in_addr),
1134 &prefix.u.prefix4);
1135 i += sizeof(struct in_addr);
1136 break;
1137 case INETADDRESSTYPEIPV6:
1138 prefix.family = AF_INET6;
1139 oid2in_addr(&name[i], sizeof(struct in6_addr),
1140 &prefix.u.prefix4); /* sic */
1141 i += sizeof(struct in6_addr);
1142 break;
1143 }
1144 prefix.prefixlen = (uint8_t)name[i++];
1145 *policy |= name[i++] << 8;
1146 *policy |= name[i++];
1147 nexthop_type = name[i++];
1148 switch (nexthop_type) {
1149 case INETADDRESSTYPEUNKNOWN:
1150 nexthop.ipa_type = (prefix.family == AF_INET)
1151 ? IPADDR_V4
1152 : IPADDR_V6;
1153 break;
1154 case INETADDRESSTYPEIPV4:
1155 nexthop.ipa_type = IPADDR_V4;
1156 oid2in_addr(&name[i], sizeof(struct in_addr),
1157 &nexthop.ip._v4_addr);
1158 i += sizeof(struct in_addr);
1159 break;
1160 case INETADDRESSTYPEIPV6:
1161 nexthop.ipa_type = IPADDR_V6;
1162 oid2in_addr(&name[i], sizeof(struct in6_addr),
1163 &nexthop.ip._v4_addr); /* sic */
1164 i += sizeof(struct in6_addr);
1165 break;
1166 }
1167 }
1168
1169 if (exact) {
1170 *l3vpn_bgp = bgp_lookup_by_name(vrf_name);
1171 if (*l3vpn_bgp && !is_bgp_vrf_mplsvpn(*l3vpn_bgp))
1172 return NULL;
1173 if (*l3vpn_bgp == NULL)
1174 return NULL;
1175
1176 /* now lookup the route in this bgp table */
1177 pi = bgp_lookup_route(*l3vpn_bgp, dest, &prefix, *policy,
1178 &nexthop);
1179 } else {
1180 int str_len;
1181
1182 str_len = strnlen(vrf_name, VRF_NAMSIZ);
1183 if (str_len == 0) {
1184 *l3vpn_bgp = bgp_lookup_by_name_next(vrf_name);
1185 } else
1186 /* otherwise lookup the one we have */
1187 *l3vpn_bgp = bgp_lookup_by_name(vrf_name);
1188
1189 if (l3vpn_bgp == NULL)
1190 return NULL;
1191
1192 pi = bgp_lookup_route_next(l3vpn_bgp, dest, &prefix, policy,
1193 &nexthop);
1194 if (pi) {
1195 uint8_t vrf_name_len =
1196 strnlen((*l3vpn_bgp)->name, VRF_NAMSIZ);
1197 const struct prefix *p = bgp_dest_get_prefix(*dest);
1198 uint8_t oid_index;
1199 bool v4 = (p->family == AF_INET);
1200 uint8_t addr_len = v4 ? sizeof(struct in_addr)
1201 : sizeof(struct in6_addr);
1202 struct attr *attr = pi->attr;
1203
1204 /* copy the index parameters */
1205 oid_copy_str(&name[namelen], (*l3vpn_bgp)->name,
1206 vrf_name_len);
1207 oid_index = namelen + vrf_name_len;
1208 name[oid_index++] =
1209 v4 ? INETADDRESSTYPEIPV4 : INETADDRESSTYPEIPV6;
1210 oid_copy_addr(&name[oid_index], &p->u.prefix4,
1211 addr_len);
1212 oid_index += addr_len;
1213 name[oid_index++] = p->prefixlen;
1214 name[oid_index++] = *policy >> 8;
1215 name[oid_index++] = *policy & 0xff;
1216
1217 if (!BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
1218 if (attr->nexthop.s_addr == INADDR_ANY)
1219 name[oid_index++] =
1220 INETADDRESSTYPEUNKNOWN;
1221 else {
1222 name[oid_index++] = INETADDRESSTYPEIPV4;
1223 oid_copy_addr(&name[oid_index],
1224 &attr->nexthop,
1225 sizeof(struct in_addr));
1226 oid_index += sizeof(struct in_addr);
1227 }
1228 } else {
1229 if (IN6_IS_ADDR_UNSPECIFIED(
1230 &attr->mp_nexthop_global))
1231 name[oid_index++] =
1232 INETADDRESSTYPEUNKNOWN;
1233 else {
1234 name[oid_index++] = INETADDRESSTYPEIPV6;
1235 oid_copy_addr(
1236 &name[oid_index],
1237 (struct in_addr *)&attr
1238 ->mp_nexthop_global,
1239 sizeof(struct in6_addr));
1240 oid_index += sizeof(struct in6_addr);
1241 }
1242 }
1243 *length = oid_index;
1244 }
1245 }
1246 return pi;
1247}
1248
1249static uint8_t *mplsL3vpnRteTable(struct variable *v, oid name[],
1250 size_t *length, int exact, size_t *var_len,
1251 WriteMethod **write_method)
1252{
1253 char vrf_name[VRF_NAMSIZ];
1254 struct bgp *l3vpn_bgp;
1255 struct bgp_dest *dest;
1256 struct bgp_path_info *pi;
1257 const struct prefix *p;
1258 uint16_t policy = 0;
1259
1260 if (smux_header_table(v, name, length, exact, var_len, write_method)
1261 == MATCH_FAILED)
1262 return NULL;
1263
1264 memset(vrf_name, 0, VRF_NAMSIZ);
1265 pi = bgpL3vpnRte_lookup(v, name, length, vrf_name, &l3vpn_bgp, &dest,
1266 &policy, exact);
1267
1268
1269 if (!pi)
1270 return NULL;
1271
1272 p = bgp_dest_get_prefix(dest);
1273
1274 if (!p)
1275 return NULL;
1276
1277 switch (v->magic) {
1278 case MPLSL3VPNVRFRTEINETCIDRDESTTYPE:
1279 switch (p->family) {
1280 case AF_INET:
1281 return SNMP_INTEGER(INETADDRESSTYPEIPV4);
1282 case AF_INET6:
1283 return SNMP_INTEGER(INETADDRESSTYPEIPV6);
1284 default:
1285 return SNMP_INTEGER(INETADDRESSTYPEUNKNOWN);
1286 }
1287 case MPLSL3VPNVRFRTEINETCIDRDEST:
1288 switch (p->family) {
1289 case AF_INET:
1290 return SNMP_IPADDRESS(p->u.prefix4);
1291 case AF_INET6:
1292 return SNMP_IP6ADDRESS(p->u.prefix6);
1293 default:
1294 *var_len = 0;
1295 return NULL;
1296 }
1297 case MPLSL3VPNVRFRTEINETCIDRPFXLEN:
1298 return SNMP_INTEGER(p->prefixlen);
1299 case MPLSL3VPNVRFRTEINETCIDRPOLICY:
1300 *var_len = sizeof(mpls_l3vpn_policy_oid);
1301 mpls_l3vpn_policy_oid[0] = policy >> 8;
1302 mpls_l3vpn_policy_oid[1] = policy & 0xff;
1303 return (uint8_t *)mpls_l3vpn_policy_oid;
1304 case MPLSL3VPNVRFRTEINETCIDRNHOPTYPE:
1305 if (!BGP_ATTR_NEXTHOP_AFI_IP6(pi->attr)) {
1306 if (pi->attr->nexthop.s_addr == INADDR_ANY)
1307 return SNMP_INTEGER(INETADDRESSTYPEUNKNOWN);
1308 else
1309 return SNMP_INTEGER(INETADDRESSTYPEIPV4);
1310 } else if (IN6_IS_ADDR_UNSPECIFIED(
1311 &pi->attr->mp_nexthop_global))
1312 return SNMP_INTEGER(INETADDRESSTYPEUNKNOWN);
1313 else
1314 return SNMP_INTEGER(INETADDRESSTYPEIPV6);
1315
1316 case MPLSL3VPNVRFRTEINETCIDRNEXTHOP:
1317 if (!BGP_ATTR_NEXTHOP_AFI_IP6(pi->attr))
1318 if (pi->attr->nexthop.s_addr == INADDR_ANY) {
1319 *var_len = 0;
1320 return (uint8_t *)empty_nhop;
1321 } else
1322 return SNMP_IPADDRESS(pi->attr->nexthop);
1323 else if (IN6_IS_ADDR_UNSPECIFIED(
1324 &pi->attr->mp_nexthop_global)) {
1325 *var_len = 0;
1326 return (uint8_t *)empty_nhop;
1327 } else
1328 return SNMP_IP6ADDRESS(pi->attr->mp_nexthop_global);
1329
1330 case MPLSL3VPNVRFRTEINETCIDRIFINDEX:
1331 if (pi->nexthop && pi->nexthop->nexthop)
1332 return SNMP_INTEGER(pi->nexthop->nexthop->ifindex);
1333 else
1334 return SNMP_INTEGER(0);
1335 case MPLSL3VPNVRFRTEINETCIDRTYPE:
1336 if (pi->nexthop && pi->nexthop->nexthop) {
1337 switch (pi->nexthop->nexthop->type) {
1338 case NEXTHOP_TYPE_IFINDEX:
1339 return SNMP_INTEGER(
1340 MPLSL3VPNVRFRTECIDRTYPELOCAL);
1341 case NEXTHOP_TYPE_IPV4:
1342 case NEXTHOP_TYPE_IPV4_IFINDEX:
1343 case NEXTHOP_TYPE_IPV6:
1344 case NEXTHOP_TYPE_IPV6_IFINDEX:
1345 return SNMP_INTEGER(
1346 MPLSL3VPNVRFRTECIDRTYPEREMOTE);
1347 case NEXTHOP_TYPE_BLACKHOLE:
1348 switch (pi->nexthop->nexthop->bh_type) {
1349 case BLACKHOLE_REJECT:
1350 return SNMP_INTEGER(
1351 MPLSL3VPNVRFRTECIDRTYPEREJECT);
1352 default:
1353 return SNMP_INTEGER(
1354 MPLSL3VPNVRFRTECIDRTYPEBLACKHOLE);
1355 }
1356 default:
1357 return SNMP_INTEGER(
1358 MPLSL3VPNVRFRTECIDRTYPEOTHER);
1359 }
1360 } else
1361 return SNMP_INTEGER(MPLSL3VPNVRFRTECIDRTYPEOTHER);
1362 case MPLSL3VPNVRFRTEINETCIDRPROTO:
1363 switch (pi->type) {
1364 case ZEBRA_ROUTE_CONNECT:
1365 return SNMP_INTEGER(IANAIPROUTEPROTOCOLLOCAL);
1366 case ZEBRA_ROUTE_STATIC:
1367 return SNMP_INTEGER(IANAIPROUTEPROTOCOLNETMGMT);
1368 case ZEBRA_ROUTE_RIP:
1369 case ZEBRA_ROUTE_RIPNG:
1370 return SNMP_INTEGER(IANAIPROUTEPROTOCOLRIP);
1371 case ZEBRA_ROUTE_OSPF:
1372 case ZEBRA_ROUTE_OSPF6:
1373 return SNMP_INTEGER(IANAIPROUTEPROTOCOLOSPF);
1374 case ZEBRA_ROUTE_ISIS:
1375 return SNMP_INTEGER(IANAIPROUTEPROTOCOLISIS);
1376 case ZEBRA_ROUTE_BGP:
1377 return SNMP_INTEGER(IANAIPROUTEPROTOCOLBGP);
1378 case ZEBRA_ROUTE_EIGRP:
1379 return SNMP_INTEGER(IANAIPROUTEPROTOCOLCISCOEIGRP);
1380 default:
1381 return SNMP_INTEGER(IANAIPROUTEPROTOCOLOTHER);
1382 }
1383 case MPLSL3VPNVRFRTEINETCIDRAGE:
1384 return SNMP_INTEGER(pi->uptime);
1385 case MPLSL3VPNVRFRTEINETCIDRNEXTHOPAS:
1386 return SNMP_INTEGER(pi->peer ? pi->peer->as : 0);
1387 case MPLSL3VPNVRFRTEINETCIDRMETRIC1:
1388 if (pi->extra)
1389 return SNMP_INTEGER(pi->extra->igpmetric);
1390 else
1391 return SNMP_INTEGER(0);
1392 case MPLSL3VPNVRFRTEINETCIDRMETRIC2:
1393 return SNMP_INTEGER(-1);
1394 case MPLSL3VPNVRFRTEINETCIDRMETRIC3:
1395 return SNMP_INTEGER(-1);
1396 case MPLSL3VPNVRFRTEINETCIDRMETRIC4:
1397 return SNMP_INTEGER(-1);
1398 case MPLSL3VPNVRFRTEINETCIDRMETRIC5:
1399 return SNMP_INTEGER(-1);
1400 case MPLSL3VPNVRFRTEINETCIDRXCPOINTER:
1401 return SNMP_OCTET(0);
1402 case MPLSL3VPNVRFRTEINETCIDRSTATUS:
1403 return SNMP_INTEGER(1);
1404 }
1405 return NULL;
1406}
1407
aa53f693
PR
1408void bgp_mpls_l3vpn_module_init(void)
1409{
0d020cd6
PR
1410 hook_register(bgp_vrf_status_changed, bgp_vrf_check_update_active);
1411 hook_register(bgp_snmp_init_stats, bgp_init_snmp_stats);
1412 hook_register(bgp_snmp_update_last_changed,
1413 bgp_mpls_l3vpn_update_last_changed);
7fd28dd2 1414 hook_register(bgp_snmp_update_stats, bgp_snmp_update_route_stats);
aa53f693
PR
1415 REGISTER_MIB("mplsL3VpnMIB", mpls_l3vpn_variables, variable,
1416 mpls_l3vpn_oid);
1417}