mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-04 20:18:54 +00:00
Merge pull request #3020 from donaldsharp/global_5549
Allow v6 global addresses to be nexthops for v4 addresses in bgp
This commit is contained in:
commit
82977e243a
@ -415,6 +415,8 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
|
||||
bnc->change_flags |= BGP_NEXTHOP_CHANGED;
|
||||
|
||||
if (nhr.nexthop_num) {
|
||||
struct peer *peer = bnc->nht_info;
|
||||
|
||||
/* notify bgp fsm if nbr ip goes from invalid->valid */
|
||||
if (!bnc->nexthop_num)
|
||||
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
|
||||
@ -430,6 +432,22 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
|
||||
|
||||
nexthop = nexthop_from_zapi_nexthop(&nhr.nexthops[i]);
|
||||
|
||||
/*
|
||||
* Turn on RA for the v6 nexthops
|
||||
* we receive from bgp. This is to allow us
|
||||
* to work with v4 routing over v6 nexthops
|
||||
*/
|
||||
if (peer &&
|
||||
CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)
|
||||
&& nhr.prefix.family == AF_INET6) {
|
||||
struct interface *ifp;
|
||||
|
||||
ifp = if_lookup_by_index(nexthop->ifindex,
|
||||
nexthop->vrf_id);
|
||||
zclient_send_interface_radv_req(
|
||||
zclient, nexthop->vrf_id, ifp, true,
|
||||
BGP_UNNUM_DEFAULT_RA_INTERVAL);
|
||||
}
|
||||
/* There is at least one label-switched path */
|
||||
if (nexthop->nh_label &&
|
||||
nexthop->nh_label->num_labels) {
|
||||
|
@ -1331,7 +1331,6 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
|
||||
*/
|
||||
if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)
|
||||
&& peer->su.sa.sa_family == AF_INET6
|
||||
&& IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr)
|
||||
&& afi == AFI_IP
|
||||
&& (safi == SAFI_UNICAST
|
||||
|| safi == SAFI_LABELED_UNICAST)) {
|
||||
|
@ -845,6 +845,15 @@ Configuring Peers
|
||||
specified number of hops away will be allowed to become neighbors. This
|
||||
command is mutually exclusive with *ebgp-multihop*.
|
||||
|
||||
.. index:: [no] neighbor PEER capability extended-nexthop
|
||||
.. clicmd:: [no] neighbor PEER capability extended-nexthop
|
||||
|
||||
Allow bgp to negotiate the extended-nexthop capability with it's peer.
|
||||
If you are peering over a v6 LL address then this capability is turned
|
||||
on automatically. If you are peering over a v6 Global Address then
|
||||
turning on this command will allow BGP to install v4 routes with
|
||||
v6 nexthops if you do not have v4 configured on interfaces.
|
||||
|
||||
.. index:: [no] bgp fast-external-failover
|
||||
.. clicmd:: [no] bgp fast-external-failover
|
||||
|
||||
|
@ -51,6 +51,8 @@
|
||||
#include "zebra/zebra_vxlan.h"
|
||||
#include "zebra/zebra_errors.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(ZEBRA, ZINFO, "Zebra Interface Information")
|
||||
|
||||
#define ZEBRA_PTM_SUPPORT
|
||||
|
||||
DEFINE_HOOK(zebra_if_extra_info, (struct vty * vty, struct interface *ifp),
|
||||
@ -99,7 +101,7 @@ static int if_zebra_new_hook(struct interface *ifp)
|
||||
{
|
||||
struct zebra_if *zebra_if;
|
||||
|
||||
zebra_if = XCALLOC(MTYPE_TMP, sizeof(struct zebra_if));
|
||||
zebra_if = XCALLOC(MTYPE_ZINFO, sizeof(struct zebra_if));
|
||||
|
||||
zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC;
|
||||
zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
|
||||
@ -136,6 +138,8 @@ static int if_zebra_new_hook(struct interface *ifp)
|
||||
}
|
||||
#endif /* HAVE_RTADV */
|
||||
|
||||
memset(&zebra_if->neigh_mac[0], 0, 6);
|
||||
|
||||
/* Initialize installed address chains tree. */
|
||||
zebra_if->ipv4_subnets =
|
||||
route_table_init_with_delegate(&zebra_if_table_delegate);
|
||||
@ -175,7 +179,7 @@ static int if_zebra_delete_hook(struct interface *ifp)
|
||||
|
||||
THREAD_OFF(zebra_if->speed_update);
|
||||
|
||||
XFREE(MTYPE_TMP, zebra_if);
|
||||
XFREE(MTYPE_ZINFO, zebra_if);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -802,19 +806,32 @@ static void ipv6_ll_address_to_mac(struct in6_addr *address, uint8_t *mac)
|
||||
mac[5] = address->s6_addr[15];
|
||||
}
|
||||
|
||||
void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp,
|
||||
struct in6_addr *address, int add)
|
||||
static bool mac_is_same(char *mac1, char *mac2)
|
||||
{
|
||||
if (mac1[0] == mac2[0] &&
|
||||
mac1[1] == mac2[1] &&
|
||||
mac1[2] == mac2[2] &&
|
||||
mac1[3] == mac2[3] &&
|
||||
mac1[4] == mac2[4] &&
|
||||
mac1[5] == mac2[5])
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp,
|
||||
char mac[6],
|
||||
struct in6_addr *address,
|
||||
int add)
|
||||
{
|
||||
struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
|
||||
struct zebra_if *zif = ifp->info;
|
||||
char buf[16] = "169.254.0.1";
|
||||
struct in_addr ipv4_ll;
|
||||
char mac[6];
|
||||
ns_id_t ns_id;
|
||||
|
||||
inet_pton(AF_INET, buf, &ipv4_ll);
|
||||
|
||||
ipv6_ll_address_to_mac(address, (uint8_t *)mac);
|
||||
ns_id = zvrf->zns->ns_id;
|
||||
|
||||
/*
|
||||
@ -823,10 +840,16 @@ void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp,
|
||||
*
|
||||
* supported message types are RTM_NEWNEIGH and RTM_DELNEIGH
|
||||
*/
|
||||
kernel_neigh_update(0, ifp->ifindex, ipv4_ll.s_addr, mac, 6, ns_id);
|
||||
if (!mac_is_same(zif->neigh_mac, mac)) {
|
||||
kernel_neigh_update(0, ifp->ifindex, ipv4_ll.s_addr,
|
||||
mac, 6, ns_id);
|
||||
|
||||
/* Add arp record */
|
||||
kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr, mac, 6, ns_id);
|
||||
/* Add arp record */
|
||||
kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr,
|
||||
mac, 6, ns_id);
|
||||
}
|
||||
|
||||
memcpy(&zif->neigh_mac[0], &mac[0], 6);
|
||||
|
||||
/*
|
||||
* We need to note whether or not we originated a v6
|
||||
@ -840,6 +863,16 @@ void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp,
|
||||
zvrf->neigh_updates++;
|
||||
}
|
||||
|
||||
void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp,
|
||||
struct in6_addr *address, int add)
|
||||
{
|
||||
|
||||
char mac[6];
|
||||
|
||||
ipv6_ll_address_to_mac(address, (uint8_t *)mac);
|
||||
if_nbr_mac_to_ipv4ll_neigh_update(ifp, mac, address, add);
|
||||
}
|
||||
|
||||
static void if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(struct interface *ifp)
|
||||
{
|
||||
if (listhead(ifp->nbr_connected)) {
|
||||
|
@ -279,6 +279,7 @@ struct zebra_if {
|
||||
* for bgp unnumbered?
|
||||
*/
|
||||
bool v6_2_v4_ll_neigh_entry;
|
||||
char neigh_mac[6];
|
||||
struct in6_addr v6_2_v4_ll_addr6;
|
||||
};
|
||||
|
||||
@ -332,6 +333,10 @@ extern struct interface *if_link_per_ns(struct zebra_ns *, struct interface *);
|
||||
extern const char *ifindex2ifname_per_ns(struct zebra_ns *, unsigned int);
|
||||
|
||||
extern void if_unlink_per_ns(struct interface *);
|
||||
extern void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *fip,
|
||||
char mac[6],
|
||||
struct in6_addr *address,
|
||||
int add);
|
||||
extern void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp,
|
||||
struct in6_addr *address,
|
||||
int add);
|
||||
|
@ -455,6 +455,38 @@ static void rtadv_process_solicit(struct interface *ifp)
|
||||
rtadv_send_packet(zns->rtadv.sock, ifp);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function processes optional attributes off of
|
||||
* end of a RA packet received. At this point in
|
||||
* time we only care about this in one situation
|
||||
* which is when a interface does not have a LL
|
||||
* v6 address. We still need to be able to install
|
||||
* the mac address for v4 to v6 resolution
|
||||
*/
|
||||
static void rtadv_process_optional(uint8_t *optional, unsigned int len,
|
||||
struct interface *ifp,
|
||||
struct sockaddr_in6 *addr)
|
||||
{
|
||||
char *mac;
|
||||
|
||||
while (len > 0) {
|
||||
struct nd_opt_hdr *opt_hdr = (struct nd_opt_hdr *)optional;
|
||||
|
||||
switch(opt_hdr->nd_opt_type) {
|
||||
case ND_OPT_SOURCE_LINKADDR:
|
||||
mac = (char *)(optional+2);
|
||||
if_nbr_mac_to_ipv4ll_neigh_update(ifp, mac,
|
||||
&addr->sin6_addr, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
len -= 8 * opt_hdr->nd_opt_len;
|
||||
optional += 8 * opt_hdr->nd_opt_len;
|
||||
}
|
||||
}
|
||||
|
||||
static void rtadv_process_advert(uint8_t *msg, unsigned int len,
|
||||
struct interface *ifp,
|
||||
struct sockaddr_in6 *addr)
|
||||
@ -469,14 +501,19 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
|
||||
inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
|
||||
|
||||
if (len < sizeof(struct nd_router_advert)) {
|
||||
zlog_debug("%s(%u): Rx RA with invalid length %d from %s",
|
||||
ifp->name, ifp->ifindex, len, addr_str);
|
||||
if (IS_ZEBRA_DEBUG_PACKET)
|
||||
zlog_debug("%s(%u): Rx RA with invalid length %d from %s",
|
||||
ifp->name, ifp->ifindex, len, addr_str);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
|
||||
zlog_debug(
|
||||
"%s(%u): Rx RA with non-linklocal source address from %s",
|
||||
ifp->name, ifp->ifindex, addr_str);
|
||||
rtadv_process_optional(msg + sizeof(struct nd_router_advert),
|
||||
len - sizeof(struct nd_router_advert),
|
||||
ifp, addr);
|
||||
if (IS_ZEBRA_DEBUG_PACKET)
|
||||
zlog_debug("%s(%u): Rx RA with non-linklocal source address from %s",
|
||||
ifp->name, ifp->ifindex, addr_str);
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user