Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2804

kernel-2.6.18-238.el5.src.rpm

From: Thomas Graf <tgraf@redhat.com>
Date: Thu, 16 Sep 2010 07:56:34 -0400
Subject: [net] ipvs: add one-packet scheduler
Message-id: <20100916075634.GA17860@lsx.localdomain>
Patchwork-id: 28255
O-Subject: [PATCH RHEL5.6] ipvs: add one-packet scheduler (BZ578836)
Bugzilla: 578836
RH-Acked-by: Neil Horman <nhorman@redhat.com>
RH-Acked-by: David S. Miller <davem@redhat.com>
RH-Acked-by: Amerigo Wang <amwang@redhat.com>

A customer requested the inclusion of the one-packet scheduler
for ipvs as found in RHEL6 and upstream kernel. This patch
backports the one-packet scheduler.

Brew:
https://brewweb.devel.redhat.com/taskinfo?taskID=2764178

Tested by Jan Friesse.

Resolves BZ578836

Signed-off-by: Jarod Wilson <jarod@redhat.com>

diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 8616dab..25f6d3f 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -19,6 +19,7 @@
  */
 #define IP_VS_SVC_F_PERSISTENT	0x0001		/* persistent port */
 #define IP_VS_SVC_F_HASHED	0x0002		/* hashed entry */
+#define IP_VS_SVC_F_ONEPACKET	0x0004		/* one-packet scheduling */
 
 /*
  *      Destination Server Flags
@@ -85,6 +86,7 @@
 #define IP_VS_CONN_F_SEQ_MASK	0x0600		/* in/out sequence mask */
 #define IP_VS_CONN_F_NO_CPORT	0x0800		/* no client port set yet */
 #define IP_VS_CONN_F_TEMPLATE	0x1000		/* template, not connection */
+#define IP_VS_CONN_F_ONE_PACKET	0x2000		/* forward only one packet */
 
 /* Move it to better place one day, for now keep it unique */
 #define NFC_IPVS_PROPERTY	0x10000
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index 87b8381..3a0bb85 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -131,6 +131,9 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
 	unsigned hash;
 	int ret;
 
+	if (cp->flags & IP_VS_CONN_F_ONE_PACKET)
+		return 0;
+
 	/* Hash by protocol, client address and port */
 	hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr, cp->cport);
 
@@ -314,6 +317,11 @@ struct ip_vs_conn *ip_vs_conn_out_get
  */
 void ip_vs_conn_put(struct ip_vs_conn *cp)
 {
+	if (cp->flags & IP_VS_CONN_F_ONE_PACKET) {
+		ip_vs_conn_expire_now(cp);
+		return;
+	}
+
 	/* reset it expire in its timeout */
 	mod_timer(&cp->timer, jiffies+cp->timeout);
 
@@ -547,7 +555,7 @@ static void ip_vs_conn_expire(unsigned long data)
 	/*
 	 *	unhash it if it is hashed in the conn table
 	 */
-	if (!ip_vs_conn_unhash(cp))
+	if (!ip_vs_conn_unhash(cp) && !(cp->flags & IP_VS_CONN_F_ONE_PACKET))
 		goto expire_later;
 
 	/*
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 4efefd9..49c6efa 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -216,6 +216,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
 	struct ip_vs_dest *dest;
 	struct ip_vs_conn *ct;
 	__u16  dport;	 /* destination port to forward */
+	__u16 flags;
 	__u32  snet;	 /* source network of the client, after masking */
 
 	/* Mask saddr with the netmask to adjust template granularity */
@@ -346,6 +347,9 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
 		dport = ports[1];
 	}
 
+	flags = (svc->flags & IP_VS_SVC_F_ONEPACKET
+		 && iph->protocol == IPPROTO_UDP)?
+		IP_VS_CONN_F_ONE_PACKET : 0;
 	/*
 	 *    Create a new connection according to the template
 	 */
@@ -353,7 +357,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
 			    iph->saddr, ports[0],
 			    iph->daddr, ports[1],
 			    dest->addr, dport,
-			    0,
+			    flags,
 			    dest);
 	if (cp == NULL) {
 		ip_vs_conn_put(ct);
@@ -384,6 +388,7 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	struct iphdr *iph = skb->nh.iph;
 	struct ip_vs_dest *dest;
 	__u16 _ports[2], *pptr;
+	__u16 flags;
 
 	pptr = skb_header_pointer(skb, iph->ihl*4,
 				  sizeof(_ports), _ports);
@@ -413,6 +418,9 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 		return NULL;
 	}
 
+	flags = (svc->flags & IP_VS_SVC_F_ONEPACKET
+		 && iph->protocol == IPPROTO_UDP)?
+		IP_VS_CONN_F_ONE_PACKET : 0;
 	/*
 	 *    Create a connection entry.
 	 */
@@ -420,7 +428,7 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 			    iph->saddr, pptr[0],
 			    iph->daddr, pptr[1],
 			    dest->addr, dest->port?dest->port:pptr[1],
-			    0,
+			    flags,
 			    dest);
 	if (cp == NULL)
 		return NULL;
@@ -463,6 +471,9 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 	    && (inet_addr_type(iph->daddr) == RTN_UNICAST)) {
 		int ret, cs;
 		struct ip_vs_conn *cp;
+		__u16 flags = (svc->flags & IP_VS_SVC_F_ONEPACKET &&
+				iph->protocol == IPPROTO_UDP)?
+				IP_VS_CONN_F_ONE_PACKET : 0;
 
 		ip_vs_service_put(svc);
 
@@ -472,7 +483,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 				    iph->saddr, pptr[0],
 				    iph->daddr, pptr[1],
 				    0, 0,
-				    IP_VS_CONN_F_BYPASS,
+				    IP_VS_CONN_F_BYPASS | flags,
 				    NULL);
 		if (cp == NULL)
 			return NF_DROP;
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 6a28faf..c47c415 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -1754,14 +1754,18 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v)
 		const struct ip_vs_dest *dest;
 
 		if (iter->table == ip_vs_svc_table)
-			seq_printf(seq, "%s  %08X:%04X %s ",
+			seq_printf(seq, "%s  %08X:%04X %s%s ",
 				   ip_vs_proto_name(svc->protocol),
 				   ntohl(svc->addr),
 				   ntohs(svc->port),
-				   svc->scheduler->name);
+				   svc->scheduler->name,
+				   (svc->flags & IP_VS_SVC_F_ONEPACKET)?
+				   " ops":"");
 		else
-			seq_printf(seq, "FWM  %08X %s ",
-				   svc->fwmark, svc->scheduler->name);
+			seq_printf(seq, "FWM  %08X %s%s ",
+				   svc->fwmark, svc->scheduler->name,
+				   (svc->flags & IP_VS_SVC_F_ONEPACKET)?
+				   " ops":"");
 
 		if (svc->flags & IP_VS_SVC_F_PERSISTENT)
 			seq_printf(seq, "persistent %d %08X\n",