summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet/ip_carp.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet/ip_carp.c')
-rw-r--r--freebsd/sys/netinet/ip_carp.c137
1 files changed, 63 insertions, 74 deletions
diff --git a/freebsd/sys/netinet/ip_carp.c b/freebsd/sys/netinet/ip_carp.c
index 1fb208a2..03ce7bbe 100644
--- a/freebsd/sys/netinet/ip_carp.c
+++ b/freebsd/sys/netinet/ip_carp.c
@@ -646,6 +646,7 @@ carp_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af)
struct carp_softc *sc;
uint64_t tmp_counter;
struct timeval sc_tv, ch_tv;
+ struct epoch_tracker et;
int error;
/*
@@ -659,7 +660,7 @@ carp_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af)
* (these should never happen, and as noted above, we may
* miss real loops; this is just a double-check).
*/
- IF_ADDR_RLOCK(ifp);
+ NET_EPOCH_ENTER(et);
error = 0;
match = NULL;
IFNET_FOREACH_IFA(ifp, ifa) {
@@ -673,7 +674,7 @@ carp_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af)
ifa = error ? NULL : match;
if (ifa != NULL)
ifa_ref(ifa);
- IF_ADDR_RUNLOCK(ifp);
+ NET_EPOCH_EXIT(et);
if (ifa == NULL) {
if (error == ELOOP) {
@@ -881,18 +882,19 @@ carp_send_ad_error(struct carp_softc *sc, int error)
static struct ifaddr *
carp_best_ifa(int af, struct ifnet *ifp)
{
+ struct epoch_tracker et;
struct ifaddr *ifa, *best;
if (af >= AF_MAX)
return (NULL);
best = NULL;
- IF_ADDR_RLOCK(ifp);
+ NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family == af &&
(best == NULL || ifa_preferred(best, ifa)))
best = ifa;
}
- IF_ADDR_RUNLOCK(ifp);
+ NET_EPOCH_EXIT(et);
if (best != NULL)
ifa_ref(best);
return (best);
@@ -1169,10 +1171,11 @@ carp_send_na(struct carp_softc *sc)
struct ifaddr *
carp_iamatch6(struct ifnet *ifp, struct in6_addr *taddr)
{
+ struct epoch_tracker et;
struct ifaddr *ifa;
ifa = NULL;
- IF_ADDR_RLOCK(ifp);
+ NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
@@ -1184,7 +1187,7 @@ carp_iamatch6(struct ifnet *ifp, struct in6_addr *taddr)
ifa_ref(ifa);
break;
}
- IF_ADDR_RUNLOCK(ifp);
+ NET_EPOCH_EXIT(et);
return (ifa);
}
@@ -1192,16 +1195,17 @@ carp_iamatch6(struct ifnet *ifp, struct in6_addr *taddr)
caddr_t
carp_macmatch6(struct ifnet *ifp, struct mbuf *m, const struct in6_addr *taddr)
{
+ struct epoch_tracker et;
struct ifaddr *ifa;
- IF_ADDR_RLOCK(ifp);
+ NET_EPOCH_ENTER(et);
IFNET_FOREACH_IFA(ifp, ifa)
if (ifa->ifa_addr->sa_family == AF_INET6 &&
IN6_ARE_ADDR_EQUAL(taddr, IFA_IN6(ifa))) {
struct carp_softc *sc = ifa->ifa_carp;
struct m_tag *mtag;
- IF_ADDR_RUNLOCK(ifp);
+ NET_EPOCH_EXIT(et);
mtag = m_tag_get(PACKET_TAG_CARP,
sizeof(struct carp_softc *), M_NOWAIT);
@@ -1214,7 +1218,7 @@ carp_macmatch6(struct ifnet *ifp, struct mbuf *m, const struct in6_addr *taddr)
return (LLADDR(&sc->sc_addr));
}
- IF_ADDR_RUNLOCK(ifp);
+ NET_EPOCH_EXIT(et);
return (NULL);
}
@@ -1369,25 +1373,24 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
case AF_INET:
{
struct ip_moptions *imo = &cif->cif_imo;
+ struct in_mfilter *imf;
struct in_addr addr;
- if (imo->imo_membership)
+ if (ip_mfilter_first(&imo->imo_head) != NULL)
return (0);
- imo->imo_membership = (struct in_multi **)malloc(
- (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_CARP,
- M_WAITOK);
- imo->imo_mfilters = NULL;
- imo->imo_max_memberships = IP_MIN_MEMBERSHIPS;
+ imf = ip_mfilter_alloc(M_WAITOK, 0, 0);
+ ip_mfilter_init(&imo->imo_head);
imo->imo_multicast_vif = -1;
addr.s_addr = htonl(INADDR_CARP_GROUP);
if ((error = in_joingroup(ifp, &addr, NULL,
- &imo->imo_membership[0])) != 0) {
- free(imo->imo_membership, M_CARP);
+ &imf->imf_inm)) != 0) {
+ ip_mfilter_free(imf);
break;
}
- imo->imo_num_memberships++;
+
+ ip_mfilter_insert(&imo->imo_head, imf);
imo->imo_multicast_ifp = ifp;
imo->imo_multicast_ttl = CARP_DFLTTL;
imo->imo_multicast_loop = 0;
@@ -1398,17 +1401,16 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
case AF_INET6:
{
struct ip6_moptions *im6o = &cif->cif_im6o;
+ struct in6_mfilter *im6f[2];
struct in6_addr in6;
- struct in6_multi *in6m;
- if (im6o->im6o_membership)
+ if (ip6_mfilter_first(&im6o->im6o_head))
return (0);
- im6o->im6o_membership = (struct in6_multi **)malloc(
- (sizeof(struct in6_multi *) * IPV6_MIN_MEMBERSHIPS), M_CARP,
- M_ZERO | M_WAITOK);
- im6o->im6o_mfilters = NULL;
- im6o->im6o_max_memberships = IPV6_MIN_MEMBERSHIPS;
+ im6f[0] = ip6_mfilter_alloc(M_WAITOK, 0, 0);
+ im6f[1] = ip6_mfilter_alloc(M_WAITOK, 0, 0);
+
+ ip6_mfilter_init(&im6o->im6o_head);
im6o->im6o_multicast_hlim = CARP_DFLTTL;
im6o->im6o_multicast_ifp = ifp;
@@ -1417,17 +1419,15 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
in6.s6_addr16[0] = htons(0xff02);
in6.s6_addr8[15] = 0x12;
if ((error = in6_setscope(&in6, ifp, NULL)) != 0) {
- free(im6o->im6o_membership, M_CARP);
+ ip6_mfilter_free(im6f[0]);
+ ip6_mfilter_free(im6f[1]);
break;
}
- in6m = NULL;
- if ((error = in6_joingroup(ifp, &in6, NULL, &in6m, 0)) != 0) {
- free(im6o->im6o_membership, M_CARP);
+ if ((error = in6_joingroup(ifp, &in6, NULL, &im6f[0]->im6f_in6m, 0)) != 0) {
+ ip6_mfilter_free(im6f[0]);
+ ip6_mfilter_free(im6f[1]);
break;
}
- in6m_acquire(in6m);
- im6o->im6o_membership[0] = in6m;
- im6o->im6o_num_memberships++;
/* Join solicited multicast address. */
bzero(&in6, sizeof(in6));
@@ -1436,20 +1436,21 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
in6.s6_addr32[2] = htonl(1);
in6.s6_addr32[3] = 0;
in6.s6_addr8[12] = 0xff;
+
if ((error = in6_setscope(&in6, ifp, NULL)) != 0) {
- in6_leavegroup(im6o->im6o_membership[0], NULL);
- free(im6o->im6o_membership, M_CARP);
+ ip6_mfilter_free(im6f[0]);
+ ip6_mfilter_free(im6f[1]);
break;
}
- in6m = NULL;
- if ((error = in6_joingroup(ifp, &in6, NULL, &in6m, 0)) != 0) {
- in6_leavegroup(im6o->im6o_membership[0], NULL);
- free(im6o->im6o_membership, M_CARP);
+
+ if ((error = in6_joingroup(ifp, &in6, NULL, &im6f[1]->im6f_in6m, 0)) != 0) {
+ in6_leavegroup(im6f[0]->im6f_in6m, NULL);
+ ip6_mfilter_free(im6f[0]);
+ ip6_mfilter_free(im6f[1]);
break;
}
- in6m_acquire(in6m);
- im6o->im6o_membership[1] = in6m;
- im6o->im6o_num_memberships++;
+ ip6_mfilter_insert(&im6o->im6o_head, im6f[0]);
+ ip6_mfilter_insert(&im6o->im6o_head, im6f[1]);
break;
}
#endif
@@ -1464,35 +1465,38 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
static void
carp_multicast_cleanup(struct carp_if *cif, sa_family_t sa)
{
-
+#ifdef INET
+ struct ip_moptions *imo = &cif->cif_imo;
+ struct in_mfilter *imf;
+#endif
+#ifdef INET6
+ struct ip6_moptions *im6o = &cif->cif_im6o;
+ struct in6_mfilter *im6f;
+#endif
sx_assert(&carp_sx, SA_XLOCKED);
switch (sa) {
#ifdef INET
case AF_INET:
- if (cif->cif_naddrs == 0) {
- struct ip_moptions *imo = &cif->cif_imo;
-
- in_leavegroup(imo->imo_membership[0], NULL);
- KASSERT(imo->imo_mfilters == NULL,
- ("%s: imo_mfilters != NULL", __func__));
- free(imo->imo_membership, M_CARP);
- imo->imo_membership = NULL;
+ if (cif->cif_naddrs != 0)
+ break;
+ while ((imf = ip_mfilter_first(&imo->imo_head)) != NULL) {
+ ip_mfilter_remove(&imo->imo_head, imf);
+ in_leavegroup(imf->imf_inm, NULL);
+ ip_mfilter_free(imf);
}
break;
#endif
#ifdef INET6
case AF_INET6:
- if (cif->cif_naddrs6 == 0) {
- struct ip6_moptions *im6o = &cif->cif_im6o;
-
- in6_leavegroup(im6o->im6o_membership[0], NULL);
- in6_leavegroup(im6o->im6o_membership[1], NULL);
- KASSERT(im6o->im6o_mfilters == NULL,
- ("%s: im6o_mfilters != NULL", __func__));
- free(im6o->im6o_membership, M_CARP);
- im6o->im6o_membership = NULL;
+ if (cif->cif_naddrs6 != 0)
+ break;
+
+ while ((im6f = ip6_mfilter_first(&im6o->im6o_head)) != NULL) {
+ ip6_mfilter_remove(&im6o->im6o_head, im6f);
+ in6_leavegroup(im6f->im6f_in6m, NULL);
+ ip6_mfilter_free(im6f);
}
break;
#endif
@@ -2178,21 +2182,6 @@ static struct protosw in6_carp_protosw = {
};
#endif
-#ifdef VIMAGE
-#if defined(__i386__)
-/*
- * XXX This is a hack to work around an absolute relocation outside
- * set_vnet by one (on the stop symbol) for carpstats. Add a dummy variable
- * to the end of the file in the hope that the linker will just keep the
- * order (as it seems to do at the moment). It is understood to be fragile.
- * See PR 230857 for a longer discussion of the problem and the referenced
- * review for possible alternate solutions. Each is a hack; we just need
- * the least intrusive one for the next release.
- */
-VNET_DEFINE(char, carp_zzz) = 0xde;
-#endif
-#endif
-
static void
carp_mod_cleanup(void)
{