Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/ip_carp.c
Show First 20 Lines • Show All 206 Lines • ▼ Show 20 Lines | |||||
/* Send error demotion factor. */ | /* Send error demotion factor. */ | ||||
static VNET_DEFINE(int, carp_senderr_adj) = CARP_MAXSKEW; | static VNET_DEFINE(int, carp_senderr_adj) = CARP_MAXSKEW; | ||||
#define V_carp_senderr_adj VNET(carp_senderr_adj) | #define V_carp_senderr_adj VNET(carp_senderr_adj) | ||||
/* Iface down demotion factor. */ | /* Iface down demotion factor. */ | ||||
static VNET_DEFINE(int, carp_ifdown_adj) = CARP_MAXSKEW; | static VNET_DEFINE(int, carp_ifdown_adj) = CARP_MAXSKEW; | ||||
#define V_carp_ifdown_adj VNET(carp_ifdown_adj) | #define V_carp_ifdown_adj VNET(carp_ifdown_adj) | ||||
static int carp_allow_sysctl(SYSCTL_HANDLER_ARGS); | |||||
static int carp_demote_adj_sysctl(SYSCTL_HANDLER_ARGS); | static int carp_demote_adj_sysctl(SYSCTL_HANDLER_ARGS); | ||||
SYSCTL_NODE(_net_inet, IPPROTO_CARP, carp, CTLFLAG_RW, 0, "CARP"); | SYSCTL_NODE(_net_inet, IPPROTO_CARP, carp, CTLFLAG_RW, 0, "CARP"); | ||||
SYSCTL_INT(_net_inet_carp, OID_AUTO, allow, CTLFLAG_VNET | CTLFLAG_RW, | SYSCTL_PROC(_net_inet_carp, OID_AUTO, allow, | ||||
&VNET_NAME(carp_allow), 0, "Accept incoming CARP packets"); | CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW, 0, 0, carp_allow_sysctl, "I", | ||||
"Accept incoming CARP packets"); | |||||
SYSCTL_INT(_net_inet_carp, OID_AUTO, preempt, CTLFLAG_VNET | CTLFLAG_RW, | SYSCTL_INT(_net_inet_carp, OID_AUTO, preempt, CTLFLAG_VNET | CTLFLAG_RW, | ||||
&VNET_NAME(carp_preempt), 0, "High-priority backup preemption mode"); | &VNET_NAME(carp_preempt), 0, "High-priority backup preemption mode"); | ||||
SYSCTL_INT(_net_inet_carp, OID_AUTO, log, CTLFLAG_VNET | CTLFLAG_RW, | SYSCTL_INT(_net_inet_carp, OID_AUTO, log, CTLFLAG_VNET | CTLFLAG_RW, | ||||
&VNET_NAME(carp_log), 0, "CARP log level"); | &VNET_NAME(carp_log), 0, "CARP log level"); | ||||
SYSCTL_PROC(_net_inet_carp, OID_AUTO, demotion, | SYSCTL_PROC(_net_inet_carp, OID_AUTO, demotion, | ||||
CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW, | CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW, | ||||
0, 0, carp_demote_adj_sysctl, "I", | 0, 0, carp_demote_adj_sysctl, "I", | ||||
"Adjust demotion factor (skew of advskew)"); | "Adjust demotion factor (skew of advskew)"); | ||||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | |||||
static void carp_master_down_locked(struct carp_softc *, | static void carp_master_down_locked(struct carp_softc *, | ||||
const char* reason); | const char* reason); | ||||
static void carp_send_ad(void *); | static void carp_send_ad(void *); | ||||
static void carp_send_ad_locked(struct carp_softc *); | static void carp_send_ad_locked(struct carp_softc *); | ||||
static void carp_addroute(struct carp_softc *); | static void carp_addroute(struct carp_softc *); | ||||
static void carp_ifa_addroute(struct ifaddr *); | static void carp_ifa_addroute(struct ifaddr *); | ||||
static void carp_delroute(struct carp_softc *); | static void carp_delroute(struct carp_softc *); | ||||
static void carp_ifa_delroute(struct ifaddr *); | static void carp_ifa_delroute(struct ifaddr *); | ||||
static void carp_reset(void *, int); | |||||
static void carp_send_ad_all(void *, int); | static void carp_send_ad_all(void *, int); | ||||
static void carp_demote_adj(int, char *); | static void carp_demote_adj(int, char *); | ||||
static LIST_HEAD(, carp_softc) carp_list; | static LIST_HEAD(, carp_softc) carp_list; | ||||
static struct mtx carp_mtx; | static struct mtx carp_mtx; | ||||
static struct sx carp_sx; | static struct sx carp_sx; | ||||
static struct task carp_reset_task = | |||||
TASK_INITIALIZER(0, carp_reset, NULL); | |||||
static struct task carp_sendall_task = | static struct task carp_sendall_task = | ||||
TASK_INITIALIZER(0, carp_send_ad_all, NULL); | TASK_INITIALIZER(0, carp_send_ad_all, NULL); | ||||
static void | static void | ||||
carp_hmac_prepare(struct carp_softc *sc) | carp_hmac_prepare(struct carp_softc *sc) | ||||
{ | { | ||||
uint8_t version = CARP_VERSION, type = CARP_ADVERTISEMENT; | uint8_t version = CARP_VERSION, type = CARP_ADVERTISEMENT; | ||||
uint8_t vhid = sc->sc_vhid & 0xff; | uint8_t vhid = sc->sc_vhid & 0xff; | ||||
▲ Show 20 Lines • Show All 464 Lines • ▼ Show 20 Lines | carp_prepare_ad(struct mbuf *m, struct carp_softc *sc, struct carp_header *ch) | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* To avoid LORs and possible recursions this function shouldn't | * To avoid LORs and possible recursions this function shouldn't | ||||
* be called directly, but scheduled via taskqueue. | * be called directly, but scheduled via taskqueue. | ||||
*/ | */ | ||||
static void | static void | ||||
carp_reset(void *ctx __unused, int pending __unused) | |||||
{ | |||||
struct carp_softc *sc; | |||||
sx_xlock(&carp_sx); | |||||
mtx_lock(&carp_mtx); | |||||
LIST_FOREACH(sc, &carp_list, sc_next) { | |||||
CARP_LOCK(sc); | |||||
CURVNET_SET(sc->sc_carpdev->if_vnet); | |||||
if ((V_carp_allow == 0) != (sc->sc_state == INIT)) | |||||
carp_sc_state(sc); | |||||
CURVNET_RESTORE(); | |||||
CARP_UNLOCK(sc); | |||||
} | |||||
mtx_unlock(&carp_mtx); | |||||
sx_xunlock(&carp_sx); | |||||
} | |||||
/* | |||||
* To avoid LORs and possible recursions this function shouldn't | |||||
* be called directly, but scheduled via taskqueue. | |||||
*/ | |||||
static void | |||||
carp_send_ad_all(void *ctx __unused, int pending __unused) | carp_send_ad_all(void *ctx __unused, int pending __unused) | ||||
{ | { | ||||
struct carp_softc *sc; | struct carp_softc *sc; | ||||
mtx_lock(&carp_mtx); | mtx_lock(&carp_mtx); | ||||
LIST_FOREACH(sc, &carp_list, sc_next) | LIST_FOREACH(sc, &carp_list, sc_next) | ||||
if (sc->sc_state == MASTER) { | if (sc->sc_state == MASTER) { | ||||
CARP_LOCK(sc); | CARP_LOCK(sc); | ||||
▲ Show 20 Lines • Show All 476 Lines • ▼ Show 20 Lines | |||||
carp_setrun(struct carp_softc *sc, sa_family_t af) | carp_setrun(struct carp_softc *sc, sa_family_t af) | ||||
{ | { | ||||
struct timeval tv; | struct timeval tv; | ||||
CARP_LOCK_ASSERT(sc); | CARP_LOCK_ASSERT(sc); | ||||
if ((sc->sc_carpdev->if_flags & IFF_UP) == 0 || | if ((sc->sc_carpdev->if_flags & IFF_UP) == 0 || | ||||
sc->sc_carpdev->if_link_state != LINK_STATE_UP || | sc->sc_carpdev->if_link_state != LINK_STATE_UP || | ||||
(sc->sc_naddrs == 0 && sc->sc_naddrs6 == 0)) | (sc->sc_naddrs == 0 && sc->sc_naddrs6 == 0) || | ||||
!V_carp_allow) | |||||
return; | return; | ||||
switch (sc->sc_state) { | switch (sc->sc_state) { | ||||
case INIT: | case INIT: | ||||
carp_set_state(sc, BACKUP, "initialization complete"); | carp_set_state(sc, BACKUP, "initialization complete"); | ||||
carp_setrun(sc, 0); | carp_setrun(sc, 0); | ||||
break; | break; | ||||
case BACKUP: | case BACKUP: | ||||
▲ Show 20 Lines • Show All 756 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
carp_sc_state(struct carp_softc *sc) | carp_sc_state(struct carp_softc *sc) | ||||
{ | { | ||||
CARP_LOCK_ASSERT(sc); | CARP_LOCK_ASSERT(sc); | ||||
if (sc->sc_carpdev->if_link_state != LINK_STATE_UP || | if (sc->sc_carpdev->if_link_state != LINK_STATE_UP || | ||||
!(sc->sc_carpdev->if_flags & IFF_UP)) { | !(sc->sc_carpdev->if_flags & IFF_UP) || | ||||
!V_carp_allow) { | |||||
callout_stop(&sc->sc_ad_tmo); | callout_stop(&sc->sc_ad_tmo); | ||||
#ifdef INET | #ifdef INET | ||||
callout_stop(&sc->sc_md_tmo); | callout_stop(&sc->sc_md_tmo); | ||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
callout_stop(&sc->sc_md6_tmo); | callout_stop(&sc->sc_md6_tmo); | ||||
#endif | #endif | ||||
carp_set_state(sc, INIT, "hardware interface down"); | carp_set_state(sc, INIT, "hardware interface down"); | ||||
Show All 14 Lines | |||||
carp_demote_adj(int adj, char *reason) | carp_demote_adj(int adj, char *reason) | ||||
{ | { | ||||
atomic_add_int(&V_carp_demotion, adj); | atomic_add_int(&V_carp_demotion, adj); | ||||
CARP_LOG("demoted by %d to %d (%s)\n", adj, V_carp_demotion, reason); | CARP_LOG("demoted by %d to %d (%s)\n", adj, V_carp_demotion, reason); | ||||
taskqueue_enqueue(taskqueue_swi, &carp_sendall_task); | taskqueue_enqueue(taskqueue_swi, &carp_sendall_task); | ||||
} | } | ||||
static int | static int | ||||
carp_allow_sysctl(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
int new, error; | |||||
new = V_carp_allow; | |||||
error = sysctl_handle_int(oidp, &new, 0, req); | |||||
if (error || !req->newptr) | |||||
return (error); | |||||
if(V_carp_allow != new) { | |||||
V_carp_allow = new; | |||||
taskqueue_enqueue(taskqueue_swi, &carp_reset_task); | |||||
} | |||||
return (0); | |||||
} | |||||
static int | |||||
carp_demote_adj_sysctl(SYSCTL_HANDLER_ARGS) | carp_demote_adj_sysctl(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
int new, error; | int new, error; | ||||
new = V_carp_demotion; | new = V_carp_demotion; | ||||
error = sysctl_handle_int(oidp, &new, 0, req); | error = sysctl_handle_int(oidp, &new, 0, req); | ||||
if (error || !req->newptr) | if (error || !req->newptr) | ||||
return (error); | return (error); | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | #endif | ||||
carp_detach_p = NULL; | carp_detach_p = NULL; | ||||
carp_get_vhid_p = NULL; | carp_get_vhid_p = NULL; | ||||
carp_linkstate_p = NULL; | carp_linkstate_p = NULL; | ||||
carp_forus_p = NULL; | carp_forus_p = NULL; | ||||
carp_output_p = NULL; | carp_output_p = NULL; | ||||
carp_demote_adj_p = NULL; | carp_demote_adj_p = NULL; | ||||
carp_master_p = NULL; | carp_master_p = NULL; | ||||
mtx_unlock(&carp_mtx); | mtx_unlock(&carp_mtx); | ||||
taskqueue_drain(taskqueue_swi, &carp_reset_task); | |||||
taskqueue_drain(taskqueue_swi, &carp_sendall_task); | taskqueue_drain(taskqueue_swi, &carp_sendall_task); | ||||
mtx_destroy(&carp_mtx); | mtx_destroy(&carp_mtx); | ||||
sx_destroy(&carp_sx); | sx_destroy(&carp_sx); | ||||
} | } | ||||
static int | static int | ||||
carp_mod_load(void) | carp_mod_load(void) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 82 Lines • Show Last 20 Lines |