Skip to content

Commit 5f334b9

Browse files
bgpd: add multiple paths support for draft ietf bgp4v2 in nlriTable
There is no support for dumping multiple paths for the same prefix. The current implementation only takes the first available entry. Fix this by walking over the list of available paths, ordered by peer. The nlri index is set gradually for each path. Signed-off-by: Francois Dumontet <[email protected]>
1 parent 27be058 commit 5f334b9

File tree

1 file changed

+70
-20
lines changed

1 file changed

+70
-20
lines changed

bgpd/bgp_snmp_bgp4v2.c

+70-20
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,8 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
446446
size_t afi_len;
447447
long prefix_type = 0;
448448
long peer_addr_type = 0;
449+
long nrli_index = 1;
450+
long cur_index = 0;
449451

450452
/* Bgp4V2AddressFamilyIdentifierTC limited to IPv6 */
451453
if (name[namelen - 1] > IANA_AFI_IPV6)
@@ -455,12 +457,17 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
455457
assert(IS_VALID_AFI(afi));
456458

457459
#define BGP_NLRI_ENTRY_OFFSET namelen
460+
#define BGP4V2_NLRI_V4_V4_OFFSET IN_ADDR_SIZE + IN_ADDR_SIZE + 5
461+
#define BGP4V2_NLRI_V4_V6_OFFSET IN_ADDR_SIZE + IN6_ADDR_SIZE + 5
462+
#define BGP4V2_NLRI_V6_V6_OFFSET IN6_ADDR_SIZE + IN6_ADDR_SIZE + 5
458463

459464

460465
sockunion_init(&su);
461466

462467
if (exact) {
463-
if (*length - namelen != BGP_NLRI_ENTRY_OFFSET)
468+
if (*length - namelen != BGP4V2_NLRI_V4_V4_OFFSET &&
469+
*length - namelen != BGP4V2_NLRI_V4_V6_OFFSET &&
470+
*length - namelen != BGP4V2_NLRI_V6_V6_OFFSET)
464471
return NULL;
465472

466473
/* Set OID offset for prefix type */
@@ -504,21 +511,29 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
504511
su.sin.sin_family = family;
505512

506513
/* get bgp4V2PeerRemoteAddr*/
507-
if (family == AF_INET)
514+
if (family == AF_INET) {
508515
oid2in_addr(offset, IN_ADDR_SIZE, &su.sin.sin_addr);
509-
else
516+
offset += IN_ADDR_SIZE;
517+
} else {
510518
oid2in6_addr(offset, &su.sin6.sin6_addr);
519+
offset += IN6_ADDR_SIZE;
520+
}
511521

512-
/* bgp4V2NlriIndex currently ignored */
522+
/* bgp4V2NlriIndex */
523+
nrli_index = *offset;
524+
offset++;
513525

514526
/* Lookup node */
515527
dest = bgp_node_lookup(bgp->rib[afi][safi], addr);
516528
if (dest) {
517529
for (path = bgp_dest_get_bgp_path_info(dest); path;
518530
path = path->next)
519531
if (sockunion_same(&path->peer->connection->su,
520-
&su))
521-
return path;
532+
&su)) {
533+
cur_index++;
534+
if (cur_index == nrli_index)
535+
return path;
536+
}
522537

523538
bgp_dest_unlock_node(dest);
524539
}
@@ -573,7 +588,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
573588
offsetlen--;
574589

575590
/* get node */
576-
dest = bgp_node_get(bgp->rib[afi][safi], addr);
591+
dest = bgp_node_lookup(bgp->rib[afi][safi], addr);
577592
}
578593

579594
if (!dest)
@@ -593,22 +608,31 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
593608
family = AF_INET6;
594609
offset++;
595610

596-
if (family == AF_INET)
611+
if (family == AF_INET) {
597612
oid2in_addr(offset, IN_ADDR_SIZE, &paddr.ip._v4_addr);
598-
else
613+
offset += IN_ADDR_SIZE;
614+
} else {
599615
oid2in6_addr(offset, &paddr.ip._v6_addr);
616+
offset += IN6_ADDR_SIZE;
617+
}
618+
/* get bgp4V2NlriIndex */
619+
nrli_index = *offset;
620+
offset++;
621+
600622
} else {
601623
/* default case start with ipv4*/
602624
if (afi == AFI_IP)
603625
family = AF_INET;
604626
else
605627
family = AF_INET6;
606628
memset(&paddr.ip, 0, sizeof(paddr.ip));
629+
nrli_index = 1;
607630
}
608631

609632
do {
610633
min = NULL;
611634
min_family = 0;
635+
cur_index = 0;
612636

613637
for (path = bgp_dest_get_bgp_path_info(dest); path;
614638
path = path->next) {
@@ -618,19 +642,44 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
618642
if (path_family < family)
619643
continue;
620644

621-
if (family == AF_INET
622-
&& IPV4_ADDR_CMP(&paddr.ip._v4_addr,
623-
&path->peer->connection->su.sin.sin_addr)
624-
>= 0)
645+
if (family == AF_INET &&
646+
IPV4_ADDR_CMP(&paddr.ip._v4_addr,
647+
&path->peer->connection->su.sin
648+
.sin_addr) > 0)
625649
continue;
626-
else if (family == AF_INET6
627-
&& IPV6_ADDR_CMP(
628-
&paddr.ip._v6_addr,
629-
&path->peer->connection->su.sin6.sin6_addr)
630-
>= 0)
650+
else if (family == AF_INET6 &&
651+
IPV6_ADDR_CMP(&paddr.ip._v6_addr,
652+
&path->peer->connection->su.sin6
653+
.sin6_addr) > 0)
631654
continue;
632655

633-
/* first valid path its the min*/
656+
if (family == AF_INET &&
657+
IPV4_ADDR_CMP(&paddr.ip._v4_addr,
658+
&path->peer->connection->su.sin
659+
.sin_addr) == 0) {
660+
if (cur_index == nrli_index) {
661+
min = path;
662+
min_family = family;
663+
nrli_index++;
664+
break;
665+
}
666+
cur_index++;
667+
continue;
668+
} else if (family == AF_INET6 &&
669+
IPV6_ADDR_CMP(&paddr.ip._v6_addr,
670+
&path->peer->connection->su
671+
.sin6.sin6_addr) == 0) {
672+
if (cur_index == nrli_index) {
673+
min = path;
674+
min_family = family;
675+
nrli_index++;
676+
break;
677+
}
678+
cur_index++;
679+
continue;
680+
}
681+
682+
/* first valid path its the min peer addr*/
634683
if (!min) {
635684
min = path;
636685
min_family = path_family;
@@ -706,7 +755,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
706755

707756
/* Encode bgp4V2NlriIndex*/
708757

709-
*offset = 1;
758+
*offset = nrli_index;
710759
offset++;
711760

712761
*length = offset - name;
@@ -720,6 +769,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length,
720769
}
721770

722771
memset(&paddr.ip, 0, sizeof(paddr.ip));
772+
nrli_index = 1;
723773

724774
} while ((dest = bgp_route_next(dest)));
725775

0 commit comments

Comments
 (0)