- cd $TOOLS_DIR
- sudo git clean -fx
- git pull --ff-only
+ - git checkout -f origin/data-v3.2
- "mv $DIR/build-netlab/* netlab/common/"
- ln -s $STAYRTR_BINARY netlab/common/stayrtr
- cd netlab
- "mkdir $DIR/netlab-failure"
- git status --porcelain > $DIR/netlab-failure.log
- for f in $(git status --porcelain | sed -rn 's#^.[^DRT] netlab/##p'); do mkdir -p $DIR/netlab-failure/$(dirname $f); sudo chmod a+rw $f; sudo mv $f $DIR/netlab-failure/$(dirname $f); done
+ - git checkout -f master
artifacts:
when: on_failure
untracked: true
<tag><label id="rta-igp-metric"><m/int/ igp_metric</tag>
The optional attribute that can be used to specify a distance to the
network for routes that do not have a native protocol metric attribute
- (like <cf/ospf_metric1/ for OSPF routes). It is used mainly by BGP to
- compare internal distances to boundary routers (see below).
+ (like <cf/ospf_metric1/ for OSPF routes). It is used to fill in
+ <ref id="rta-local-metric" name="local_metric"> attribute when recursive
+ nexthops are resolved, so that BGP can compare internal distances
+ to boundary routers (see below).
+
+ <tag><label id="rta-local-metric"><m/int/ local_metric</tag>
+ Attribute storing the route's metric to the resolved recursive nexthop,
+ mainly used by BGP best route selection. Also known as "interior cost"
+ in RFC 4271.
+ It's the copy of the underlying protocol's metric, e.g.
+ <cf/ospf_metric1/, or the generic <cf/igp_metric/. For recursive nexthops,
+ setting the <cf/local_metric/ attribute in the import filters is futile,
+ as the nexthop resolver overwrites it.
+ Note: In versions 3.0.x and 3.1.x, the <cf/igp_metric/ attribute was confusingly
+ used for this purpose.
<tag><label id="rta-mpls-label"><m/int/ mpls_label</tag>
Local MPLS label attached to the route. This attribute is produced by
<item>Prefer IGP origin over EGP and EGP origin over incomplete.
<item>Prefer the lowest value of the Multiple Exit Discriminator.
<item>Prefer routes received via eBGP over ones received via iBGP.
- <item>Prefer routes with lower internal distance to a boundary router.
+ <item>Prefer routes with lower <ref id="rta-local-metric" name="internal distance"> to a boundary router.
<item>Prefer the route with the lowest value of router ID of the
advertising router.
</itemize>
test_ca_lclist7 = ---empty---;
igp_metric = 53;
+ local_metric = 75;
babel_metric = 64;
t = defined(babel_router_id);
static inline u32 rt_get_preference(const rte *rt)
{ return ea_get_int(rt->attrs, &ea_gen_preference, 0); }
-/* IGP metric: second-order comparison */
+/* IGP metric: explicit metric to be used as local_metric in case of recursive nexthop */
extern struct ea_class ea_gen_igp_metric;
u32 rt_get_igp_metric(const rte *rt);
#define IGP_METRIC_UNKNOWN 0x80000000 /* Default igp_metric used when no other
protocol-specific metric is availabe */
+/* local metric: second-order comparison */
+extern struct ea_class ea_gen_local_metric;
+
/* From: Advertising router */
extern struct ea_class ea_gen_from;
- cd $TOOLS_DIR
- sudo git clean -fx
- git pull --ff-only
+ - git checkout -f origin/data-v3.2
- "mv $DIR/build-netlab/* netlab/common/"
- ln -s $STAYRTR_BINARY netlab/common/stayrtr
- cd netlab
- "mkdir $DIR/netlab-failure"
- git status --porcelain > $DIR/netlab-failure.log
- for f in $(git status --porcelain | sed -rn 's#^.[^DRT] netlab/##p'); do mkdir -p $DIR/netlab-failure/$(dirname $f); sudo chmod a+rw $f; sudo mv $f $DIR/netlab-failure/$(dirname $f); done
+ - git checkout -f master
artifacts:
when: on_failure
untracked: true
.type = T_INT,
};
+struct ea_class ea_gen_local_metric = {
+ .name = "local_metric",
+ .type = T_INT,
+};
+
struct ea_class ea_gen_preference = {
.name = "preference",
.type = T_INT,
switch (e->type)
{
case T_INT:
- if ((cls == &ea_gen_igp_metric) && e->u.data >= IGP_METRIC_UNKNOWN)
- return;
-
- bsprintf(pos, "%u", e->u.data);
+ if ((cls == &ea_gen_local_metric) && e->u.data >= IGP_METRIC_UNKNOWN)
+ bsprintf(pos, "unknown");
+ else
+ bsprintf(pos, "%u", e->u.data);
break;
case T_OPAQUE:
opaque_format(ad, pos, end - pos);
/* Other generic route attributes */
ea_register_init(&ea_gen_preference);
ea_register_init(&ea_gen_igp_metric);
+ ea_register_init(&ea_gen_local_metric);
ea_register_init(&ea_gen_from);
ea_register_init(&ea_gen_source);
ea_register_init(&ea_gen_flowspec_valid);
/* Jump-away block for applying the actual attributes */
do {
- ea_set_attr_u32(to, &ea_gen_igp_metric, 0, he->igp_metric);
-
ea_list *src = atomic_load_explicit(&he->src, memory_order_acquire);
if (!src)
{
break;
}
+ ea_set_attr_u32(to, &ea_gen_local_metric, 0, he->igp_metric);
+
eattr *he_nh_ea = ea_find(src, &ea_gen_nexthop);
ASSERT_DIE(he_nh_ea);
return 0;
u64 aigp = get_u64(b + 3);
- u64 step = rt_get_igp_metric(e);
+ u64 step = ea_get_int(e->attrs, &ea_gen_local_metric, IGP_METRIC_UNKNOWN);
if (!rte_resolvable(e) || (step >= IGP_METRIC_UNKNOWN))
step = BGP_AIGP_MAX;
return 1;
/* RFC 4271 9.1.2.2. e) Compare IGP metrics */
- n = new_bgp->cf->igp_metric ? rt_get_igp_metric(new) : 0;
- o = old_bgp->cf->igp_metric ? rt_get_igp_metric(old) : 0;
+ n = new_bgp->cf->igp_metric ? ea_get_int(new->attrs, &ea_gen_local_metric, 0) : 0;
+ o = old_bgp->cf->igp_metric ? ea_get_int(old->attrs, &ea_gen_local_metric, 0) : 0;
if (n < o)
return 1;
if (n > o)
return 0;
/* RFC 4271 9.1.2.2. e) Compare IGP metrics */
- p = pri_bgp->cf->igp_metric ? rt_get_igp_metric(pri) : 0;
- s = sec_bgp->cf->igp_metric ? rt_get_igp_metric(sec) : 0;
+ p = pri_bgp->cf->igp_metric ? ea_get_int(pri->attrs, &ea_gen_local_metric, 0) : 0;
+ s = sec_bgp->cf->igp_metric ? ea_get_int(sec->attrs, &ea_gen_local_metric, 0) : 0;
if (p != s)
return 0;
if (rte_stale(e))
buf += bsprintf(buf, "s");
+ eattr *ic;
u64 metric = bgp_total_aigp_metric(e);
if (metric < BGP_AIGP_MAX)
{
buf += bsprintf(buf, "/%lu", metric);
}
- else if (metric = rt_get_igp_metric(e))
+ else if (ic = ea_find(e->attrs, &ea_gen_local_metric))
{
if (!rte_resolvable(e))
buf += bsprintf(buf, "/-");
- else if (metric >= IGP_METRIC_UNKNOWN)
+ else if (ic->u.i >= IGP_METRIC_UNKNOWN)
buf += bsprintf(buf, "/?");
- else
- buf += bsprintf(buf, "/%d", metric);
+ else if (ic->u.i > 0)
+ buf += bsprintf(buf, "/%d", ic->u.i);
}
}
buf += bsprintf(buf, ") [");
if (nbr->scope == SCOPE_HOST)
WITHDRAW(BAD_NEXT_HOP " - address %I is local", nbr->addr);
- ea_set_attr_u32(to, &ea_gen_igp_metric, 0, c->cf->cost);
+ if (c->cf->cost)
+ ea_set_attr_u32(to, &ea_gen_local_metric, 0, c->cf->cost);
struct nexthop_adata_mpls nam;
memset(&nam, 0, sizeof nam);
ea_set_attr_data(&new->attrs, &ea_gen_nexthop, 0, nhad.ad.data, nhad.ad.length);
}
- /* Drop original IGP metric on export;
+ /* Drop original local metric on export;
* kept on import as a base for L3VPN metric */
- ea_unset_attr(&new->attrs, 0, &ea_gen_igp_metric);
+ ea_unset_attr(&new->attrs, 0, &ea_gen_local_metric);
}
rte_update(dst, n, new, src);
return 1;
}
+static inline u32
+l3vpn_metric(const rte *e)
+{
+ eattr *a = ea_find(e->attrs, &ea_gen_igp_metric) ?: ea_find(e->attrs, &ea_gen_local_metric);
+ return a ? a->u.i : IGP_METRIC_UNKNOWN;
+}
+
static int
l3vpn_rte_better(const rte *new, const rte *old)
{
/* This is hack, we should have full BGP-style comparison */
- return rt_get_igp_metric(new) < rt_get_igp_metric(old);
+ return l3vpn_metric(new) < l3vpn_metric(old);
}
static void
l3vpn_get_route_info(const rte *rte, byte *buf)
{
u32 pref = rt_get_preference(rte);
- u32 metric = rt_get_igp_metric(rte);
+ u32 metric = l3vpn_metric(rte);
if (metric < IGP_METRIC_UNKNOWN)
bsprintf(buf, " (%u/%u)", pref, metric);