diff options
| -rw-r--r-- | include/linux/ip_vs.h | 2 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_conn.c | 10 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 20 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 10 |
4 files changed, 31 insertions, 11 deletions
diff --git a/include/linux/ip_vs.h b/include/linux/ip_vs.h index dfc170362842..9708de265bb1 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 d8f7e8ef67b4..717e6233d50f 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 | */ |
| 356 | void ip_vs_conn_put(struct ip_vs_conn *cp) | 359 | void 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 1cd6e3fd058b..50907d8472a3 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 36dc1d88c2fa..0f0c079c422a 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) |
| < | |||
