diff options
| author | Venkata Mohan Reddy <mohanreddykv@gmail.com> | 2010-02-18 06:31:05 -0500 |
|---|---|---|
| committer | Patrick McHardy <kaber@trash.net> | 2010-02-18 06:31:05 -0500 |
| commit | 2906f66a5682e5670a5eefe991843689b8d8563f (patch) | |
| tree | dcbc3ef175c609d2fa32a8e7478eb0d17015c0a7 | |
| parent | 477c608673526afc094be521086fed186c7ccf7d (diff) | |
ipvs: SCTP Trasport Loadbalancing Support
Enhance IPVS to load balance SCTP transport protocol packets. This is done
based on the SCTP rfc 4960. All possible control chunks have been taken
care. The state machine used in this code looks some what lengthy. I tried
to make the state machine easy to understand.
Signed-off-by: Venkata Mohan Reddy Koppula <mohanreddykv@gmail.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Patrick McHardy <kaber@trash.net>
| -rw-r--r-- | include/net/ip_vs.h | 22 | ||||
| -rw-r--r-- | net/netfilter/ipvs/Kconfig | 7 | ||||
| -rw-r--r-- | net/netfilter/ipvs/Makefile | 1 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 62 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 5 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_proto.c | 3 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_proto_sctp.c | 1183 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_sync.c | 14 |
8 files changed, 1285 insertions, 12 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index a816c37417bb..fe82b1e10a29 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h | |||
| @@ -225,6 +225,26 @@ enum { | |||
| 225 | }; | 225 | }; |
| 226 | 226 | ||
| 227 | /* | 227 | /* |
| 228 | * SCTP State Values | ||
| 229 | */ | ||
| 230 | enum ip_vs_sctp_states { | ||
| 231 | IP_VS_SCTP_S_NONE, | ||
| 232 | IP_VS_SCTP_S_INIT_CLI, | ||
| 233 | IP_VS_SCTP_S_INIT_SER, | ||
| 234 | IP_VS_SCTP_S_INIT_ACK_CLI, | ||
| 235 | IP_VS_SCTP_S_INIT_ACK_SER, | ||
| 236 | IP_VS_SCTP_S_ECHO_CLI, | ||
| 237 | IP_VS_SCTP_S_ECHO_SER, | ||
| 238 | IP_VS_SCTP_S_ESTABLISHED, | ||
| 239 | IP_VS_SCTP_S_SHUT_CLI, | ||
| 240 | IP_VS_SCTP_S_SHUT_SER, | ||
| 241 | IP_VS_SCTP_S_SHUT_ACK_CLI, | ||
| 242 | IP_VS_SCTP_S_SHUT_ACK_SER, | ||
| 243 | IP_VS_SCTP_S_CLOSED, | ||
| 244 | IP_VS_SCTP_S_LAST | ||
| 245 | }; | ||
| 246 | |||
| 247 | /* | ||
| 228 | * Delta sequence info structure | 248 | * Delta sequence info structure |
| 229 | * Each ip_vs_conn has 2 (output AND input seq. changes). | 249 | * Each ip_vs_conn has 2 (output AND input seq. changes). |
| 230 | * Only used in the VS/NAT. | 250 | * Only used in the VS/NAT. |
| @@ -741,7 +761,7 @@ extern struct ip_vs_protocol ip_vs_protocol_udp; | |||
| 741 | extern struct ip_vs_protocol ip_vs_protocol_icmp; | 761 | extern struct ip_vs_protocol ip_vs_protocol_icmp; |
| 742 | extern struct ip_vs_protocol ip_vs_protocol_esp; | 762 | extern struct ip_vs_protocol ip_vs_protocol_esp; |
| 743 | extern struct ip_vs_protocol ip_vs_protocol_ah; | 763 | extern struct ip_vs_protocol ip_vs_protocol_ah; |
| 744 | 764 | extern struct ip_vs_protocol ip_vs_protocol_sctp; | |
| 745 | 765 | ||
| 746 | /* | 766 | /* |
| 747 | * Registering/unregistering scheduler functions | 767 | * Registering/unregistering scheduler functions |
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig index 817a8898203b..712ccad13344 100644 --- a/net/netfilter/ipvs/Kconfig +++ b/net/netfilter/ipvs/Kconfig | |||
| @@ -104,6 +104,13 @@ config IP_VS_PROTO_AH | |||
| 104 | This option enables support for load balancing AH (Authentication | 104 | This option enables support for load balancing AH (Authentication |
| 105 | Header) transport protocol. Say Y if unsure. | 105 | Header) transport protocol. Say Y if unsure. |
| 106 | 106 | ||
| 107 | config IP_VS_PROTO_SCTP | ||
| 108 | bool "SCTP load balancing support" | ||
| 109 | select LIBCRC32C | ||
| 110 | ---help--- | ||
| 111 | This option enables support for load balancing SCTP transport | ||
| 112 | protocol. Say Y if unsure. | ||
| 113 | |||
| 107 | comment "IPVS scheduler" | 114 | comment "IPVS scheduler" |
| 108 | 115 | ||
| 109 | config IP_VS_RR | 116 | config IP_VS_RR |
diff --git a/net/netfilter/ipvs/Makefile b/net/netfilter/ipvs/Makefile index 73a46fe1fe4c..e3baefd7066e 100644 --- a/net/netfilter/ipvs/Makefile +++ b/net/netfilter/ipvs/Makefile | |||
| @@ -7,6 +7,7 @@ ip_vs_proto-objs-y := | |||
| 7 | ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_TCP) += ip_vs_proto_tcp.o | 7 | ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_TCP) += ip_vs_proto_tcp.o |
| 8 | ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_UDP) += ip_vs_proto_udp.o | 8 | ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_UDP) += ip_vs_proto_udp.o |
| 9 | ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_AH_ESP) += ip_vs_proto_ah_esp.o | 9 | ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_AH_ESP) += ip_vs_proto_ah_esp.o |
| 10 | ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_SCTP) += ip_vs_proto_sctp.o | ||
| 10 | 11 | ||
| 11 | ip_vs-objs := ip_vs_conn.o ip_vs_core.o ip_vs_ctl.o ip_vs_sched.o \ | 12 | ip_vs-objs := ip_vs_conn.o ip_vs_core.o ip_vs_ctl.o ip_vs_sched.o \ |
| 12 | ip_vs_xmit.o ip_vs_app.o ip_vs_sync.o \ | 13 | ip_vs_xmit.o ip_vs_app.o ip_vs_sync.o \ |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 847ffca40184..72e96d823ebf 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
| 32 | #include <linux/ip.h> | 32 | #include <linux/ip.h> |
| 33 | #include <linux/tcp.h> | 33 | #include <linux/tcp.h> |
| 34 | #include <linux/sctp.h> | ||
| 34 | #include <linux/icmp.h> | 35 | #include <linux/icmp.h> |
| 35 | 36 | ||
| 36 | #include <net/ip.h> | 37 | #include <net/ip.h> |
| @@ -81,6 +82,8 @@ const char *ip_vs_proto_name(unsigned proto) | |||
| 81 | return "UDP"; | 82 | return "UDP"; |
| 82 | case IPPROTO_TCP: | 83 | case IPPROTO_TCP: |
| 83 | return "TCP"; | 84 | return "TCP"; |
| 85 | case IPPROTO_SCTP: | ||
| 86 | return "SCTP"; | ||
| 84 | case IPPROTO_ICMP: | 87 | case IPPROTO_ICMP: |
| 85 | return "ICMP"; | 88 | return "ICMP"; |
| 86 | #ifdef CONFIG_IP_VS_IPV6 | 89 | #ifdef CONFIG_IP_VS_IPV6 |
| @@ -589,8 +592,9 @@ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
| 589 | ip_send_check(ciph); | 592 | ip_send_check(ciph); |
| 590 | } | 593 | } |
| 591 | 594 | ||
| 592 | /* the TCP/UDP port */ | 595 | /* the TCP/UDP/SCTP port */ |
| 593 | if (IPPROTO_TCP == ciph->protocol || IPPROTO_UDP == ciph->protocol) { | 596 | if (IPPROTO_TCP == ciph->protocol || IPPROTO_UDP == ciph->protocol || |
| 597 | IPPROTO_SCTP == ciph->protocol) { | ||
| 594 | __be16 *ports = (void *)ciph + ciph->ihl*4; | 598 | __be16 *ports = (void *)ciph + ciph->ihl*4; |
| 595 | 599 | ||
| 596 | if (inout) | 600 | if (inout) |
| @@ -630,8 +634,9 @@ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
| 630 | ciph->saddr = cp->daddr.in6; | 634 | ciph->saddr = cp->daddr.in6; |
| 631 | } | 635 | } |
| 632 | 636 | ||
| 633 | /* the TCP/UDP port */ | 637 | /* the TCP/UDP/SCTP port */ |
| 634 | if (IPPROTO_TCP == ciph->nexthdr || IPPROTO_UDP == ciph->nexthdr) { | 638 | if (IPPROTO_TCP == ciph->nexthdr || IPPROTO_UDP == ciph->nexthdr || |
| 639 | IPPROTO_SCTP == ciph->nexthdr) { | ||
| 635 | __be16 *ports = (void *)ciph + sizeof(struct ipv6hdr); | 640 | __be16 *ports = (void *)ciph + sizeof(struct ipv6hdr); |
| 636 | 641 | ||
| 637 | if (inout) | 642 | if (inout) |
| @@ -679,7 +684,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb, | |||
| 679 | goto out; | 684 | goto out; |
| 680 | } | 685 | } |
| 681 | 686 | ||
| 682 | if (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol) | 687 | if (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol || |
| 688 | IPPROTO_SCTP == protocol) | ||
| 683 | offset += 2 * sizeof(__u16); | 689 | offset += 2 * sizeof(__u16); |
| 684 | if (!skb_make_writable(skb, offset)) | 690 | if (!skb_make_writable(skb, offset)) |
| 685 | goto out; | 691 | goto out; |
| @@ -857,6 +863,21 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related) | |||
| 857 | } | 863 | } |
| 858 | #endif | 864 | #endif |
| 859 | 865 | ||
| 866 | /* | ||
| 867 | * Check if sctp chunc is ABORT chunk | ||
| 868 | */ | ||
| 869 | static inline int is_sctp_abort(const struct sk_buff *skb, int nh_len) | ||
| 870 | { | ||
| 871 | sctp_chunkhdr_t *sch, schunk; | ||
| 872 | sch = skb_header_pointer(skb, nh_len + sizeof(sctp_sctphdr_t), | ||
| 873 | sizeof(schunk), &schunk); | ||
| 874 | if (sch == NULL) | ||
| 875 | return 0; | ||
| 876 | if (sch->type == SCTP_CID_ABORT) | ||
| 877 | return 1; | ||
| 878 | return 0; | ||
| 879 | } | ||
| 880 | |||
| 860 | static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len) | 881 | static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len) |
| 861 | { | 882 | { |
| 862 | struct tcphdr _tcph, *th; | 883 | struct tcphdr _tcph, *th; |
| @@ -999,7 +1020,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, | |||
| 999 | if (unlikely(!cp)) { | 1020 | if (unlikely(!cp)) { |
| 1000 | if (sysctl_ip_vs_nat_icmp_send && | 1021 | if (sysctl_ip_vs_nat_icmp_send && |
| 1001 | (pp->protocol == IPPROTO_TCP || | 1022 | (pp->protocol == IPPROTO_TCP || |
| 1002 | pp->protocol == IPPROTO_UDP)) { | 1023 | pp->protocol == IPPROTO_UDP || |
| 1024 | pp->protocol == IPPROTO_SCTP)) { | ||
| 1003 | __be16 _ports[2], *pptr; | 1025 | __be16 _ports[2], *pptr; |
| 1004 | 1026 | ||
| 1005 | pptr = skb_header_pointer(skb, iph.len, | 1027 | pptr = skb_header_pointer(skb, iph.len, |
| @@ -1014,8 +1036,13 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, | |||
| 1014 | * existing entry if it is not RST | 1036 | * existing entry if it is not RST |
| 1015 | * packet or not TCP packet. | 1037 | * packet or not TCP packet. |
| 1016 | */ | 1038 | */ |
| 1017 | if (iph.protocol != IPPROTO_TCP | 1039 | if ((iph.protocol != IPPROTO_TCP && |
| 1018 | || !is_tcp_reset(skb, iph.len)) { | ||
