diff -ur v2.4.26/linux/include/net/ip_vs.h linux/include/net/ip_vs.h --- v2.4.26/linux/include/net/ip_vs.h 2004-03-28 16:23:57.000000000 +0300 +++ linux/include/net/ip_vs.h 2004-03-31 00:09:01.717956912 +0300 @@ -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 @@ -82,6 +83,7 @@ #define IP_VS_CONN_F_IN_SEQ 0x0400 /* must do input seq adjust */ #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_ONE_PACKET 0x1000 /* forward only one packet */ /* Move it to better place one day, for now keep it unique */ #define NFC_IPVS_PROPERTY 0x10000 diff -ur v2.4.26/linux/net/ipv4/ipvs/ip_vs_conn.c linux/net/ipv4/ipvs/ip_vs_conn.c --- v2.4.26/linux/net/ipv4/ipvs/ip_vs_conn.c 2004-03-28 16:23:57.000000000 +0300 +++ linux/net/ipv4/ipvs/ip_vs_conn.c 2004-03-31 00:55:34.256426536 +0300 @@ -139,6 +139,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->protocol, cp->caddr, cp->cport); @@ -292,6 +295,11 @@ */ 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); @@ -1204,7 +1212,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 v2.4.26/linux/net/ipv4/ipvs/ip_vs_core.c linux/net/ipv4/ipvs/ip_vs_core.c --- v2.4.26/linux/net/ipv4/ipvs/ip_vs_core.c 2003-11-28 22:04:14.000000000 +0200 +++ linux/net/ipv4/ipvs/ip_vs_core.c 2004-03-31 00:29:52.246847624 +0300 @@ -159,6 +159,7 @@ const __u16 *portp; struct ip_vs_conn *ct; __u16 dport; /* destination port to forward */ + __u16 flags; __u32 snet; /* source network of the client, after masking */ portp = (__u16 *)&(((char *)iph)[iph->ihl*4]); @@ -290,6 +291,9 @@ dport = portp[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 */ @@ -297,7 +301,7 @@ iph->saddr, portp[0], iph->daddr, portp[1], dest->addr, dport, - 0, + flags, dest); if (cp == NULL) { ip_vs_conn_put(ct); @@ -332,6 +336,7 @@ struct ip_vs_conn *cp = NULL; struct ip_vs_dest *dest; const __u16 *portp; + __u16 flags; /* * Persistent service @@ -357,6 +362,9 @@ 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. */ @@ -364,7 +372,7 @@ iph->saddr, portp[0], iph->daddr, portp[1], dest->addr, dest->port?dest->port:portp[1], - 0, + flags, dest); if (cp == NULL) return NULL; @@ -404,6 +412,9 @@ && (inet_addr_type(iph->daddr) == RTN_UNICAST)) { int ret; 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); @@ -413,7 +424,7 @@ iph->saddr, portp[0], iph->daddr, portp[1], 0, 0, - IP_VS_CONN_F_BYPASS, + IP_VS_CONN_F_BYPASS | flags, NULL); if (cp == NULL) { kfree_skb(skb); diff -ur v2.4.26/linux/net/ipv4/ipvs/ip_vs_ctl.c linux/net/ipv4/ipvs/ip_vs_ctl.c --- v2.4.26/linux/net/ipv4/ipvs/ip_vs_ctl.c 2004-03-28 16:23:57.000000000 +0300 +++ linux/net/ipv4/ipvs/ip_vs_ctl.c 2004-03-31 00:45:36.897238936 +0300 @@ -1517,11 +1517,13 @@ else temp2[0] = '\0'; - sprintf(temp, "%s %08X:%04X %s %s", + sprintf(temp, "%s %08X:%04X %s %s%s", ip_vs_proto_name(svc->protocol), ntohl(svc->addr), ntohs(svc->port), - svc->scheduler->name, temp2); + svc->scheduler->name, temp2, + (svc->flags & IP_VS_SVC_F_ONEPACKET)? + " ops":""); len += sprintf(buf+len, "%-63s\n", temp); if (len >= length) goto done; @@ -1562,9 +1564,11 @@ else temp2[0] = '\0'; - sprintf(temp, "FWM %08X %s %s", + sprintf(temp, "FWM %08X %s %s%s", svc->fwmark, - svc->scheduler->name, temp2); + svc->scheduler->name, temp2, + (svc->flags & IP_VS_SVC_F_ONEPACKET)? + " ops":""); len += sprintf(buf+len, "%-63s\n", temp); if (len >= length) goto done;