ip_addr gw; /* Next hop */
struct iface *iface; /* Outgoing interface */
struct nexthop *next;
+ byte flags;
byte weight;
byte labels_orig; /* Number of labels before hostentry was applied */
byte labels; /* Number of all labels */
u32 label[0];
};
+#define RNF_ONLINK 0x1 /* Gateway is onlink regardless of IP ranges */
+
+
struct rte_src {
struct rte_src *next; /* Hash chain */
struct proto *proto; /* Protocol the source is based on */
{
for (; x && y; x = x->next, y = y->next)
{
- if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) || (x->weight != y->weight) || (x->labels != y->labels))
+ if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) ||
+ (x->flags != y->flags) || (x->weight != y->weight) ||
+ (x->labels != y->labels))
return 0;
for (int i = 0; i < x->labels; i++)
if (!y)
return -1;
+ /* Should we also compare flags ? */
+
r = ((int) y->weight) - ((int) x->weight);
if (r)
return r;
for (nh = &(a->nh); nh; nh = nh->next)
{
char mpls[MPLS_MAX_LABEL_STACK*12 + 5], *lsp = mpls;
+ char *onlink = (nh->flags & RNF_ONLINK) ? " onlink" : "";
if (nh->labels)
{
*lsp = '\0';
if (a->nh.next)
- cli_printf(c, -1007, "\tvia %I%s on %s weight %d", nh->gw, mpls, nh->iface->name, nh->weight + 1);
+ cli_printf(c, -1007, "\tvia %I%s on %s%s weight %d",
+ nh->gw, mpls, nh->iface->name, onlink, nh->weight + 1);
else
- cli_printf(c, -1007, "\tvia %I%s on %s", nh->gw, mpls, nh->iface->name);
+ cli_printf(c, -1007, "\tvia %I%s on %s%s",
+ nh->gw, mpls, nh->iface->name, onlink);
}
if (d->verbose)
}
}
if (ipa_nonzero(nh->gw))
- nhp->gw = nh->gw; /* Router nexthop */
+ {
+ nhp->gw = nh->gw; /* Router nexthop */
+ nhp->flags |= (nh->flags & RNF_ONLINK);
+ }
else if (ipa_nonzero(he->link))
nhp->gw = he->link; /* Device nexthop with link-local address known */
else
CF_DECLS
CF_KEYWORDS(STATIC, ROUTE, VIA, DROP, REJECT, PROHIBIT, PREFERENCE, CHECK, LINK)
-CF_KEYWORDS(WEIGHT, RECURSIVE, IGP, TABLE, BLACKHOLE, UNREACHABLE, BFD, MPLS)
+CF_KEYWORDS(ONLINK, WEIGHT, RECURSIVE, IGP, TABLE, BLACKHOLE, UNREACHABLE, BFD, MPLS)
CF_GRAMMAR
| stat_nexthop MPLS label_stack {
this_snh->mls = $3;
}
+ | stat_nexthop ONLINK bool {
+ this_snh->onlink = $3;
+ }
| stat_nexthop WEIGHT expr {
this_snh->weight = $3 - 1;
if (($3<1) || ($3>256)) cf_error("Weight must be in range 1-256");
struct nexthop *nh = allocz(NEXTHOP_MAX_SIZE);
nh->gw = r2->via;
nh->iface = r2->neigh->iface;
+ nh->flags = r2->onlink ? RNF_ONLINK : 0;
nh->weight = r2->weight;
if (r2->mls)
{
for (r2 = r; r2; r2 = r2->mp_next)
{
n = ipa_nonzero(r2->via) ?
- neigh_find2(&p->p, &r2->via, r2->iface, NEF_STICKY) :
+ neigh_find2(&p->p, &r2->via, r2->iface,
+ NEF_STICKY | (r2->onlink ? NEF_ONLINK : 0)) :
neigh_find_iface(&p->p, r2->iface);
if (!n)
{
if (!ipa_equal(x->via, y->via) ||
(x->iface != y->iface) ||
- (x->use_bfd != y->use_bfd) ||
+ (x->onlink != y->onlink) ||
(x->weight != y->weight) ||
+ (x->use_bfd != y->use_bfd) ||
(!x->mls != !y->mls) ||
((x->mls) && (y->mls) && (x->mls->len != y->mls->len)))
return 0;
for (r2 = r; r2; r2 = r2->mp_next)
{
if (r2->iface && ipa_zero(r2->via))
- cli_msg(-1009, "\tdev %s%s%s", r2->iface->name,
- r2->bfd_req ? " (bfd)" : "", r2->active ? "" : " (dormant)");
+ cli_msg(-1009, "\tdev %s%s", r2->iface->name,
+ r2->active ? "" : " (dormant)");
else
- cli_msg(-1009, "\tvia %I%J%s%s", r2->via, r2->iface,
- r2->bfd_req ? " (bfd)" : "", r2->active ? "" : " (dormant)");
+ cli_msg(-1009, "\tvia %I%J%s%s%s", r2->via, r2->iface,
+ r2->onlink ? " onlink" : "",
+ r2->bfd_req ? " (bfd)" : "",
+ r2->active ? "" : " (dormant)");
}
break;
}
byte dest; /* Destination type (RTD_*) */
byte state; /* State of route announcement (SRS_*) */
byte active; /* Next hop is active (nbr/iface/BFD available) */
+ byte onlink; /* Gateway is onlink regardless of IP ranges */
byte weight; /* Multipath next hop weight */
byte use_bfd; /* Configured to use BFD */
struct bfd_request *bfd_req; /* BFD request, if BFD is used */
nl_add_nexthop(h, bufsize, nh, af);
+ if (nh->flags & RNF_ONLINK)
+ rtnh->rtnh_flags |= RTNH_F_ONLINK;
+
nl_close_nexthop(h, rtnh);
}
rv->next = NULL;
last = &(rv->next);
+ rv->flags = 0;
rv->weight = nh->rtnh_hops;
rv->iface = if_find_by_index(nh->rtnh_ifindex);
if (!rv->iface)
{
rv->gw = rta_get_ipa(a[RTA_GATEWAY]);
+ if (nh->rtnh_flags & RTNH_F_ONLINK)
+ rv->flags |= RNF_ONLINK;
+
neighbor *nbr;
nbr = neigh_find2(&p->p, &rv->gw, rv->iface,
- (nh->rtnh_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
+ (rv->flags & RNF_ONLINK) ? NEF_ONLINK : 0);
if (!nbr || (nbr->scope == SCOPE_HOST))
return NULL;
}
{
nl_add_attr_u32(&r->h, rsize, RTA_OIF, nh->iface->index);
nl_add_nexthop(&r->h, rsize, nh, p->af);
+
+ if (nh->flags & RNF_ONLINK)
+ r->r.rtm_flags |= RTNH_F_ONLINK;
}
break;
case RTD_BLACKHOLE:
if ((i->rtm_family == AF_INET6) && ipa_in_netX(ra->nh.gw, (net_addr *) &sit))
return;
+ if (i->rtm_flags & RTNH_F_ONLINK)
+ ra->nh.flags |= RNF_ONLINK;
+
neighbor *nbr;
nbr = neigh_find2(&p->p, &(ra->nh.gw), ra->nh.iface,
- (i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
+ (ra->nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0);
if (!nbr || (nbr->scope == SCOPE_HOST))
{
log(L_ERR "KRT: Received route %N with strange next-hop %I", net->n.addr,