LVS
lvs-users
Google
 
Web LinuxVirtualServer.org

Re: ipvsadm version mismatch in debian

To: "LinuxVirtualServer.org users mailing list." <lvs-users@xxxxxxxxxxxxxxxxxxxxxx>
Subject: Re: ipvsadm version mismatch in debian
From: Roberto Nibali <ratz@xxxxxxxxxxxx>
Date: Mon, 18 Oct 2004 16:12:13 +0200
Hello,

It sounds to me that it is some sort of sparc specific problem in the
LVS/ipvsadm code itself.  I am more than happy to work on a kernel-side
or ipvsadm fix for it. The former I can put into debian myself, the

The problem is easily identified (in this example by invoking ipvsadm without arguments):

From ip_vs.h:

struct ip_vs_get_services {
        /* number of virtual services */
        unsigned int num_services;

        /* service table */
        struct ip_vs_service_user entrytable[0];
};

In user space we use the following ioctl structures to pass a command:

struct ip_vs_get_services *ipvs_get_services(void)
{
        struct ip_vs_get_services *get;
        socklen_t len;

        len = sizeof(*get) +
                sizeof(struct ip_vs_service_user) * ipvs_info.num_services;
        if (!(get = malloc(len)))
                return NULL;

        ipvs_cmd = GET_CMD(IP_VS_SO_GET_SERVICES);
        get->num_services = ipvs_info.num_services;
        printf("get [%d], len [%d] services [%d]\n", sizeof(*get), len,
                        ipvs_info.num_services);
        if (getsockopt(sockfd, IPPROTO_IP,
                       IP_VS_SO_GET_SERVICES, get, &len) < 0) {
                free(get);
                return NULL;
        }
        return get;
}

struct ip_vs_get_services *get is 4 bytes, independant on the architecture, at least this is what I see on sparc64 and IA32.

The output is:

    ipvs_init successfull, returning socket fd=3 len=12
    IP Virtual Server version 1.0.11 (size=16384)
    get [4], len [4] services [0]
    Module is wrong version [ipvsadm.c:list_all:1579]

In the kernel (ip_vs_ctl.c) we use the following structures:

       case IP_VS_SO_GET_SERVICES:
        {
                struct ip_vs_get_services get;

                if (*len < sizeof(get)) {
                        printk("sparc64  [%d]\n", sizeof(get));
                        IP_VS_ERR("length: %u < %Zu\n", *len, sizeof(get));
                        ret = -EINVAL;
                        goto out;
                }
                if (copy_from_user(&get, user, sizeof(get))) {
                        ret = -EFAULT;
                        goto out;
                }
if (*len != (sizeof(get)+sizeof(struct ip_vs_service_user)*get.n
um_services)) {
                        IP_VS_ERR("length: %u != %Zu\n", *len,
sizeof(get)+sizeof(struct ip_vs_service_user)*
get.num_services);
                        ret = -EINVAL;
                        goto out;
                }
                ret = __ip_vs_get_service_entries(&get, user);
        }
        break;

struct ip_vs_get_services is 8 bytes. I'm a bit unsure as to why it works under IA32 at all. I probably need some more sleep ;).

That's why I correctly get following entry in the kernlog:

    sparc64 [8]
    IPVS: length: 4 < 8

HTH and best regards,
Roberto Nibali, ratz
--
echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq' | dc
<Prev in Thread] Current Thread [Next in Thread>