summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>2003-02-22 23:47:45 +0100
committerMartin Mares <mj@ucw.cz>2003-02-22 23:47:45 +0100
commit11d4474c17e76e9811dcb32f555fa1c6f3684fab (patch)
tree68ed6fd715e7b72eba4bcfec7d3ef2990373915f
parent7b7a7b43a6915efbe9180f07cd1284a39efacf02 (diff)
downloadbird-11d4474c17e76e9811dcb32f555fa1c6f3684fab.tar
bird-11d4474c17e76e9811dcb32f555fa1c6f3684fab.zip
Better selection of link-local NLRI addresses, at least for our own
address. Need to do it better for the other neighbors -- the current solution works only if they use the standard 64+64 global addresses and the interface identifier in lower 64 bits is the same as for the link-scope addresses.
-rw-r--r--proto/bgp/bgp.c13
-rw-r--r--proto/bgp/bgp.h1
-rw-r--r--proto/bgp/packets.c17
3 files changed, 26 insertions, 5 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index f6cbed4..7069d98 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -434,6 +434,19 @@ bgp_start_neighbor(struct bgp_proto *p)
{
p->local_addr = p->neigh->iface->addr->ip;
DBG("BGP: local=%I remote=%I\n", p->local_addr, p->next_hop);
+#ifdef IPV6
+ {
+ struct ifa *a;
+ p->local_link = ipa_or(ipa_build(0xfe80,0,0,0), ipa_and(p->local_addr, ipa_build(0,0,~0,~0)));
+ WALK_LIST(a, p->neigh->iface->addrs)
+ if (a->scope == SCOPE_LINK)
+ {
+ p->local_link = a->ip;
+ break;
+ }
+ DBG("BGP: Selected link-level address %I\n", p->local_link);
+ }
+#endif
bgp_initiate(p);
}
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index 03f47f9..6519db8 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -74,6 +74,7 @@ struct bgp_proto {
#ifdef IPV6
byte *mp_reach_start, *mp_unreach_start; /* Multiprotocol BGP attribute notes */
unsigned mp_reach_len, mp_unreach_len;
+ ip_addr local_link; /* Link-level version of local_addr */
#endif
};
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index bf89343..03b2211 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -193,20 +193,27 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
nh = ea_find(buck->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP));
ASSERT(nh);
ip = *(ip_addr *) nh->u.ptr->data;
+ is_ll = 0;
if (ipa_equal(ip, p->local_addr))
- is_ll = 1;
+ {
+ is_ll = 1;
+ ip_ll = p->local_link;
+ }
else
{
n = neigh_find(&p->p, &ip, 0);
if (n && n->iface == p->neigh->iface)
- is_ll = 1;
- else
- is_ll = 0;
+ {
+ /* FIXME: We are assuming the global scope addresses use the lower 64 bits
+ * as an interface identifier which hasn't necessarily to be true.
+ */
+ is_ll = 1;
+ ip_ll = ipa_or(ipa_build(0xfe800000,0,0,0), ipa_and(ip, ipa_build(0,0,~0,~0)));
+ }
}
if (is_ll)
{
*tmp++ = 32;
- ip_ll = ipa_or(ipa_build(0xfe80,0,0,0), ipa_and(ip, ipa_build(0,0,~0,~0)));
ipa_hton(ip);
memcpy(tmp, &ip, 16);
ipa_hton(ip_ll);