]> Pileus Git - ~andy/linux/commitdiff
ipv6: Switch to using new offload infrastructure.
authorVlad Yasevich <vyasevic@redhat.com>
Thu, 15 Nov 2012 08:49:15 +0000 (08:49 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 15 Nov 2012 22:36:17 +0000 (17:36 -0500)
Switch IPv6 protocol to using the new GRO/GSO calls and data.

Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/protocol.h
net/ipv6/af_inet6.c
net/ipv6/exthdrs.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c

index 3bb70510b686109fd6da250cd698083168c51114..7019c16378481f0288824e304ade6319b0a3452c 100644 (file)
@@ -54,14 +54,6 @@ struct inet6_protocol {
                               struct inet6_skb_parm *opt,
                               u8 type, u8 code, int offset,
                               __be32 info);
-
-       int     (*gso_send_check)(struct sk_buff *skb);
-       struct sk_buff *(*gso_segment)(struct sk_buff *skb,
-                                      netdev_features_t features);
-       struct sk_buff **(*gro_receive)(struct sk_buff **head,
-                                       struct sk_buff *skb);
-       int     (*gro_complete)(struct sk_buff *skb);
-
        unsigned int    flags;  /* INET6_PROTO_xxx */
 };
 
index 6e245177608c98d268e4420c857166b78ea95906..eb63dac687289bd86d3e2e0bca50b24f395d66a6 100644 (file)
@@ -701,14 +701,14 @@ EXPORT_SYMBOL_GPL(ipv6_opt_accepted);
 
 static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
 {
-       const struct inet6_protocol *ops = NULL;
+       const struct net_offload *ops = NULL;
 
        for (;;) {
                struct ipv6_opt_hdr *opth;
                int len;
 
                if (proto != NEXTHDR_HOP) {
-                       ops = rcu_dereference(inet6_protos[proto]);
+                       ops = rcu_dereference(inet6_offloads[proto]);
 
                        if (unlikely(!ops))
                                break;
@@ -736,7 +736,7 @@ static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
 static int ipv6_gso_send_check(struct sk_buff *skb)
 {
        const struct ipv6hdr *ipv6h;
-       const struct inet6_protocol *ops;
+       const struct net_offload *ops;
        int err = -EINVAL;
 
        if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
@@ -747,7 +747,7 @@ static int ipv6_gso_send_check(struct sk_buff *skb)
        err = -EPROTONOSUPPORT;
 
        rcu_read_lock();
-       ops = rcu_dereference(inet6_protos[
+       ops = rcu_dereference(inet6_offloads[
                ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]);
 
        if (likely(ops && ops->gso_send_check)) {
@@ -765,7 +765,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
        struct ipv6hdr *ipv6h;
-       const struct inet6_protocol *ops;
+       const struct net_offload *ops;
        int proto;
        struct frag_hdr *fptr;
        unsigned int unfrag_ip6hlen;
@@ -792,7 +792,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 
        proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
        rcu_read_lock();
-       ops = rcu_dereference(inet6_protos[proto]);
+       ops = rcu_dereference(inet6_offloads[proto]);
        if (likely(ops && ops->gso_segment)) {
                skb_reset_transport_header(skb);
                segs = ops->gso_segment(skb, features);
@@ -825,7 +825,7 @@ out:
 static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
                                         struct sk_buff *skb)
 {
-       const struct inet6_protocol *ops;
+       const struct net_offload *ops;
        struct sk_buff **pp = NULL;
        struct sk_buff *p;
        struct ipv6hdr *iph;
@@ -852,7 +852,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
 
        rcu_read_lock();
        proto = iph->nexthdr;
-       ops = rcu_dereference(inet6_protos[proto]);
+       ops = rcu_dereference(inet6_offloads[proto]);
        if (!ops || !ops->gro_receive) {
                __pskb_pull(skb, skb_gro_offset(skb));
                proto = ipv6_gso_pull_exthdrs(skb, proto);
@@ -860,7 +860,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
                skb_reset_transport_header(skb);
                __skb_push(skb, skb_gro_offset(skb));
 
-               ops = rcu_dereference(inet6_protos[proto]);
+               ops = rcu_dereference(inet6_offloads[proto]);
                if (!ops || !ops->gro_receive)
                        goto out_unlock;
 
@@ -915,7 +915,7 @@ out:
 
 static int ipv6_gro_complete(struct sk_buff *skb)
 {
-       const struct inet6_protocol *ops;
+       const struct net_offload *ops;
        struct ipv6hdr *iph = ipv6_hdr(skb);
        int err = -ENOSYS;
 
@@ -923,7 +923,7 @@ static int ipv6_gro_complete(struct sk_buff *skb)
                                 sizeof(*iph));
 
        rcu_read_lock();
-       ops = rcu_dereference(inet6_protos[NAPI_GRO_CB(skb)->proto]);
+       ops = rcu_dereference(inet6_offloads[NAPI_GRO_CB(skb)->proto]);
        if (WARN_ON(!ops || !ops->gro_complete))
                goto out_unlock;
 
index cb6f0828ca44a32019c729cb0d6a4befaf060475..de6559e3aa0ace735175fdc13188969328a181d0 100644 (file)
@@ -549,14 +549,44 @@ static const struct inet6_protocol nodata_protocol = {
        .flags          =       INET6_PROTO_NOPOLICY,
 };
 
+static int ipv6_exthdrs_offload_init(void)
+{
+       int ret;
+
+       ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING);
+       if (!ret)
+               goto out;
+
+       ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS);
+       if (!ret)
+               goto out_rt;
+
+out:
+       return ret;
+
+out_rt:
+       inet_del_offload(&rthdr_offload, IPPROTO_ROUTING);
+       goto out;
+}
+
+static void ipv6_exthdrs_offload_exit(void)
+{
+       inet_del_offload(&rthdr_offload, IPPROTO_ROUTING);
+       inet_del_offload(&rthdr_offload, IPPROTO_DSTOPTS);
+}
+
 int __init ipv6_exthdrs_init(void)
 {
        int ret;
 
-       ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING);
+       ret = ipv6_exthdrs_offload_init();
        if (ret)
                goto out;
 
+       ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING);
+       if (ret)
+               goto out_offload;
+
        ret = inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
        if (ret)
                goto out_rthdr;
@@ -567,10 +597,12 @@ int __init ipv6_exthdrs_init(void)
 
 out:
        return ret;
-out_rthdr:
-       inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
 out_destopt:
        inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
+out_rthdr:
+       inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
+out_offload:
+       ipv6_exthdrs_offload_exit();
        goto out;
 };
 
index 6884a95be433a070b41a41f36f40501f83d19af6..635206e8987e28364a66f39f905855ad84a7a79e 100644 (file)
@@ -2066,10 +2066,6 @@ static const struct inet6_protocol tcpv6_protocol = {
        .early_demux    =       tcp_v6_early_demux,
        .handler        =       tcp_v6_rcv,
        .err_handler    =       tcp_v6_err,
-       .gso_send_check =       tcp_v6_gso_send_check,
-       .gso_segment    =       tcp_tso_segment,
-       .gro_receive    =       tcp6_gro_receive,
-       .gro_complete   =       tcp6_gro_complete,
        .flags          =       INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 
@@ -2116,10 +2112,14 @@ int __init tcpv6_init(void)
 {
        int ret;
 
-       ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP);
+       ret = inet6_add_offload(&tcpv6_offload, IPPROTO_TCP);
        if (ret)
                goto out;
 
+       ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP);
+       if (ret)
+               goto out_offload;
+
        /* register inet6 protocol */
        ret = inet6_register_protosw(&tcpv6_protosw);
        if (ret)
@@ -2131,10 +2131,12 @@ int __init tcpv6_init(void)
 out:
        return ret;
 
-out_tcpv6_protocol:
-       inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
 out_tcpv6_protosw:
        inet6_unregister_protosw(&tcpv6_protosw);
+out_tcpv6_protocol:
+       inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
+out_offload:
+       inet6_del_offload(&tcpv6_offload, IPPROTO_TCP);
        goto out;
 }
 
@@ -2143,4 +2145,5 @@ void tcpv6_exit(void)
        unregister_pernet_subsys(&tcpv6_net_ops);
        inet6_unregister_protosw(&tcpv6_protosw);
        inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
+       inet6_del_offload(&tcpv6_offload, IPPROTO_TCP);
 }
index 3ad44e1765033e832badf898e4bd3eda7e1d66d1..e4cc1f41012d90fec14bccc7bc55d5884529a1e4 100644 (file)
@@ -1438,8 +1438,6 @@ out:
 static const struct inet6_protocol udpv6_protocol = {
        .handler        =       udpv6_rcv,
        .err_handler    =       udpv6_err,
-       .gso_send_check =       udp6_ufo_send_check,
-       .gso_segment    =       udp6_ufo_fragment,
        .flags          =       INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 
@@ -1570,10 +1568,14 @@ int __init udpv6_init(void)
 {
        int ret;
 
-       ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP);
+       ret = inet6_add_offload(&udpv6_offload, IPPROTO_UDP);
        if (ret)
                goto out;
 
+       ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP);
+       if (ret)
+               goto out_offload;
+
        ret = inet6_register_protosw(&udpv6_protosw);
        if (ret)
                goto out_udpv6_protocol;
@@ -1582,6 +1584,8 @@ out:
 
 out_udpv6_protocol:
        inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
+out_offload:
+       inet6_del_offload(&udpv6_offload, IPPROTO_UDP);
        goto out;
 }
 
@@ -1589,4 +1593,5 @@ void udpv6_exit(void)
 {
        inet6_unregister_protosw(&udpv6_protosw);
        inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
+       inet6_del_offload(&udpv6_offload, IPPROTO_UDP);
 }