| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ip_carp.c,v 1.36 2009/05/12 22:01:20 elad Exp $ */ | | 1 | /* $NetBSD: ip_carp.c,v 1.37 2009/05/27 21:32:31 christos Exp $ */ |
2 | /* $OpenBSD: ip_carp.c,v 1.113 2005/11/04 08:11:54 mcbride Exp $ */ | | 2 | /* $OpenBSD: ip_carp.c,v 1.113 2005/11/04 08:11:54 mcbride Exp $ */ |
3 | | | 3 | |
4 | /* | | 4 | /* |
5 | * Copyright (c) 2002 Michael Shalayeff. All rights reserved. | | 5 | * Copyright (c) 2002 Michael Shalayeff. All rights reserved. |
6 | * Copyright (c) 2003 Ryan McBride. All rights reserved. | | 6 | * Copyright (c) 2003 Ryan McBride. All rights reserved. |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
| @@ -18,27 +18,27 @@ | | | @@ -18,27 +18,27 @@ |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 | * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, | | 20 | * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, |
21 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | | 21 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | | 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
23 | * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 23 | * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | | 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
25 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | | 25 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
26 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | 26 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
27 | * THE POSSIBILITY OF SUCH DAMAGE. | | 27 | * THE POSSIBILITY OF SUCH DAMAGE. |
28 | */ | | 28 | */ |
29 | | | 29 | |
30 | #include <sys/cdefs.h> | | 30 | #include <sys/cdefs.h> |
31 | __KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.36 2009/05/12 22:01:20 elad Exp $"); | | 31 | __KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.37 2009/05/27 21:32:31 christos Exp $"); |
32 | | | 32 | |
33 | /* | | 33 | /* |
34 | * TODO: | | 34 | * TODO: |
35 | * - iface reconfigure | | 35 | * - iface reconfigure |
36 | * - support for hardware checksum calculations; | | 36 | * - support for hardware checksum calculations; |
37 | * | | 37 | * |
38 | */ | | 38 | */ |
39 | | | 39 | |
40 | #include <sys/param.h> | | 40 | #include <sys/param.h> |
41 | #include <sys/proc.h> | | 41 | #include <sys/proc.h> |
42 | #include <sys/mbuf.h> | | 42 | #include <sys/mbuf.h> |
43 | #include <sys/socket.h> | | 43 | #include <sys/socket.h> |
44 | #include <sys/socketvar.h> | | 44 | #include <sys/socketvar.h> |
| @@ -687,48 +687,51 @@ carp_proto_input_c(struct mbuf *m, struc | | | @@ -687,48 +687,51 @@ carp_proto_input_c(struct mbuf *m, struc |
687 | ch_tv.tv_usec = ch->carp_advskew * 1000000 / 256; | | 687 | ch_tv.tv_usec = ch->carp_advskew * 1000000 / 256; |
688 | | | 688 | |
689 | switch (sc->sc_state) { | | 689 | switch (sc->sc_state) { |
690 | case INIT: | | 690 | case INIT: |
691 | break; | | 691 | break; |
692 | case MASTER: | | 692 | case MASTER: |
693 | /* | | 693 | /* |
694 | * If we receive an advertisement from a backup who's going to | | 694 | * If we receive an advertisement from a backup who's going to |
695 | * be more frequent than us, go into BACKUP state. | | 695 | * be more frequent than us, go into BACKUP state. |
696 | */ | | 696 | */ |
697 | if (timercmp(&sc_tv, &ch_tv, >) || | | 697 | if (timercmp(&sc_tv, &ch_tv, >) || |
698 | timercmp(&sc_tv, &ch_tv, ==)) { | | 698 | timercmp(&sc_tv, &ch_tv, ==)) { |
699 | callout_stop(&sc->sc_ad_tmo); | | 699 | callout_stop(&sc->sc_ad_tmo); |
| | | 700 | CARP_LOG(sc, "MASTER -> BACKUP (more frequent advertisement received)"); |
700 | carp_set_state(sc, BACKUP); | | 701 | carp_set_state(sc, BACKUP); |
701 | carp_setrun(sc, 0); | | 702 | carp_setrun(sc, 0); |
702 | carp_setroute(sc, RTM_DELETE); | | 703 | carp_setroute(sc, RTM_DELETE); |
703 | } | | 704 | } |
704 | break; | | 705 | break; |
705 | case BACKUP: | | 706 | case BACKUP: |
706 | /* | | 707 | /* |
707 | * If we're pre-empting masters who advertise slower than us, | | 708 | * If we're pre-empting masters who advertise slower than us, |
708 | * and this one claims to be slower, treat him as down. | | 709 | * and this one claims to be slower, treat him as down. |
709 | */ | | 710 | */ |
710 | if (carp_opts[CARPCTL_PREEMPT] && timercmp(&sc_tv, &ch_tv, <)) { | | 711 | if (carp_opts[CARPCTL_PREEMPT] && timercmp(&sc_tv, &ch_tv, <)) { |
| | | 712 | CARP_LOG(sc, "BACKUP -> MASTER (preempting a slower master)"); |
711 | carp_master_down(sc); | | 713 | carp_master_down(sc); |
712 | break; | | 714 | break; |
713 | } | | 715 | } |
714 | | | 716 | |
715 | /* | | 717 | /* |
716 | * If the master is going to advertise at such a low frequency | | 718 | * If the master is going to advertise at such a low frequency |
717 | * that he's guaranteed to time out, we'd might as well just | | 719 | * that he's guaranteed to time out, we'd might as well just |
718 | * treat him as timed out now. | | 720 | * treat him as timed out now. |
719 | */ | | 721 | */ |
720 | sc_tv.tv_sec = sc->sc_advbase * 3; | | 722 | sc_tv.tv_sec = sc->sc_advbase * 3; |
721 | if (timercmp(&sc_tv, &ch_tv, <)) { | | 723 | if (timercmp(&sc_tv, &ch_tv, <)) { |
| | | 724 | CARP_LOG(sc, "BACKUP -> MASTER (master timed out)") |
722 | carp_master_down(sc); | | 725 | carp_master_down(sc); |
723 | break; | | 726 | break; |
724 | } | | 727 | } |
725 | | | 728 | |
726 | /* | | 729 | /* |
727 | * Otherwise, we reset the counter and wait for the next | | 730 | * Otherwise, we reset the counter and wait for the next |
728 | * advertisement. | | 731 | * advertisement. |
729 | */ | | 732 | */ |
730 | carp_setrun(sc, af); | | 733 | carp_setrun(sc, af); |
731 | break; | | 734 | break; |
732 | } | | 735 | } |
733 | | | 736 | |
734 | m_freem(m); | | 737 | m_freem(m); |
| @@ -1378,26 +1381,27 @@ carp_input(struct mbuf *m, u_int8_t *sho | | | @@ -1378,26 +1381,27 @@ carp_input(struct mbuf *m, u_int8_t *sho |
1378 | void | | 1381 | void |
1379 | carp_master_down(void *v) | | 1382 | carp_master_down(void *v) |
1380 | { | | 1383 | { |
1381 | struct carp_softc *sc = v; | | 1384 | struct carp_softc *sc = v; |
1382 | | | 1385 | |
1383 | switch (sc->sc_state) { | | 1386 | switch (sc->sc_state) { |
1384 | case INIT: | | 1387 | case INIT: |
1385 | printf("%s: master_down event in INIT state\n", | | 1388 | printf("%s: master_down event in INIT state\n", |
1386 | sc->sc_if.if_xname); | | 1389 | sc->sc_if.if_xname); |
1387 | break; | | 1390 | break; |
1388 | case MASTER: | | 1391 | case MASTER: |
1389 | break; | | 1392 | break; |
1390 | case BACKUP: | | 1393 | case BACKUP: |
| | | 1394 | CARP_LOG(sc, "INIT -> MASTER (preempting)"); |
1391 | carp_set_state(sc, MASTER); | | 1395 | carp_set_state(sc, MASTER); |
1392 | carp_send_ad(sc); | | 1396 | carp_send_ad(sc); |
1393 | carp_send_arp(sc); | | 1397 | carp_send_arp(sc); |
1394 | #ifdef INET6 | | 1398 | #ifdef INET6 |
1395 | carp_send_na(sc); | | 1399 | carp_send_na(sc); |
1396 | #endif /* INET6 */ | | 1400 | #endif /* INET6 */ |
1397 | carp_setrun(sc, 0); | | 1401 | carp_setrun(sc, 0); |
1398 | carp_setroute(sc, RTM_ADD); | | 1402 | carp_setroute(sc, RTM_ADD); |
1399 | break; | | 1403 | break; |
1400 | } | | 1404 | } |
1401 | } | | 1405 | } |
1402 | | | 1406 | |
1403 | /* | | 1407 | /* |
| @@ -2042,29 +2046,32 @@ carp_output(struct ifnet *ifp, struct mb | | | @@ -2042,29 +2046,32 @@ carp_output(struct ifnet *ifp, struct mb |
2042 | struct carp_softc *sc = ((struct carp_softc *)ifp->if_softc); | | 2046 | struct carp_softc *sc = ((struct carp_softc *)ifp->if_softc); |
2043 | | | 2047 | |
2044 | if (sc->sc_carpdev != NULL && sc->sc_state == MASTER) { | | 2048 | if (sc->sc_carpdev != NULL && sc->sc_state == MASTER) { |
2045 | return (sc->sc_carpdev->if_output(ifp, m, sa, rt)); | | 2049 | return (sc->sc_carpdev->if_output(ifp, m, sa, rt)); |
2046 | } else { | | 2050 | } else { |
2047 | m_freem(m); | | 2051 | m_freem(m); |
2048 | return (ENETUNREACH); | | 2052 | return (ENETUNREACH); |
2049 | } | | 2053 | } |
2050 | } | | 2054 | } |
2051 | | | 2055 | |
2052 | void | | 2056 | void |
2053 | carp_set_state(struct carp_softc *sc, int state) | | 2057 | carp_set_state(struct carp_softc *sc, int state) |
2054 | { | | 2058 | { |
| | | 2059 | static const char *carp_states[] = { CARP_STATES }; |
2055 | if (sc->sc_state == state) | | 2060 | if (sc->sc_state == state) |
2056 | return; | | 2061 | return; |
2057 | | | 2062 | |
| | | 2063 | CARP_LOG(sc, ("state transition from: %s -> to: %s", carp_states[sc->sc_state], carp_states[state])); |
| | | 2064 | |
2058 | sc->sc_state = state; | | 2065 | sc->sc_state = state; |
2059 | switch (state) { | | 2066 | switch (state) { |
2060 | case BACKUP: | | 2067 | case BACKUP: |
2061 | sc->sc_if.if_link_state = LINK_STATE_DOWN; | | 2068 | sc->sc_if.if_link_state = LINK_STATE_DOWN; |
2062 | break; | | 2069 | break; |
2063 | case MASTER: | | 2070 | case MASTER: |
2064 | sc->sc_if.if_link_state = LINK_STATE_UP; | | 2071 | sc->sc_if.if_link_state = LINK_STATE_UP; |
2065 | break; | | 2072 | break; |
2066 | default: | | 2073 | default: |
2067 | sc->sc_if.if_link_state = LINK_STATE_UNKNOWN; | | 2074 | sc->sc_if.if_link_state = LINK_STATE_UNKNOWN; |
2068 | break; | | 2075 | break; |
2069 | } | | 2076 | } |
2070 | rt_ifmsg(&sc->sc_if); | | 2077 | rt_ifmsg(&sc->sc_if); |