summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2012-12-27 12:56:23 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2012-12-27 12:56:23 +0100
commit79b4e12e6032faf6bb1f3feac385bd36ee53019e (patch)
tree0509f66417bbaf3429594ac7c359971d75b3ec49 /nest
parenta92cf57dd6ba021a495fe7268c86dc8e6aeecbb2 (diff)
Implements interface masks for choosing router id.
Router ID could be automatically determined based of subset of ifaces/addresses specified by 'router id from' option. The patch also does some minor changes related to router ID reconfiguration. Thanks to Alexander V. Chernikov for most of the work.
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);
}