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.
This commit is contained in:
Ondrej Zajicek 2012-12-27 12:56:23 +01:00
parent a92cf57dd6
commit 79b4e12e60
9 changed files with 108 additions and 29 deletions

View file

@ -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."); log(L_WARN "Reconfiguration of BGP listening socket not implemented, please restart BIRD.");
if (!new->router_id) if (!new->router_id)
{
new->router_id = old->router_id; new->router_id = old->router_id;
if (new->router_id != old->router_id)
return 1; 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; return 0;
} }

View file

@ -26,6 +26,7 @@ struct config {
int mrtdump_file; /* Configured MRTDump file (sysdep, fd in unix) */ int mrtdump_file; /* Configured MRTDump file (sysdep, fd in unix) */
char *syslog_name; /* Name used for syslog (NULL -> no syslog) */ char *syslog_name; /* Name used for syslog (NULL -> no syslog) */
struct rtable_config *master_rtc; /* Configuration of master routing table */ 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 */ u32 router_id; /* Our Router ID */
ip_addr listen_bgp_addr; /* Listening BGP socket should use this address */ ip_addr listen_bgp_addr; /* Listening BGP socket should use this address */

View file

@ -337,7 +337,18 @@ protocol rip {
Besides, there are some predefined numeric constants based on /etc/iproute2/rt_* files. 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. 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> <tag>listen bgp [address <m/address/] [port <m/port/] [dual]</tag>
This option allows to specify address and port where BGP This option allows to specify address and port where BGP

View file

@ -75,9 +75,9 @@ CF_GRAMMAR
CF_ADDTO(conf, rtrid) CF_ADDTO(conf, rtrid)
rtrid: ROUTER ID idval ';' { rtrid:
new_config->router_id = $3; ROUTER ID idval ';' { new_config->router_id = $3; }
} | ROUTER ID FROM iface_patt ';' { new_config->router_id_from = this_ipatt; }
; ;
idval: idval:
@ -264,6 +264,17 @@ iface_patt_list:
| iface_patt_list ',' iface_patt_node | 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 */ /* Direct device route protocol */

View file

@ -35,8 +35,6 @@
static pool *if_pool; static pool *if_pool;
static void auto_router_id(void);
list iface_list; list iface_list;
/** /**
@ -354,9 +352,6 @@ if_end_update(void)
struct iface *i; struct iface *i;
struct ifa *a, *b; struct ifa *a, *b;
if (!config->router_id)
auto_router_id();
WALK_LIST(i, iface_list) WALK_LIST(i, iface_list)
{ {
if (!(i->flags & IF_UPDATED)) if (!(i->flags & IF_UPDATED))
@ -583,24 +578,57 @@ ifa_delete(struct ifa *a)
} }
} }
static void u32
auto_router_id(void) if_choose_router_id(struct iface_patt *mask, u32 old_id)
{ {
#ifndef IPV6 #ifndef IPV6
struct iface *i, *j; struct iface *i;
struct ifa *a, *b;
j = NULL; b = NULL;
WALK_LIST(i, iface_list) WALK_LIST(i, iface_list)
if ((i->flags & IF_ADMIN_UP) && {
!(i->flags & (IF_IGNORE | IF_SHUTDOWN)) && if (!(i->flags & IF_ADMIN_UP) ||
i->addr && (i->flags & (IF_IGNORE | IF_SHUTDOWN)))
!(i->addr->flags & IA_PEER) && continue;
(!j || ipa_to_u32(i->addr->ip) < ipa_to_u32(j->addr->ip)))
j = i; WALK_LIST(a, i->addrs)
if (!j) {
die("Cannot determine router ID (no suitable network interface found), please configure it manually"); if (a->flags & IA_SECONDARY)
log(L_INFO "Guessed router ID %I according to interface %s", j->addr->ip, j->name); continue;
config->router_id = ipa_to_u32(j->addr->ip);
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 #endif
} }

View file

@ -101,6 +101,7 @@ struct iface *if_find_by_name(char *);
struct iface *if_get_by_name(char *); struct iface *if_get_by_name(char *);
void ifa_recalc_all_primary_addresses(void); void ifa_recalc_all_primary_addresses(void);
/* The Neighbor Cache */ /* The Neighbor Cache */
typedef struct neighbor { 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); 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 *)); 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 #endif

View file

@ -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 there is a too big change in core attributes, ... */
if ((nc->protocol != oc->protocol) || if ((nc->protocol != oc->protocol) ||
(nc->disabled != p->disabled) || (nc->disabled != p->disabled) ||
(nc->table->table != oc->table->table) || (nc->table->table != oc->table->table))
(proto_get_router_id(nc) != proto_get_router_id(oc)))
return 0; return 0;
p->debug = nc->debug; p->debug = nc->debug;
p->mrtdump = nc->mrtdump; p->mrtdump = nc->mrtdump;
proto_reconfig_type = type; 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; 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) WALK_LIST_DELSAFE(p, n, initial_proto_list)
proto_rethink_goal(p); proto_rethink_goal(p);
} }

View file

@ -1009,6 +1009,9 @@ bgp_reconfigure(struct proto *P, struct proto_config *C)
struct bgp_proto *p = (struct bgp_proto *) P; struct bgp_proto *p = (struct bgp_proto *) P;
struct bgp_config *old = p->cf; 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), int same = !memcmp(((byte *) old) + sizeof(struct proto_config),
((byte *) new) + sizeof(struct proto_config), ((byte *) new) + sizeof(struct proto_config),
// password item is last and must be checked separately // password item is last and must be checked separately

View file

@ -729,6 +729,9 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
struct ospf_iface *ifa, *ifx; struct ospf_iface *ifa, *ifx;
struct ospf_iface_patt *ip; struct ospf_iface_patt *ip;
if (proto_get_router_id(c) != po->router_id)
return 0;
if (po->rfc1583 != new->rfc1583) if (po->rfc1583 != new->rfc1583)
return 0; return 0;