summaryrefslogtreecommitdiff
path: root/proto/ospf/topology.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/ospf/topology.c')
-rw-r--r--proto/ospf/topology.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index 9fe68264..78022423 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -1402,6 +1402,46 @@ lsab_put_prefix(struct ospf_proto *p, net_addr *n, u32 cost)
ospf3_put_prefix(buf, n, flags, cost);
}
+static inline void
+update_loopback_addr(struct ospf_proto *p)
+{
+ ip_addr old_addr = p->loopback_addr;
+ ip_addr best_addr = IPA_NONE;
+ int best_pref = 0;
+
+ struct ospf_iface *ifa;
+ WALK_LIST(ifa, p->iface_list)
+ {
+ if (ifa->type == OSPF_IT_VLINK)
+ continue;
+
+ struct ifa *a;
+ WALK_LIST(a, ifa->iface->addrs)
+ {
+ if ((a->prefix.type != ospf_get_af(p)) ||
+ (a->flags & IA_SECONDARY) ||
+ (a->scope <= SCOPE_LINK))
+ continue;
+
+ int pref = (a->flags & IA_HOST) ? 3 : (ifa->stub ? 2 : 1);
+ if ((pref > best_pref) || ((pref == best_pref) && ipa_equal(a->ip, old_addr)))
+ {
+ best_addr = a->ip;
+ best_pref = pref;
+ }
+ }
+ }
+
+ if (ipa_equal(best_addr, old_addr))
+ return;
+
+ p->loopback_addr = best_addr;
+
+ WALK_LIST(ifa, p->iface_list)
+ if (ifa->loopback_addr_used)
+ ospf_notify_link_lsa(ifa);
+}
+
static void
prepare_link_lsa_body(struct ospf_proto *p, struct ospf_iface *ifa)
{
@@ -1427,6 +1467,12 @@ prepare_link_lsa_body(struct ospf_proto *p, struct ospf_iface *ifa)
i++;
}
+ if (ospf_is_ip4(p) && ipa_zero(nh))
+ {
+ nh = p->loopback_addr;
+ ifa->loopback_addr_used = 1;
+ }
+
/* Filling the preallocated header */
struct ospf_lsa_link *ll = p->lsab;
ll->options = ifa->oa->options | (ifa->priority << 24);
@@ -1853,6 +1899,9 @@ ospf_update_topology(struct ospf_proto *p)
}
}
+ if (ospf_is_v3(p) && ospf_is_ip4(p))
+ update_loopback_addr(p);
+
WALK_LIST(ifa, p->iface_list)
{
if (ifa->type == OSPF_IT_VLINK)
@@ -1860,6 +1909,8 @@ ospf_update_topology(struct ospf_proto *p)
if (ifa->update_link_lsa)
{
+ ifa->loopback_addr_used = 0;
+
if ((ifa->state > OSPF_IS_LOOP) && !ifa->link_lsa_suppression)
ospf_originate_link_lsa(p, ifa);
else