Download raw body.
carp(4): replace vhosts SRPL with an SMR_SLIST
this is pretty mechanical, and appears to work.
the biggest difference between the SRP and SMR code is the smr_barrier
in carp_destroy_vhosts. the list pointer stuff in carp_new_vhost is a
bit different too.
tests? ok?
Index: ip_carp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_carp.c,v
diff -u -p -r1.370 ip_carp.c
--- ip_carp.c 8 Jul 2025 00:47:41 -0000 1.370
+++ ip_carp.c 25 Aug 2025 00:07:18 -0000
@@ -43,6 +43,7 @@
#include <sys/errno.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
+#include <sys/smr.h>
#include <sys/refcnt.h>
#include <net/if.h>
@@ -92,8 +93,7 @@ struct carp_mc_entry {
enum { HMAC_ORIG=0, HMAC_NOV6LL=1, HMAC_MAX=2 };
struct carp_vhost_entry {
- SRPL_ENTRY(carp_vhost_entry) vhost_entries;
- struct refcnt vhost_refcnt;
+ SMR_SLIST_ENTRY(carp_vhost_entry) vhost_entries;
struct carp_softc *parent_sc;
int vhe_leader;
@@ -114,12 +114,6 @@ struct carp_vhost_entry {
u_int8_t vhe_enaddr[ETHER_ADDR_LEN];
};
-void carp_vh_ref(void *, void *);
-void carp_vh_unref(void *, void *);
-
-struct srpl_rc carp_vh_rc =
- SRPL_RC_INITIALIZER(carp_vh_ref, carp_vh_unref, NULL);
-
struct carp_softc {
struct arpcom sc_ac;
#define sc_if sc_ac.ac_if
@@ -147,7 +141,7 @@ struct carp_softc {
char sc_curlladdr[ETHER_ADDR_LEN];
- SRPL_HEAD(, carp_vhost_entry) carp_vhosts;
+ SMR_SLIST_HEAD(, carp_vhost_entry) carp_vhosts;
int sc_vhe_count;
u_int8_t sc_vhids[CARP_MAXNODES];
u_int8_t sc_advskews[CARP_MAXNODES];
@@ -283,7 +277,7 @@ carp_hmac_prepare(struct carp_softc *sc)
KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */
- SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
+ SMR_SLIST_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
for (i = 0; i < HMAC_MAX; i++) {
carp_hmac_prepare_ctx(vhe, i);
}
@@ -632,7 +626,7 @@ carp_proto_input_c(struct ifnet *ifp, st
if (af == AF_INET &&
ismulti != IN_MULTICAST(sc->sc_peer.s_addr))
continue;
- SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
+ SMR_SLIST_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
if (vhe->vhid == ch->carp_vhid)
goto found;
}
@@ -802,7 +796,7 @@ carp_clone_create(struct if_clone *ifc,
sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
refcnt_init(&sc->sc_refcnt);
- SRPL_INIT(&sc->carp_vhosts);
+ SMR_SLIST_INIT(&sc->carp_vhosts);
sc->sc_vhe_count = 0;
if (carp_new_vhost(sc, 0, 0)) {
free(sc, M_DEVBUF, sizeof(*sc));
@@ -857,13 +851,12 @@ carp_clone_create(struct if_clone *ifc,
int
carp_new_vhost(struct carp_softc *sc, int vhid, int advskew)
{
- struct carp_vhost_entry *vhe, *vhe0;
+ struct carp_vhost_entry *vhe, *vhe0, *nvhe;
vhe = malloc(sizeof(*vhe), M_DEVBUF, M_NOWAIT | M_ZERO);
if (vhe == NULL)
return (ENOMEM);
- refcnt_init(&vhe->vhost_refcnt);
carp_sc_ref(NULL, sc); /* give a sc ref to the vhe */
vhe->parent_sc = sc;
vhe->vhid = vhid;
@@ -876,20 +869,19 @@ carp_new_vhost(struct carp_softc *sc, in
KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */
/* mark the first vhe as leader */
- if (SRPL_EMPTY_LOCKED(&sc->carp_vhosts)) {
+ vhe0 = SMR_SLIST_FIRST_LOCKED(&sc->carp_vhosts);
+ if (vhe0 == NULL) {
vhe->vhe_leader = 1;
- SRPL_INSERT_HEAD_LOCKED(&carp_vh_rc, &sc->carp_vhosts,
+ SMR_SLIST_INSERT_HEAD_LOCKED(&sc->carp_vhosts,
vhe, vhost_entries);
sc->sc_vhe_count = 1;
return (0);
}
- SRPL_FOREACH_LOCKED(vhe0, &sc->carp_vhosts, vhost_entries) {
- if (SRPL_NEXT_LOCKED(vhe0, vhost_entries) == NULL)
- break;
- }
+ while ((nvhe = SMR_SLIST_NEXT_LOCKED(vhe0, vhost_entries)) != NULL)
+ vhe0 = nvhe;
- SRPL_INSERT_AFTER_LOCKED(&carp_vh_rc, vhe0, vhe, vhost_entries);
+ SMR_SLIST_INSERT_AFTER_LOCKED(vhe0, vhe, vhost_entries);
sc->sc_vhe_count++;
return (0);
@@ -925,7 +917,7 @@ carp_del_all_timeouts(struct carp_softc
struct carp_vhost_entry *vhe;
KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */
- SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
+ SMR_SLIST_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
timeout_del(&vhe->ad_tmo);
timeout_del(&vhe->md_tmo);
timeout_del(&vhe->md6_tmo);
@@ -972,16 +964,20 @@ void
carp_destroy_vhosts(struct carp_softc *sc)
{
/* XXX bow out? */
- struct carp_vhost_entry *vhe;
+ struct carp_vhost_entry *vhe, *nvhe;
KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */
+ nvhe = SMR_SLIST_FIRST_LOCKED(&sc->carp_vhosts);
+ SMR_SLIST_INIT(&sc->carp_vhosts);
+ sc->sc_vhe_count = 0;
+
+ smr_barrier();
- while ((vhe = SRPL_FIRST_LOCKED(&sc->carp_vhosts)) != NULL) {
- SRPL_REMOVE_LOCKED(&carp_vh_rc, &sc->carp_vhosts, vhe,
- carp_vhost_entry, vhost_entries);
- carp_vh_unref(NULL, vhe); /* drop last ref */
+ while ((vhe = nvhe) != NULL) {
+ nvhe = SMR_SLIST_NEXT_LOCKED(vhe, vhost_entries);
+ carp_sc_unref(NULL, vhe->parent_sc);
+ free(vhe, M_DEVBUF, sizeof(*vhe));
}
- sc->sc_vhe_count = 0;
}
void
@@ -1036,8 +1032,7 @@ carp_vhe_send_ad_all(struct carp_softc *
struct carp_vhost_entry *vhe;
KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */
-
- SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
+ SMR_SLIST_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
if (vhe->state == MASTER)
carp_send_ad(vhe);
}
@@ -1326,7 +1321,7 @@ carp_update_lsmask(struct carp_softc *sc
count = 0;
KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */
- SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
+ SMR_SLIST_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
if (vhe->state == MASTER && count < sizeof(sc->sc_lsmask) * 8)
sc->sc_lsmask |= 1 << count;
count++;
@@ -1340,13 +1335,13 @@ carp_iamatch(struct ifnet *ifp)
{
struct carp_softc *sc = ifp->if_softc;
struct carp_vhost_entry *vhe;
- struct srp_ref sr;
int match = 0;
- vhe = SRPL_FIRST(&sr, &sc->carp_vhosts);
+ smr_read_enter();
+ vhe = SMR_SLIST_FIRST(&sc->carp_vhosts);
if (vhe->state == MASTER)
match = 1;
- SRPL_LEAVE(&sr);
+ smr_read_leave();
return (match);
}
@@ -1380,12 +1375,12 @@ int
carp_vhe_match(struct carp_softc *sc, uint64_t dst)
{
struct carp_vhost_entry *vhe;
- struct srp_ref sr;
int active = 0;
- vhe = SRPL_FIRST(&sr, &sc->carp_vhosts);
+ smr_read_enter();
+ vhe = SMR_SLIST_FIRST(&sc->carp_vhosts);
active = (vhe->state == MASTER || sc->sc_balancing >= CARP_BAL_IP);
- SRPL_LEAVE(&sr);
+ smr_read_leave();
return (active && (dst ==
ether_addr_to_e64((struct ether_addr *)sc->sc_ac.ac_enaddr)));
@@ -1560,7 +1555,7 @@ carp_setrun_all(struct carp_softc *sc, s
struct carp_vhost_entry *vhe;
KERNEL_ASSERT_LOCKED(); /* touching carp_vhost */
- SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
+ SMR_SLIST_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
carp_setrun(vhe, af);
}
}
@@ -1711,8 +1706,8 @@ carp_set_ifp(struct carp_softc *sc, stru
if (vr == sc)
myself = 1;
- vrhead = SRPL_FIRST_LOCKED(&vr->carp_vhosts);
- schead = SRPL_FIRST_LOCKED(&sc->carp_vhosts);
+ vrhead = SMR_SLIST_FIRST_LOCKED(&vr->carp_vhosts);
+ schead = SMR_SLIST_FIRST_LOCKED(&sc->carp_vhosts);
if (vrhead->vhid < schead->vhid)
after = vr;
}
@@ -1764,10 +1759,10 @@ carp_set_enaddr(struct carp_softc *sc)
struct carp_vhost_entry *vhe;
KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */
- SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries)
+ SMR_SLIST_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries)
carp_set_vhe_enaddr(vhe);
- vhe = SRPL_FIRST_LOCKED(&sc->carp_vhosts);
+ vhe = SMR_SLIST_FIRST_LOCKED(&sc->carp_vhosts);
/*
* Use the carp lladdr if the running one isn't manually set.
@@ -2008,7 +2003,7 @@ carp_ioctl(struct ifnet *ifp, u_long cmd
case SIOCSIFFLAGS:
KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */
- vhe = SRPL_FIRST_LOCKED(&sc->carp_vhosts);
+ vhe = SMR_SLIST_FIRST_LOCKED(&sc->carp_vhosts);
if (vhe->state != INIT && !(ifr->ifr_flags & IFF_UP)) {
carp_del_all_timeouts(sc);
@@ -2036,7 +2031,7 @@ carp_ioctl(struct ifnet *ifp, u_long cmd
case SIOCSVH:
KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */
- vhe = SRPL_FIRST_LOCKED(&sc->carp_vhosts);
+ vhe = SMR_SLIST_FIRST_LOCKED(&sc->carp_vhosts);
if ((error = suser(p)) != 0)
break;
if ((error = copyin(ifr->ifr_data, &carpr, sizeof carpr)))
@@ -2066,7 +2061,7 @@ carp_ioctl(struct ifnet *ifp, u_long cmd
case MASTER:
KERNEL_ASSERT_LOCKED();
/* touching carp_vhosts */
- SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts,
+ SMR_SLIST_FOREACH_LOCKED(vhe, &sc->carp_vhosts,
vhost_entries)
carp_master_down(vhe);
break;
@@ -2088,7 +2083,7 @@ carp_ioctl(struct ifnet *ifp, u_long cmd
sizeof(sc->sc_advskews))) {
i = 0;
KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */
- SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts,
+ SMR_SLIST_FOREACH_LOCKED(vhe, &sc->carp_vhosts,
vhost_entries)
vhe->advskew = carpr.carpr_advskews[i++];
bcopy(carpr.carpr_advskews, sc->sc_advskews,
@@ -2120,7 +2115,7 @@ carp_ioctl(struct ifnet *ifp, u_long cmd
if_put(ifp0);
i = 0;
KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */
- SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
+ SMR_SLIST_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
carpr.carpr_vhids[i] = vhe->vhid;
carpr.carpr_advskews[i] = vhe->advskew;
carpr.carpr_states[i] = vhe->state;
@@ -2172,14 +2167,15 @@ carp_check_dup_vhids(struct carp_softc *
SRPL_FOREACH_LOCKED(vr, cif, sc_list) {
if (vr == sc)
continue;
- SRPL_FOREACH_LOCKED(vhe, &vr->carp_vhosts, vhost_entries) {
+ SMR_SLIST_FOREACH_LOCKED(vhe, &vr->carp_vhosts,
+ vhost_entries) {
if (carpr) {
for (i = 0; carpr->carpr_vhids[i]; i++) {
if (vhe->vhid == carpr->carpr_vhids[i])
return (EINVAL);
}
}
- SRPL_FOREACH_LOCKED(vhe0, &sc->carp_vhosts,
+ SMR_SLIST_FOREACH_LOCKED(vhe0, &sc->carp_vhosts,
vhost_entries) {
if (vhe->vhid == vhe0->vhid)
return (EINVAL);
@@ -2365,13 +2361,13 @@ carp_output(struct ifnet *ifp, struct mb
{
struct carp_softc *sc = ((struct carp_softc *)ifp->if_softc);
struct carp_vhost_entry *vhe;
- struct srp_ref sr;
int ismaster;
if (sc->cur_vhe == NULL) {
- vhe = SRPL_FIRST(&sr, &sc->carp_vhosts);
+ smr_read_enter();
+ vhe = SMR_SLIST_FIRST(&sc->carp_vhosts);
ismaster = (vhe->state == MASTER);
- SRPL_LEAVE(&sr);
+ smr_read_leave();
} else {
ismaster = (sc->cur_vhe->state == MASTER);
}
@@ -2390,8 +2386,7 @@ carp_set_state_all(struct carp_softc *sc
struct carp_vhost_entry *vhe;
KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */
-
- SRPL_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
+ SMR_SLIST_FOREACH_LOCKED(vhe, &sc->carp_vhosts, vhost_entries) {
if (vhe->state == state)
continue;
@@ -2429,7 +2424,7 @@ carp_set_state(struct carp_vhost_entry *
KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */
sc->sc_if.if_link_state = LINK_STATE_INVALID;
- SRPL_FOREACH_LOCKED(vhe0, &sc->carp_vhosts, vhost_entries) {
+ SMR_SLIST_FOREACH_LOCKED(vhe0, &sc->carp_vhosts, vhost_entries) {
/*
* Link must be up if at least one vhe is in state MASTER to
* bring or keep route up.
@@ -2663,25 +2658,6 @@ carp_ether_purgemulti(struct carp_softc
}
if_put(ifp0);
-}
-
-void
-carp_vh_ref(void *null, void *v)
-{
- struct carp_vhost_entry *vhe = v;
-
- refcnt_take(&vhe->vhost_refcnt);
-}
-
-void
-carp_vh_unref(void *null, void *v)
-{
- struct carp_vhost_entry *vhe = v;
-
- if (refcnt_rele(&vhe->vhost_refcnt)) {
- carp_sc_unref(NULL, vhe->parent_sc);
- free(vhe, M_DEVBUF, sizeof(*vhe));
- }
}
void
carp(4): replace vhosts SRPL with an SMR_SLIST