mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-09 07:30:53 +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;
|
bnc->change_flags |= BGP_NEXTHOP_CHANGED;
|
||||||
|
|
||||||
if (nhr.nexthop_num) {
|
if (nhr.nexthop_num) {
|
||||||
|
struct peer *peer = bnc->nht_info;
|
||||||
|
|
||||||
/* notify bgp fsm if nbr ip goes from invalid->valid */
|
/* notify bgp fsm if nbr ip goes from invalid->valid */
|
||||||
if (!bnc->nexthop_num)
|
if (!bnc->nexthop_num)
|
||||||
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
|
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]);
|
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 */
|
/* There is at least one label-switched path */
|
||||||
if (nexthop->nh_label &&
|
if (nexthop->nh_label &&
|
||||||
nexthop->nh_label->num_labels) {
|
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)
|
if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)
|
||||||
&& peer->su.sa.sa_family == AF_INET6
|
&& peer->su.sa.sa_family == AF_INET6
|
||||||
&& IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr)
|
|
||||||
&& afi == AFI_IP
|
&& afi == AFI_IP
|
||||||
&& (safi == SAFI_UNICAST
|
&& (safi == SAFI_UNICAST
|
||||||
|| safi == SAFI_LABELED_UNICAST)) {
|
|| safi == SAFI_LABELED_UNICAST)) {
|
||||||
|
@ -845,6 +845,15 @@ Configuring Peers
|
|||||||
specified number of hops away will be allowed to become neighbors. This
|
specified number of hops away will be allowed to become neighbors. This
|
||||||
command is mutually exclusive with *ebgp-multihop*.
|
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
|
.. index:: [no] bgp fast-external-failover
|
||||||
.. clicmd:: [no] bgp fast-external-failover
|
.. clicmd:: [no] bgp fast-external-failover
|
||||||
|
|
||||||
|
@ -51,6 +51,8 @@
|
|||||||
#include "zebra/zebra_vxlan.h"
|
#include "zebra/zebra_vxlan.h"
|
||||||
#include "zebra/zebra_errors.h"
|
#include "zebra/zebra_errors.h"
|
||||||
|
|
||||||
|
DEFINE_MTYPE_STATIC(ZEBRA, ZINFO, "Zebra Interface Information")
|
||||||
|
|
||||||
#define ZEBRA_PTM_SUPPORT
|
#define ZEBRA_PTM_SUPPORT
|
||||||
|
|
||||||
DEFINE_HOOK(zebra_if_extra_info, (struct vty * vty, struct interface *ifp),
|
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;
|
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->multicast = IF_ZEBRA_MULTICAST_UNSPEC;
|
||||||
zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
|
zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
|
||||||
@ -136,6 +138,8 @@ static int if_zebra_new_hook(struct interface *ifp)
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_RTADV */
|
#endif /* HAVE_RTADV */
|
||||||
|
|
||||||
|
memset(&zebra_if->neigh_mac[0], 0, 6);
|
||||||
|
|
||||||
/* Initialize installed address chains tree. */
|
/* Initialize installed address chains tree. */
|
||||||
zebra_if->ipv4_subnets =
|
zebra_if->ipv4_subnets =
|
||||||
route_table_init_with_delegate(&zebra_if_table_delegate);
|
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);
|
THREAD_OFF(zebra_if->speed_update);
|
||||||
|
|
||||||
XFREE(MTYPE_TMP, zebra_if);
|
XFREE(MTYPE_ZINFO, zebra_if);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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];
|
mac[5] = address->s6_addr[15];
|
||||||
}
|
}
|
||||||
|
|
||||||
void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp,
|
static bool mac_is_same(char *mac1, char *mac2)
|
||||||
struct in6_addr *address, int add)
|
{
|
||||||
|
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_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
|
||||||
struct zebra_if *zif = ifp->info;
|
struct zebra_if *zif = ifp->info;
|
||||||
char buf[16] = "169.254.0.1";
|
char buf[16] = "169.254.0.1";
|
||||||
struct in_addr ipv4_ll;
|
struct in_addr ipv4_ll;
|
||||||
char mac[6];
|
|
||||||
ns_id_t ns_id;
|
ns_id_t ns_id;
|
||||||
|
|
||||||
inet_pton(AF_INET, buf, &ipv4_ll);
|
inet_pton(AF_INET, buf, &ipv4_ll);
|
||||||
|
|
||||||
ipv6_ll_address_to_mac(address, (uint8_t *)mac);
|
|
||||||
ns_id = zvrf->zns->ns_id;
|
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
|
* 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 */
|
/* Add arp record */
|
||||||
kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr, mac, 6, ns_id);
|
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
|
* 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++;
|
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)
|
static void if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(struct interface *ifp)
|
||||||
{
|
{
|
||||||
if (listhead(ifp->nbr_connected)) {
|
if (listhead(ifp->nbr_connected)) {
|
||||||
|
@ -279,6 +279,7 @@ struct zebra_if {
|
|||||||
* for bgp unnumbered?
|
* for bgp unnumbered?
|
||||||
*/
|
*/
|
||||||
bool v6_2_v4_ll_neigh_entry;
|
bool v6_2_v4_ll_neigh_entry;
|
||||||
|
char neigh_mac[6];
|
||||||
struct in6_addr v6_2_v4_ll_addr6;
|
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 const char *ifindex2ifname_per_ns(struct zebra_ns *, unsigned int);
|
||||||
|
|
||||||
extern void if_unlink_per_ns(struct interface *);
|
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,
|
extern void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp,
|
||||||
struct in6_addr *address,
|
struct in6_addr *address,
|
||||||
int add);
|
int add);
|
||||||
|
@ -455,6 +455,38 @@ static void rtadv_process_solicit(struct interface *ifp)
|
|||||||
rtadv_send_packet(zns->rtadv.sock, 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,
|
static void rtadv_process_advert(uint8_t *msg, unsigned int len,
|
||||||
struct interface *ifp,
|
struct interface *ifp,
|
||||||
struct sockaddr_in6 *addr)
|
struct sockaddr_in6 *addr)
|
||||||
@ -469,13 +501,18 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
|
|||||||
inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
|
inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
|
||||||
|
|
||||||
if (len < sizeof(struct nd_router_advert)) {
|
if (len < sizeof(struct nd_router_advert)) {
|
||||||
|
if (IS_ZEBRA_DEBUG_PACKET)
|
||||||
zlog_debug("%s(%u): Rx RA with invalid length %d from %s",
|
zlog_debug("%s(%u): Rx RA with invalid length %d from %s",
|
||||||
ifp->name, ifp->ifindex, len, addr_str);
|
ifp->name, ifp->ifindex, len, addr_str);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
|
if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
|
||||||
zlog_debug(
|
rtadv_process_optional(msg + sizeof(struct nd_router_advert),
|
||||||
"%s(%u): Rx RA with non-linklocal source address from %s",
|
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);
|
ifp->name, ifp->ifindex, addr_str);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user