Hello,

we have a problem with ifstated detecting state change on multiple CARP
interfaces.

After digging deeper, it seems that reading on the routing socket does
not give us all the state changes that we'd expect. We tried with the
latest snapshot kernel and got the same behavior.

Our CARP interfaces are as follows:
carp0
carp1
carp1010 (VLAN on carp1)
carp1011 (Another VLAN on carp1)
carp2
carp3

The condition we'd like to test is:
carp_up = 'carp0.link.up \
        && carp1.link.up \
        && carp1010.link.up \
        && carp1011.link.up \
        && carp2.link.up \
        && carp3.link.up'

Doing a little check using a quick C program (see below), and playing
with the demote counter, we can clearly see why the condition is not
always met as it should:

# ./getifinfo &
[1] 20942
# ifconfig -g carp carpdemote 50
carp0 -> LINK_STATE_DOWN
carp2 -> LINK_STATE_DOWN
carp3 -> LINK_STATE_DOWN
carp1010 -> LINK_STATE_DOWN
carp1011 -> LINK_STATE_DOWN
# ifconfig -g carp -carpdemote 50
carp1 -> LINK_STATE_UP
carp1010 -> LINK_STATE_UP
carp0 -> LINK_STATE_UP
carp2 -> LINK_STATE_UP
carp1011 -> LINK_STATE_UP
carp3 -> LINK_STATE_UP
# ifconfig -g carp carpdemote 50
carp0 -> LINK_STATE_DOWN
carp1 -> LINK_STATE_DOWN
carp2 -> LINK_STATE_DOWN
carp3 -> LINK_STATE_DOWN
carp1010 -> LINK_STATE_DOWN
# ifconfig -g carp -carpdemote 50
carp0 -> LINK_STATE_UP
carp1 -> LINK_STATE_UP
carp1010 -> LINK_STATE_UP
carp1011 -> LINK_STATE_UP
# 

Question is, is it normal that the routing socket doesn't report all
changes? Anyone else having similar issues?

Thanks in advance,
--
Pascal


getifinfo.c:
----
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/route.h>
#include <ifaddrs.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <err.h>

char *if_states[] = {
        "LINK_STATE_UNKNOWN",
        "LINK_STATE_DOWN",
        "LINK_STATE_UP",
        "LINK_STATE_HALF_DUPLEX",
        "LINK_STATE_FULL_DUPLEX"
};

int
main(int argc, char **argv)
{
        int                      rt_fd;
        char                     msg[2048];
        struct ifaddrs          *ifap, *ifa;
        struct rt_msghdr        *rtm = (struct rt_msghdr *)&msg;
        struct if_msghdr        *ifm = (struct if_msghdr *)&msg;
        int                      len;
        char                     ifs[64][16];

        if (getifaddrs(&ifap))
                err(1, "getifaddrs");

        for (ifa = ifap; ifa->ifa_next != NULL; ifa = ifa->ifa_next) {
                strlcpy(ifs[if_nametoindex(ifa->ifa_name)], ifa->ifa_name, 16);
        }

        freeifaddrs(ifap);

        if ((rt_fd = socket(PF_ROUTE, SOCK_RAW, 0)) < 0)
                err(1, "no routing socket");

        while ((len = read(rt_fd, msg, sizeof(msg)))) {
                if (len < sizeof(struct rt_msghdr)) {
                        warnx("len < sizeof(struct rt_msghdr)");
                        continue;
                }

                if (rtm->rtm_version != RTM_VERSION)
                        continue;

                if (rtm->rtm_type != RTM_IFINFO)
                        continue;

                printf("%s -> %s\n", ifs[ifm->ifm_index],
                    if_states[ifm->ifm_data.ifi_link_state]);
        }
        return 0;
}

Reply via email to