summaryrefslogtreecommitdiffstats
path: root/sys/net
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/net
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/net')
-rw-r--r--sys/net/if.c22
-rw-r--r--sys/net/if.h5
-rw-r--r--sys/net/if_ethersubr.c2
-rw-r--r--sys/net/if_types.h1
-rw-r--r--sys/net/if_var.h2
-rw-r--r--sys/net/rtsock.c16
6 files changed, 39 insertions, 9 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 8c6c24c..4377343 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -130,17 +130,19 @@ void (*lagg_linkstate_p)(struct ifnet *ifp, int state);
/* These are external hooks for CARP. */
void (*carp_linkstate_p)(struct ifnet *ifp);
#if defined(INET) || defined(INET6)
-struct ifnet *(*carp_forus_p)(struct ifnet *ifp, u_char *dhost);
+int (*carp_forus_p)(struct ifnet *ifp, u_char *dhost);
int (*carp_output_p)(struct ifnet *ifp, struct mbuf *m,
- struct sockaddr *sa, struct rtentry *rt);
+ struct sockaddr *sa);
+int (*carp_ioctl_p)(struct ifreq *, u_long, struct thread *);
+int (*carp_attach_p)(struct ifaddr *, int);
+void (*carp_detach_p)(struct ifaddr *);
#endif
#ifdef INET
-int (*carp_iamatch_p)(struct ifnet *, struct in_ifaddr *, struct in_addr *,
- u_int8_t **);
+int (*carp_iamatch_p)(struct ifaddr *, uint8_t **);
#endif
#ifdef INET6
struct ifaddr *(*carp_iamatch6_p)(struct ifnet *ifp, struct in6_addr *taddr6);
-caddr_t (*carp_macmatch6_p)(struct ifnet *ifp, struct mbuf *m,
+caddr_t (*carp_macmatch6_p)(struct ifnet *ifp, struct mbuf *m,
const struct in6_addr *taddr);
#endif
@@ -2506,6 +2508,16 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
error = if_getgroupmembers((struct ifgroupreq *)data);
CURVNET_RESTORE();
return (error);
+#if defined(INET) || defined(INET6)
+ case SIOCSVH:
+ case SIOCGVH:
+ if (carp_ioctl_p == NULL)
+ error = EPROTONOSUPPORT;
+ else
+ error = (*carp_ioctl_p)(ifr, cmd, td);
+ CURVNET_RESTORE();
+ return (error);
+#endif
}
ifp = ifunit_ref(ifr->ifr_name);
diff --git a/sys/net/if.h b/sys/net/if.h
index 4f2dc6f..08420f4 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -85,7 +85,7 @@ struct if_data {
u_char ifi_addrlen; /* media address length */
u_char ifi_hdrlen; /* media header length */
u_char ifi_link_state; /* current link state */
- u_char ifi_spare_char1; /* spare byte */
+ u_char ifi_vhid; /* carp vhid */
u_char ifi_spare_char2; /* spare byte */
u_char ifi_datalen; /* length of this data struct */
u_long ifi_mtu; /* maximum transmission unit */
@@ -267,6 +267,8 @@ struct ifa_msghdr {
int ifam_flags; /* value of ifa_flags */
u_short ifam_index; /* index for associated ifp */
int ifam_metric; /* value of ifa_metric */
+ struct if_data ifam_data;/* statistics and other data about if or
+ * address */
};
/*
@@ -357,6 +359,7 @@ struct ifaliasreq {
struct sockaddr ifra_addr;
struct sockaddr ifra_broadaddr;
struct sockaddr ifra_mask;
+ int ifra_vhid;
};
struct ifmediareq {
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 9eae683..253371a 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -397,7 +397,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
#if defined(INET) || defined(INET6)
if (ifp->if_carp &&
- (error = (*carp_output_p)(ifp, m, dst, NULL)))
+ (error = (*carp_output_p)(ifp, m, dst)))
goto bad;
#endif
diff --git a/sys/net/if_types.h b/sys/net/if_types.h
index c2effac..fe6ab5e 100644
--- a/sys/net/if_types.h
+++ b/sys/net/if_types.h
@@ -250,6 +250,5 @@
#define IFT_ENC 0xf4
#define IFT_PFLOG 0xf6
#define IFT_PFSYNC 0xf7
-#define IFT_CARP 0xf8 /* Common Address Redundancy Protocol */
#define IFT_IPXIP 0xf9 /* IPX over IP tunneling; no longer used. */
#endif /* !_NET_IF_TYPES_H_ */
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 1cb8440..ea60944 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -69,6 +69,7 @@ struct rt_addrinfo;
struct socket;
struct ether_header;
struct carp_if;
+struct carp_softc;
struct ifvlantrunk;
struct route;
struct vnet;
@@ -729,6 +730,7 @@ struct ifaddr {
struct sockaddr *ifa_netmask; /* used to determine subnet */
struct if_data if_data; /* not all members are meaningful */
struct ifnet *ifa_ifp; /* back-pointer to interface */
+ struct carp_softc *ifa_carp; /* pointer to CARP data */
TAILQ_ENTRY(ifaddr) ifa_link; /* queue macro glue */
void (*ifa_rtrequest) /* check or clean routes (+ or -)'d */
(int, struct rtentry *, struct rt_addrinfo *);
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index b2313c0..3520824 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -63,6 +63,7 @@
#include <netinet/in.h>
#include <netinet/if_ether.h>
+#include <netinet/ip_carp.h>
#ifdef INET6
#include <netinet6/scope6_var.h>
#endif
@@ -83,7 +84,7 @@ struct if_data32 {
uint8_t ifi_addrlen;
uint8_t ifi_hdrlen;
uint8_t ifi_link_state;
- uint8_t ifi_spare_char1;
+ uint8_t ifi_vhid;
uint8_t ifi_spare_char2;
uint8_t ifi_datalen;
uint32_t ifi_mtu;
@@ -122,6 +123,9 @@ MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
static struct sockaddr route_src = { 2, PF_ROUTE, };
static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, };
+/* These are external hooks for CARP. */
+int (*carp_get_vhid_p)(struct ifaddr *);
+
/*
* Used by rtsock/raw_input callback code to decide whether to filter the update
* notification to a socket bound to a particular FIB.
@@ -1508,6 +1512,7 @@ copy_ifdata32(struct if_data *src, struct if_data32 *dst)
CP(*src, *dst, ifi_addrlen);
CP(*src, *dst, ifi_hdrlen);
CP(*src, *dst, ifi_link_state);
+ CP(*src, *dst, ifi_vhid);
dst->ifi_datalen = sizeof(struct if_data32);
CP(*src, *dst, ifi_mtu);
CP(*src, *dst, ifi_metric);
@@ -1559,6 +1564,9 @@ sysctl_iflist(int af, struct walkarg *w)
ifm32->ifm_flags = ifp->if_flags |
ifp->if_drv_flags;
copy_ifdata32(&ifp->if_data, &ifm32->ifm_data);
+ if (carp_get_vhid_p != NULL)
+ ifm32->ifm_data.ifi_vhid =
+ (*carp_get_vhid_p)(ifa);
ifm32->ifm_addrs = info.rti_addrs;
error = SYSCTL_OUT(w->w_req, (caddr_t)ifm32,
len);
@@ -1569,6 +1577,9 @@ sysctl_iflist(int af, struct walkarg *w)
ifm->ifm_index = ifp->if_index;
ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
ifm->ifm_data = ifp->if_data;
+ if (carp_get_vhid_p != NULL)
+ ifm->ifm_data.ifi_vhid =
+ (*carp_get_vhid_p)(ifa);
ifm->ifm_addrs = info.rti_addrs;
error = SYSCTL_OUT(w->w_req, (caddr_t)ifm, len);
#ifdef COMPAT_FREEBSD32
@@ -1595,6 +1606,9 @@ sysctl_iflist(int af, struct walkarg *w)
ifam->ifam_flags = ifa->ifa_flags;
ifam->ifam_metric = ifa->ifa_metric;
ifam->ifam_addrs = info.rti_addrs;
+ if (carp_get_vhid_p != NULL)
+ ifam->ifam_data.ifi_vhid =
+ (*carp_get_vhid_p)(ifa);
error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
if (error)
goto done;
OpenPOWER on IntegriCloud