Subject: Re: [patch v5 04/12] IPVS: Add struct ip_vs_conn_param, IPv6 forgotten ?

From: Hans Schillstrom <[email-masked]>
Date: Tue, 19 Oct 2010 11:41:21 +0200

Hi Simon,
There is a show stopper for IPv6 in this patch.
ip_vs_conn_fill_param() doesn't handle IPv6.

On Monday 04 October 2010 15:46:28 Simon Horman wrote:
> Signed-off-by: Simon Horman <[email-masked]>
> Acked-by: Julian Anastasov <[email-masked]>
>
> ---
>
> The motivation for this is to allow persistence engine modules to
> fill in the parameters.
>
> v0.3
> * Add missing changes to ip_vs_ftp.c
>
> v2
> * make "union nf_inet_addr fwmark" const
> * Update for the recent addition of ip_vs_nfct.c
>
> v3
> * As suggested by Julian Anastasov
>   - Correct logic for inverse case in ip_vs_conn_fill_param_proto()
>     and ah_esp_conn_fill_param_proto()
>   - Update ip_vs_conn_out_get()'s comments as its parameters have changed
>   - Add missing call to ip_vs_conn_fill_param() before the second
>     invocation of ip_vs_conn_new() in ip_vs_sched_persist()
> * Trivial re-diff
>
> v4
> * As suggested by Julian Anastasov
>   - Fix logic in ip_vs_conn_out_get_proto()
>     + An error occurs if ip_vs_conn_fill_param_proto is non-zero,
>       not if it is zero
>
  v5+
   * IPv6 addr copy in  ip_vs_conn_fill_param()

> Index: lvs-test-2.6/include/net/ip_vs.h
> ===================================================================
> --- lvs-test-2.6.orig/include/net/ip_vs.h       2010-10-04 17:00:28.000000000 +0900
> +++ lvs-test-2.6/include/net/ip_vs.h    2010-10-04 17:49:20.000000000 +0900
> @@ -357,6 +357,15 @@ struct ip_vs_protocol {
>
>  extern struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto);
>
> +struct ip_vs_conn_param {
> +       const union nf_inet_addr        *caddr;
> +       const union nf_inet_addr        *vaddr;
> +       __be16                          cport;
> +       __be16                          vport;
> +       __u16                           protocol;
> +       u16                             af;
> +};
> +
>  /*
>   *     IP_VS structure allocated for each dynamically scheduled connection
>   */
> @@ -626,13 +635,23 @@ enum {
>         IP_VS_DIR_LAST,
>  };
>
> -extern struct ip_vs_conn *ip_vs_conn_in_get
> -(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
> - const union nf_inet_addr *d_addr, __be16 d_port);
> -
> -extern struct ip_vs_conn *ip_vs_ct_in_get
> -(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
> - const union nf_inet_addr *d_addr, __be16 d_port);
> +static inline void ip_vs_conn_fill_param(int af, int protocol,
> +                                        const union nf_inet_addr *caddr,
> +                                        __be16 cport,
> +                                        const union nf_inet_addr *vaddr,
> +                                        __be16 vport,
> +                                        struct ip_vs_conn_param *p)
> +{
> +       p->af = af;
> +       p->protocol = protocol;

#ifdef CONFIG_IP_VS_IPV6
	if (af == AF_INET6) {
		ipv6_addr_copy(&p->caddr, caddr);
		ipv6_addr_copy(&p->caddr, caddr);
	}
	else
#else
	}
		p->caddr = caddr;
		p->vaddr = vaddr;
	}
+#endif

> +       p->caddr = caddr;
remove line above
> +       p->cport = cport;

> +       p->vaddr = vaddr;
> +       p->vport = vport;
remove line above
> +}
> +
> +struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p);
> +struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p);
>
>  struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
>                                             struct ip_vs_protocol *pp,
> @@ -640,9 +659,7 @@ struct ip_vs_conn * ip_vs_conn_in_get_pr
>                                             unsigned int proto_off,
>                                             int inverse);
>
> -extern struct ip_vs_conn *ip_vs_conn_out_get
> -(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
> - const union nf_inet_addr *d_addr, __be16 d_port);
> +struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p);
>
>  struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
>                                              struct ip_vs_protocol *pp,
> @@ -658,11 +675,10 @@ static inline void __ip_vs_conn_put(stru
>  extern void ip_vs_conn_put(struct ip_vs_conn *cp);
>  extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
>
> -extern struct ip_vs_conn *
> -ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
> -              const union nf_inet_addr *vaddr, __be16 vport,
> -              const union nf_inet_addr *daddr, __be16 dport, unsigned flags,
> -              struct ip_vs_dest *dest);
> +struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p,
> +                                 const union nf_inet_addr *daddr,
> +                                 __be16 dport, unsigned flags,
> +                                 struct ip_vs_dest *dest);
>  extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
>
>  extern const char * ip_vs_state_name(__u16 proto, int state);
> Index: lvs-test-2.6/net/netfilter/ipvs/ip_vs_conn.c
> ===================================================================
> --- lvs-test-2.6.orig/net/netfilter/ipvs/ip_vs_conn.c   2010-10-04 17:00:28.000000000 +0900
> +++ lvs-test-2.6/net/netfilter/ipvs/ip_vs_conn.c        2010-10-04 17:49:20.000000000 +0900
> @@ -218,27 +218,26 @@ static inline int ip_vs_conn_unhash(stru
>  /*
>   *  Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
>   *  Called for pkts coming from OUTside-to-INside.
> - *     s_addr, s_port: pkt source address (foreign host)
> - *     d_addr, d_port: pkt dest address (load balancer)
> + *     p->caddr, p->cport: pkt source address (foreign host)
> + *     p->vaddr, p->vport: pkt dest address (load balancer)
>   */
> -static inline struct ip_vs_conn *__ip_vs_conn_in_get
> -(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
> - const union nf_inet_addr *d_addr, __be16 d_port)
> +static inline struct ip_vs_conn *
> +__ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
>  {
>         unsigned hash;
>         struct ip_vs_conn *cp;
>
> -       hash = ip_vs_conn_hashkey(af, protocol, s_addr, s_port);
> +       hash = ip_vs_conn_hashkey(p->af, p->protocol, p->caddr, p->cport);
>
>         ct_read_lock(hash);
>
>         list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
> -               if (cp->af == af &&
> -                   ip_vs_addr_equal(af, s_addr, &cp->caddr) &&
> -                   ip_vs_addr_equal(af, d_addr, &cp->vaddr) &&
> -                   s_port == cp->cport && d_port == cp->vport &&
> -                   ((!s_port) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
> -                   protocol == cp->protocol) {
> +               if (cp->af == p->af &&
> +                   ip_vs_addr_equal(p->af, p->caddr, &cp->caddr) &&
> +                   ip_vs_addr_equal(p->af, p->vaddr, &cp->vaddr) &&
> +                   p->cport == cp->cport && p->vport == cp->vport &&
> +                   ((!p->cport) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
> +                   p->protocol == cp->protocol) {
>                         /* HIT */
>                         atomic_inc(&cp->refcnt);
>                         ct_read_unlock(hash);
> @@ -251,71 +250,82 @@ static inline struct ip_vs_conn *__ip_vs
>         return NULL;
>  }
>
> -struct ip_vs_conn *ip_vs_conn_in_get
> -(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
> - const union nf_inet_addr *d_addr, __be16 d_port)
> +struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
>  {
>         struct ip_vs_conn *cp;
>
> -       cp = __ip_vs_conn_in_get(af, protocol, s_addr, s_port, d_addr, d_port);
> -       if (!cp && atomic_read(&ip_vs_conn_no_cport_cnt))
> -               cp = __ip_vs_conn_in_get(af, protocol, s_addr, 0, d_addr,
> -                                        d_port);
> +       cp = __ip_vs_conn_in_get(p);
> +       if (!cp && atomic_read(&ip_vs_conn_no_cport_cnt)) {
> +               struct ip_vs_conn_param cport_zero_p = *p;
> +               cport_zero_p.cport = 0;
> +               cp = __ip_vs_conn_in_get(&cport_zero_p);
> +       }
>
>         IP_VS_DBG_BUF(9, "lookup/in %s %s:%d->%s:%d %s\n",
> -                     ip_vs_proto_name(protocol),
> -                     IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
> -                     IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
> +                     ip_vs_proto_name(p->protocol),
> +                     IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
> +                     IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
>                       cp ? "hit" : "not hit");
>
>         return cp;
>  }
>
> +static int
> +ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb,
> +                           const struct ip_vs_iphdr *iph,
> +                           unsigned int proto_off, int inverse,
> +                           struct ip_vs_conn_param *p)
> +{
> +       __be16 _ports[2], *pptr;
> +
> +       pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
> +       if (pptr == NULL)
> +               return 1;
> +
> +       if (likely(!inverse))
> +               ip_vs_conn_fill_param(af, iph->protocol, &iph->saddr, pptr[0],
> +                                     &iph->daddr, pptr[1], p);
> +       else
> +               ip_vs_conn_fill_param(af, iph->protocol, &iph->daddr, pptr[1],
> +                                     &iph->saddr, pptr[0], p);
> +       return 0;
> +}
> +
>  struct ip_vs_conn *
>  ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
>                         struct ip_vs_protocol *pp,
>                         const struct ip_vs_iphdr *iph,
>                         unsigned int proto_off, int inverse)
>  {
> -       __be16 _ports[2], *pptr;
> +       struct ip_vs_conn_param p;
>
> -       pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
> -       if (pptr == NULL)
> +       if (ip_vs_conn_fill_param_proto(af, skb, iph, proto_off, inverse, &p))
>                 return NULL;
>
> -       if (likely(!inverse))
> -               return ip_vs_conn_in_get(af, iph->protocol,
> -                                        &iph->saddr, pptr[0],
> -                                        &iph->daddr, pptr[1]);
> -       else
> -               return ip_vs_conn_in_get(af, iph->protocol,
> -                                        &iph->daddr, pptr[1],
> -                                        &iph->saddr, pptr[0]);
> +       return ip_vs_conn_in_get(&p);
>  }
>  EXPORT_SYMBOL_GPL(ip_vs_conn_in_get_proto);
>
>  /* Get reference to connection template */
> -struct ip_vs_conn *ip_vs_ct_in_get
> -(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
> - const union nf_inet_addr *d_addr, __be16 d_port)
> +struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p)
>  {
>         unsigned hash;
>         struct ip_vs_conn *cp;
>
> -       hash = ip_vs_conn_hashkey(af, protocol, s_addr, s_port);
> +       hash = ip_vs_conn_hashkey(p->af, p->protocol, p->caddr, p->cport);
>
>         ct_read_lock(hash);
>
>         list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
> -               if (cp->af == af &&
> -                   ip_vs_addr_equal(af, s_addr, &cp->caddr) &&
> +               if (cp->af == p->af &&
> +                   ip_vs_addr_equal(p->af, p->caddr, &cp->caddr) &&
>                     /* protocol should only be IPPROTO_IP if
> -                    * d_addr is a fwmark */
> -                   ip_vs_addr_equal(protocol == IPPROTO_IP ? AF_UNSPEC : af,
> -                                    d_addr, &cp->vaddr) &&
> -                   s_port == cp->cport && d_port == cp->vport &&
> +                    * p->vaddr is a fwmark */
> +                   ip_vs_addr_equal(p->protocol == IPPROTO_IP ? AF_UNSPEC :
> +                                    p->af, p->vaddr, &cp->vaddr) &&
> +                   p->cport == cp->cport && p->vport == cp->vport &&
>                     cp->flags & IP_VS_CONN_F_TEMPLATE &&
> -                   protocol == cp->protocol) {
> +                   p->protocol == cp->protocol) {
>                         /* HIT */
>                         atomic_inc(&cp->refcnt);
>                         goto out;
> @@ -327,23 +337,19 @@ struct ip_vs_conn *ip_vs_ct_in_get
>         ct_read_unlock(hash);
>
>         IP_VS_DBG_BUF(9, "template lookup/in %s %s:%d->%s:%d %s\n",
> -                     ip_vs_proto_name(protocol),
> -                     IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
> -                     IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
> +                     ip_vs_proto_name(p->protocol),
> +                     IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
> +                     IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
>                       cp ? "hit" : "not hit");
>
>         return cp;
>  }
>
> -/*
> - *  Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
> - *  Called for pkts coming from inside-to-OUTside.
> - *     s_addr, s_port: pkt source address (inside host)
> - *     d_addr, d_port: pkt dest address (foreign host)
> - */
> -struct ip_vs_conn *ip_vs_conn_out_get
> -(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
> - const union nf_inet_addr *d_addr, __be16 d_port)
> +/* Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
> + * Called for pkts coming from inside-to-OUTside.
> + *     p->caddr, p->cport: pkt source address (inside host)
> + *     p->vaddr, p->vport: pkt dest address (foreign host) */
> +struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
>  {
>         unsigned hash;
>         struct ip_vs_conn *cp, *ret=NULL;
> @@ -351,16 +357,16 @@ struct ip_vs_conn *ip_vs_conn_out_get
>         /*
>          *      Check for "full" addressed entries
>          */
> -       hash = ip_vs_conn_hashkey(af, protocol, d_addr, d_port);
> +       hash = ip_vs_conn_hashkey(p->af, p->protocol, p->vaddr, p->vport);
>
>         ct_read_lock(hash);
>
>         list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
> -               if (cp->af == af &&
> -                   ip_vs_addr_equal(af, d_addr, &cp->caddr) &&
> -                   ip_vs_addr_equal(af, s_addr, &cp->daddr) &&
> -                   d_port == cp->cport && s_port == cp->dport &&
> -                   protocol == cp->protocol) {
> +               if (cp->af == p->af &&
> +                   ip_vs_addr_equal(p->af, p->vaddr, &cp->caddr) &&
> +                   ip_vs_addr_equal(p->af, p->caddr, &cp->daddr) &&
> +                   p->vport == cp->cport && p->cport == cp->dport &&
> +                   p->protocol == cp->protocol) {
>                         /* HIT */
>                         atomic_inc(&cp->refcnt);
>                         ret = cp;
> @@ -371,9 +377,9 @@ struct ip_vs_conn *ip_vs_conn_out_get
>         ct_read_unlock(hash);
>
>         IP_VS_DBG_BUF(9, "lookup/out %s %s:%d->%s:%d %s\n",
> -                     ip_vs_proto_name(protocol),
> -                     IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
> -                     IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
> +                     ip_vs_proto_name(p->protocol),
> +                     IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
> +                     IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
>                       ret ? "hit" : "not hit");
>
>         return ret;
> @@ -385,20 +391,12 @@ ip_vs_conn_out_get_proto(int af, const s
>                          const struct ip_vs_iphdr *iph,
>                          unsigned int proto_off, int inverse)
>  {
> -       __be16 _ports[2], *pptr;
> +       struct ip_vs_conn_param p;
>
> -       pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
> -       if (pptr == NULL)
> +       if (ip_vs_conn_fill_param_proto(af, skb, iph, proto_off, inverse, &p))
>                 return NULL;
>
> -       if (likely(!inverse))
> -               return ip_vs_conn_out_get(af, iph->protocol,
> -                                         &iph->saddr, pptr[0],
> -                                         &iph->daddr, pptr[1]);
> -       else
> -               return ip_vs_conn_out_get(af, iph->protocol,
> -                                         &iph->daddr, pptr[1],
> -                                         &iph->saddr, pptr[0]);
> +       return ip_vs_conn_out_get(&p);
>  }
>  EXPORT_SYMBOL_GPL(ip_vs_conn_out_get_proto);
>
> @@ -758,13 +756,12 @@ void ip_vs_conn_expire_now(struct ip_vs_
>   *     Create a new connection entry and hash it into the ip_vs_conn_tab
>   */
>  struct ip_vs_conn *
> -ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
> -              const union nf_inet_addr *vaddr, __be16 vport,
> +ip_vs_conn_new(const struct ip_vs_conn_param *p,
>                const union nf_inet_addr *daddr, __be16 dport, unsigned flags,
>                struct ip_vs_dest *dest)
>  {
>         struct ip_vs_conn *cp;
> -       struct ip_vs_protocol *pp = ip_vs_proto_get(proto);
> +       struct ip_vs_protocol *pp = ip_vs_proto_get(p->protocol);
>
>         cp = kmem_cache_zalloc(ip_vs_conn_cachep, GFP_ATOMIC);
>         if (cp == NULL) {
> @@ -774,14 +771,14 @@ ip_vs_conn_new(int af, int proto, const
>
>         INIT_LIST_HEAD(&cp->c_list);
>         setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp);
> -       cp->af             = af;
> -       cp->protocol       = proto;
> -       ip_vs_addr_copy(af, &cp->caddr, caddr);
> -       cp->cport          = cport;
> -       ip_vs_addr_copy(af, &cp->vaddr, vaddr);
> -       cp->vport          = vport;
> +       cp->af             = p->af;
> +       cp->protocol       = p->protocol;
> +       ip_vs_addr_copy(p->af, &cp->caddr, p->caddr);
> +       cp->cport          = p->cport;
> +       ip_vs_addr_copy(p->af, &cp->vaddr, p->vaddr);
> +       cp->vport          = p->vport;
>         /* proto should only be IPPROTO_IP if d_addr is a fwmark */
> -       ip_vs_addr_copy(proto == IPPROTO_IP ? AF_UNSPEC : af,
> +       ip_vs_addr_copy(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
>                         &cp->daddr, daddr);
>         cp->dport          = dport;
>         cp->flags          = flags;
> @@ -810,7 +807,7 @@ ip_vs_conn_new(int af, int proto, const
>
>         /* Bind its packet transmitter */
>  #ifdef CONFIG_IP_VS_IPV6
> -       if (af == AF_INET6)
> +       if (p->af == AF_INET6)
>                 ip_vs_bind_xmit_v6(cp);
>         else
>  #endif
> Index: lvs-test-2.6/net/netfilter/ipvs/ip_vs_core.c
> ===================================================================
> --- lvs-test-2.6.orig/net/netfilter/ipvs/ip_vs_core.c   2010-10-04 17:00:45.000000000 +0900
> +++ lvs-test-2.6/net/netfilter/ipvs/ip_vs_core.c        2010-10-04 17:49:20.000000000 +0900
> @@ -193,14 +193,11 @@ ip_vs_sched_persist(struct ip_vs_service
>         struct ip_vs_iphdr iph;
>         struct ip_vs_dest *dest;
>         struct ip_vs_conn *ct;
> -       int protocol = iph.protocol;
>         __be16 dport = 0;               /* destination port to forward */
> -       __be16 vport = 0;               /* virtual service port */
>         unsigned int flags;
> +       struct ip_vs_conn_param param;
>         union nf_inet_addr snet;        /* source network of the client,
>                                            after masking */
> -       const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };
> -       const union nf_inet_addr *vaddr = &iph.daddr;
>
>         ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
>
> @@ -232,6 +229,11 @@ ip_vs_sched_persist(struct ip_vs_service
>          * is created for other persistent services.
>          */
>         {
> +               int protocol = iph.protocol;
> +               const union nf_inet_addr *vaddr = &iph.daddr;
> +               const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };
> +               __be16 vport = 0;
> +
>                 if (ports[1] == svc->port) {
>                         /* non-FTP template:
>                          * <protocol, caddr, 0, vaddr, vport, daddr, dport>
> @@ -253,11 +255,12 @@ ip_vs_sched_persist(struct ip_vs_service
>                                 vaddr = &fwmark;
>                         }
>                 }
> +               ip_vs_conn_fill_param(svc->af, protocol, &snet, 0,
> +                                     vaddr, vport, &param);
>         }
>
>         /* Check if a template already exists */
> -       ct = ip_vs_ct_in_get(svc->af, protocol, &snet, 0, vaddr, vport);
> -
> +       ct = ip_vs_ct_in_get(&param);
>         if (!ct || !ip_vs_check_template(ct)) {
>                 /* No template found or the dest of the connection
>                  * template is not available.
> @@ -272,8 +275,7 @@ ip_vs_sched_persist(struct ip_vs_service
>                         dport = dest->port;
>
>                 /* Create a template */
> -               ct = ip_vs_conn_new(svc->af, protocol, &snet, 0,vaddr, vport,
> -                                   &dest->addr, dport,
> +               ct = ip_vs_conn_new(&param, &dest->addr, dport,
>                                     IP_VS_CONN_F_TEMPLATE, dest);
>                 if (ct == NULL)
>                         return NULL;
> @@ -294,12 +296,9 @@ ip_vs_sched_persist(struct ip_vs_service
>         /*
>          *    Create a new connection according to the template
>          */
> -       cp = ip_vs_conn_new(svc->af, iph.protocol,
> -                           &iph.saddr, ports[0],
> -                           &iph.daddr, ports[1],
> -                           &dest->addr, dport,
> -                           flags,
> -                           dest);
> +       ip_vs_conn_fill_param(svc->af, iph.protocol, &iph.saddr, ports[0],
> +                             &iph.daddr, ports[1], &param);
> +       cp = ip_vs_conn_new(&param, &dest->addr, dport, flags, dest);
>         if (cp == NULL) {
>                 ip_vs_conn_put(ct);
>                 return NULL;
> @@ -366,14 +365,16 @@ ip_vs_schedule(struct ip_vs_service *svc
>         /*
>          *    Create a connection entry.
>          */
> -       cp = ip_vs_conn_new(svc->af, iph.protocol,
> -                           &iph.saddr, pptr[0],
> -                           &iph.daddr, pptr[1],
> -                           &dest->addr, dest->port ? dest->port : pptr[1],
> -                           flags,
> -                           dest);
> -       if (cp == NULL)
> -               return NULL;
> +       {
> +               struct ip_vs_conn_param p;
> +               ip_vs_conn_fill_param(svc->af, iph.protocol, &iph.saddr,
> +                                     pptr[0], &iph.daddr, pptr[1], &p);
> +               cp = ip_vs_conn_new(&p, &dest->addr,
> +                                   dest->port ? dest->port : pptr[1],
> +                                   flags, dest);
> +               if (!cp)
> +                       return NULL;
> +       }
>
>         IP_VS_DBG_BUF(6, "Schedule fwd:%c c:%s:%u v:%s:%u "
>                       "d:%s:%u conn->flags:%X conn->refcnt:%d\n",
> @@ -429,14 +430,17 @@ int ip_vs_leave(struct ip_vs_service *sv
>
>                 /* create a new connection entry */
>                 IP_VS_DBG(6, "%s(): create a cache_bypass entry\n", __func__);
> -               cp = ip_vs_conn_new(svc->af, iph.protocol,
> -                                   &iph.saddr, pptr[0],
> -                                   &iph.daddr, pptr[1],
> -                                   &daddr, 0,
> -                                   IP_VS_CONN_F_BYPASS | flags,
> -                                   NULL);
> -               if (cp == NULL)
> -                       return NF_DROP;
> +               {
> +                       struct ip_vs_conn_param p;
> +                       ip_vs_conn_fill_param(svc->af, iph.protocol,
> +                                             &iph.saddr, pptr[0],
> +                                             &iph.daddr, pptr[1], &p);
> +                       cp = ip_vs_conn_new(&p, &daddr, 0,
> +                                           IP_VS_CONN_F_BYPASS | flags,
> +                                           NULL);
> +                       if (!cp)
> +                               return NF_DROP;
> +               }
>
>                 /* statistics */
>                 ip_vs_in_stats(cp, skb);
> Index: lvs-test-2.6/net/netfilter/ipvs/ip_vs_ftp.c
> ===================================================================
> --- lvs-test-2.6.orig/net/netfilter/ipvs/ip_vs_ftp.c    2010-10-04 16:58:31.000000000 +0900
> +++ lvs-test-2.6/net/netfilter/ipvs/ip_vs_ftp.c 2010-10-04 17:00:45.000000000 +0900
> @@ -195,13 +195,17 @@ static int ip_vs_ftp_out(struct ip_vs_ap
>                 /*
>                  * Now update or create an connection entry for it
>                  */
> -               n_cp = ip_vs_conn_out_get(AF_INET, iph->protocol, &from, port,
> -                                         &cp->caddr, 0);
> +               {
> +                       struct ip_vs_conn_param p;
> +                       ip_vs_conn_fill_param(AF_INET, iph->protocol,
> +                                             &from, port, &cp->caddr, 0, &p);
> +                       n_cp = ip_vs_conn_out_get(&p);
> +               }
>                 if (!n_cp) {
> -                       n_cp = ip_vs_conn_new(AF_INET, IPPROTO_TCP,
> -                                             &cp->caddr, 0,
> -                                             &cp->vaddr, port,
> -                                             &from, port,
> +                       struct ip_vs_conn_param p;
> +                       ip_vs_conn_fill_param(AF_INET, IPPROTO_TCP, &cp->caddr,
> +                                             0, &cp->vaddr, port, &p);
> +                       n_cp = ip_vs_conn_new(&p, &from, port,
>                                               IP_VS_CONN_F_NO_CPORT |
>                                               IP_VS_CONN_F_NFCT,
>                                               cp->dest);
> @@ -347,21 +351,22 @@ static int ip_vs_ftp_in(struct ip_vs_app
>                   ip_vs_proto_name(iph->protocol),
>                   &to.ip, ntohs(port), &cp->vaddr.ip, 0);
>
> -       n_cp = ip_vs_conn_in_get(AF_INET, iph->protocol,
> -                                &to, port,
> -                                &cp->vaddr, htons(ntohs(cp->vport)-1));
> -       if (!n_cp) {
> -               n_cp = ip_vs_conn_new(AF_INET, IPPROTO_TCP,
> -                                     &to, port,
> +       {
> +               struct ip_vs_conn_param p;
> +               ip_vs_conn_fill_param(AF_INET, iph->protocol, &to, port,
>                                       &cp->vaddr, htons(ntohs(cp->vport)-1),
> -                                     &cp->daddr, htons(ntohs(cp->dport)-1),
> -                                     IP_VS_CONN_F_NFCT,
> -                                     cp->dest);
> -               if (!n_cp)
> -                       return 0;
> +                                     &p);
> +               n_cp = ip_vs_conn_in_get(&p);
> +               if (!n_cp) {
> +                       n_cp = ip_vs_conn_new(&p, &cp->daddr,
> +                                             htons(ntohs(cp->dport)-1),
> +                                             IP_VS_CONN_F_NFCT, cp->dest);
> +                       if (!n_cp)
> +                               return 0;
>
> -               /* add its controller */
> -               ip_vs_control_add(n_cp, cp);
> +                       /* add its controller */
> +                       ip_vs_control_add(n_cp, cp);
> +               }
>         }
>
>         /*
> Index: lvs-test-2.6/net/netfilter/ipvs/ip_vs_nfct.c
> ===================================================================
> --- lvs-test-2.6.orig/net/netfilter/ipvs/ip_vs_nfct.c   2010-10-04 16:58:31.000000000 +0900
> +++ lvs-test-2.6/net/netfilter/ipvs/ip_vs_nfct.c        2010-10-04 17:00:45.000000000 +0900
> @@ -140,6 +140,7 @@ static void ip_vs_nfct_expect_callback(s
>  {
>         struct nf_conntrack_tuple *orig, new_reply;
>         struct ip_vs_conn *cp;
> +       struct ip_vs_conn_param p;
>
>         if (exp->tuple.src.l3num != PF_INET)
>                 return;
> @@ -154,9 +155,10 @@ static void ip_vs_nfct_expect_callback(s
>
>         /* RS->CLIENT */
>         orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
> -       cp = ip_vs_conn_out_get(exp->tuple.src.l3num, orig->dst.protonum,
> -                               &orig->src.u3, orig->src.u.tcp.port,
> -                               &orig->dst.u3, orig->dst.u.tcp.port);
> +       ip_vs_conn_fill_param(exp->tuple.src.l3num, orig->dst.protonum,
> +                             &orig->src.u3, orig->src.u.tcp.port,
> +                             &orig->dst.u3, orig->dst.u.tcp.port, &p);
> +       cp = ip_vs_conn_out_get(&p);
>         if (cp) {
>                 /* Change reply CLIENT->RS to CLIENT->VS */
>                 new_reply = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
> @@ -176,9 +178,7 @@ static void ip_vs_nfct_expect_callback(s
>         }
>
>         /* CLIENT->VS */
> -       cp = ip_vs_conn_in_get(exp->tuple.src.l3num, orig->dst.protonum,
> -                              &orig->src.u3, orig->src.u.tcp.port,
> -                              &orig->dst.u3, orig->dst.u.tcp.port);
> +       cp = ip_vs_conn_in_get(&p);
>         if (cp) {
>                 /* Change reply VS->CLIENT to RS->CLIENT */
>                 new_reply = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
> Index: lvs-test-2.6/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
> ===================================================================
> --- lvs-test-2.6.orig/net/netfilter/ipvs/ip_vs_proto_ah_esp.c   2010-10-04 16:58:31.000000000 +0900
> +++ lvs-test-2.6/net/netfilter/ipvs/ip_vs_proto_ah_esp.c        2010-10-04 17:00:45.000000000 +0900
> @@ -40,6 +40,19 @@ struct isakmp_hdr {
>
>  #define PORT_ISAKMP    500
>
> +static void
> +ah_esp_conn_fill_param_proto(int af, const struct ip_vs_iphdr *iph,
> +                            int inverse, struct ip_vs_conn_param *p)
> +{
> +       if (likely(!inverse))
> +               ip_vs_conn_fill_param(af, IPPROTO_UDP,
> +                                     &iph->saddr, htons(PORT_ISAKMP),
> +                                     &iph->daddr, htons(PORT_ISAKMP), p);
> +       else
> +               ip_vs_conn_fill_param(af, IPPROTO_UDP,
> +                                     &iph->daddr, htons(PORT_ISAKMP),
> +                                     &iph->saddr, htons(PORT_ISAKMP), p);
> +}
>
>  static struct ip_vs_conn *
>  ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
> @@ -47,21 +60,10 @@ ah_esp_conn_in_get(int af, const struct
>                    int inverse)
>  {
>         struct ip_vs_conn *cp;
> +       struct ip_vs_conn_param p;
>
> -       if (likely(!inverse)) {
> -               cp = ip_vs_conn_in_get(af, IPPROTO_UDP,
> -                                      &iph->saddr,
> -                                      htons(PORT_ISAKMP),
> -                                      &iph->daddr,
> -                                      htons(PORT_ISAKMP));
> -       } else {
> -               cp = ip_vs_conn_in_get(af, IPPROTO_UDP,
> -                                      &iph->daddr,
> -                                      htons(PORT_ISAKMP),
> -                                      &iph->saddr,
> -                                      htons(PORT_ISAKMP));
> -       }
> -
> +       ah_esp_conn_fill_param_proto(af, iph, inverse, &p);
> +       cp = ip_vs_conn_in_get(&p);
>         if (!cp) {
>                 /*
>                  * We are not sure if the packet is from our
> @@ -87,21 +89,10 @@ ah_esp_conn_out_get(int af, const struct
>                     int inverse)
>  {
>         struct ip_vs_conn *cp;
> +       struct ip_vs_conn_param p;
>
> -       if (likely(!inverse)) {
> -               cp = ip_vs_conn_out_get(af, IPPROTO_UDP,
> -                                       &iph->saddr,
> -                                       htons(PORT_ISAKMP),
> -                                       &iph->daddr,
> -                                       htons(PORT_ISAKMP));
> -       } else {
> -               cp = ip_vs_conn_out_get(af, IPPROTO_UDP,
> -                                       &iph->daddr,
> -                                       htons(PORT_ISAKMP),
> -                                       &iph->saddr,
> -                                       htons(PORT_ISAKMP));
> -       }
> -
> +       ah_esp_conn_fill_param_proto(af, iph, inverse, &p);
> +       cp = ip_vs_conn_out_get(&p);
>         if (!cp) {
>                 IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet "
>                               "%s%s %s->%s\n",
> Index: lvs-test-2.6/net/netfilter/ipvs/ip_vs_sync.c
> ===================================================================
> --- lvs-test-2.6.orig/net/netfilter/ipvs/ip_vs_sync.c   2010-10-04 16:58:31.000000000 +0900
> +++ lvs-test-2.6/net/netfilter/ipvs/ip_vs_sync.c        2010-10-04 17:49:20.000000000 +0900
> @@ -301,6 +301,7 @@ static void ip_vs_process_message(const
>         struct ip_vs_conn *cp;
>         struct ip_vs_protocol *pp;
>         struct ip_vs_dest *dest;
> +       struct ip_vs_conn_param param;
>         char *p;
>         int i;
>
> @@ -370,18 +371,17 @@ static void ip_vs_process_message(const
>                         }
>                 }
>
> -               if (!(flags & IP_VS_CONN_F_TEMPLATE))
> -                       cp = ip_vs_conn_in_get(AF_INET, s->protocol,
> -                                              (union nf_inet_addr *)&s->caddr,
> -                                              s->cport,
> -                                              (union nf_inet_addr *)&s->vaddr,
> -                                              s->vport);
> -               else
> -                       cp = ip_vs_ct_in_get(AF_INET, s->protocol,
> -                                            (union nf_inet_addr *)&s->caddr,
> -                                            s->cport,
> -                                            (union nf_inet_addr *)&s->vaddr,
> -                                            s->vport);
> +               {
> +                       ip_vs_conn_fill_param(AF_INET, s->protocol,
> +                                             (union nf_inet_addr *)&s->caddr,
> +                                             s->cport,
> +                                             (union nf_inet_addr *)&s->vaddr,
> +                                             s->vport, &param);
> +                       if (!(flags & IP_VS_CONN_F_TEMPLATE))
> +                               cp = ip_vs_conn_in_get(&param);
> +                       else
> +                               cp = ip_vs_ct_in_get(&param);
> +               }
>                 if (!cp) {
>                         /*
>                          * Find the appropriate destination for the connection.
> @@ -406,14 +406,9 @@ static void ip_vs_process_message(const
>                                 else
>                                         flags &= ~IP_VS_CONN_F_INACTIVE;
>                         }
> -                       cp = ip_vs_conn_new(AF_INET, s->protocol,
> -                                           (union nf_inet_addr *)&s->caddr,
> -                                           s->cport,
> -                                           (union nf_inet_addr *)&s->vaddr,
> -                                           s->vport,
> +                       cp = ip_vs_conn_new(&param,
>                                             (union nf_inet_addr *)&s->daddr,
> -                                           s->dport,
> -                                           flags, dest);
> +                                           s->dport, flags, dest);
>                         if (dest)
>                                 atomic_dec(&dest->refcnt);
>                         if (!cp) {
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to [email-masked]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

Patch applied for patch :-)

iff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 52fbe23..7646ff7 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -670,9 +670,19 @@ static inline void ip_vs_conn_fill_param(int af, int protocol,
 {
 	p->af = af;
 	p->protocol = protocol;
-	p->caddr = caddr;
 	p->cport = cport;
-	p->vaddr = vaddr;
+#ifdef CONFIG_IP_VS_IPV6
+	if (af == AF_INET6) {
+		ipv6_addr_copy(&p->caddr, caddr);
+		ipv6_addr_copy(&p->caddr, caddr);
+	}
+	else
+#else
+	}
+		p->caddr = caddr;
+		p->vaddr = vaddr;
+	}
+#endif
 	p->vport = vport;
 	p->pe = NULL;
 	p->pe_data = NULL;

--
Regards
Hans Schillstrom <[email-masked]>