aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVenkata Mohan Reddy <mohanreddykv@gmail.com>2010-02-18 06:31:05 -0500
committerPatrick McHardy <kaber@trash.net>2010-02-18 06:31:05 -0500
commit2906f66a5682e5670a5eefe991843689b8d8563f (patch)
treedcbc3ef175c609d2fa32a8e7478eb0d17015c0a7
parent477c608673526afc094be521086fed186c7ccf7d (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.h22
-rw-r--r--net/netfilter/ipvs/Kconfig7
-rw-r--r--net/netfilter/ipvs/Makefile1
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c62
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c5
-rw-r--r--net/netfilter/ipvs/ip_vs_proto.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_sctp.c1183
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c14
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 */
230enum 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;
741extern struct ip_vs_protocol ip_vs_protocol_icmp; 761extern struct ip_vs_protocol ip_vs_protocol_icmp;
742extern struct ip_vs_protocol ip_vs_protocol_esp; 762extern struct ip_vs_protocol ip_vs_protocol_esp;
743extern struct ip_vs_protocol ip_vs_protocol_ah; 763extern struct ip_vs_protocol ip_vs_protocol_ah;
744 764extern 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
107config 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
107comment "IPVS scheduler" 114comment "IPVS scheduler"
108 115
109config IP_VS_RR 116config 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 :=
7ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_TCP) += ip_vs_proto_tcp.o 7ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_TCP) += ip_vs_proto_tcp.o
8ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_UDP) += ip_vs_proto_udp.o 8ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_UDP) += ip_vs_proto_udp.o
9ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_AH_ESP) += ip_vs_proto_ah_esp.o 9ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_AH_ESP) += ip_vs_proto_ah_esp.o
10ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_SCTP) += ip_vs_proto_sctp.o
10 11
11ip_vs-objs := ip_vs_conn.o ip_vs_core.o ip_vs_ctl.o ip_vs_sched.o \ 12ip_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 */
869static 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
860static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len) 881static 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)) {