]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Implements default router preference (RFC 4191) for RAdv.
authorOndrej Zajicek <santiago@crfreenet.org>
Mon, 7 Jul 2014 20:56:21 +0000 (22:56 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Mon, 7 Jul 2014 20:56:21 +0000 (22:56 +0200)
Thanks to Baptiste Jonglez for the patch.

doc/bird.sgml
proto/radv/config.Y
proto/radv/packets.c
proto/radv/radv.c
proto/radv/radv.h

index beacd4be45269ee933b45f0d135cbc902d7e1b9f..1a8e233d644da5f2657a210dd579265e88eb2275 100644 (file)
@@ -3013,6 +3013,10 @@ definitions, prefix definitions and DNS definitions:
        as a default router. For <cf/sensitive/ option, see <ref id="dsc-trigger" name="trigger">.
        Default: 3 * <cf/max ra interval/, <cf/sensitive/ yes.
 
+       <tag>default preference low|medium|high</tag>
+       This option specifies the Default Router Preference value to advertise
+       to hosts. Default: medium.
+
        <tag>rdnss local <m/switch/</tag>
        Use only local (interface-specific) RDNSS definitions for this
        interface. Otherwise, both global and local definitions are used. Could
index 88a9e298eb9249b5819909d4d70bfe4a3d8e2b15..a26ea88e9ed95e866a336ddabdb7c7dc956ddf44 100644 (file)
@@ -30,9 +30,9 @@ CF_KEYWORDS(RADV, PREFIX, INTERFACE, MIN, MAX, RA, DELAY, INTERVAL,
        MANAGED, OTHER, CONFIG, LINK, MTU, REACHABLE, TIME, RETRANS,
        TIMER, CURRENT, HOP, LIMIT, DEFAULT, VALID, PREFERRED, MULT,
        LIFETIME, SKIP, ONLINK, AUTONOMOUS, RDNSS, DNSSL, NS, DOMAIN,
-       LOCAL, TRIGGER, SENSITIVE)
+       LOCAL, TRIGGER, SENSITIVE, PREFERENCE, LOW, MEDIUM, HIGH)
 
-%type<i> radv_mult radv_sensitive
+%type<i> radv_mult radv_sensitive radv_preference
 
 CF_GRAMMAR
 
@@ -84,6 +84,7 @@ radv_iface_start:
   RADV_IFACE->current_hop_limit = DEFAULT_CURRENT_HOP_LIMIT;
   RADV_IFACE->default_lifetime = -1;
   RADV_IFACE->default_lifetime_sensitive = 1;
+  RADV_IFACE->default_preference = RA_PREF_MEDIUM;
 };
 
 radv_iface_item:
@@ -101,6 +102,7 @@ radv_iface_item:
      if (($3 < 0) || ($3 > 9000))  cf_error("Default lifetime must be in range 0-9000");
      if ($4 != -1) RADV_IFACE->default_lifetime_sensitive = $4;
    }
+ | DEFAULT PREFERENCE radv_preference { RADV_IFACE->default_preference = $3; }
  | PREFIX radv_prefix { add_tail(&RADV_IFACE->pref_list, NODE this_radv_prefix); }
  | RDNSS { init_list(&radv_dns_list); } radv_rdnss { add_tail_list(&RADV_IFACE->rdnss_list, &radv_dns_list); }
  | DNSSL { init_list(&radv_dns_list); } radv_dnssl { add_tail_list(&RADV_IFACE->dnssl_list, &radv_dns_list); }
@@ -108,6 +110,11 @@ radv_iface_item:
  | DNSSL LOCAL bool { RADV_IFACE->dnssl_local = $3; }
  ;
 
+radv_preference:
+   LOW { $$ = RA_PREF_LOW; }
+ | MEDIUM { $$ = RA_PREF_MEDIUM; }
+ | HIGH { $$ = RA_PREF_HIGH; }
+
 radv_iface_finish:
 {
   struct radv_iface_config *ic = RADV_IFACE;
index 1d7e04f41e19b1981cda636ec96f023fe125219f..ef8697224eb9725433718745aa74206ac0c61c59 100644 (file)
@@ -251,10 +251,11 @@ radv_prepare_ra(struct radv_iface *ifa)
   pkt->code = 0;
   pkt->checksum = 0;
   pkt->current_hop_limit = ic->current_hop_limit;
-  pkt->flags = (ic->managed ? OPT_RA_MANAGED : 0) |
-    (ic->other_config ? OPT_RA_OTHER_CFG : 0);
   pkt->router_lifetime = (ra->active || !ic->default_lifetime_sensitive) ?
     htons(ic->default_lifetime) : 0;
+  pkt->flags = (ic->managed ? OPT_RA_MANAGED : 0) |
+    (ic->other_config ? OPT_RA_OTHER_CFG : 0) |
+    (pkt->router_lifetime ? ic->default_preference : 0);
   pkt->reachable_time = htonl(ic->reachable_time);
   pkt->retrans_timer = htonl(ic->retrans_timer);
   buf += sizeof(*pkt);
@@ -330,10 +331,15 @@ radv_send_ra(struct radv_iface *ifa, int shutdown)
 
   if (shutdown)
   {
-    /* Modify router lifetime to 0, it is not restored because
-       we suppose that the iface will be removed */
+    /*
+     * Modify router lifetime to 0, it is not restored because we suppose that
+     * the iface will be removed. The preference value also has to be zeroed.
+     * (RFC 4191 2.2: If router lifetime is 0, the preference value must be 0.)
+     */
+
     struct radv_ra_packet *pkt = (void *) ifa->sk->tbuf;
     pkt->router_lifetime = 0;
+    pkt->flags &= ~RA_PREF_MASK;
   }
 
   RADV_TRACE(D_PACKETS, "Sending RA via %s", ifa->iface->name);
index 90408536db5706a7a936697e248a0b218bb82a47..6be7cd84720eaf56436bceaf267d42a459ef1eb5 100644 (file)
@@ -40,6 +40,7 @@
  * Supported standards:
  * - RFC 4861 - main RA standard
  * - RFC 6106 - DNS extensions (RDDNS, DNSSL)
+ * - RFC 4191 (partial) - Default Router Preference
  */
 
 static void
index f80e4530162e402ada67eede44255012acce0535..bb80d65fb9d4cd42fd6120cfa238bf25bf10d81f 100644 (file)
@@ -80,6 +80,7 @@ struct radv_iface_config
   u32 current_hop_limit;
   u32 default_lifetime;
   u8 default_lifetime_sensitive; /* Whether default_lifetime depends on trigger */
+  u8 default_preference;       /* Default Router Preference (RFC 4191) */
 };
 
 struct radv_prefix_config
@@ -144,6 +145,11 @@ struct radv_iface
 #define RA_EV_CHANGE 2         /* Change of options or prefixes */
 #define RA_EV_RS 3             /* Received RS */
 
+/* Default Router Preferences (RFC 4191) */
+#define RA_PREF_LOW    0x18
+#define RA_PREF_MEDIUM 0x00
+#define RA_PREF_HIGH   0x08
+#define RA_PREF_MASK   0x18
 
 
 #ifdef LOCAL_DEBUG