From 15fb7209eede6226bbe15a9618a8d06b88d44a08 Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Mon, 22 Jul 2024 10:57:21 +0200 Subject: [PATCH 1/4] bgpd: fix ipv4-mapped ipv6 for ipv6 over ipv4 peer When IPv6 prefixes are sent over an IPv4 session, the UPDATE is sent with a link-local nexthop as global nexthop instead of a IPv4-mapped IPv6 address. If the peer interface has no IPv6 address, routes are not installed. Seen with bgp_nexthop_mp_ipv4_6 topotests on step2: > root@r2:/# vtysh -c 'show bgp ipv6 fd00:100::/64 json' | jq . > { > "prefix": "fd00:100::/64", > "paths": [ > { > "nexthops": [ > { > "ip": "fe80::449a:f8ff:fe67:1f93", > "hostname": "r1", > "afi": "ipv6", > "scope": "global", > "metric": 0, > "accessible": true > }, > { > "ip": "fe80::449a:f8ff:fe67:1f93", > "hostname": "r1", > "afi": "ipv6", > "scope": "link-local", > "accessible": true, > "used": true > } > ], > } > ] > } Now: > root@r2:/# vtysh -c 'show bgp ipv6 fd00:100::/64 json' | jq . > { > "prefix": "fd00:100::/64", > "paths": [ > "nexthops": [ > { > "ip": "::ffff:172.16.0.1", > "hostname": "r1", > "afi": "ipv6", > "scope": "global", > "metric": 0, > "accessible": true > }, > { > "ip": "fe80::3842:28ff:fe90:f815", > "hostname": "r1", > "afi": "ipv6", > "scope": "link-local", > "accessible": true, > "used": true > } > ], > } > ] > } Note that the link-local is still preferred over the global address. Fixes: 25995695f5 ("bgpd: set ipv4-mapped ipv6 for ipv4 with ipv6 nexthop") Signed-off-by: Louis Scalbert --- bgpd/bgp_updgrp_packet.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 6e30d4f846..468bf47715 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -526,8 +526,10 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, if (peer->nexthop.v4.s_addr != INADDR_ANY && (IN6_IS_ADDR_UNSPECIFIED(mod_v6nhg) || (IN6_IS_ADDR_LINKLOCAL(mod_v6nhg) && - peer->connection->su.sa.sa_family == AF_INET6 && - paf->afi == AFI_IP))) { + ((peer->connection->su.sa.sa_family == AF_INET6 && + paf->afi == AFI_IP) || + (peer->connection->su.sa.sa_family == AF_INET && + paf->afi == AFI_IP6))))) { ipv4_to_ipv4_mapped_ipv6(mod_v6nhg, peer->nexthop.v4); gnh_modified = 1; } From 6e8897fcf527299f546c4a26ef020e4d30fd68ed Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Mon, 22 Jul 2024 16:17:40 +0200 Subject: [PATCH 2/4] bgpd: fix nexthop resolution of ipv4-mapped ipv6 Fix nexthop resolution of ipv4-mapped ipv6 nexthop addresses. Fixes: 5dd731af84 ("bgpd: prefer link-local to a ipv4-mapped ipv6 global") Signed-off-by: Louis Scalbert --- bgpd/bgp_nht.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 8ce45558e9..67e7463fe4 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -351,7 +351,9 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, } return 0; } - + if (afi == AFI_IP6 && p.family == AF_INET) + /* IPv4 mapped IPv6 nexthop address */ + afi = AFI_IP; srte_color = bgp_attr_get_color(pi->attr); } else if (peer) { @@ -1078,14 +1080,25 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p) &ipv4); p->u.prefix4 = ipv4; p->prefixlen = IPV4_MAX_BITLEN; + p->family = AF_INET; } else p->u.prefix6 = pi->attr->mp_nexthop_global; } else p->u.prefix6 = pi->attr->mp_nexthop_local; - } else - p->u.prefix6 = pi->attr->mp_nexthop_global; + } else { + if (IS_MAPPED_IPV6( + &pi->attr->mp_nexthop_global)) { + ipv4_mapped_ipv6_to_ipv4(&pi->attr->mp_nexthop_global, + &ipv4); + p->u.prefix4 = ipv4; + p->prefixlen = IPV4_MAX_BITLEN; + p->family = AF_INET; + } else + p->u.prefix6 = + pi->attr->mp_nexthop_global; + } } break; default: From 5d2289db26803caed3533706076523c670754b6e Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Tue, 23 Jul 2024 10:26:36 +0200 Subject: [PATCH 3/4] bgpd: replace ipv4-mapped ipv6 at update forwarding Replace IPv4-mapped IPv6 at update forwarding because the peer may not be able to create a route with the IPv4-mapped IPv6. Signed-off-by: Louis Scalbert --- bgpd/bgp_updgrp_packet.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 468bf47715..12feac8353 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -508,6 +508,9 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, gnh_modified = 1; } } else if (IN6_IS_ADDR_UNSPECIFIED(&v6nhglobal)) { + /* the UPDATE is originating from the local router. + * Build the global nexthop. + */ mod_v6nhg = &peer->nexthop.v6_global; gnh_modified = 1; } else if ((peer->sort == BGP_PEER_EBGP) @@ -521,6 +524,14 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, */ mod_v6nhg = &peer->nexthop.v6_global; gnh_modified = 1; + } else if (IS_MAPPED_IPV6(&v6nhglobal) && + !IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_global)) { + /* prefer a IPv6 native global address over + * an IPv4-mapped IPv6 address as nexthop when + * forwarding UPDATEs. + */ + mod_v6nhg = &peer->nexthop.v6_global; + gnh_modified = 1; } if (peer->nexthop.v4.s_addr != INADDR_ANY && @@ -535,6 +546,10 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, } if (IS_MAPPED_IPV6(&peer->nexthop.v6_global)) { + /* If the interface to the peer has no global IPv6 + * address, replace the nexthop in UPDATE with + * the IPv4-mapped IPv6 address if any. + */ mod_v6nhg = &peer->nexthop.v6_global; gnh_modified = 1; } From d61843621140cb8c5730786fb7ce738f3ce72e72 Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Tue, 23 Jul 2024 10:38:04 +0200 Subject: [PATCH 4/4] topotests: bgp_nexthop_mp_ipv4_6, test ipv4-mapped Test that a IPv4-mapped IPv6 is sent from a peer that has no global IPv6 address. Signed-off-by: Louis Scalbert --- tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv6_step2.json | 5 +++++ tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv6_step2.json | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv6_step2.json index 21f36089b6..6738d45750 100644 --- a/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv6_step2.json +++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv6_step2.json @@ -6,6 +6,11 @@ "bestpath": true, "path": "65100", "nexthops": [ + { + "ip": "::ffff:ac10:1", + "afi": "ipv6", + "scope": "global" + }, { "afi": "ipv6", "scope": "link-local", diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv6_step2.json index 21f36089b6..807806ff8d 100644 --- a/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv6_step2.json +++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv6_step2.json @@ -6,6 +6,11 @@ "bestpath": true, "path": "65100", "nexthops": [ + { + "ip": "::ffff:ac10:101", + "afi": "ipv6", + "scope": "global" + }, { "afi": "ipv6", "scope": "link-local",