diff options
-rw-r--r-- | nest/route.h | 6 | ||||
-rw-r--r-- | nest/rt-table.c | 15 | ||||
-rw-r--r-- | proto/bgp/packets.c | 12 |
3 files changed, 21 insertions, 12 deletions
diff --git a/nest/route.h b/nest/route.h index 45b78e38..4dd43750 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 af1a920c..1f84e975 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 ba43cd28..632c564e 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; } |