Hi, the attached patch adds support for using link-local v6 addresses for BGP peerings by adding an interface attribute to the BGP protocol. It has been succesfully tested in a Bird<->Quagga configuration on Linux, and with Bird<->Bird using Linux<->Linux and Linux<->FreeBSD.
I know the BGP RFCs (especially 2545) are a bit unclear if this should be allowed, but RFC 4659 suggests it should, and also describes how to set the NEXT_HOP attribute when no global addresses are used. Anyways, I'd love to see this patch included in Bird. It shouldn't make any difference when you don't use the interface attribute, so it won't have bad influence on people not using this feature, and it makes Bird an alternative to Quagga when you need link-local peering support. :-) Matthias Schiffer
From 993d07798e10f41c258c2a485650507c564e6990 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer <mschif...@universe-factory.net> Date: Tue, 14 Dec 2010 03:26:51 +0100 Subject: [PATCH] BGP: Add support for peering with link-local IPv6 addresses --- nest/iface.c | 2 +- proto/bgp/bgp.c | 13 ++++++++++++- proto/bgp/bgp.h | 1 + proto/bgp/config.Y | 3 ++- proto/bgp/packets.c | 3 +++ sysdep/bsd/krt-sock.c | 2 +- 6 files changed, 20 insertions(+), 4 deletions(-) diff --git a/nest/iface.c b/nest/iface.c index c523678..2b0b9c6 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -483,7 +483,7 @@ ifa_update(struct ifa *a) break; } - if (!(i->flags & IF_MULTIACCESS) && a->pxlen < BITS_PER_IP_ADDRESS - 2) + if (!(i->flags & IF_MULTIACCESS) && !ipa_has_link_scope(a->ip) && a->pxlen < BITS_PER_IP_ADDRESS - 2) log(L_WARN "Strange prefix length %d for point-to-point interface %s", a->pxlen, i->name); #ifndef IPV6 if ((i->flags & IF_BROADCAST) && !ipa_nonzero(a->brd)) diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 327292a..84c353e 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -574,6 +574,7 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c s->saddr = p->source_addr; s->daddr = p->cf->remote_ip; s->dport = BGP_PORT; + s->iface = p->neigh->iface; s->ttl = p->cf->multihop ? : 1; s->rbsize = BGP_RX_BUFFER_SIZE; s->tbsize = BGP_TX_BUFFER_SIZE; @@ -743,6 +744,7 @@ bgp_start_locked(struct object_lock *lock) { struct bgp_proto *p = lock->data; struct bgp_config *cf = p->cf; + struct iface *interface = NULL; if (p->p.proto_state != PS_START) { @@ -759,7 +761,16 @@ bgp_start_locked(struct object_lock *lock) return; } - p->neigh = neigh_find(&p->p, &cf->remote_ip, NEF_STICKY); + if (*cf->interface) { + interface = if_find_by_name(cf->interface); + + if (!interface) { + BGP_TRACE(D_EVENTS, "Waiting for interface %s", cf->interface); + return; + } + } + + p->neigh = neigh_find2(&p->p, &cf->remote_ip, interface, NEF_STICKY); if (!p->neigh || (p->neigh->scope == SCOPE_HOST)) { log(L_ERR "%s: Invalid remote address %I", p->p.name, cf->remote_ip); diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index b06f20a..c8acb25 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -47,6 +47,7 @@ struct bgp_config { unsigned error_delay_time_min; /* Time to wait after an error is detected */ unsigned error_delay_time_max; unsigned disable_after_error; /* Disable the protocol when error is detected */ + char interface[16]; /* Interface to use */ char *password; /* Password used for MD5 authentication */ struct rtable_config *igp_table; /* Table used for recursive next hop lookups */ }; diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index e932a7f..6ea94d6 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -25,7 +25,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, ADVERTISE, IPV4, CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH, INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP, TABLE, - GATEWAY, DIRECT, RECURSIVE) + GATEWAY, DIRECT, RECURSIVE, INTERFACE) CF_GRAMMAR @@ -92,6 +92,7 @@ bgp_proto: | bgp_proto ENABLE AS4 bool ';' { BGP_CFG->enable_as4 = $4; } | bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; } | bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; } + | bgp_proto INTERFACE TEXT ';' { strncpy(BGP_CFG->interface, $3, sizeof(BGP_CFG->interface)-1); } | bgp_proto PASSWORD TEXT ';' { BGP_CFG->password = $3; } | bgp_proto ROUTE LIMIT expr ';' { BGP_CFG->route_limit = $4; } | bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; } diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index bf98640..7816c1d 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -434,6 +434,9 @@ bgp_create_update(struct bgp_conn *conn, byte *buf) *tmp++ = BGP_AF_IPV6; *tmp++ = 1; + if (ipa_has_link_scope(ip)) + ip = IPA_NONE; + if (ipa_nonzero(ip_ll)) { *tmp++ = 32; diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 53b30ca..fc73be8 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -541,7 +541,7 @@ krt_read_addr(struct ks_msg *msg) _I0(ifa.ip) = 0xfe800000; #endif - if (iface->flags & IF_MULTIACCESS) + if ((iface->flags & IF_MULTIACCESS) || ipa_has_link_scope(ifa.ip)) { ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(masklen)); -- 1.7.3.3
signature.asc
Description: OpenPGP digital signature