aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Chalk <nick@loadbalancer.org>2010-06-22 02:07:01 -0400
committerPatrick McHardy <kaber@trash.net>2010-06-22 02:07:01 -0400
commit26ec037f9841e49cc5c615deb8e1e73e5beab2ca (patch)
treea7c4a77d173dd8759ed413a60b2941cbb1fca899
parentc68cd6cc21eb329c47ff020ff7412bf58176984e (diff)
IPVS: one-packet scheduling
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 <nick@loadbalancer.org> Signed-off-by: Simon Horman <horms@verge.net.au> Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--include/linux/ip_vs.h2
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c10
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c20
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c10
4 files changed, 31 insertions, 11 deletions
diff --git a/include/linux/ip_vs.h b/include/linux/ip_vs.h
index dfc17036284..9708de265bb 100644
--- a/include/linux/ip_vs.h
+++ b/include/linux/ip_vs.h
@@ -19,6 +19,7 @@
19 */ 19 */
20#define IP_VS_SVC_F_PERSISTENT 0x0001 /* persistent port */ 20#define IP_VS_SVC_F_PERSISTENT 0x0001 /* persistent port */
21#define IP_VS_SVC_F_HASHED 0x0002 /* hashed entry */ 21#define IP_VS_SVC_F_HASHED 0x0002 /* hashed entry */
22#define IP_VS_SVC_F_ONEPACKET 0x0004 /* one-packet scheduling */
22 23
23/* 24/*
24 * Destination Server Flags 25 * Destination Server Flags
@@ -85,6 +86,7 @@
85#define IP_VS_CONN_F_SEQ_MASK 0x0600 /* in/out sequence mask */ 86#define IP_VS_CONN_F_SEQ_MASK 0x0600 /* in/out sequence mask */
86#define IP_VS_CONN_F_NO_CPORT 0x0800 /* no client port set yet */ 87#define IP_VS_CONN_F_NO_CPORT 0x0800 /* no client port set yet */
87#define IP_VS_CONN_F_TEMPLATE 0x1000 /* template, not connection */ 88#define IP_VS_CONN_F_TEMPLATE 0x1000 /* template, not connection */
89#define IP_VS_CONN_F_ONE_PACKET 0x2000 /* forward only one packet */
88 90
89#define IP_VS_SCHEDNAME_MAXLEN 16 91#define IP_VS_SCHEDNAME_MAXLEN 16
90#define IP_VS_IFNAME_MAXLEN 16 92#define IP_VS_IFNAME_MAXLEN 16
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index d8f7e8ef67b..717e6233d50 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -158,6 +158,9 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
158 unsigned hash; 158 unsigned hash;
159 int ret; 159 int ret;
160 160
161 if (cp->flags & IP_VS_CONN_F_ONE_PACKET)
162 return 0;
163
161 /* Hash by protocol, client address and port */ 164 /* Hash by protocol, client address and port */
162 hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport); 165 hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);
163 166
@@ -355,8 +358,9 @@ struct ip_vs_conn *ip_vs_conn_out_get
355 */ 358 */
356void ip_vs_conn_put(struct ip_vs_conn *cp) 359void ip_vs_conn_put(struct ip_vs_conn *cp)
357{ 360{
358 /* reset it expire in its timeout */ 361 unsigned long t = (cp->flags & IP_VS_CONN_F_ONE_PACKET) ?
359 mod_timer(&cp->timer, jiffies+cp->timeout); 362 0 : cp->timeout;
363 mod_timer(&cp->timer, jiffies+t);
360 364
361 __ip_vs_conn_put(cp); 365 __ip_vs_conn_put(cp);
362} 366}
@@ -649,7 +653,7 @@ static void ip_vs_conn_expire(unsigned long data)
649 /* 653 /*
650 * unhash it if it is hashed in the conn table 654 * unhash it if it is hashed in the conn table
651 */ 655 */
652 if (!ip_vs_conn_unhash(cp)) 656 if (!ip_vs_conn_unhash(cp) && !(cp->flags & IP_VS_CONN_F_ONE_PACKET))
653 goto expire_later; 657 goto expire_later;
654 658
655 /* 659 /*
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 1cd6e3fd058..50907d8472a 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -194,6 +194,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
194 struct ip_vs_dest *dest; 194 struct ip_vs_dest *dest;
195 struct ip_vs_conn *ct; 195 struct ip_vs_conn *ct;
196 __be16 dport; /* destination port to forward */ 196 __be16 dport; /* destination port to forward */
197 __be16 flags;
197 union nf_inet_addr snet; /* source network of the client, 198 union nf_inet_addr snet; /* source network of the client,
198 after masking */ 199 after masking */
199 200
@@ -340,6 +341,10 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
340 dport = ports[1]; 341 dport = ports[1];
341 } 342 }
342 343
344 flags = (svc->flags & IP_VS_SVC_F_ONEPACKET
345 && iph.protocol == IPPROTO_UDP)?
346 IP_VS_CONN_F_ONE_PACKET : 0;
347
343 /* 348 /*
344 * Create a new connection according to the template 349 * Create a new connection according to the template
345 */ 350 */
@@ -347,7 +352,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
347 &iph.saddr, ports[0], 352 &iph.saddr, ports[0],
348 &iph.daddr, ports[1], 353 &iph.daddr, ports[1],
349 &dest->addr, dport, 354 &dest->addr, dport,
350 0, 355 flags,
351 dest); 356 dest);
352 if (cp == NULL) { 357 if (cp == NULL) {
353 ip_vs_conn_put(ct); 358 ip_vs_conn_put(ct);
@@ -377,7 +382,7 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
377 struct ip_vs_conn *cp = NULL; 382 struct ip_vs_conn *cp = NULL;
378 struct ip_vs_iphdr iph; 383 struct ip_vs_iphdr iph;
379 struct ip_vs_dest *dest; 384 struct ip_vs_dest *dest;
380 __be16 _ports[2], *pptr; 385 __be16 _ports[2], *pptr, flags;
381 386
382 ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph); 387 ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
383 pptr = skb_header_pointer(skb, iph.len, sizeof(_ports), _ports); 388 pptr = skb_header_pointer(skb, iph.len, sizeof(_ports), _ports);
@@ -407,6 +412,10 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
407 return NULL; 412 return NULL;
408 } 413 }
409 414
415 flags = (svc->flags & IP_VS_SVC_F_ONEPACKET
416 && iph.protocol == IPPROTO_UDP)?
417 IP_VS_CONN_F_ONE_PACKET : 0;
418
410 /* 419 /*
411 * Create a connection entry. 420 * Create a connection entry.
412 */ 421 */
@@ -414,7 +423,7 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
414 &iph.saddr, pptr[0], 423 &iph.saddr, pptr[0],
415 &iph.daddr, pptr[1], 424 &iph.daddr, pptr[1],
416 &dest->addr, dest->port ? dest->port : pptr[1], 425 &dest->addr, dest->port ? dest->port : pptr[1],
417 0, 426 flags,
418 dest); 427 dest);
419 if (cp == NULL) 428 if (cp == NULL)
420 return NULL; 429 return NULL;
@@ -464,6 +473,9 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
464 if (sysctl_ip_vs_cache_bypass && svc->fwmark && unicast) { 473 if (sysctl_ip_vs_cache_bypass && svc->fwmark && unicast) {
465 int ret, cs; 474 int ret, cs;
466 struct ip_vs_conn *cp; 475 struct ip_vs_conn *cp;
476 __u16 flags = (svc->flags & IP_VS_SVC_F_ONEPACKET &&
477 iph.protocol == IPPROTO_UDP)?
478 IP_VS_CONN_F_ONE_PACKET : 0;
467 union nf_inet_addr daddr = { .all = { 0, 0, 0, 0 } }; 479 union nf_inet_addr daddr = { .all = { 0, 0, 0, 0 } };
468 480
469 ip_vs_service_put(svc); 481 ip_vs_service_put(svc);
@@ -474,7 +486,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
474 &iph.saddr, pptr[0], 486 &iph.saddr, pptr[0],
475 &iph.daddr, pptr[1], 487 &iph.daddr, pptr[1],
476 &daddr, 0, 488 &daddr, 0,
477 IP_VS_CONN_F_BYPASS, 489 IP_VS_CONN_F_BYPASS | flags,
478 NULL); 490 NULL);
479 if (cp == NULL) 491 if (cp == NULL)
480 return NF_DROP; 492 return NF_DROP;
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 36dc1d88c2f..0f0c079c422 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1864,14 +1864,16 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v)
1864 svc->scheduler->name); 1864 svc->scheduler->name);
1865 else 1865 else
1866#endif 1866#endif
1867 seq_printf(seq, "%s %08X:%04X %s ", 1867 seq_printf(seq, "%s %08X:%04X %s %s ",
1868 ip_vs_proto_name(svc->protocol), 1868 ip_vs_proto_name(svc->protocol),
1869 ntohl(svc->addr.ip), 1869 ntohl(svc->addr.ip),
1870 ntohs(svc->port), 1870 ntohs(svc->port),
1871 svc->scheduler->name); 1871 svc->scheduler->name,
1872 (svc->flags & IP_VS_SVC_F_ONEPACKET)?"ops ":"");
1872 } else { 1873 } else {
1873 seq_printf(seq, "FWM %08X %s ", 1874 seq_printf(seq, "FWM %08X %s %s",
1874 svc->fwmark, svc->scheduler->name); 1875 svc->fwmark, svc->scheduler->name,
1876 (svc->flags & IP_VS_SVC_F_ONEPACKET)?"ops ":"");
1875 } 1877 }
1876 1878
1877 if (svc->flags & IP_VS_SVC_F_PERSISTENT) 1879 if (svc->flags & IP_VS_SVC_F_PERSISTENT)