ipvsadm version mismatch in debian

Roberto Nibali ratz at drugphish.ch
Mon Oct 18 15:12:13 BST 2004


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


More information about the lvs-users mailing list