Skip to content

Commit

Permalink
bgpd: fix 6vpe nexthop
Browse files Browse the repository at this point in the history
6vPE enables the announcement of IPv6 VPN prefixes through an IPv4 BGP
session. In this scenario, the next hop addresses for these prefixes are
represented in an IPv4-mapped IPv6 format, noted as ::ffff:[IPv4]. This
format indicates to the peer that it should route these IPv6 addresses
using information from the IPv4 nexthop. For example:

> Path Attribute - MP_REACH_NLRI
> [...]
>     Address family identifier (AFI): IPv6 (2)
>     Subsequent address family identifier (SAFI): Labeled VPN Unicast (128)
>     Next hop:  RD=0:0 IPv6=::ffff:192.0.2.5 RD=0:0 Link-local=fe80::501d:42ff:feef:b021
>     Number of Subnetwork points of attachment (SNPA): 0

However, in some situations, bgpd sends a standard nexthop IPv6 address
instead of an IPv4-mapped IPv6 address because the outgoing interface for
the BGP session has a valid IPv6 address. This is problematic because
the peer router may not be able to route the nexthop IPv6 address (ie.
if the outgoing interface has not IPv6).

Fix the issue by always sending a IPv4-mapped IPv6 address as nexthop
when the BGP session is on IPv4.

Fixes: 92d6f76 ("lib,zebra,bgpd: Fix for nexthop as IPv4 mapped IPv6 address")
Signed-off-by: Louis Scalbert <[email protected]>
  • Loading branch information
louis-6wind committed Feb 14, 2024
1 parent a5c9286 commit 5640d05
Showing 1 changed file with 14 additions and 21 deletions.
35 changes: 14 additions & 21 deletions bgpd/bgp_updgrp_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,35 +504,30 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
if (CHECK_FLAG(
vec->flags,
BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)) {
mod_v6nhg = &peer->nexthop.v6_global;
gnh_modified = 1;
}
} else if (IN6_IS_ADDR_UNSPECIFIED(&v6nhglobal)) {
mod_v6nhg = &peer->nexthop.v6_global;
} else if (IN6_IS_ADDR_UNSPECIFIED(&v6nhglobal))
gnh_modified = 1;
} else if ((peer->sort == BGP_PEER_EBGP)
&& (!bgp_multiaccess_check_v6(v6nhglobal, peer))
&& !CHECK_FLAG(vec->flags,
BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED)
&& !peer_af_flag_check(
peer, paf->afi, paf->safi,
PEER_FLAG_NEXTHOP_UNCHANGED)) {
else if ((peer->sort == BGP_PEER_EBGP) &&
(!bgp_multiaccess_check_v6(v6nhglobal, peer)) &&
!CHECK_FLAG(vec->flags,
BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) &&
!peer_af_flag_check(peer, paf->afi, paf->safi,
PEER_FLAG_NEXTHOP_UNCHANGED))
/* NOTE: not handling case where NH has new AFI
*/
mod_v6nhg = &peer->nexthop.v6_global;
gnh_modified = 1;
}

if (IN6_IS_ADDR_UNSPECIFIED(mod_v6nhg)) {
if (peer->nexthop.v4.s_addr != INADDR_ANY) {
if (gnh_modified) {
if (peer->connection->su.sa.sa_family == AF_INET)
/* IPv4 neighbor */
ipv4_to_ipv4_mapped_ipv6(mod_v6nhg,
peer->nexthop.v4);
}
}
else
/* IPv6 neighbor */
mod_v6nhg = &peer->nexthop.v6_global;

if (IS_MAPPED_IPV6(&peer->nexthop.v6_global)) {
mod_v6nhg = &peer->nexthop.v6_global;
gnh_modified = 1;
stream_put_in6_addr_at(s, offset_nhglobal, mod_v6nhg);
}

if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
Expand All @@ -545,8 +540,6 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
}
}

if (gnh_modified)
stream_put_in6_addr_at(s, offset_nhglobal, mod_v6nhg);
if (lnh_modified)
stream_put_in6_addr_at(s, offset_nhlocal, mod_v6nhl);

Expand Down

0 comments on commit 5640d05

Please sign in to comment.