From b60668d092f1778395b6c10b406059b8cbf235b8 Mon Sep 17 00:00:00 2001 From: Chris Caputo Date: Sun, 3 May 2009 04:40:57 +0000 Subject: RFC 4191 Default Router Preference support for router advertisements Adds "ipv6 nd router-preference (high|medium|low)" and "no ipv6 nd router-preference" interface commands. Files modified: doc/ipv6.texi zebra/interface.c zebra/interface.h zebra/rtadv.c zebra/rtadv.h Signed-off-by: Chris Caputo --- zebra/interface.c | 9 ++++++++ zebra/interface.h | 9 +++++++- zebra/rtadv.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- zebra/rtadv.h | 2 ++ 4 files changed, 82 insertions(+), 2 deletions(-) (limited to 'zebra') diff --git a/zebra/interface.c b/zebra/interface.c index 3e4867c4..9dfb6d50 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 968430ab..0cf66403 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 dd2be812..ff96648a 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 abd1c6fc..d8d263d0 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 */ -- cgit v1.2.1