summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2011-12-16 12:16:56 +0000
committerglebius <glebius@FreeBSD.org>2011-12-16 12:16:56 +0000
commit27a36f6ac8242750daa092abd7180b10d16f4508 (patch)
tree059f66a20d251fa947969ff34292206d47ffc45c /sys/netinet6
parentb646d3f6998d3f539bcda6f94be4926461780cf7 (diff)
downloadFreeBSD-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.c24
-rw-r--r--sys/netinet6/in6_ifattach.c1
-rw-r--r--sys/netinet6/in6_var.h1
-rw-r--r--sys/netinet6/nd6.c3
-rw-r--r--sys/netinet6/nd6_nbr.c14
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:
OpenPOWER on IntegriCloud