ipvsadm version mismatch in debian

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


> 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,
         if (getsockopt(sockfd, IPPROTO_IP,
                        IP_VS_SO_GET_SERVICES, get, &len) < 0) {
                 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 
um_services)) {
                         IP_VS_ERR("length: %u != %Zu\n", *len,
                         ret = -EINVAL;
                         goto out;
                 ret = __ip_vs_get_service_entries(&get, user);

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
'[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq' | dc

More information about the lvs-users mailing list