summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
Diffstat (limited to 'nest')
-rw-r--r--nest/config.Y17
-rw-r--r--nest/iface.c66
-rw-r--r--nest/iface.h4
-rw-r--r--nest/proto.c14
4 files changed, 76 insertions, 25 deletions
diff --git a/nest/config.Y b/nest/config.Y
index cb6a85c2..dbd72055 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -75,9 +75,9 @@ CF_GRAMMAR
CF_ADDTO(conf, rtrid)
-rtrid: ROUTER ID idval ';' {
- new_config->router_id = $3;
- }
+rtrid:
+ ROUTER ID idval ';' { new_config->router_id = $3; }
+ | ROUTER ID FROM iface_patt ';' { new_config->router_id_from = this_ipatt; }
;
idval:
@@ -264,6 +264,17 @@ iface_patt_list:
| iface_patt_list ',' iface_patt_node
;
+iface_patt_init: {
+ /* Generic this_ipatt init */
+ this_ipatt = cfg_allocz(sizeof(struct iface_patt));
+ init_list(&this_ipatt->ipn_list);
+ }
+ ;
+
+iface_patt:
+ iface_patt_init iface_patt_list
+ ;
+
/* Direct device route protocol */
diff --git a/nest/iface.c b/nest/iface.c
index eea3d3b1..da79b21f 100644
--- a/nest/iface.c
+++ b/nest/iface.c
@@ -35,8 +35,6 @@
static pool *if_pool;
-static void auto_router_id(void);
-
list iface_list;
/**
@@ -354,9 +352,6 @@ if_end_update(void)
struct iface *i;
struct ifa *a, *b;
- if (!config->router_id)
- auto_router_id();
-
WALK_LIST(i, iface_list)
{
if (!(i->flags & IF_UPDATED))
@@ -583,24 +578,57 @@ ifa_delete(struct ifa *a)
}
}
-static void
-auto_router_id(void)
+u32
+if_choose_router_id(struct iface_patt *mask, u32 old_id)
{
#ifndef IPV6
- struct iface *i, *j;
+ struct iface *i;
+ struct ifa *a, *b;
- j = NULL;
+ b = NULL;
WALK_LIST(i, iface_list)
- if ((i->flags & IF_ADMIN_UP) &&
- !(i->flags & (IF_IGNORE | IF_SHUTDOWN)) &&
- i->addr &&
- !(i->addr->flags & IA_PEER) &&
- (!j || ipa_to_u32(i->addr->ip) < ipa_to_u32(j->addr->ip)))
- j = i;
- if (!j)
- die("Cannot determine router ID (no suitable network interface found), please configure it manually");
- log(L_INFO "Guessed router ID %I according to interface %s", j->addr->ip, j->name);
- config->router_id = ipa_to_u32(j->addr->ip);
+ {
+ if (!(i->flags & IF_ADMIN_UP) ||
+ (i->flags & (IF_IGNORE | IF_SHUTDOWN)))
+ continue;
+
+ WALK_LIST(a, i->addrs)
+ {
+ if (a->flags & IA_SECONDARY)
+ continue;
+
+ if (a->scope <= SCOPE_LINK)
+ continue;
+
+ /* FIXME: This should go away */
+ if (a->flags & IA_PEER)
+ continue;
+
+ /* FIXME: This should go away too */
+ if (!mask && (a != i->addr))
+ continue;
+
+ /* Check pattern if specified */
+ if (mask && !iface_patt_match(mask, i, a))
+ continue;
+
+ /* No pattern or pattern matched */
+ if (!b || ipa_to_u32(a->ip) < ipa_to_u32(b->ip))
+ b = a;
+ }
+ }
+
+ if (!b)
+ return 0;
+
+ u32 id = ipa_to_u32(b->ip);
+ if (id != old_id)
+ log(L_INFO "Chosen router ID %R according to interface %s", id, b->iface->name);
+
+ return id;
+
+#else
+ return 0;
#endif
}
diff --git a/nest/iface.h b/nest/iface.h
index 2416f82f..697ea543 100644
--- a/nest/iface.h
+++ b/nest/iface.h
@@ -101,6 +101,7 @@ struct iface *if_find_by_name(char *);
struct iface *if_get_by_name(char *);
void ifa_recalc_all_primary_addresses(void);
+
/* The Neighbor Cache */
typedef struct neighbor {
@@ -161,4 +162,7 @@ int iface_patt_match(struct iface_patt *ifp, struct iface *i, struct ifa *a);
struct iface_patt *iface_patt_find(list *l, struct iface *i, struct ifa *a);
int iface_patts_equal(list *, list *, int (*)(struct iface_patt *, struct iface_patt *));
+
+u32 if_choose_router_id(struct iface_patt *mask, u32 old_id);
+
#endif
diff --git a/nest/proto.c b/nest/proto.c
index 1334884e..b976a6cb 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -382,11 +382,9 @@ proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config
/* If there is a too big change in core attributes, ... */
if ((nc->protocol != oc->protocol) ||
(nc->disabled != p->disabled) ||
- (nc->table->table != oc->table->table) ||
- (proto_get_router_id(nc) != proto_get_router_id(oc)))
+ (nc->table->table != oc->table->table))
return 0;
-
p->debug = nc->debug;
p->mrtdump = nc->mrtdump;
proto_reconfig_type = type;
@@ -552,6 +550,16 @@ protos_commit(struct config *new, struct config *old, int force_reconfig, int ty
initial_device_proto = NULL;
}
+ /* Determine router ID for the first time - it has to be here and not in
+ global_commit() because it is postponed after start of device protocol */
+ if (!config->router_id)
+ {
+ config->router_id = if_choose_router_id(config->router_id_from, 0);
+ if (!config->router_id)
+ die("Cannot determine router ID, please configure it manually");
+ }
+
+ /* Start all other protocols */
WALK_LIST_DELSAFE(p, n, initial_proto_list)
proto_rethink_goal(p);
}