#504069 keepalived: healthchecker doesn't realize the local unreachable realserver

Package:
keepalived
Source:
keepalived
Description:
Failover and monitoring daemon for LVS clusters
Submitter:
Bin Tian
Date:
2022-07-04 17:36:08 UTC
Severity:
normal
Tags:
#504069#5
Date:
2008-10-31 06:37:07 UTC
From:
To:
If you add an unreachable route to one realserver, the healthchecker doesn't remove the realserver.

For example,

# ip ro add unreachable 10.1.8.48
# telnet 10.1.8.48 80
Trying 10.1.8.48...
telnet: Unable to connect to remote host: Network is unreachable

But HTTP_GET/SMTP_CHECK/TCP_CHECK isn't aware of the connect problem.

The following codes may be helpful to solve the problem

ipvs1:~# cat a.c
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main (void)
{
        int ret, sock, status;
        struct sockaddr_in sa = { AF_INET };
        socklen_t slen = sizeof (status);

        sa.sin_addr.s_addr = inet_addr ("10.1.8.48");
        sa.sin_port = htons (80);

        sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
        ret = connect (sock, (struct sockaddr *)&sa, sizeof (sa));
        printf ("connect return %d\n", ret);
        if (ret != 0)
                perror ("connect: ");

		/*
			After calling connect, keepalived use getsockopt(SO_ERROR)
			to get the connection status in function tcp_socket_state.
			But it report no error in this case.
		*/
        ret = getsockopt (sock, SOL_SOCKET, SO_ERROR, (void *) &status, &slen);
        if (ret != 0)
                perror ("getsockopt: ");
        printf ("status = %d\n", status);
};
ipvs1:~# gcc a.c
ipvs1:~# ./a.out
connect return -1
connect: : Network is unreachable
status = 0
ipvs1:~#

#504069#10
Date:
2008-10-31 06:59:49 UTC
From:
To:
I made some corection to the test codes

ipvs1:~# cat a.c
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>

int main (void)
{
int ret, sock, status, flags;
struct sockaddr_in sa = { AF_INET };
socklen_t slen = sizeof (status);

sa.sin_addr.s_addr = inet_addr ("10.1.8.48");
sa.sin_port = htons (8088);

sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
flags = fcntl(sock, F_GETFL);
fcntl (sock, F_SETFL, flags|O_NONBLOCK);
ret = connect (sock, (struct sockaddr *)&sa, sizeof (sa));
printf ("connect return %d\n", ret);
if (ret != 0)
perror ("connect: ");
/*
After calling connect, keepalived use getsockopt(SO_ERROR)
to get the connection status in function tcp_socket_state.
But it report no error in this case.
*/

ret = getsockopt (sock, SOL_SOCKET, SO_ERROR, (void *) &status, &slen);
if (ret != 0)
perror ("getsockopt: ");
printf ("status = %d\n", status);
};
ipvs1:~# gcc a.c
ipvs1:~# ./a.out
connect return -1
connect: : Network is unreachable
status = 0
ipvs1:~#


Bin Tian wrote: