aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)