Nexthop: Fixed hostentry
This commit is contained in:
parent
93f50ca317
commit
039a65d0e4
5 changed files with 57 additions and 60 deletions
|
@ -200,8 +200,8 @@ struct hostentry {
|
||||||
unsigned hash_key; /* Hash key */
|
unsigned hash_key; /* Hash key */
|
||||||
unsigned uc; /* Use count */
|
unsigned uc; /* Use count */
|
||||||
struct rta *src; /* Source rta entry */
|
struct rta *src; /* Source rta entry */
|
||||||
struct nexthop *nh; /* Chosen next hop */
|
|
||||||
byte dest; /* Chosen route destination type (RTD_...) */
|
byte dest; /* Chosen route destination type (RTD_...) */
|
||||||
|
byte nexthop_linkable; /* Nexthop list is completely non-device */
|
||||||
u32 igp_metric; /* Chosen route IGP metric */
|
u32 igp_metric; /* Chosen route IGP metric */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -344,8 +344,8 @@ struct nexthop {
|
||||||
struct iface *iface; /* Outgoing interface */
|
struct iface *iface; /* Outgoing interface */
|
||||||
struct nexthop *next;
|
struct nexthop *next;
|
||||||
byte weight;
|
byte weight;
|
||||||
byte labels_append; /* Number of labels before hostentry was applied */
|
byte labels_orig; /* Number of labels before hostentry was applied */
|
||||||
byte labels; /* Number of labels prepended */
|
byte labels; /* Number of all labels */
|
||||||
u32 label[0];
|
u32 label[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1155,12 +1155,12 @@ rta__free(rta *a)
|
||||||
*a->pprev = a->next;
|
*a->pprev = a->next;
|
||||||
if (a->next)
|
if (a->next)
|
||||||
a->next->pprev = a->pprev;
|
a->next->pprev = a->pprev;
|
||||||
a->aflags = 0; /* Poison the entry */
|
|
||||||
rt_unlock_hostentry(a->hostentry);
|
rt_unlock_hostentry(a->hostentry);
|
||||||
rt_unlock_source(a->src);
|
rt_unlock_source(a->src);
|
||||||
if (a->nh.next)
|
if (a->nh.next)
|
||||||
nexthop_free(a->nh.next);
|
nexthop_free(a->nh.next);
|
||||||
ea_free(a->eattrs);
|
ea_free(a->eattrs);
|
||||||
|
a->aflags = 0; /* Poison the entry */
|
||||||
sl_free(rta_slab(a), a);
|
sl_free(rta_slab(a), a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1764,7 +1764,7 @@ rta_next_hop_outdated(rta *a)
|
||||||
return a->dest != RTD_UNREACHABLE;
|
return a->dest != RTD_UNREACHABLE;
|
||||||
|
|
||||||
return (a->dest != he->dest) || (a->igp_metric != he->igp_metric) ||
|
return (a->dest != he->dest) || (a->igp_metric != he->igp_metric) ||
|
||||||
!nexthop_same(&(a->nh), he->nh);
|
(!he->nexthop_linkable) || !nexthop_same(&(a->nh), &(he->src->nh));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -1774,39 +1774,49 @@ rta_apply_hostentry(rta *a, struct hostentry *he)
|
||||||
a->dest = he->dest;
|
a->dest = he->dest;
|
||||||
a->igp_metric = he->igp_metric;
|
a->igp_metric = he->igp_metric;
|
||||||
|
|
||||||
if (a->nh.labels_append == 0)
|
if ((a->nh.labels_orig == 0) && (!a->nh.next) && he->nexthop_linkable)
|
||||||
{
|
{
|
||||||
a->nh = *(he->nh);
|
a->nh = he->src->nh;
|
||||||
a->nh.labels_append = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int labels_append = a->nh.labels_append;
|
struct nexthop *nhp = alloca(NEXTHOP_MAX_SIZE);
|
||||||
u32 label_stack[MPLS_MAX_LABEL_STACK];
|
|
||||||
memcpy(label_stack, a->nh.label, labels_append * sizeof(u32));
|
|
||||||
|
|
||||||
struct nexthop *nhp = NULL;
|
for (struct nexthop *nhe = &(a->nh); nhe; nhe = nhe->next)
|
||||||
for (struct nexthop *nh = he->nh; nh; nh = nh->next)
|
|
||||||
{
|
{
|
||||||
nhp = nhp ? (nhp->next = lp_alloc(rte_update_pool, NEXTHOP_MAX_SIZE)) : &(a->nh);
|
int labels_orig = nhe->labels_orig; /* Number of labels (at the bottom of stack) */
|
||||||
nhp->gw = ipa_nonzero(nh->gw) ? nh->gw : he->link;
|
u32 label_stack[MPLS_MAX_LABEL_STACK];
|
||||||
nhp->iface = nh->iface; /* FIXME: This is at least strange, if not utter nonsense. */
|
memcpy(label_stack, nhe->label, labels_orig * sizeof(u32));
|
||||||
nhp->weight = nh->weight;
|
|
||||||
nhp->labels = nh->labels + labels_append;
|
for (struct nexthop *nh = &(he->src->nh); nh; nh = nh->next)
|
||||||
nhp->labels_append = labels_append;
|
{
|
||||||
|
nhp->iface = nh->iface;
|
||||||
|
nhp->weight = nh->weight; /* FIXME: Ignoring the recursive nexthop's weight */
|
||||||
|
nhp->labels = nh->labels + labels_orig;
|
||||||
|
nhp->labels_orig = labels_orig;
|
||||||
if (nhp->labels <= MPLS_MAX_LABEL_STACK)
|
if (nhp->labels <= MPLS_MAX_LABEL_STACK)
|
||||||
{
|
{
|
||||||
memcpy(nhp->label, nh->label, nh->labels * sizeof(u32));
|
memcpy(nhp->label, nh->label, nh->labels * sizeof(u32)); /* First the hostentry labels */
|
||||||
memcpy(&(nhp->label[nh->labels]), label_stack, labels_append * sizeof(u32));
|
memcpy(&(nhp->label[nh->labels]), label_stack, labels_orig * sizeof(u32)); /* Then the bottom labels */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log(L_WARN "Sum of label stack sizes %d + %d = %d exceedes allowed maximum (%d)",
|
log(L_WARN "Sum of label stack sizes %d + %d = %d exceedes allowed maximum (%d)",
|
||||||
nh->labels, labels_append, nhp->labels, MPLS_MAX_LABEL_STACK);
|
nh->labels, labels_orig, nhp->labels, MPLS_MAX_LABEL_STACK);
|
||||||
a->dest = RTD_UNREACHABLE;
|
continue;
|
||||||
break;
|
}
|
||||||
|
if (ipa_nonzero(nh->gw))
|
||||||
|
nhp->gw = nh->gw; /* Router nexthop */
|
||||||
|
else if (ipa_nonzero(he->link))
|
||||||
|
nhp->gw = he->link; /* Device nexthop with link-local address known */
|
||||||
|
else
|
||||||
|
nhp->gw = he->addr; /* Device nexthop with link-local address unknown */
|
||||||
|
|
||||||
|
nhp = (nhp->next = lp_alloc(rte_update_pool, NEXTHOP_MAX_SIZE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(&(a->nh), nhp, nexthop_size(nhp));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline rte *
|
static inline rte *
|
||||||
|
@ -2231,12 +2241,12 @@ hc_new_hostentry(struct hostcache *hc, ip_addr a, ip_addr ll, rtable *dep, unsig
|
||||||
{
|
{
|
||||||
struct hostentry *he = sl_alloc(hc->slab);
|
struct hostentry *he = sl_alloc(hc->slab);
|
||||||
|
|
||||||
he->addr = a;
|
*he = (struct hostentry) {
|
||||||
he->link = ll;
|
.addr = a,
|
||||||
he->tab = dep;
|
.link = ll,
|
||||||
he->hash_key = k;
|
.tab = dep,
|
||||||
he->uc = 0;
|
.hash_key = k,
|
||||||
he->src = NULL;
|
};
|
||||||
|
|
||||||
add_tail(&hc->hostentries, &he->ln);
|
add_tail(&hc->hostentries, &he->ln);
|
||||||
hc_insert(hc, he);
|
hc_insert(hc, he);
|
||||||
|
@ -2357,6 +2367,7 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
|
||||||
|
|
||||||
/* Reset the hostentry */
|
/* Reset the hostentry */
|
||||||
he->src = NULL;
|
he->src = NULL;
|
||||||
|
he->nexthop_linkable = 0;
|
||||||
he->dest = RTD_UNREACHABLE;
|
he->dest = RTD_UNREACHABLE;
|
||||||
he->igp_metric = 0;
|
he->igp_metric = 0;
|
||||||
|
|
||||||
|
@ -2377,26 +2388,12 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((a->dest == RTD_UNICAST) && ipa_zero(a->nh.gw) && !a->next)
|
he->nexthop_linkable = 1;
|
||||||
|
for (struct nexthop *nh = &(a->nh); nh; nh = nh->next)
|
||||||
|
if (ipa_zero(nh->gw))
|
||||||
{
|
{
|
||||||
/* We have singlepath device route */
|
he->nexthop_linkable = 0;
|
||||||
if (if_local_addr(he->addr, a->nh.iface))
|
break;
|
||||||
{
|
|
||||||
/* The host address is a local address, this is not valid */
|
|
||||||
log(L_WARN "Next hop address %I is a local address of iface %s",
|
|
||||||
he->addr, a->nh.iface->name);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The host is directly reachable, use link as a gateway */
|
|
||||||
he->nh = NULL;
|
|
||||||
he->dest = RTD_UNICAST;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* The host is reachable through some route entry */
|
|
||||||
he->nh = &(a->nh);
|
|
||||||
he->dest = a->dest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
he->src = rta_clone(a);
|
he->src = rta_clone(a);
|
||||||
|
|
|
@ -1705,7 +1705,7 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis
|
||||||
|
|
||||||
if (ea)
|
if (ea)
|
||||||
{
|
{
|
||||||
a = allocz(sizeof(struct rta));
|
a = allocz(RTA_MAX_SIZE);
|
||||||
|
|
||||||
a->source = RTS_BGP;
|
a->source = RTS_BGP;
|
||||||
a->scope = SCOPE_UNIVERSE;
|
a->scope = SCOPE_UNIVERSE;
|
||||||
|
|
|
@ -120,7 +120,7 @@ drop:
|
||||||
|
|
||||||
if (r->dest == RTDX_RECURSIVE)
|
if (r->dest == RTDX_RECURSIVE)
|
||||||
{
|
{
|
||||||
ap->nh.labels_append = ap->nh.labels = r->label_count;
|
ap->nh.labels_orig = ap->nh.labels = r->label_count;
|
||||||
memcpy(ap->nh.label, r->label_stack, r->label_count * sizeof(u32));
|
memcpy(ap->nh.label, r->label_stack, r->label_count * sizeof(u32));
|
||||||
rta_set_recursive_next_hop(p->main_channel->table, ap, p_igp_table(p), r->via, IPA_NONE);
|
rta_set_recursive_next_hop(p->main_channel->table, ap, p_igp_table(p), r->via, IPA_NONE);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue