Commit 79b4e12e authored by Ondřej Zajíček's avatar Ondřej Zajíček

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.
parent a92cf57d
......@@ -200,9 +200,19 @@ global_commit(struct config *new, struct config *old)
log(L_WARN "Reconfiguration of BGP listening socket not implemented, please restart BIRD.");
if (!new->router_id)
new->router_id = old->router_id;
if (new->router_id != old->router_id)
return 1;
{
new->router_id = old->router_id;
if (new->router_id_from)
{
u32 id = if_choose_router_id(new->router_id_from, old->router_id);
if (!id)
log(L_WARN "Cannot determine router ID, using old one");
else
new->router_id = id;
}
}
return 0;
}
......
......@@ -26,6 +26,7 @@ struct config {
int mrtdump_file; /* Configured MRTDump file (sysdep, fd in unix) */
char *syslog_name; /* Name used for syslog (NULL -> no syslog) */
struct rtable_config *master_rtc; /* Configuration of master routing table */
struct iface_patt *router_id_from; /* Configured list of router ID iface patterns */
u32 router_id; /* Our Router ID */
ip_addr listen_bgp_addr; /* Listening BGP socket should use this address */
......
......@@ -337,7 +337,18 @@ protocol rip {
Besides, there are some predefined numeric constants based on /etc/iproute2/rt_* files.
A list of defined constants can be seen (together with other symbols) using 'show symbols' command.
<tag>router id <m/IPv4 address/</tag> Set BIRD's router ID. It's a world-wide unique identification of your router, usually one of router's IPv4 addresses. Default: in IPv4 version, the lowest IP address of a non-loopback interface. In IPv6 version, this option is mandatory.
<tag>router id <m/IPv4 address/</tag>
Set BIRD's router ID. It's a world-wide unique identification
of your router, usually one of router's IPv4 addresses.
Default: in IPv4 version, the lowest IP address of a
non-loopback interface. In IPv6 version, this option is
mandatory.
<tag>router id from [-] [ "<m/mask/" ] [ <m/prefix/ ] [, ...]</tag>
Set BIRD's router ID based on an IP address of an interface
specified by an interface pattern. The option is applicable
for IPv4 version only. See <ref id="dsc-iface" name="interface">
section for detailed description of interface patterns.
<tag>listen bgp [address <m/address/] [port <m/port/] [dual]</tag>
This option allows to specify address and port where BGP
......
......@@ -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 */
......
......@@ -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
}
......
......@@ -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
......@@ -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);
}
......
......@@ -1009,6 +1009,9 @@ bgp_reconfigure(struct proto *P, struct proto_config *C)
struct bgp_proto *p = (struct bgp_proto *) P;
struct bgp_config *old = p->cf;
if (proto_get_router_id(C) != p->local_id)
return 0;
int same = !memcmp(((byte *) old) + sizeof(struct proto_config),
((byte *) new) + sizeof(struct proto_config),
// password item is last and must be checked separately
......
......@@ -729,6 +729,9 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
struct ospf_iface *ifa, *ifx;
struct ospf_iface_patt *ip;
if (proto_get_router_id(c) != po->router_id)
return 0;
if (po->rfc1583 != new->rfc1583)
return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment