diff options
-rw-r--r-- | doc/ipv6.texi | 10 | ||||
-rw-r--r-- | zebra/interface.c | 9 | ||||
-rw-r--r-- | zebra/interface.h | 9 | ||||
-rw-r--r-- | zebra/rtadv.c | 64 | ||||
-rw-r--r-- | zebra/rtadv.h | 2 |
5 files changed, 91 insertions, 3 deletions
diff --git a/doc/ipv6.texi b/doc/ipv6.texi index 910253c8a..a78a92fe9 100644 --- a/doc/ipv6.texi +++ b/doc/ipv6.texi @@ -150,6 +150,13 @@ in milliseconds, between successive unsolicited Router Advertisements. Default: not set @end deffn +@deffn {Interface Command} {ipv6 nd router-preference (high|medium|low)} {} +@deffnx {Interface Command} {no ipv6 nd router-preference} {} +Set default router preference in IPv6 router advertisements per RFC4191. + +Default: medium +@end deffn + @example @group interface eth0 @@ -160,4 +167,5 @@ interface eth0 For more information see @cite{RFC2462 (IPv6 Stateless Address Autoconfiguration)} , @cite{RFC2461 (Neighbor Discovery for IP Version 6 (IPv6))} -and @cite{RFC3775 (Mobility Support in IPv6 (Mobile IPv6))}. +, @cite{RFC3775 (Mobility Support in IPv6 (Mobile IPv6))} +and @cite{RFC4191 (Default Router Preferences and More-Specific Routes)}. diff --git a/zebra/interface.c b/zebra/interface.c index 3e4867c48..9dfb6d50f 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -41,6 +41,11 @@ #include "zebra/debug.h" #include "zebra/irdp.h" +#ifdef RTADV +/* Order is intentional. Matches RFC4191. This array is also used for + command matching, so only modify with care. */ +const char *rtadv_pref_strs[] = { "medium", "high", "INVALID", "low", 0 }; +#endif /* RTADV */ /* Called when new interface is added. */ static int @@ -75,6 +80,7 @@ if_zebra_new_hook (struct interface *ifp) rtadv->HomeAgentPreference = 0; rtadv->HomeAgentLifetime = RTADV_ADV_DEFAULT_LIFETIME; rtadv->AdvIntervalOption = 0; + rtadv->DefaultPreference = RTADV_PREF_MEDIUM; rtadv->AdvPrefixList = list_new (); } @@ -622,6 +628,9 @@ nd_dump_vty (struct vty *vty, struct interface *ifp) VTY_NEWLINE); vty_out (vty, " ND router advertisements live for %d seconds%s", rtadv->AdvDefaultLifetime, VTY_NEWLINE); + vty_out (vty, " ND router advertisement default router preference is " + "%s%s", rtadv_pref_strs[rtadv->DefaultPreference], + VTY_NEWLINE); if (rtadv->AdvManagedFlag) vty_out (vty, " Hosts use DHCP to obtain routable addresses.%s", VTY_NEWLINE); diff --git a/zebra/interface.h b/zebra/interface.h index 968430ab8..0cf66403b 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -46,7 +46,7 @@ #endif #ifdef RTADV -/* Router advertisement parameter. From RFC2461 and RFC3775. */ +/* Router advertisement parameter. From RFC2461, RFC3775 and RFC4191. */ struct rtadvconf { /* A flag indicating whether or not the router sends periodic Router @@ -171,6 +171,13 @@ struct rtadvconf Default: FALSE */ int AdvIntervalOption; + + /* The value to be placed in the Default Router Preference field of + a router advertisement. See [RFC 4191 2.1 & 2.2] + + Default: 0 (medium) */ + int DefaultPreference; +#define RTADV_PREF_MEDIUM 0x0 /* Per RFC4191. */ }; #endif /* RTADV */ diff --git a/zebra/rtadv.c b/zebra/rtadv.c index dd2be8126..ff96648a1 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -206,7 +206,12 @@ rtadv_send_packet (int sock, struct interface *ifp) rtadv->nd_ra_cksum = 0; rtadv->nd_ra_curhoplimit = 64; - rtadv->nd_ra_flags_reserved = 0; + + /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */ + rtadv->nd_ra_flags_reserved = + zif->rtadv.AdvDefaultLifetime == 0 ? 0 : zif->rtadv.DefaultPreference; + rtadv->nd_ra_flags_reserved <<= 3; + if (zif->rtadv.AdvManagedFlag) rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED; if (zif->rtadv.AdvOtherConfigFlag) @@ -1364,6 +1369,56 @@ DEFUN (no_ipv6_nd_prefix, return CMD_SUCCESS; } + +DEFUN (ipv6_nd_router_preference, + ipv6_nd_router_preference_cmd, + "ipv6 nd router-preference (high|medium|low)", + "Interface IPv6 config commands\n" + "Neighbor discovery\n" + "Default router preference\n" + "High default router preference\n" + "Low default router preference\n" + "Medium default router preference (default)\n") +{ + struct interface *ifp; + struct zebra_if *zif; + int i = 0; + + ifp = (struct interface *) vty->index; + zif = ifp->info; + + while (0 != rtadv_pref_strs[i]) + { + if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0) + { + zif->rtadv.DefaultPreference = i; + return CMD_SUCCESS; + } + i++; + } + + return CMD_ERR_NO_MATCH; +} + +DEFUN (no_ipv6_nd_router_preference, + no_ipv6_nd_router_preference_cmd, + "no ipv6 nd router-preference", + NO_STR + "Interface IPv6 config commands\n" + "Neighbor discovery\n" + "Default router preference\n") +{ + struct interface *ifp; + struct zebra_if *zif; + + ifp = (struct interface *) vty->index; + zif = ifp->info; + + zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */ + + return CMD_SUCCESS; +} + /* Write configuration about router advertisement. */ void rtadv_config_write (struct vty *vty, struct interface *ifp) @@ -1411,6 +1466,11 @@ rtadv_config_write (struct vty *vty, struct interface *ifp) if (zif->rtadv.AdvOtherConfigFlag) vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE); + if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM) + vty_out (vty, " ipv6 nd router-preference %s%s", + rtadv_pref_strs[zif->rtadv.DefaultPreference], + VTY_NEWLINE); + for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix)) { vty_out (vty, " ipv6 nd prefix %s/%d", @@ -1532,6 +1592,8 @@ rtadv_init (void) install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd); install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd); install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd); + install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd); + install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd); } static int diff --git a/zebra/rtadv.h b/zebra/rtadv.h index abd1c6fc0..d8d263d0b 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -94,4 +94,6 @@ struct nd_opt_homeagent_info { /* Home Agent info */ } __attribute__((__packed__)); #endif +extern const char *rtadv_pref_strs[]; + #endif /* _ZEBRA_RTADV_H */ |