Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 2276

kernel-2.6.18-194.11.1.el5.src.rpm

From: Danny Feng <dfeng@redhat.com>
Date: Thu, 26 Nov 2009 11:06:46 -0500
Subject: [net] ipvs: synchronize closing of connections
Message-id: <20091126110712.17569.46851.sendpatchset@dhcp-65-180.nay.redhat.com>
Patchwork-id: 21517
O-Subject: [PATCH RHEL5.5] [IPVS]: Synchronize closing of Connections
Bugzilla: 492942
RH-Acked-by: David S. Miller <davem@redhat.com>

RHBZ#:
https://bugzilla.redhat.com/show_bug.cgi?id=492942

Description:
This bz reports two issues about lvs. The first one is LVS connection timeout
hard-coded on slave server, which is resolved in bz524129 by Neil.

The "connection state" wasn't replicated correctly between Master and Slave servers,
is the second issue. For example, When a connection is closed, on Master server
connection's state is CLOSE_WAIT and after few seconds, TIME_WAIT. On the Slave server,
connection's state remains ESTABLISHED until the connection timeout value is reached.

Upstream status:
commit efac527 is the fix, almost the same as upstream patches. The only different line
is already added in Neil's patch.

KABI:
no harm

Brew Build#:
http://brewweb.devel.redhat.com/brew/taskinfo?taskID=2106061

Please review, any comments are welcome.

diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 6f0c2ea..8616dab 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -520,7 +520,10 @@ struct ip_vs_conn {
 	spinlock_t              lock;           /* lock for state transition */
 	volatile __u16          flags;          /* status flags */
 	volatile __u16          state;          /* state info */
-
+	volatile __u16          old_state;      /* old state, to be used for   
+						 * state transition triggerd   
+						 * synchronization             
+						 */
 	/* Control members */
 	struct ip_vs_conn       *control;       /* Master control connection */
 	atomic_t                n_control;      /* Number of controlled ones */
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 95d1e93..4efefd9 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -1033,15 +1033,23 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb,
 		ret = NF_ACCEPT;
 	}
 
-	/* increase its packet counter and check if it is needed
-	   to be synchronized */
+	/* Increase its packet counter and check if it is needed               
+	 * to be synchronized                                                  
+	 *                                                                     
+	 * Sync connection if it is about to close to                          
+	 * encorage the standby servers to update the connections timeout      
+	 */
 	atomic_inc(&cp->in_pkts);
 	if ((ip_vs_sync_state & IP_VS_STATE_MASTER) &&
-	    (cp->protocol != IPPROTO_TCP ||
-	     cp->state == IP_VS_TCP_S_ESTABLISHED) &&
-	    (atomic_read(&cp->in_pkts) % sysctl_ip_vs_sync_threshold[1]
-	     == sysctl_ip_vs_sync_threshold[0]))
+	    (((cp->protocol != IPPROTO_TCP ||
+	       cp->state == IP_VS_TCP_S_ESTABLISHED) &&
+	      (atomic_read(&cp->in_pkts) % sysctl_ip_vs_sync_threshold[1]
+	       == sysctl_ip_vs_sync_threshold[0])) ||
+	     ((cp->protocol == IPPROTO_TCP) && (cp->old_state != cp->state) &&
+	      ((cp->state == IP_VS_TCP_S_FIN_WAIT) ||
+	       (cp->state == IP_VS_TCP_S_CLOSE)))))
 		ip_vs_sync_conn(cp);
+	cp->old_state = cp->state;
 
 	ip_vs_conn_put(cp);
 	return ret;
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 03fcde8..6caa10b 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -371,7 +371,6 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
 			}
 		} else if (!cp->dest) {
 			/* it is an entry created by the synchronization */
-			cp->state = ntohs(s->state);
 			cp->flags = flags | IP_VS_CONN_F_HASHED;
 		}	/* Note that we don't touch its state and flags
 			   if it is a normal entry. */