summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Thomas McBride <mcbride@cvs.openbsd.org>2004-05-08 02:53:04 +0000
committerRyan Thomas McBride <mcbride@cvs.openbsd.org>2004-05-08 02:53:04 +0000
commitc8561b5c4f91aeb363d01182215a54da48f8adfa (patch)
tree5522721cdfba0ff651f70fc129c291eff0ce77eb
parent97ea8f0a797a731e94768a4f2d6e4809ed88ea83 (diff)
If a carp interface has more than CARP_SENDAD_MAX_ERRORS failed
advertisements in a row, back off all the other interfaces, until CARP_SENDAD_MIN_SUCCESS advertisements are successful. This makes carp deal better with ip output errors.
-rw-r--r--sys/netinet/ip_carp.c42
1 files changed, 39 insertions, 3 deletions
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index f9806c00a3f..260913a3876 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_carp.c,v 1.45 2004/04/28 00:28:43 mcbride Exp $ */
+/* $OpenBSD: ip_carp.c,v 1.46 2004/05/08 02:53:03 mcbride Exp $ */
/*
* Copyright (c) 2002 Michael Shalayeff. All rights reserved.
@@ -108,6 +108,12 @@ struct carp_softc {
int sc_flags_backup;
int sc_suppress;
+
+ int sc_sendad_errors;
+#define CARP_SENDAD_MAX_ERRORS 3
+ int sc_sendad_success;
+#define CARP_SENDAD_MIN_SUCCESS 3
+
int sc_vhid;
int sc_advskew;
int sc_naddrs;
@@ -791,8 +797,23 @@ carp_send_ad(void *v)
sc->sc_ac.ac_if.if_obytes += len;
carpstats.carps_opackets++;
- if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL))
+ if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL)) {
sc->sc_ac.ac_if.if_oerrors++;
+ if (sc->sc_sendad_errors < INT_MAX)
+ sc->sc_sendad_errors++;
+ if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS)
+ carp_suppress_preempt++;
+ sc->sc_sendad_success = 0;
+ } else {
+ if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS) {
+ if (++sc->sc_sendad_success >=
+ CARP_SENDAD_MIN_SUCCESS) {
+ carp_suppress_preempt--;
+ sc->sc_sendad_errors = 0;
+ }
+ } else
+ sc->sc_sendad_errors = 0;
+ }
}
#endif /* INET */
#ifdef INET6
@@ -841,8 +862,23 @@ carp_send_ad(void *v)
sc->sc_ac.ac_if.if_obytes += len;
carpstats.carps_opackets6++;
- if (ip6_output(m, NULL, NULL, 0, &sc->sc_im6o, NULL))
+ if (ip6_output(m, NULL, NULL, 0, &sc->sc_im6o, NULL)) {
sc->sc_ac.ac_if.if_oerrors++;
+ if (sc->sc_sendad_errors < INT_MAX)
+ sc->sc_sendad_errors++;
+ if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS)
+ carp_suppress_preempt++;
+ sc->sc_sendad_success = 0;
+ } else {
+ if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS) {
+ if (++sc->sc_sendad_success >=
+ CARP_SENDAD_MIN_SUCCESS) {
+ carp_suppress_preempt--;
+ sc->sc_sendad_errors = 0;
+ }
+ } else
+ sc->sc_sendad_errors = 0;
+ }
}
#endif /* INET6 */