diff options
-rw-r--r-- | include/net/protocol.h | 8 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 22 | ||||
-rw-r--r-- | net/ipv6/exthdrs.c | 38 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 17 | ||||
-rw-r--r-- | net/ipv6/udp.c | 11 |
5 files changed, 64 insertions, 32 deletions
diff --git a/include/net/protocol.h b/include/net/protocol.h index 3bb70510b686..7019c1637848 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h | |||
@@ -54,14 +54,6 @@ struct inet6_protocol { | |||
54 | struct inet6_skb_parm *opt, | 54 | struct inet6_skb_parm *opt, |
55 | u8 type, u8 code, int offset, | 55 | u8 type, u8 code, int offset, |
56 | __be32 info); | 56 | __be32 info); |
57 | |||
58 | int (*gso_send_check)(struct sk_buff *skb); | ||
59 | struct sk_buff *(*gso_segment)(struct sk_buff *skb, | ||
60 | netdev_features_t features); | ||
61 | struct sk_buff **(*gro_receive)(struct sk_buff **head, | ||
62 | struct sk_buff *skb); | ||
63 | int (*gro_complete)(struct sk_buff *skb); | ||
64 | |||
65 | unsigned int flags; /* INET6_PROTO_xxx */ | 57 | unsigned int flags; /* INET6_PROTO_xxx */ |
66 | }; | 58 | }; |
67 | 59 | ||
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 6e245177608c..eb63dac68728 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -701,14 +701,14 @@ EXPORT_SYMBOL_GPL(ipv6_opt_accepted); | |||
701 | 701 | ||
702 | static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto) | 702 | static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto) |
703 | { | 703 | { |
704 | const struct inet6_protocol *ops = NULL; | 704 | const struct net_offload *ops = NULL; |
705 | 705 | ||
706 | for (;;) { | 706 | for (;;) { |
707 | struct ipv6_opt_hdr *opth; | 707 | struct ipv6_opt_hdr *opth; |
708 | int len; | 708 | int len; |
709 | 709 | ||
710 | if (proto != NEXTHDR_HOP) { | 710 | if (proto != NEXTHDR_HOP) { |
711 | ops = rcu_dereference(inet6_protos[proto]); | 711 | ops = rcu_dereference(inet6_offloads[proto]); |
712 | 712 | ||
713 | if (unlikely(!ops)) | 713 | if (unlikely(!ops)) |
714 | break; | 714 | break; |
@@ -736,7 +736,7 @@ static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto) | |||
736 | static int ipv6_gso_send_check(struct sk_buff *skb) | 736 | static int ipv6_gso_send_check(struct sk_buff *skb) |
737 | { | 737 | { |
738 | const struct ipv6hdr *ipv6h; | 738 | const struct ipv6hdr *ipv6h; |
739 | const struct inet6_protocol *ops; | 739 | const struct net_offload *ops; |
740 | int err = -EINVAL; | 740 | int err = -EINVAL; |
741 | 741 | ||
742 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) | 742 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) |
@@ -747,7 +747,7 @@ static int ipv6_gso_send_check(struct sk_buff *skb) | |||
747 | err = -EPROTONOSUPPORT; | 747 | err = -EPROTONOSUPPORT; |
748 | 748 | ||
749 | rcu_read_lock(); | 749 | rcu_read_lock(); |
750 | ops = rcu_dereference(inet6_protos[ | 750 | ops = rcu_dereference(inet6_offloads[ |
751 | ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]); | 751 | ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]); |
752 | 752 | ||
753 | if (likely(ops && ops->gso_send_check)) { | 753 | if (likely(ops && ops->gso_send_check)) { |
@@ -765,7 +765,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
765 | { | 765 | { |
766 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 766 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
767 | struct ipv6hdr *ipv6h; | 767 | struct ipv6hdr *ipv6h; |
768 | const struct inet6_protocol *ops; | 768 | const struct net_offload *ops; |
769 | int proto; | 769 | int proto; |
770 | struct frag_hdr *fptr; | 770 | struct frag_hdr *fptr; |
771 | unsigned int unfrag_ip6hlen; | 771 | unsigned int unfrag_ip6hlen; |
@@ -792,7 +792,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
792 | 792 | ||
793 | proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); | 793 | proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); |
794 | rcu_read_lock(); | 794 | rcu_read_lock(); |
795 | ops = rcu_dereference(inet6_protos[proto]); | 795 | ops = rcu_dereference(inet6_offloads[proto]); |
796 | if (likely(ops && ops->gso_segment)) { | 796 | if (likely(ops && ops->gso_segment)) { |
797 | skb_reset_transport_header(skb); | 797 | skb_reset_transport_header(skb); |
798 | segs = ops->gso_segment(skb, features); | 798 | segs = ops->gso_segment(skb, features); |
@@ -825,7 +825,7 @@ out: | |||
825 | static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, | 825 | static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, |
826 | struct sk_buff *skb) | 826 | struct sk_buff *skb) |
827 | { | 827 | { |
828 | const struct inet6_protocol *ops; | 828 | const struct net_offload *ops; |
829 | struct sk_buff **pp = NULL; | 829 | struct sk_buff **pp = NULL; |
830 | struct sk_buff *p; | 830 | struct sk_buff *p; |
831 | struct ipv6hdr *iph; | 831 | struct ipv6hdr *iph; |
@@ -852,7 +852,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, | |||
852 | 852 | ||
853 | rcu_read_lock(); | 853 | rcu_read_lock(); |
854 | proto = iph->nexthdr; | 854 | proto = iph->nexthdr; |
855 | ops = rcu_dereference(inet6_protos[proto]); | 855 | ops = rcu_dereference(inet6_offloads[proto]); |
856 | if (!ops || !ops->gro_receive) { | 856 | if (!ops || !ops->gro_receive) { |
857 | __pskb_pull(skb, skb_gro_offset(skb)); | 857 | __pskb_pull(skb, skb_gro_offset(skb)); |
858 | proto = ipv6_gso_pull_exthdrs(skb, proto); | 858 | proto = ipv6_gso_pull_exthdrs(skb, proto); |
@@ -860,7 +860,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, | |||
860 | skb_reset_transport_header(skb); | 860 | skb_reset_transport_header(skb); |
861 | __skb_push(skb, skb_gro_offset(skb)); | 861 | __skb_push(skb, skb_gro_offset(skb)); |
862 | 862 | ||
863 | ops = rcu_dereference(inet6_protos[proto]); | 863 | ops = rcu_dereference(inet6_offloads[proto]); |
864 | if (!ops || !ops->gro_receive) | 864 | if (!ops || !ops->gro_receive) |
865 | goto out_unlock; | 865 | goto out_unlock; |
866 | 866 | ||
@@ -915,7 +915,7 @@ out: | |||
915 | 915 | ||
916 | static int ipv6_gro_complete(struct sk_buff *skb) | 916 | static int ipv6_gro_complete(struct sk_buff *skb) |
917 | { | 917 | { |
918 | const struct inet6_protocol *ops; | 918 | const struct net_offload *ops; |
919 | struct ipv6hdr *iph = ipv6_hdr(skb); | 919 | struct ipv6hdr *iph = ipv6_hdr(skb); |
920 | int err = -ENOSYS; | 920 | int err = -ENOSYS; |
921 | 921 | ||
@@ -923,7 +923,7 @@ static int ipv6_gro_complete(struct sk_buff *skb) | |||
923 | sizeof(*iph)); | 923 | sizeof(*iph)); |
924 | 924 | ||
925 | rcu_read_lock(); | 925 | rcu_read_lock(); |
926 | ops = rcu_dereference(inet6_protos[NAPI_GRO_CB(skb)->proto]); | 926 | ops = rcu_dereference(inet6_offloads[NAPI_GRO_CB(skb)->proto]); |
927 | if (WARN_ON(!ops || !ops->gro_complete)) | 927 | if (WARN_ON(!ops || !ops->gro_complete)) |
928 | goto out_unlock; | 928 | goto out_unlock; |
929 | 929 | ||
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index cb6f0828ca44..de6559e3aa0a 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -549,14 +549,44 @@ static const struct inet6_protocol nodata_protocol = { | |||
549 | .flags = INET6_PROTO_NOPOLICY, | 549 | .flags = INET6_PROTO_NOPOLICY, |
550 | }; | 550 | }; |
551 | 551 | ||
552 | static int ipv6_exthdrs_offload_init(void) | ||
553 | { | ||
554 | int ret; | ||
555 | |||
556 | ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING); | ||
557 | if (!ret) | ||
558 | goto out; | ||
559 | |||
560 | ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS); | ||
561 | if (!ret) | ||
562 | goto out_rt; | ||
563 | |||
564 | out: | ||
565 | return ret; | ||
566 | |||
567 | out_rt: | ||
568 | inet_del_offload(&rthdr_offload, IPPROTO_ROUTING); | ||
569 | goto out; | ||
570 | } | ||
571 | |||
572 | static void ipv6_exthdrs_offload_exit(void) | ||
573 | { | ||
574 | inet_del_offload(&rthdr_offload, IPPROTO_ROUTING); | ||
575 | inet_del_offload(&rthdr_offload, IPPROTO_DSTOPTS); | ||
576 | } | ||
577 | |||
552 | int __init ipv6_exthdrs_init(void) | 578 | int __init ipv6_exthdrs_init(void) |
553 | { | 579 | { |
554 | int ret; | 580 | int ret; |
555 | 581 | ||
556 | ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING); | 582 | ret = ipv6_exthdrs_offload_init(); |
557 | if (ret) | 583 | if (ret) |
558 | goto out; | 584 | goto out; |
559 | 585 | ||
586 | ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING); | ||
587 | if (ret) | ||
588 | goto out_offload; | ||
589 | |||
560 | ret = inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS); | 590 | ret = inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS); |
561 | if (ret) | 591 | if (ret) |
562 | goto out_rthdr; | 592 | goto out_rthdr; |
@@ -567,10 +597,12 @@ int __init ipv6_exthdrs_init(void) | |||
567 | 597 | ||
568 | out: | 598 | out: |
569 | return ret; | 599 | return ret; |
570 | out_rthdr: | ||
571 | inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING); | ||
572 | out_destopt: | 600 | out_destopt: |
573 | inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS); | 601 | inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS); |
602 | out_rthdr: | ||
603 | inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING); | ||
604 | out_offload: | ||
605 | ipv6_exthdrs_offload_exit(); | ||
574 | goto out; | 606 | goto out; |
575 | }; | 607 | }; |
576 | 608 | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 6884a95be433..635206e8987e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -2066,10 +2066,6 @@ static const struct inet6_protocol tcpv6_protocol = { | |||
2066 | .early_demux = tcp_v6_early_demux, | 2066 | .early_demux = tcp_v6_early_demux, |
2067 | .handler = tcp_v6_rcv, | 2067 | .handler = tcp_v6_rcv, |
2068 | .err_handler = tcp_v6_err, | 2068 | .err_handler = tcp_v6_err, |
2069 | .gso_send_check = tcp_v6_gso_send_check, | ||
2070 | .gso_segment = tcp_tso_segment, | ||
2071 | .gro_receive = tcp6_gro_receive, | ||
2072 | .gro_complete = tcp6_gro_complete, | ||
2073 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, | 2069 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, |
2074 | }; | 2070 | }; |
2075 | 2071 | ||
@@ -2116,10 +2112,14 @@ int __init tcpv6_init(void) | |||
2116 | { | 2112 | { |
2117 | int ret; | 2113 | int ret; |
2118 | 2114 | ||
2119 | ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP); | 2115 | ret = inet6_add_offload(&tcpv6_offload, IPPROTO_TCP); |
2120 | if (ret) | 2116 | if (ret) |
2121 | goto out; | 2117 | goto out; |
2122 | 2118 | ||
2119 | ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP); | ||
2120 | if (ret) | ||
2121 | goto out_offload; | ||
2122 | |||
2123 | /* register inet6 protocol */ | 2123 | /* register inet6 protocol */ |
2124 | ret = inet6_register_protosw(&tcpv6_protosw); | 2124 | ret = inet6_register_protosw(&tcpv6_protosw); |
2125 | if (ret) | 2125 | if (ret) |
@@ -2131,10 +2131,12 @@ int __init tcpv6_init(void) | |||
2131 | out: | 2131 | out: |
2132 | return ret; | 2132 | return ret; |
2133 | 2133 | ||
2134 | out_tcpv6_protocol: | ||
2135 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); | ||
2136 | out_tcpv6_protosw: | 2134 | out_tcpv6_protosw: |
2137 | inet6_unregister_protosw(&tcpv6_protosw); | 2135 | inet6_unregister_protosw(&tcpv6_protosw); |
2136 | out_tcpv6_protocol: | ||
2137 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); | ||
2138 | out_offload: | ||
2139 | inet6_del_offload(&tcpv6_offload, IPPROTO_TCP); | ||
2138 | goto out; | 2140 | goto out; |
2139 | } | 2141 | } |
2140 | 2142 | ||
@@ -2143,4 +2145,5 @@ void tcpv6_exit(void) | |||
2143 | unregister_pernet_subsys(&tcpv6_net_ops); | 2145 | unregister_pernet_subsys(&tcpv6_net_ops); |
2144 | inet6_unregister_protosw(&tcpv6_protosw); | 2146 | inet6_unregister_protosw(&tcpv6_protosw); |
2145 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); | 2147 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); |
2148 | inet6_del_offload(&tcpv6_offload, IPPROTO_TCP); | ||
2146 | } | 2149 | } |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 3ad44e176503..e4cc1f41012d 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -1438,8 +1438,6 @@ out: | |||
1438 | static const struct inet6_protocol udpv6_protocol = { | 1438 | static const struct inet6_protocol udpv6_protocol = { |
1439 | .handler = udpv6_rcv, | 1439 | .handler = udpv6_rcv, |
1440 | .err_handler = udpv6_err, | 1440 | .err_handler = udpv6_err, |
1441 | .gso_send_check = udp6_ufo_send_check, | ||
1442 | .gso_segment = udp6_ufo_fragment, | ||
1443 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, | 1441 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, |
1444 | }; | 1442 | }; |
1445 | 1443 | ||
@@ -1570,10 +1568,14 @@ int __init udpv6_init(void) | |||
1570 | { | 1568 | { |
1571 | int ret; | 1569 | int ret; |
1572 | 1570 | ||
1573 | ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP); | 1571 | ret = inet6_add_offload(&udpv6_offload, IPPROTO_UDP); |
1574 | if (ret) | 1572 | if (ret) |
1575 | goto out; | 1573 | goto out; |
1576 | 1574 | ||
1575 | ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP); | ||
1576 | if (ret) | ||
1577 | goto out_offload; | ||
1578 | |||
1577 | ret = inet6_register_protosw(&udpv6_protosw); | 1579 | ret = inet6_register_protosw(&udpv6_protosw); |
1578 | if (ret) | 1580 | if (ret) |
1579 | goto out_udpv6_protocol; | 1581 | goto out_udpv6_protocol; |
@@ -1582,6 +1584,8 @@ out: | |||
1582 | 1584 | ||
1583 | out_udpv6_protocol: | 1585 | out_udpv6_protocol: |
1584 | inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP); | 1586 | inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP); |
1587 | out_offload: | ||
1588 | inet6_del_offload(&udpv6_offload, IPPROTO_UDP); | ||
1585 | goto out; | 1589 | goto out; |
1586 | } | 1590 | } |
1587 | 1591 | ||
@@ -1589,4 +1593,5 @@ void udpv6_exit(void) | |||
1589 | { | 1593 | { |
1590 | inet6_unregister_protosw(&udpv6_protosw); | 1594 | inet6_unregister_protosw(&udpv6_protosw); |
1591 | inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP); | 1595 | inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP); |
1596 | inet6_del_offload(&udpv6_offload, IPPROTO_UDP); | ||
1592 | } | 1597 | } |