netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [2.4/2.6] ipvs: improve conn rehashing, other fixes
@ 2004-03-21 18:46 Julian Anastasov
  2004-03-22  7:07 ` David S. Miller
  0 siblings, 1 reply; 10+ messages in thread
From: Julian Anastasov @ 2004-03-21 18:46 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, Wensong Zhang

[-- Attachment #1: Type: TEXT/PLAIN, Size: 401 bytes --]


	Hello,

	Attached are some fixes for IPVS for Linux 2.4 and 2.6:

- Brett E. <brettspamacct@fastclick.com> noticed the missing svc
lock for dest edit

- improve the rehashing during cport changes

- one old/lost fix for 2.4: the h.raw update for tunneling

	The same changes are here:

http://www.ssi.bg/~ja/tmp/ipvs-2.6/
http://www.ssi.bg/~ja/tmp/ipvs-2.4/

Regards

--
Julian Anastasov <ja@ssi.bg>

[-- Attachment #2: 2.4 - svc lock --]
[-- Type: TEXT/PLAIN, Size: 536 bytes --]

diff -ur v2.4.25/linux/net/ipv4/ipvs/ip_vs_ctl.c linux/net/ipv4/ipvs/ip_vs_ctl.c
--- v2.4.25/linux/net/ipv4/ipvs/ip_vs_ctl.c	2003-11-28 22:04:14.000000000 +0200
+++ linux/net/ipv4/ipvs/ip_vs_ctl.c	2004-03-20 11:24:28.574545872 +0200
@@ -892,9 +892,13 @@
 
 	__ip_vs_update_dest(svc, dest, ur);
 
+	write_lock_bh(&__ip_vs_svc_lock);
+
 	/* call the update_service, because server weight may be changed */
 	svc->scheduler->update_service(svc);
 
+	write_unlock_bh(&__ip_vs_svc_lock);
+
 	LeaveFunction(2);
 
 	return 0;

[-- Attachment #3: 2.4 - improve unhashing --]
[-- Type: TEXT/PLAIN, Size: 3508 bytes --]

diff -ur v2.4.25/linux/net/ipv4/ipvs/ip_vs_conn.c linux/net/ipv4/ipvs/ip_vs_conn.c
--- v2.4.25/linux/net/ipv4/ipvs/ip_vs_conn.c	2003-11-28 22:04:14.000000000 +0200
+++ linux/net/ipv4/ipvs/ip_vs_conn.c	2004-03-21 19:33:35.802303232 +0200
@@ -141,25 +141,27 @@
 static int ip_vs_conn_hash(struct ip_vs_conn *cp)
 {
 	unsigned hash;
-
-	if (cp->flags & IP_VS_CONN_F_HASHED) {
-		IP_VS_ERR("ip_vs_conn_hash(): request for already hashed, "
-			  "called from %p\n", __builtin_return_address(0));
-		return 0;
-	}
+	int ret;
 
 	/* Hash by protocol, client address and port */
 	hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr, cp->cport);
 
 	ct_write_lock(hash);
 
-	list_add(&cp->c_list, &ip_vs_conn_tab[hash]);
-	cp->flags |= IP_VS_CONN_F_HASHED;
-	atomic_inc(&cp->refcnt);
+	if (!(cp->flags & IP_VS_CONN_F_HASHED)) {
+		list_add(&cp->c_list, &ip_vs_conn_tab[hash]);
+		cp->flags |= IP_VS_CONN_F_HASHED;
+		atomic_inc(&cp->refcnt);
+		ret = 1;
+	} else {
+		IP_VS_ERR("ip_vs_conn_hash(): request for already hashed, "
+			  "called from %p\n", __builtin_return_address(0));
+		ret = 0;
+	}
 
 	ct_write_unlock(hash);
 
-	return 1;
+	return ret;
 }
 
 
@@ -170,24 +172,23 @@
 static int ip_vs_conn_unhash(struct ip_vs_conn *cp)
 {
 	unsigned hash;
-
-	if (!(cp->flags & IP_VS_CONN_F_HASHED)) {
-		IP_VS_ERR("ip_vs_conn_unhash(): request for unhash flagged, "
-			  "called from %p\n", __builtin_return_address(0));
-		return 0;
-	}
+	int ret;
 
 	/* unhash it and decrease its reference counter */
 	hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr, cp->cport);
 	ct_write_lock(hash);
 
-	list_del(&cp->c_list);
-	cp->flags &= ~IP_VS_CONN_F_HASHED;
-	atomic_dec(&cp->refcnt);
+	if (cp->flags & IP_VS_CONN_F_HASHED) {
+		list_del(&cp->c_list);
+		cp->flags &= ~IP_VS_CONN_F_HASHED;
+		atomic_dec(&cp->refcnt);
+		ret = 1;
+	} else
+		ret = 0;
 
 	ct_write_unlock(hash);
 
-	return 1;
+	return ret;
 }
 
 
@@ -725,15 +726,20 @@
 	/*
 	 *  Check if it is no_cport connection ...
 	 */
-	if (cp->flags & IP_VS_CONN_F_NO_CPORT) {
-		atomic_dec(&ip_vs_conn_no_cport_cnt);
-		ip_vs_conn_unhash(cp);
-		cp->flags &= ~IP_VS_CONN_F_NO_CPORT;
-		cp->cport = h.portp[0];
-		/* hash on new dport */
-		ip_vs_conn_hash(cp);
+	if (unlikely(cp->flags & IP_VS_CONN_F_NO_CPORT)) {
+		if (ip_vs_conn_unhash(cp)) {
+			spin_lock(&cp->lock);
+			if (cp->flags & IP_VS_CONN_F_NO_CPORT) {
+				atomic_dec(&ip_vs_conn_no_cport_cnt);
+				cp->flags &= ~IP_VS_CONN_F_NO_CPORT;
+				cp->cport = h.portp[0];
+				IP_VS_DBG(10, "filled cport=%d\n", ntohs(cp->dport));
+			}
+			spin_unlock(&cp->lock);
 
-		IP_VS_DBG(10, "filled cport=%d\n", ntohs(cp->dport));
+			/* hash on new dport */
+			ip_vs_conn_hash(cp);
+		}
 	}
 
 	if (!(rt = __ip_vs_get_out_rt(cp, RT_TOS(iph->tos))))
@@ -1142,11 +1148,14 @@
 		/*
 		 * Invalidate the connection template
 		 */
-		ip_vs_conn_unhash(ct);
-		ct->dport = 65535;
-		ct->vport = 65535;
-		ct->cport = 0;
-		ip_vs_conn_hash(ct);
+		if (ct->cport) {
+			if (ip_vs_conn_unhash(ct)) {
+				ct->dport = 65535;
+				ct->vport = 65535;
+				ct->cport = 0;
+				ip_vs_conn_hash(ct);
+			}
+		}
 
 		/*
 		 * Simply decrease the refcnt of the template,
@@ -1200,7 +1209,8 @@
 	/*
 	 *	unhash it if it is hashed in the conn table
 	 */
-	ip_vs_conn_unhash(cp);
+	if (!ip_vs_conn_unhash(cp))
+		goto expire_later;
 
 	/*
 	 *	refcnt==1 implies I'm the only one referrer

[-- Attachment #4: 2.4 - h.raw --]
[-- Type: TEXT/PLAIN, Size: 654 bytes --]

diff -ur v2.4.25/linux/net/ipv4/ipvs/ip_vs_conn.c linux/net/ipv4/ipvs/ip_vs_conn.c
--- v2.4.25/linux/net/ipv4/ipvs/ip_vs_conn.c	2003-11-28 22:04:14.000000000 +0200
+++ linux/net/ipv4/ipvs/ip_vs_conn.c	2004-03-20 11:19:35.121157568 +0200
@@ -890,8 +890,6 @@
 	/* update checksum because skb might be defragmented */
 	ip_send_check(old_iph);
 
-	skb->h.raw = skb->nh.raw;
-
 	/*
 	 * Okay, now see if we can stuff it in the buffer as-is.
 	 */
@@ -911,6 +909,7 @@
 		old_iph = skb->nh.iph;
 	}
 
+	skb->h.raw = skb->nh.raw;
 	skb->nh.raw = skb_push(skb, sizeof(struct iphdr));
 	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
 

[-- Attachment #5: 2.6 - svc lock --]
[-- Type: TEXT/PLAIN, Size: 1049 bytes --]

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.1818  -> 1.1819 
#	net/ipv4/ipvs/ip_vs_ctl.c	1.14    -> 1.15   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 04/03/20	brettspamacct@fastclick.com	1.1819
# [IPVS]: Hold the svc lock during service update in dest edit
# --------------------------------------------
#
diff -Nru a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
--- a/net/ipv4/ipvs/ip_vs_ctl.c	Sat Mar 20 16:45:13 2004
+++ b/net/ipv4/ipvs/ip_vs_ctl.c	Sat Mar 20 16:45:13 2004
@@ -898,8 +898,12 @@
 
 	__ip_vs_update_dest(svc, dest, udest);
 
+	write_lock_bh(&__ip_vs_svc_lock);
+
 	/* call the update_service, because server weight may be changed */
 	svc->scheduler->update_service(svc);
+
+	write_unlock_bh(&__ip_vs_svc_lock);
 
 	LeaveFunction(2);
 

[-- Attachment #6: 2.6 - improve unhashing --]
[-- Type: TEXT/PLAIN, Size: 3729 bytes --]

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.1818  -> 1.1819 
#	net/ipv4/ipvs/ip_vs_conn.c	1.13    -> 1.14   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 04/03/21	ja@ssi.bg	1.1819
# [IPVS]: Improve the rehashing with new cport
# --------------------------------------------
#
diff -Nru a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
--- a/net/ipv4/ipvs/ip_vs_conn.c	Sun Mar 21 19:44:22 2004
+++ b/net/ipv4/ipvs/ip_vs_conn.c	Sun Mar 21 19:44:22 2004
@@ -125,25 +125,27 @@
 static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
 {
 	unsigned hash;
-
-	if (cp->flags & IP_VS_CONN_F_HASHED) {
-		IP_VS_ERR("ip_vs_conn_hash(): request for already hashed, "
-			  "called from %p\n", __builtin_return_address(0));
-		return 0;
-	}
+	int ret;
 
 	/* Hash by protocol, client address and port */
 	hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr, cp->cport);
 
 	ct_write_lock(hash);
 
-	list_add(&cp->c_list, &ip_vs_conn_tab[hash]);
-	cp->flags |= IP_VS_CONN_F_HASHED;
-	atomic_inc(&cp->refcnt);
+	if (!(cp->flags & IP_VS_CONN_F_HASHED)) {
+		list_add(&cp->c_list, &ip_vs_conn_tab[hash]);
+		cp->flags |= IP_VS_CONN_F_HASHED;
+		atomic_inc(&cp->refcnt);
+		ret = 1;
+	} else {
+		IP_VS_ERR("ip_vs_conn_hash(): request for already hashed, "
+			  "called from %p\n", __builtin_return_address(0));
+		ret = 0;
+	}
 
 	ct_write_unlock(hash);
 
-	return 1;
+	return ret;
 }
 
 
@@ -154,24 +156,24 @@
 static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
 {
 	unsigned hash;
-
-	if (!(cp->flags & IP_VS_CONN_F_HASHED)) {
-		IP_VS_ERR("ip_vs_conn_unhash(): request for unhash flagged, "
-			  "called from %p\n", __builtin_return_address(0));
-		return 0;
-	}
+	int ret;
 
 	/* unhash it and decrease its reference counter */
 	hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr, cp->cport);
+
 	ct_write_lock(hash);
 
-	list_del(&cp->c_list);
-	cp->flags &= ~IP_VS_CONN_F_HASHED;
-	atomic_dec(&cp->refcnt);
+	if (cp->flags & IP_VS_CONN_F_HASHED) {
+		list_del(&cp->c_list);
+		cp->flags &= ~IP_VS_CONN_F_HASHED;
+		atomic_dec(&cp->refcnt);
+		ret = 1;
+	} else
+		ret = 0;
 
 	ct_write_unlock(hash);
 
-	return 1;
+	return ret;
 }
 
 
@@ -285,12 +287,18 @@
  */
 void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __u16 cport)
 {
-	atomic_dec(&ip_vs_conn_no_cport_cnt);
-	ip_vs_conn_unhash(cp);
-	cp->flags &= ~IP_VS_CONN_F_NO_CPORT;
-	cp->cport = cport;
-	/* hash on new dport */
-	ip_vs_conn_hash(cp);
+	if (ip_vs_conn_unhash(cp)) {
+		spin_lock(&cp->lock);
+		if (cp->flags & IP_VS_CONN_F_NO_CPORT) {
+			atomic_dec(&ip_vs_conn_no_cport_cnt);
+			cp->flags &= ~IP_VS_CONN_F_NO_CPORT;
+			cp->cport = cport;
+		}
+		spin_unlock(&cp->lock);
+
+		/* hash on new dport */
+		ip_vs_conn_hash(cp);
+	}
 }
 
 
@@ -457,11 +465,14 @@
 		/*
 		 * Invalidate the connection template
 		 */
-		ip_vs_conn_unhash(ct);
-		ct->dport = 65535;
-		ct->vport = 65535;
-		ct->cport = 0;
-		ip_vs_conn_hash(ct);
+		if (ct->cport) {
+			if (ip_vs_conn_unhash(ct)) {
+				ct->dport = 65535;
+				ct->vport = 65535;
+				ct->cport = 0;
+				ip_vs_conn_hash(ct);
+			}
+		}
 
 		/*
 		 * Simply decrease the refcnt of the template,
@@ -493,7 +504,8 @@
 	/*
 	 *	unhash it if it is hashed in the conn table
 	 */
-	ip_vs_conn_unhash(cp);
+	if (!ip_vs_conn_unhash(cp))
+		goto expire_later;
 
 	/*
 	 *	refcnt==1 implies I'm the only one referrer

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2004-03-24 21:59 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-03-21 18:46 [2.4/2.6] ipvs: improve conn rehashing, other fixes Julian Anastasov
2004-03-22  7:07 ` David S. Miller
2004-03-22 11:26   ` Julian Anastasov
2004-03-22 13:21   ` Wensong Zhang
2004-03-22 16:58   ` Wensong Zhang
2004-03-23  2:36     ` David S. Miller
2004-03-23  8:34       ` Julian Anastasov
2004-03-23  8:40         ` David S. Miller
2004-03-23  8:48           ` Julian Anastasov
2004-03-24 21:59             ` David S. Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).