diff options
author | glebius <glebius@FreeBSD.org> | 2011-12-16 12:16:56 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2011-12-16 12:16:56 +0000 |
commit | 27a36f6ac8242750daa092abd7180b10d16f4508 (patch) | |
tree | 059f66a20d251fa947969ff34292206d47ffc45c /sys/netinet6 | |
parent | b646d3f6998d3f539bcda6f94be4926461780cf7 (diff) | |
download | FreeBSD-src-27a36f6ac8242750daa092abd7180b10d16f4508.zip FreeBSD-src-27a36f6ac8242750daa092abd7180b10d16f4508.tar.gz |
A major overhaul of the CARP implementation. The ip_carp.c was started
from scratch, copying needed functionality from the old implemenation
on demand, with a thorough review of all code. The main change is that
interface layer has been removed from the CARP. Now redundant addresses
are configured exactly on the interfaces, they run on.
The CARP configuration itself is, as before, configured and read via
SIOCSVH/SIOCGVH ioctls. A new prefix created with SIOCAIFADDR or
SIOCAIFADDR_IN6 may now be configured to a particular virtual host id,
which makes the prefix redundant.
ifconfig(8) semantics has been changed too: now one doesn't need
to clone carpXX interface, he/she should directly configure a vhid
on a Ethernet interface.
To supply vhid data from the kernel to an application the getifaddrs(8)
function had been changed to pass ifam_data with each address. [1]
The new implementation definitely closes all PRs related to carp(4)
being an interface, and may close several others. It also allows
to run a single redundant IP per interface.
Big thanks to Bjoern Zeeb for his help with inet6 part of patch, for
idea on using ifam_data and for several rounds of reviewing!
PR: kern/117000, kern/126945, kern/126714, kern/120130, kern/117448
Reviewed by: bz
Submitted by: bz [1]
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/in6.c | 24 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.c | 1 | ||||
-rw-r--r-- | sys/netinet6/in6_var.h | 1 | ||||
-rw-r--r-- | sys/netinet6/nd6.c | 3 | ||||
-rw-r--r-- | sys/netinet6/nd6_nbr.c | 14 |
5 files changed, 33 insertions, 10 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 8514f73..ef22f03 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -95,6 +95,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/in_systm.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> +#include <netinet/ip_carp.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> @@ -272,6 +273,7 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, struct in6_ifaddr *ia = NULL; struct in6_aliasreq *ifra = (struct in6_aliasreq *)data; struct sockaddr_in6 *sa6; + int carp_attached = 0; int error; switch (cmd) { @@ -652,6 +654,18 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, break; } + if (ifra->ifra_vhid > 0) { + if (carp_attach_p != NULL) + error = (*carp_attach_p)(&ia->ia_ifa, + ifra->ifra_vhid); + else + error = EPROTONOSUPPORT; + if (error) + goto out; + else + carp_attached = 1; + } + /* * then, make the prefix on-link on the interface. * XXX: we'd rather create the prefix before the address, but @@ -695,9 +709,14 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, * nd6_prelist_add will install the corresponding * interface route. */ - if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0) + if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0) { + if (carp_attached) + (*carp_detach_p)(&ia->ia_ifa); goto out; + } if (pr == NULL) { + if (carp_attached) + (*carp_detach_p)(&ia->ia_ifa); log(LOG_ERR, "nd6_prelist_add succeeded but " "no prefix\n"); error = EINVAL; @@ -1301,6 +1320,9 @@ in6_purgeaddr(struct ifaddr *ifa) struct rtentry *rt; struct ifaddr *ifa0, *nifa; + if (ifa->ifa_carp) + (*carp_detach_p)(ifa); + /* * find another IPv6 address as the gateway for the * link-local and node-local all-nodes multicast diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index 2ff7455..1dae2c0 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -705,7 +705,6 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) switch (ifp->if_type) { case IFT_PFLOG: case IFT_PFSYNC: - case IFT_CARP: return; } diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h index 00342fd..3e93e71 100644 --- a/sys/netinet6/in6_var.h +++ b/sys/netinet6/in6_var.h @@ -287,6 +287,7 @@ struct in6_aliasreq { struct sockaddr_in6 ifra_prefixmask; int ifra_flags; struct in6_addrlifetime ifra_lifetime; + int ifra_vhid; }; /* prefix type macro */ diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 875daa0..5d6f8c0 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -2173,9 +2173,6 @@ nd6_need_cache(struct ifnet *ifp) #ifdef IFT_IEEE80211 case IFT_IEEE80211: #endif -#ifdef IFT_CARP - case IFT_CARP: -#endif case IFT_INFINIBAND: case IFT_GIF: /* XXX need more cases? */ case IFT_PPP: diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c index 0221c72..a2aaeea 100644 --- a/sys/netinet6/nd6_nbr.c +++ b/sys/netinet6/nd6_nbr.c @@ -225,7 +225,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len) /* (1) and (3) check. */ if (ifp->if_carp) ifa = (*carp_iamatch6_p)(ifp, &taddr6); - if (ifa == NULL) + else ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6); /* (2) check. */ @@ -688,7 +688,14 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len) lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3; } - ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6); + /* + * This effectively disables the DAD check on a non-master CARP + * address. + */ + if (ifp->if_carp) + ifa = (*carp_iamatch6_p)(ifp, &taddr6); + else + ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6); /* * Target address matches one of my interface address. @@ -1133,9 +1140,6 @@ nd6_ifptomac(struct ifnet *ifp) #ifdef IFT_IEEE80211 case IFT_IEEE80211: #endif -#ifdef IFT_CARP - case IFT_CARP: -#endif case IFT_INFINIBAND: case IFT_BRIDGE: case IFT_ISO88025: |