Skip to content

Commit

Permalink
IPVS: one-packet scheduling
Browse files Browse the repository at this point in the history
Allow one-packet scheduling for UDP connections. When the fwmark-based or
normal virtual service is marked with '-o' or '--ops' options all
connections are created only to schedule one packet. Useful to schedule UDP
packets from same client port to different real servers. Recommended with
RR or WRR schedulers (the connections are not visible with ipvsadm -L).

Signed-off-by: Nick Chalk <[email protected]>
Signed-off-by: Simon Horman <[email protected]>
Signed-off-by: Patrick McHardy <[email protected]>
  • Loading branch information
Nick Chalk authored and kaber committed Jun 22, 2010
1 parent c68cd6c commit 26ec037
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 11 deletions.
2 changes: 2 additions & 0 deletions include/linux/ip_vs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */

#define IP_VS_SCHEDNAME_MAXLEN 16
#define IP_VS_IFNAME_MAXLEN 16
Expand Down
10 changes: 7 additions & 3 deletions net/netfilter/ipvs/ip_vs_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,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->af, cp->protocol, &cp->caddr, cp->cport);

Expand Down Expand Up @@ -355,8 +358,9 @@ struct ip_vs_conn *ip_vs_conn_out_get
*/
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);
}
Expand Down Expand Up @@ -649,7 +653,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;

/*
Expand Down
20 changes: 16 additions & 4 deletions net/netfilter/ipvs/ip_vs_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
struct ip_vs_dest *dest;
struct ip_vs_conn *ct;
__be16 dport; /* destination port to forward */
__be16 flags;
union nf_inet_addr snet; /* source network of the client,
after masking */

Expand Down Expand Up @@ -340,14 +341,18 @@ 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
*/
cp = ip_vs_conn_new(svc->af, iph.protocol,
&iph.saddr, ports[0],
&iph.daddr, ports[1],
&dest->addr, dport,
0,
flags,
dest);
if (cp == NULL) {
ip_vs_conn_put(ct);
Expand Down Expand Up @@ -377,7 +382,7 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
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);
Expand Down Expand Up @@ -407,14 +412,18 @@ 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.
*/
cp = ip_vs_conn_new(svc->af, iph.protocol,
&iph.saddr, pptr[0],
&iph.daddr, pptr[1],
&dest->addr, dest->port ? dest->port : pptr[1],
0,
flags,
dest);
if (cp == NULL)
return NULL;
Expand Down Expand Up @@ -464,6 +473,9 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
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);
Expand All @@ -474,7 +486,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
&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;
Expand Down
10 changes: 6 additions & 4 deletions net/netfilter/ipvs/ip_vs_ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1864,14 +1864,16 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v)
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)
Expand Down

0 comments on commit 26ec037

Please sign in to comment.