ipvs: always update some of the flags bits in backup
authorJulian Anastasov <ja@ssi.bg>
Tue, 24 Apr 2012 20:46:38 +0000 (23:46 +0300)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 8 May 2012 17:38:31 +0000 (19:38 +0200)
As the goal is to mirror the inactconns/activeconns
counters in the backup server, make sure the cp->flags are
updated even if cp is still not bound to dest. If cp->flags
are not updated ip_vs_bind_dest will rely only on the initial
flags when updating the counters. To avoid mistakes and
complicated checks for protocol state rely only on the
IP_VS_CONN_F_INACTIVE bit when updating the counters.

Signed-off-by: Julian Anastasov <ja@ssi.bg>
Tested-by: Aleksey Chudov <aleksey.chudov@gmail.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
include/linux/ip_vs.h
net/netfilter/ipvs/ip_vs_sync.c

index be0ef3df4acbe4ffbddec38356089343d6c0d6ce..8a2d438dc4999bfbb35b52a60325affdae7d9347 100644 (file)
@@ -89,6 +89,7 @@
 #define IP_VS_CONN_F_TEMPLATE  0x1000          /* template, not connection */
 #define IP_VS_CONN_F_ONE_PACKET        0x2000          /* forward only one packet */
 
+/* Initial bits allowed in backup server */
 #define IP_VS_CONN_F_BACKUP_MASK (IP_VS_CONN_F_FWD_MASK | \
                                  IP_VS_CONN_F_NOOUTPUT | \
                                  IP_VS_CONN_F_INACTIVE | \
                                  IP_VS_CONN_F_TEMPLATE \
                                 )
 
+/* Bits allowed to update in backup server */
+#define IP_VS_CONN_F_BACKUP_UPD_MASK (IP_VS_CONN_F_INACTIVE | \
+                                     IP_VS_CONN_F_SEQ_MASK)
+
 /* Flags that are not sent to backup server start from bit 16 */
 #define IP_VS_CONN_F_NFCT      (1 << 16)       /* use netfilter conntrack */
 
index bf5e538af67b9094c62dca4fad5f82ad1b2dee36..d2df694405f12badab10ef7464776c6ce226e0a4 100644 (file)
@@ -731,9 +731,30 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param,
        else
                cp = ip_vs_ct_in_get(param);
 
-       if (cp && param->pe_data)       /* Free pe_data */
+       if (cp) {
+               /* Free pe_data */
                kfree(param->pe_data);
-       if (!cp) {
+
+               dest = cp->dest;
+               if ((cp->flags ^ flags) & IP_VS_CONN_F_INACTIVE &&
+                   !(flags & IP_VS_CONN_F_TEMPLATE) && dest) {
+                       if (flags & IP_VS_CONN_F_INACTIVE) {
+                               atomic_dec(&dest->activeconns);
+                               atomic_inc(&dest->inactconns);
+                       } else {
+                               atomic_inc(&dest->activeconns);
+                               atomic_dec(&dest->inactconns);
+                       }
+               }
+               flags &= IP_VS_CONN_F_BACKUP_UPD_MASK;
+               flags |= cp->flags & ~IP_VS_CONN_F_BACKUP_UPD_MASK;
+               cp->flags = flags;
+               if (!dest) {
+                       dest = ip_vs_try_bind_dest(cp);
+                       if (dest)
+                               atomic_dec(&dest->refcnt);
+               }
+       } else {
                /*
                 * Find the appropriate destination for the connection.
                 * If it is not found the connection will remain unbound
@@ -742,18 +763,6 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param,
                dest = ip_vs_find_dest(net, type, daddr, dport, param->vaddr,
                                       param->vport, protocol, fwmark, flags);
 
-               /*  Set the approprite ativity flag */
-               if (protocol == IPPROTO_TCP) {
-                       if (state != IP_VS_TCP_S_ESTABLISHED)
-                               flags |= IP_VS_CONN_F_INACTIVE;
-                       else
-                               flags &= ~IP_VS_CONN_F_INACTIVE;
-               } else if (protocol == IPPROTO_SCTP) {
-                       if (state != IP_VS_SCTP_S_ESTABLISHED)
-                               flags |= IP_VS_CONN_F_INACTIVE;
-                       else
-                               flags &= ~IP_VS_CONN_F_INACTIVE;
-               }
                cp = ip_vs_conn_new(param, daddr, dport, flags, dest, fwmark);
                if (dest)
                        atomic_dec(&dest->refcnt);
@@ -763,34 +772,6 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param,
                        IP_VS_DBG(2, "BACKUP, add new conn. failed\n");
                        return;
                }
-       } else if (!cp->dest) {
-               dest = ip_vs_try_bind_dest(cp);
-               if (dest)
-                       atomic_dec(&dest->refcnt);
-       } else if ((cp->dest) && (cp->protocol == IPPROTO_TCP) &&
-               (cp->state != state)) {
-               /* update active/inactive flag for the connection */
-               dest = cp->dest;
-               if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
-                       (state != IP_VS_TCP_S_ESTABLISHED)) {
-                       atomic_dec(&dest->activeconns);
-                       atomic_inc(&dest->inactconns);
-                       cp->flags |= IP_VS_CONN_F_INACTIVE;
-               } else if ((cp->flags & IP_VS_CONN_F_INACTIVE) &&
-                       (state == IP_VS_TCP_S_ESTABLISHED)) {
-                       atomic_inc(&dest->activeconns);
-                       atomic_dec(&dest->inactconns);
-                       cp->flags &= ~IP_VS_CONN_F_INACTIVE;
-               }
-       } else if ((cp->dest) && (cp->protocol == IPPROTO_SCTP) &&
-               (cp->state != state)) {
-               dest = cp->dest;
-               if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
-               (state != IP_VS_SCTP_S_ESTABLISHED)) {
-                       atomic_dec(&dest->activeconns);
-                       atomic_inc(&dest->inactconns);
-                       cp->flags &= ~IP_VS_CONN_F_INACTIVE;
-               }
        }
 
        if (opt)