]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Implements interface masks for choosing router id.
authorOndrej Zajicek <santiago@crfreenet.org>
Thu, 27 Dec 2012 11:56:23 +0000 (12:56 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Thu, 27 Dec 2012 11:56:23 +0000 (12:56 +0100)
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.

conf/conf.c
conf/conf.h
doc/bird.sgml
nest/config.Y
nest/iface.c
nest/iface.h
nest/proto.c
proto/bgp/bgp.c
proto/ospf/ospf.c

index 6dfa369136a0f1fe0b9d92594033d6dae97e962a..14225d3ba37ba011fa76c7983e9a62dfe41dd8f3 100644 (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.");
 
   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;
 }
 
index 19300f54bab6ec3478dd7ff945191acc17a55403..683374e01dd97f54cb7acba1e08ab3b8940fe71d 100644 (file)
@@ -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 */
index 615ced986ded876f795d8ef6ce22e523ef0ae53a..4e04a13881075c9784a4d915b7702c6d755e7c0f 100644 (file)
@@ -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
index cb6a85c2547978744dd6df36adbe54e08c566e0a..dbd7205560b98a18ce8e00bdf128a709d465b444 100644 (file)
@@ -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 */
 
index eea3d3b1ac8f24b53c0051b2953a13954de9efcc..da79b21f7d452d93c9e7651a8cb6c1d27a5dd0a5 100644 (file)
@@ -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
 }
 
index 2416f82f598b0debbc9d6231420d66e3dd394ff1..697ea543638ef0f828cadffe67e04b057c3e38ee 100644 (file)
@@ -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
index 1334884e6f7e35c1e4ee915581cdbdad7635bb85..b976a6cbcb03a19c9b14e8c2d791ee1b9792798f 100644 (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 ((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);
 }
index 346c641b385c898efc964aa88395447bdb7a2ffb..249d2e07e8524386d8034ecc51fd3c84b4f45b67 100644 (file)
@@ -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
index 6654e107cbd09226362031c27322cd7e9c0223a5..a3b6b2e722a3d4f610cf351c94296d28af86dbda 100644 (file)
@@ -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;