diff options
author | Vlad Yasevich <vyasevic@redhat.com> | 2012-11-15 03:49:17 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-11-15 17:36:18 -0500 |
commit | 8663e02aba154e04679c9bb1665af52021d32547 (patch) | |
tree | 901900f79125e60134c2663b409c2d8170870dfb /net/ipv6/tcp_ipv6.c | |
parent | d1da932ed4ecad2a14cbcc01ed589d617d0f0f09 (diff) |
ipv6: Separate tcp offload functionality
Pull TCPv6 offload functionality into its won file in preparation
for moving it out of the module.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 113 |
1 files changed, 4 insertions, 109 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 635206e8987e..5bed594b429d 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -71,15 +71,13 @@ | |||
71 | 71 | ||
72 | #include <linux/crypto.h> | 72 | #include <linux/crypto.h> |
73 | #include <linux/scatterlist.h> | 73 | #include <linux/scatterlist.h> |
74 | #include "ip6_offload.h" | ||
74 | 75 | ||
75 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); | 76 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); |
76 | static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | 77 | static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, |
77 | struct request_sock *req); | 78 | struct request_sock *req); |
78 | 79 | ||
79 | static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); | 80 | static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); |
80 | static void __tcp_v6_send_check(struct sk_buff *skb, | ||
81 | const struct in6_addr *saddr, | ||
82 | const struct in6_addr *daddr); | ||
83 | 81 | ||
84 | static const struct inet_connection_sock_af_ops ipv6_mapped; | 82 | static const struct inet_connection_sock_af_ops ipv6_mapped; |
85 | static const struct inet_connection_sock_af_ops ipv6_specific; | 83 | static const struct inet_connection_sock_af_ops ipv6_specific; |
@@ -119,14 +117,6 @@ static void tcp_v6_hash(struct sock *sk) | |||
119 | } | 117 | } |
120 | } | 118 | } |
121 | 119 | ||
122 | static __inline__ __sum16 tcp_v6_check(int len, | ||
123 | const struct in6_addr *saddr, | ||
124 | const struct in6_addr *daddr, | ||
125 | __wsum base) | ||
126 | { | ||
127 | return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); | ||
128 | } | ||
129 | |||
130 | static __u32 tcp_v6_init_sequence(const struct sk_buff *skb) | 120 | static __u32 tcp_v6_init_sequence(const struct sk_buff *skb) |
131 | { | 121 | { |
132 | return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32, | 122 | return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32, |
@@ -722,94 +712,6 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { | |||
722 | }; | 712 | }; |
723 | #endif | 713 | #endif |
724 | 714 | ||
725 | static void __tcp_v6_send_check(struct sk_buff *skb, | ||
726 | const struct in6_addr *saddr, const struct in6_addr *daddr) | ||
727 | { | ||
728 | struct tcphdr *th = tcp_hdr(skb); | ||
729 | |||
730 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | ||
731 | th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0); | ||
732 | skb->csum_start = skb_transport_header(skb) - skb->head; | ||
733 | skb->csum_offset = offsetof(struct tcphdr, check); | ||
734 | } else { | ||
735 | th->check = tcp_v6_check(skb->len, saddr, daddr, | ||
736 | csum_partial(th, th->doff << 2, | ||
737 | skb->csum)); | ||
738 | } | ||
739 | } | ||
740 | |||
741 | static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb) | ||
742 | { | ||
743 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
744 | |||
745 | __tcp_v6_send_check(skb, &np->saddr, &np->daddr); | ||
746 | } | ||
747 | |||
748 | static int tcp_v6_gso_send_check(struct sk_buff *skb) | ||
749 | { | ||
750 | const struct ipv6hdr *ipv6h; | ||
751 | struct tcphdr *th; | ||
752 | |||
753 | if (!pskb_may_pull(skb, sizeof(*th))) | ||
754 | return -EINVAL; | ||
755 | |||
756 | ipv6h = ipv6_hdr(skb); | ||
757 | th = tcp_hdr(skb); | ||
758 | |||
759 | th->check = 0; | ||
760 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
761 | __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr); | ||
762 | return 0; | ||
763 | } | ||
764 | |||
765 | static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, | ||
766 | struct sk_buff *skb) | ||
767 | { | ||
768 | const struct ipv6hdr *iph = skb_gro_network_header(skb); | ||
769 | __wsum wsum; | ||
770 | __sum16 sum; | ||
771 | |||
772 | switch (skb->ip_summed) { | ||
773 | case CHECKSUM_COMPLETE: | ||
774 | if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr, | ||
775 | skb->csum)) { | ||
776 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
777 | break; | ||
778 | } | ||
779 | flush: | ||
780 | NAPI_GRO_CB(skb)->flush = 1; | ||
781 | return NULL; | ||
782 | |||
783 | case CHECKSUM_NONE: | ||
784 | wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr, | ||
785 | skb_gro_len(skb), | ||
786 | IPPROTO_TCP, 0)); | ||
787 | sum = csum_fold(skb_checksum(skb, | ||
788 | skb_gro_offset(skb), | ||
789 | skb_gro_len(skb), | ||
790 | wsum)); | ||
791 | if (sum) | ||
792 | goto flush; | ||
793 | |||
794 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
795 | break; | ||
796 | } | ||
797 | |||
798 | return tcp_gro_receive(head, skb); | ||
799 | } | ||
800 | |||
801 | static int tcp6_gro_complete(struct sk_buff *skb) | ||
802 | { | ||
803 | const struct ipv6hdr *iph = ipv6_hdr(skb); | ||
804 | struct tcphdr *th = tcp_hdr(skb); | ||
805 | |||
806 | th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb), | ||
807 | &iph->saddr, &iph->daddr, 0); | ||
808 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; | ||
809 | |||
810 | return tcp_gro_complete(skb); | ||
811 | } | ||
812 | |||
813 | static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | 715 | static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, |
814 | u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass) | 716 | u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass) |
815 | { | 717 | { |
@@ -2069,13 +1971,6 @@ static const struct inet6_protocol tcpv6_protocol = { | |||
2069 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, | 1971 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, |
2070 | }; | 1972 | }; |
2071 | 1973 | ||
2072 | static const struct net_offload tcpv6_offload = { | ||
2073 | .gso_send_check = tcp_v6_gso_send_check, | ||
2074 | .gso_segment = tcp_tso_segment, | ||
2075 | .gro_receive = tcp6_gro_receive, | ||
2076 | .gro_complete = tcp6_gro_complete, | ||
2077 | }; | ||
2078 | |||
2079 | static struct inet_protosw tcpv6_protosw = { | 1974 | static struct inet_protosw tcpv6_protosw = { |
2080 | .type = SOCK_STREAM, | 1975 | .type = SOCK_STREAM, |
2081 | .protocol = IPPROTO_TCP, | 1976 | .protocol = IPPROTO_TCP, |
@@ -2112,7 +2007,7 @@ int __init tcpv6_init(void) | |||
2112 | { | 2007 | { |
2113 | int ret; | 2008 | int ret; |
2114 | 2009 | ||
2115 | ret = inet6_add_offload(&tcpv6_offload, IPPROTO_TCP); | 2010 | ret = tcpv6_offload_init(); |
2116 | if (ret) | 2011 | if (ret) |
2117 | goto out; | 2012 | goto out; |
2118 | 2013 | ||
@@ -2136,7 +2031,7 @@ out_tcpv6_protosw: | |||
2136 | out_tcpv6_protocol: | 2031 | out_tcpv6_protocol: |
2137 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); | 2032 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); |
2138 | out_offload: | 2033 | out_offload: |
2139 | inet6_del_offload(&tcpv6_offload, IPPROTO_TCP); | 2034 | tcpv6_offload_cleanup(); |
2140 | goto out; | 2035 | goto out; |
2141 | } | 2036 | } |
2142 | 2037 | ||
@@ -2145,5 +2040,5 @@ void tcpv6_exit(void) | |||
2145 | unregister_pernet_subsys(&tcpv6_net_ops); | 2040 | unregister_pernet_subsys(&tcpv6_net_ops); |
2146 | inet6_unregister_protosw(&tcpv6_protosw); | 2041 | inet6_unregister_protosw(&tcpv6_protosw); |
2147 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); | 2042 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); |
2148 | inet6_del_offload(&tcpv6_offload, IPPROTO_TCP); | 2043 | tcpv6_offload_cleanup(); |
2149 | } | 2044 | } |