summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/bird.sgml15
-rw-r--r--proto/babel/babel.c12
-rw-r--r--proto/ospf/ospf.c25
-rw-r--r--proto/ospf/topology.c32
-rw-r--r--proto/rip/rip.c12
5 files changed, 46 insertions, 50 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml
index ae308d4c..b4d9ea4e 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -1618,9 +1618,7 @@ regarded as empty bgppath/*clist for most purposes.
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). It is also
- used when the route is exported to OSPF as a default value for OSPF type
- 1 metric.
+ compare internal distances to boundary routers (see below).
</descrip>
<p>There also exist protocol-specific attributes which are described in the
@@ -3536,8 +3534,15 @@ protocol ospf [v2|v3] &lt;name&gt; {
with internal <cf/metric/, a <cf/metric of type 2/ is always longer than any
<cf/metric of type 1/ or any <cf/internal metric/. <cf/Internal metric/ or
<cf/metric of type 1/ is stored in attribute <cf/ospf_metric1/, <cf/metric type
-2/ is stored in attribute <cf/ospf_metric2/. If you specify both metrics only
-metric1 is used.
+2/ is stored in attribute <cf/ospf_metric2/.
+
+When both metrics are specified then <cf/metric of type 2/ is used. This is
+relevant e.g. when a type 2 external route is propagated from one OSPF domain to
+another and <cf/ospf_metric1/ is an internal distance to the original ASBR,
+while <cf/ospf_metric2/ stores the type 2 metric. Note that in such cases if
+<cf/ospf_metric1/ is non-zero then <cf/ospf_metric2/ is increased by one to
+ensure monotonicity of metric, as internal distance is reset to zero when an
+external route is announced.
<p>Each external route can also carry attribute <cf/ospf_tag/ which is a 32-bit
integer which is used when exporting routes to other protocols; otherwise, it
diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index ce05191c..44c6adb8 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -2087,20 +2087,14 @@ babel_prepare_attrs(struct linpool *pool, ea_list *next, uint metric, u64 router
static int
-babel_import_control(struct proto *P, struct rte **new, struct ea_list **attrs, struct linpool *pool)
+babel_import_control(struct proto *P, struct rte **new, struct ea_list **attrs UNUSED, struct linpool *pool UNUSED)
{
- struct babel_proto *p = (void *) P;
- rte *rt = *new;
+ rte *e = *new;
/* Reject our own unreachable routes */
- if ((rt->attrs->dest == RTD_UNREACHABLE) && (rt->attrs->src->proto == P))
+ if ((e->attrs->dest == RTD_UNREACHABLE) && (e->attrs->src->proto == P))
return -1;
-
- /* Prepare attributes with initial values */
- if (rt->attrs->source != RTS_BABEL)
- *attrs = babel_prepare_attrs(pool, NULL, 0, p->router_id);
-
return 0;
}
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index df6c452e..0a9efd19 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -446,34 +446,21 @@ ospf_disp(timer * timer)
* import to the filters.
*/
static int
-ospf_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool)
+ospf_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
{
struct ospf_proto *p = (struct ospf_proto *) P;
struct ospf_area *oa = ospf_main_area(p);
rte *e = *new;
+ /* Reject our own routes */
if (e->attrs->src->proto == P)
- return -1; /* Reject our own routes */
+ return -1;
+ /* Do not export routes to stub areas */
if (oa_is_stub(oa))
- return -1; /* Do not export routes to stub areas */
-
- ea_list *ea = e->attrs->eattrs;
- u32 m0 = ea_get_int(ea, EA_GEN_IGP_METRIC, LSINFINITY);
- u32 m1 = MIN(m0, LSINFINITY);
- u32 m2 = 10000;
- u32 tag = 0;
-
- /* Hack for setting attributes directly in static protocol */
- if (e->attrs->source == RTS_STATIC)
- {
- m1 = ea_get_int(ea, EA_OSPF_METRIC1, m1);
- m2 = ea_get_int(ea, EA_OSPF_METRIC2, 10000);
- tag = ea_get_int(ea, EA_OSPF_TAG, 0);
- }
+ return -1;
- *attrs = ospf_build_attrs(*attrs, pool, m1, m2, tag, 0);
- return 0; /* Leave decision to the filters */
+ return 0;
}
static struct ea_list *
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index 717c8280..e909bbe9 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -1281,14 +1281,34 @@ ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte
/* Get route attributes */
rta *a = new->attrs;
- u32 m1 = ea_get_int(ea, EA_OSPF_METRIC1, LSINFINITY);
- u32 m2 = ea_get_int(ea, EA_OSPF_METRIC2, 10000);
- int ebit = (m1 == LSINFINITY);
- u32 metric = ebit ? m2 : m1;
- u32 tag = ea_get_int(ea, EA_OSPF_TAG, 0);
- ip_addr fwd = IPA_NONE;
+ eattr *m1a = ea_find(ea, EA_OSPF_METRIC1);
+ eattr *m2a = ea_find(ea, EA_OSPF_METRIC2);
+ uint m1 = m1a ? m1a->u.data : 0;
+ uint m2 = m2a ? m2a->u.data : 10000;
+ if (m1 > LSINFINITY)
+ {
+ log(L_WARN "%s: Invalid ospf_metric1 value %u for route %N",
+ p->p.name, m1, n->n.addr);
+ m1 = LSINFINITY;
+ }
+ if (m2 > LSINFINITY)
+ {
+ log(L_WARN "%s: Invalid ospf_metric2 value %u for route %N",
+ p->p.name, m2, n->n.addr);
+ m2 = LSINFINITY;
+ }
+
+ /* Ensure monotonicity of metric if both m1 and m2 are used */
+ if ((m1 > 0) && (m2 < LSINFINITY))
+ m2++;
+
+ uint ebit = m2a || !m1a;
+ uint metric = ebit ? m2 : m1;
+ uint tag = ea_get_int(ea, EA_OSPF_TAG, 0);
+
+ ip_addr fwd = IPA_NONE;
if ((a->dest == RTD_UNICAST) && use_gw_for_fwaddr(p, a->nh.gw, a->nh.iface))
fwd = a->nh.gw;
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index 85e37cea..baf98737 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -1020,16 +1020,6 @@ rip_prepare_attrs(struct linpool *pool, ea_list *next, u8 metric, u16 tag)
return l;
}
-static int
-rip_import_control(struct proto *P UNUSED, struct rte **rt, struct ea_list **attrs, struct linpool *pool)
-{
- /* Prepare attributes with initial values */
- if ((*rt)->attrs->source != RTS_RIP)
- *attrs = rip_prepare_attrs(pool, *attrs, 1, 0);
-
- return 0;
-}
-
static void
rip_reload_routes(struct channel *C)
{
@@ -1091,7 +1081,7 @@ rip_init(struct proto_config *CF)
P->if_notify = rip_if_notify;
P->rt_notify = rip_rt_notify;
P->neigh_notify = rip_neigh_notify;
- P->import_control = rip_import_control;
+ // P->import_control = rip_import_control;
P->reload_routes = rip_reload_routes;
P->make_tmp_attrs = rip_make_tmp_attrs;
P->store_tmp_attrs = rip_store_tmp_attrs;