summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2010-07-28 11:45:35 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2010-07-28 11:45:35 +0200
commit1b180121a90ef98f3adce1a355d48d64c6fc3c4f (patch)
treeea7e2474aef579a585b4e82fa3098ed5ee8b416d
parentc477f48916d74c2db6156145851f9536ae0a0a6c (diff)
downloadbird-1b180121a90ef98f3adce1a355d48d64c6fc3c4f.tar
bird-1b180121a90ef98f3adce1a355d48d64c6fc3c4f.zip
Use link-local addresses in recursive next hops for IPv6 BGP.
-rw-r--r--nest/route.h6
-rw-r--r--nest/rt-table.c15
-rw-r--r--proto/bgp/packets.c12
3 files changed, 21 insertions, 12 deletions
diff --git a/nest/route.h b/nest/route.h
index 45b78e3..4dd4375 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -163,7 +163,9 @@ struct hostcache {
struct hostentry {
node ln;
- ip_addr addr; /* IP of host, part of key */
+ ip_addr addr; /* IP address of host, part of key */
+ ip_addr link; /* (link-local) IP address of host, used as gw
+ if host is directly attached */
struct rtable *tab; /* Dependent table, part of key*/
struct hostentry *next; /* Next in hash chain */
unsigned hash_key; /* Hash key */
@@ -386,7 +388,7 @@ static inline void rta_free(rta *r) { if (r && !--r->uc) rta__free(r); }
void rta_dump(rta *);
void rta_dump_all(void);
void rta_show(struct cli *, rta *, ea_list *);
-void rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr *gw);
+void rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr *gw, ip_addr *ll);
/*
* rta_set_recursive_next_hop() acquires hostentry from hostcache and
diff --git a/nest/rt-table.c b/nest/rt-table.c
index af1a920..1f84e97 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -1358,11 +1358,12 @@ hc_resize(struct hostcache *hc, unsigned new_order)
}
static struct hostentry *
-hc_new_hostentry(struct hostcache *hc, ip_addr a, rtable *dep, unsigned k)
+hc_new_hostentry(struct hostcache *hc, ip_addr a, ip_addr ll, rtable *dep, unsigned k)
{
struct hostentry *he = sl_alloc(hc->slab);
he->addr = a;
+ he->link = ll;
he->tab = dep;
he->hash_key = k;
he->uc = 0;
@@ -1475,9 +1476,9 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
}
else
{
- /* The host is directly reachable, us it as a gateway */
+ /* The host is directly reachable, use link as a gateway */
he->iface = a->iface;
- he->gw = he->addr;
+ he->gw = he->link;
he->dest = RTD_ROUTER;
}
}
@@ -1531,7 +1532,7 @@ rt_update_hostcache(rtable *tab)
}
static struct hostentry *
-rt_find_hostentry(rtable *tab, ip_addr a, rtable *dep)
+rt_find_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep)
{
struct hostentry *he;
@@ -1544,15 +1545,15 @@ rt_find_hostentry(rtable *tab, ip_addr a, rtable *dep)
if (ipa_equal(he->addr, a) && (he->tab == dep))
return he;
- he = hc_new_hostentry(hc, a, dep, k);
+ he = hc_new_hostentry(hc, a, ll, dep, k);
rt_update_hostentry(tab, he);
return he;
}
void
-rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr *gw)
+rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr *gw, ip_addr *ll)
{
- rta_apply_hostentry(a, rt_find_hostentry(tab, *gw, dep));
+ rta_apply_hostentry(a, rt_find_hostentry(tab, *gw, *ll, dep));
}
/*
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index ba43cd2..632c564 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -805,11 +805,17 @@ static inline int
bgp_set_next_hop(struct bgp_proto *p, rta *a)
{
struct eattr *nh = ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP));
- ip_addr nexthop = *(ip_addr *) nh->u.ptr->data;
+ ip_addr *nexthop = (ip_addr *) nh->u.ptr->data;
+
+#ifdef IPV6
+ int second = (nh->u.ptr->length == NEXT_HOP_LENGTH);
+#else
+ int second = 0;
+#endif
if (p->cf->gw_mode == GW_DIRECT)
{
- neighbor *ng = neigh_find(&p->p, &nexthop, 0) ? : p->neigh;
+ neighbor *ng = neigh_find(&p->p, nexthop, 0) ? : p->neigh;
if (ng->scope == SCOPE_HOST)
return 0;
@@ -819,7 +825,7 @@ bgp_set_next_hop(struct bgp_proto *p, rta *a)
a->hostentry = NULL;
}
else /* GW_RECURSIVE */
- rta_set_recursive_next_hop(p->p.table, a, p->igp_table, &nexthop);
+ rta_set_recursive_next_hop(p->p.table, a, p->igp_table, nexthop, nexthop + second);
return 1;
}