diff -ur linux-2.6.32.7/include/linux/ip_vs.h linux-2.6.32.7-ops/include/linux/ip_vs.h --- linux-2.6.32.7/include/linux/ip_vs.h 2010-01-28 23:06:20.000000000 +0000 +++ linux-2.6.32.7-ops/include/linux/ip_vs.h 2010-04-28 23:40:56.000000000 +0100 @@ -19,7 +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,7 +85,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 */ #define IP_VS_SCHEDNAME_MAXLEN 16 #define IP_VS_IFNAME_MAXLEN 16 diff -ur linux-2.6.32.7/Makefile linux-2.6.32.7-ops/Makefile --- linux-2.6.32.7/Makefile 2010-01-28 23:06:20.000000000 +0000 +++ linux-2.6.32.7-ops/Makefile 2010-04-28 23:47:39.000000000 +0100 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 32 -EXTRAVERSION = .7 +EXTRAVERSION = .7-ops NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* diff -ur linux-2.6.32.7/net/netfilter/ipvs/ip_vs_conn.c linux-2.6.32.7-ops/net/netfilter/ipvs/ip_vs_conn.c --- linux-2.6.32.7/net/netfilter/ipvs/ip_vs_conn.c 2010-01-28 23:06:20.000000000 +0000 +++ linux-2.6.32.7-ops/net/netfilter/ipvs/ip_vs_conn.c 2010-05-14 10:09:48.000000000 +0100 @@ -142,6 +142,9 @@ 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->af, cp->protocol, &cp->caddr, cp->cport); @@ -339,8 +342,9 @@ */ void ip_vs_conn_put(struct ip_vs_conn *cp) { - /* reset it expire in its timeout */ - mod_timer(&cp->timer, jiffies+cp->timeout); + unsigned long t = (cp->flags & IP_VS_CONN_F_ONE_PACKET) ? + 0 : cp->timeout; + mod_timer(&cp->timer, jiffies+t); __ip_vs_conn_put(cp); } @@ -633,7 +637,7 @@ /* * 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 -ur linux-2.6.32.7/net/netfilter/ipvs/ip_vs_core.c linux-2.6.32.7-ops/net/netfilter/ipvs/ip_vs_core.c --- linux-2.6.32.7/net/netfilter/ipvs/ip_vs_core.c 2010-01-28 23:06:20.000000000 +0000 +++ linux-2.6.32.7-ops/net/netfilter/ipvs/ip_vs_core.c 2010-05-14 10:11:17.000000000 +0100 @@ -189,7 +189,8 @@ struct ip_vs_iphdr iph; struct ip_vs_dest *dest; struct ip_vs_conn *ct; - __be16 dport; /* destination port to forward */ + __be16 dport; + __be16 flags; /* destination port to forward */ union nf_inet_addr snet; /* source network of the client, after masking */ @@ -336,6 +337,10 @@ 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 */ @@ -343,7 +348,7 @@ &iph.saddr, ports[0], &iph.daddr, ports[1], &dest->addr, dport, - 0, + flags, dest); if (cp == NULL) { ip_vs_conn_put(ct); @@ -373,7 +378,7 @@ struct ip_vs_conn *cp = NULL; struct ip_vs_iphdr iph; struct ip_vs_dest *dest; - __be16 _ports[2], *pptr; + __be16 _ports[2], *pptr, flags; ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph); pptr = skb_header_pointer(skb, iph.len, sizeof(_ports), _ports); @@ -403,6 +408,10 @@ 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. */ @@ -410,7 +419,7 @@ &iph.saddr, pptr[0], &iph.daddr, pptr[1], &dest->addr, dest->port ? dest->port : pptr[1], - 0, + flags, dest); if (cp == NULL) return NULL; @@ -460,6 +469,9 @@ if (sysctl_ip_vs_cache_bypass && svc->fwmark && 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; union nf_inet_addr daddr = { .all = { 0, 0, 0, 0 } }; ip_vs_service_put(svc); @@ -470,7 +482,7 @@ &iph.saddr, pptr[0], &iph.daddr, pptr[1], &daddr, 0, - IP_VS_CONN_F_BYPASS, + IP_VS_CONN_F_BYPASS | flags, NULL); if (cp == NULL) return NF_DROP; diff -ur linux-2.6.32.7/net/netfilter/ipvs/ip_vs_ctl.c linux-2.6.32.7-ops/net/netfilter/ipvs/ip_vs_ctl.c --- linux-2.6.32.7/net/netfilter/ipvs/ip_vs_ctl.c 2010-01-28 23:06:20.000000000 +0000 +++ linux-2.6.32.7-ops/net/netfilter/ipvs/ip_vs_ctl.c 2010-04-28 23:40:56.000000000 +0100 @@ -1863,14 +1863,16 @@ svc->scheduler->name); else #endif - seq_printf(seq, "%s %08X:%04X %s ", + seq_printf(seq, "%s %08X:%04X %s %s ", ip_vs_proto_name(svc->protocol), ntohl(svc->addr.ip), 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)