diff options
| author | Julian Anastasov <ja@ssi.bg> | 2010-10-17 09:21:07 -0400 |
|---|---|---|
| committer | Simon Horman <horms@verge.net.au> | 2010-10-21 04:50:20 -0400 |
| commit | cf356d69db0afef692cd640917bc70f708c27f14 (patch) | |
| tree | 1c1e0a277ba783066e639524bbdef0c19996e8c0 | |
| parent | 8b27b10f5863a5b63e46304a71aa01463d1efac4 (diff) | |
ipvs: switch to notrack mode
Change skb->ipvs_property semantic. This is preparation
to support ip_vs_out processing in LOCAL_OUT. ipvs_property=1
will be used to avoid expensive lookups for traffic sent by
transmitters. Now when conntrack support is not used we call
ip_vs_notrack method to avoid problems in OUTPUT and
POST_ROUTING hooks instead of exiting POST_ROUTING as before.
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Simon Horman <horms@verge.net.au>
| -rw-r--r-- | include/net/ip_vs.h | 20 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 39 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_xmit.c | 7 |
3 files changed, 28 insertions, 38 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index adcdba9dd183..0e4618470cee 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | #include <linux/ip.h> | 25 | #include <linux/ip.h> |
| 26 | #include <linux/ipv6.h> /* for struct ipv6hdr */ | 26 | #include <linux/ipv6.h> /* for struct ipv6hdr */ |
| 27 | #include <net/ipv6.h> /* for ipv6_addr_copy */ | 27 | #include <net/ipv6.h> /* for ipv6_addr_copy */ |
| 28 | #ifdef CONFIG_IP_VS_NFCT | 28 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) |
| 29 | #include <net/netfilter/nf_conntrack.h> | 29 | #include <net/netfilter/nf_conntrack.h> |
| 30 | #endif | 30 | #endif |
| 31 | 31 | ||
| @@ -1021,6 +1021,24 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum) | |||
| 1021 | return csum_partial(diff, sizeof(diff), oldsum); | 1021 | return csum_partial(diff, sizeof(diff), oldsum); |
| 1022 | } | 1022 | } |
| 1023 | 1023 | ||
| 1024 | /* | ||
| 1025 | * Forget current conntrack (unconfirmed) and attach notrack entry | ||
| 1026 | */ | ||
| 1027 | static inline void ip_vs_notrack(struct sk_buff *skb) | ||
| 1028 | { | ||
| 1029 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
| 1030 | enum ip_conntrack_info ctinfo; | ||
| 1031 | struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo); | ||
| 1032 | |||
| 1033 | if (!ct || !nf_ct_is_untracked(ct)) { | ||
| 1034 | nf_reset(skb); | ||
| 1035 | skb->nfct = &nf_ct_untracked_get()->ct_general; | ||
| 1036 | skb->nfctinfo = IP_CT_NEW; | ||
| 1037 | nf_conntrack_get(skb->nfct); | ||
| 1038 | } | ||
| 1039 | #endif | ||
| 1040 | } | ||
| 1041 | |||
| 1024 | #ifdef CONFIG_IP_VS_NFCT | 1042 | #ifdef CONFIG_IP_VS_NFCT |
| 1025 | /* | 1043 | /* |
| 1026 | * Netfilter connection tracking | 1044 | * Netfilter connection tracking |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index e5fef7aef0d4..222453029b9e 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
| @@ -507,23 +507,6 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, | |||
| 507 | return NF_DROP; | 507 | return NF_DROP; |
| 508 | } | 508 | } |
| 509 | 509 | ||
| 510 | /* | ||
| 511 | * It is hooked before NF_IP_PRI_NAT_SRC at the NF_INET_POST_ROUTING | ||
| 512 | * chain and is used to avoid double NAT and confirmation when we do | ||
| 513 | * not want to keep the conntrack structure | ||
| 514 | */ | ||
| 515 | static unsigned int ip_vs_post_routing(unsigned int hooknum, | ||
| 516 | struct sk_buff *skb, | ||
| 517 | const struct net_device *in, | ||
| 518 | const struct net_device *out, | ||
| 519 | int (*okfn)(struct sk_buff *)) | ||
| 520 | { | ||
| 521 | if (!skb->ipvs_property) | ||
| 522 | return NF_ACCEPT; | ||
| 523 | /* The packet was sent from IPVS, exit this chain */ | ||
| 524 | return NF_STOP; | ||
| 525 | } | ||
| 526 | |||
| 527 | __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset) | 510 | __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset) |
| 528 | { | 511 | { |
| 529 | return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); | 512 | return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); |
| @@ -682,8 +665,9 @@ static int handle_response_icmp(int af, struct sk_buff *skb, | |||
| 682 | /* do the statistics and put it back */ | 665 | /* do the statistics and put it back */ |
| 683 | ip_vs_out_stats(cp, skb); | 666 | ip_vs_out_stats(cp, skb); |
| 684 | 667 | ||
| 668 | skb->ipvs_property = 1; | ||
| 685 | if (!(cp->flags & IP_VS_CONN_F_NFCT)) | 669 | if (!(cp->flags & IP_VS_CONN_F_NFCT)) |
| 686 | skb->ipvs_property = 1; | 670 | ip_vs_notrack(skb); |
| 687 | else | 671 | else |
| 688 | ip_vs_update_conntrack(skb, cp, 0); | 672 | ip_vs_update_conntrack(skb, cp, 0); |
| 689 | verdict = NF_ACCEPT; | 673 | verdict = NF_ACCEPT; |
| @@ -929,8 +913,9 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
| 929 | 913 | ||
| 930 | ip_vs_out_stats(cp, skb); | 914 | ip_vs_out_stats(cp, skb); |
| 931 | ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp); | 915 | ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp); |
| 916 | skb->ipvs_property = 1; | ||
| 932 | if (!(cp->flags & IP_VS_CONN_F_NFCT)) | 917 | if (!(cp->flags & IP_VS_CONN_F_NFCT)) |
| 933 | skb->ipvs_property = 1; | 918 | ip_vs_notrack(skb); |
| 934 | else | 919 | else |
| 935 | ip_vs_update_conntrack(skb, cp, 0); | 920 | ip_vs_update_conntrack(skb, cp, 0); |
| 936 | ip_vs_conn_put(cp); | 921 | ip_vs_conn_put(cp); |
| @@ -1496,14 +1481,6 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { | |||
| 1496 | .hooknum = NF_INET_FORWARD, | 1481 | .hooknum = NF_INET_FORWARD, |
| 1497 | .priority = 99, | 1482 | .priority = 99, |
| 1498 | }, | 1483 | }, |
| 1499 | /* Before the netfilter connection tracking, exit from POST_ROUTING */ | ||
| 1500 | { | ||
| 1501 | .hook = ip_vs_post_routing, | ||
| 1502 | .owner = THIS_MODULE, | ||
| 1503 | .pf = PF_INET, | ||
| 1504 | .hooknum = NF_INET_POST_ROUTING, | ||
| 1505 | .priority = NF_IP_PRI_NAT_SRC-1, | ||
| 1506 | }, | ||
| 1507 | #ifdef CONFIG_IP_VS_IPV6 | 1484 | #ifdef CONFIG_IP_VS_IPV6 |
| 1508 | /* After packet filtering, forward packet through VS/DR, VS/TUN, | 1485 | /* After packet filtering, forward packet through VS/DR, VS/TUN, |
| 1509 | * or VS/NAT(change destination), so that filtering rules can be | 1486 | * or VS/NAT(change destination), so that filtering rules can be |
| @@ -1532,14 +1509,6 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { | |||
| 1532 | .hooknum = NF_INET_FORWARD, | 1509 | .hooknum = NF_INET_FORWARD, |
| 1533 | .priority = 99, | 1510 | .priority = 99, |
| 1534 | }, | 1511 | }, |
| 1535 | /* Before the netfilter connection tracking, exit from POST_ROUTING */ | ||
| 1536 | { | ||
| 1537 | .hook = ip_vs_post_routing, | ||
| 1538 | .owner = THIS_MODULE, | ||
| 1539 | .pf = PF_INET6, | ||
| 1540 | .hooknum = NF_INET_POST_ROUTING, | ||
| 1541 | .priority = NF_IP6_PRI_NAT_SRC-1, | ||
| 1542 | }, | ||
| 1543 | #endif | 1512 | #endif |
| 1544 | }; | 1513 | }; |
| 1545 | 1514 | ||
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index b0bd8afbf368..94b53b441028 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c | |||
| @@ -217,6 +217,7 @@ ip_vs_dst_reset(struct ip_vs_dest *dest) | |||
| 217 | ({ \ | 217 | ({ \ |
| 218 | int __ret = NF_ACCEPT; \ | 218 | int __ret = NF_ACCEPT; \ |
| 219 | \ | 219 | \ |
| 220 | (skb)->ipvs_property = 1; \ | ||
| 220 | if (unlikely((cp)->flags & IP_VS_CONN_F_NFCT)) \ | 221 | if (unlikely((cp)->flags & IP_VS_CONN_F_NFCT)) \ |
| 221 | __ret = ip_vs_confirm_conntrack(skb, cp); \ | 222 | __ret = ip_vs_confirm_conntrack(skb, cp); \ |
| 222 | if (__ret == NF_ACCEPT) { \ | 223 | if (__ret == NF_ACCEPT) { \ |
| @@ -228,8 +229,9 @@ ip_vs_dst_reset(struct ip_vs_dest *dest) | |||
| 228 | 229 | ||
| 229 | #define IP_VS_XMIT_NAT(pf, skb, cp) \ | 230 | #define IP_VS_XMIT_NAT(pf, skb, cp) \ |
| 230 | do { \ | 231 | do { \ |
| 232 | (skb)->ipvs_property = 1; \ | ||
| 231 | if (likely(!((cp)->flags & IP_VS_CONN_F_NFCT))) \ | 233 | if (likely(!((cp)->flags & IP_VS_CONN_F_NFCT))) \ |
| 232 | (skb)->ipvs_property = 1; \ | 234 | ip_vs_notrack(skb); \ |
| 233 | else \ | 235 | else \ |
| 234 | ip_vs_update_conntrack(skb, cp, 1); \ | 236 | ip_vs_update_conntrack(skb, cp, 1); \ |
| 235 | skb_forward_csum(skb); \ | 237 | skb_forward_csum(skb); \ |
| @@ -239,8 +241,9 @@ do { \ | |||
| 239 | 241 | ||
| 240 | #define IP_VS_XMIT(pf, skb, cp) \ | 242 | #define IP_VS_XMIT(pf, skb, cp) \ |
| 241 | do { \ | 243 | do { \ |
| 244 | (skb)->ipvs_property = 1; \ | ||
| 242 | if (likely(!((cp)->flags & IP_VS_CONN_F_NFCT))) \ | 245 | if (likely(!((cp)->flags & IP_VS_CONN_F_NFCT))) \ |
| 243 | (skb)->ipvs_property = 1; \ | 246 | ip_vs_notrack(skb); \ |
| 244 | skb_forward_csum(skb); \ | 247 | skb_forward_csum(skb); \ |
| 245 | NF_HOOK(pf, NF_INET_LOCAL_OUT, (skb), NULL, \ | 248 | NF_HOOK(pf, NF_INET_LOCAL_OUT, (skb), NULL, \ |
| 246 | skb_dst(skb)->dev, dst_output); \ | 249 | skb_dst(skb)->dev, dst_output); \ |
