Commit 3336288a authored by Vlad Yasevich's avatar Vlad Yasevich Committed by David S. Miller

ipv6: Switch to using new offload infrastructure.

Switch IPv6 protocol to using the new GRO/GSO calls and data.
Signed-off-by: default avatarVlad Yasevich <vyasevic@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bca49f84
...@@ -54,14 +54,6 @@ struct inet6_protocol { ...@@ -54,14 +54,6 @@ struct inet6_protocol {
struct inet6_skb_parm *opt, struct inet6_skb_parm *opt,
u8 type, u8 code, int offset, u8 type, u8 code, int offset,
__be32 info); __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 */ unsigned int flags; /* INET6_PROTO_xxx */
}; };
......
...@@ -701,14 +701,14 @@ EXPORT_SYMBOL_GPL(ipv6_opt_accepted); ...@@ -701,14 +701,14 @@ EXPORT_SYMBOL_GPL(ipv6_opt_accepted);
static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto) 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 (;;) { for (;;) {
struct ipv6_opt_hdr *opth; struct ipv6_opt_hdr *opth;
int len; int len;
if (proto != NEXTHDR_HOP) { if (proto != NEXTHDR_HOP) {
ops = rcu_dereference(inet6_protos[proto]); ops = rcu_dereference(inet6_offloads[proto]);
if (unlikely(!ops)) if (unlikely(!ops))
break; break;
...@@ -736,7 +736,7 @@ static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto) ...@@ -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) static int ipv6_gso_send_check(struct sk_buff *skb)
{ {
const struct ipv6hdr *ipv6h; const struct ipv6hdr *ipv6h;
const struct inet6_protocol *ops; const struct net_offload *ops;
int err = -EINVAL; int err = -EINVAL;
if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
...@@ -747,7 +747,7 @@ static int ipv6_gso_send_check(struct sk_buff *skb) ...@@ -747,7 +747,7 @@ static int ipv6_gso_send_check(struct sk_buff *skb)
err = -EPROTONOSUPPORT; err = -EPROTONOSUPPORT;
rcu_read_lock(); rcu_read_lock();
ops = rcu_dereference(inet6_protos[ ops = rcu_dereference(inet6_offloads[
ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]); ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]);
if (likely(ops && ops->gso_send_check)) { if (likely(ops && ops->gso_send_check)) {
...@@ -765,7 +765,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, ...@@ -765,7 +765,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
{ {
struct sk_buff *segs = ERR_PTR(-EINVAL); struct sk_buff *segs = ERR_PTR(-EINVAL);
struct ipv6hdr *ipv6h; struct ipv6hdr *ipv6h;
const struct inet6_protocol *ops; const struct net_offload *ops;
int proto; int proto;
struct frag_hdr *fptr; struct frag_hdr *fptr;
unsigned int unfrag_ip6hlen; unsigned int unfrag_ip6hlen;
...@@ -792,7 +792,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, ...@@ -792,7 +792,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
rcu_read_lock(); rcu_read_lock();
ops = rcu_dereference(inet6_protos[proto]); ops = rcu_dereference(inet6_offloads[proto]);
if (likely(ops && ops->gso_segment)) { if (likely(ops && ops->gso_segment)) {
skb_reset_transport_header(skb); skb_reset_transport_header(skb);
segs = ops->gso_segment(skb, features); segs = ops->gso_segment(skb, features);
...@@ -825,7 +825,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, ...@@ -825,7 +825,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
struct sk_buff *skb) struct sk_buff *skb)
{ {
const struct inet6_protocol *ops; const struct net_offload *ops;
struct sk_buff **pp = NULL; struct sk_buff **pp = NULL;
struct sk_buff *p; struct sk_buff *p;
struct ipv6hdr *iph; struct ipv6hdr *iph;
...@@ -852,7 +852,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, ...@@ -852,7 +852,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
rcu_read_lock(); rcu_read_lock();
proto = iph->nexthdr; proto = iph->nexthdr;
ops = rcu_dereference(inet6_protos[proto]); ops = rcu_dereference(inet6_offloads[proto]);
if (!ops || !ops->gro_receive) { if (!ops || !ops->gro_receive) {
__pskb_pull(skb, skb_gro_offset(skb)); __pskb_pull(skb, skb_gro_offset(skb));
proto = ipv6_gso_pull_exthdrs(skb, proto); proto = ipv6_gso_pull_exthdrs(skb, proto);
...@@ -860,7 +860,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, ...@@ -860,7 +860,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
skb_reset_transport_header(skb); skb_reset_transport_header(skb);
__skb_push(skb, skb_gro_offset(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) if (!ops || !ops->gro_receive)
goto out_unlock; goto out_unlock;
...@@ -915,7 +915,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, ...@@ -915,7 +915,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
static int ipv6_gro_complete(struct sk_buff *skb) 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); struct ipv6hdr *iph = ipv6_hdr(skb);
int err = -ENOSYS; int err = -ENOSYS;
...@@ -923,7 +923,7 @@ static int ipv6_gro_complete(struct sk_buff *skb) ...@@ -923,7 +923,7 @@ static int ipv6_gro_complete(struct sk_buff *skb)
sizeof(*iph)); sizeof(*iph));
rcu_read_lock(); 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)) if (WARN_ON(!ops || !ops->gro_complete))
goto out_unlock; goto out_unlock;
......
...@@ -549,14 +549,44 @@ static const struct inet6_protocol nodata_protocol = { ...@@ -549,14 +549,44 @@ static const struct inet6_protocol nodata_protocol = {
.flags = INET6_PROTO_NOPOLICY, .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 __init ipv6_exthdrs_init(void)
{ {
int ret; int ret;
ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING); ret = ipv6_exthdrs_offload_init();
if (ret) if (ret)
goto out; goto out;
ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING);
if (ret)
goto out_offload;
ret = inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS); ret = inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
if (ret) if (ret)
goto out_rthdr; goto out_rthdr;
...@@ -567,10 +597,12 @@ int __init ipv6_exthdrs_init(void) ...@@ -567,10 +597,12 @@ int __init ipv6_exthdrs_init(void)
out: out:
return ret; return ret;
out_rthdr:
inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
out_destopt: out_destopt:
inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS); inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
out_rthdr:
inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
out_offload:
ipv6_exthdrs_offload_exit();
goto out; goto out;
}; };
......
...@@ -2066,10 +2066,6 @@ static const struct inet6_protocol tcpv6_protocol = { ...@@ -2066,10 +2066,6 @@ static const struct inet6_protocol tcpv6_protocol = {
.early_demux = tcp_v6_early_demux, .early_demux = tcp_v6_early_demux,
.handler = tcp_v6_rcv, .handler = tcp_v6_rcv,
.err_handler = tcp_v6_err, .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, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
}; };
...@@ -2116,10 +2112,14 @@ int __init tcpv6_init(void) ...@@ -2116,10 +2112,14 @@ int __init tcpv6_init(void)
{ {
int ret; int ret;
ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP); ret = inet6_add_offload(&tcpv6_offload, IPPROTO_TCP);
if (ret) if (ret)
goto out; goto out;
ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP);
if (ret)
goto out_offload;
/* register inet6 protocol */ /* register inet6 protocol */
ret = inet6_register_protosw(&tcpv6_protosw); ret = inet6_register_protosw(&tcpv6_protosw);
if (ret) if (ret)
...@@ -2131,10 +2131,12 @@ int __init tcpv6_init(void) ...@@ -2131,10 +2131,12 @@ int __init tcpv6_init(void)
out: out:
return ret; return ret;
out_tcpv6_protocol:
inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
out_tcpv6_protosw: out_tcpv6_protosw:
inet6_unregister_protosw(&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; goto out;
} }
...@@ -2143,4 +2145,5 @@ void tcpv6_exit(void) ...@@ -2143,4 +2145,5 @@ void tcpv6_exit(void)
unregister_pernet_subsys(&tcpv6_net_ops); unregister_pernet_subsys(&tcpv6_net_ops);
inet6_unregister_protosw(&tcpv6_protosw); inet6_unregister_protosw(&tcpv6_protosw);
inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
inet6_del_offload(&tcpv6_offload, IPPROTO_TCP);
} }
...@@ -1438,8 +1438,6 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, ...@@ -1438,8 +1438,6 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
static const struct inet6_protocol udpv6_protocol = { static const struct inet6_protocol udpv6_protocol = {
.handler = udpv6_rcv, .handler = udpv6_rcv,
.err_handler = udpv6_err, .err_handler = udpv6_err,
.gso_send_check = udp6_ufo_send_check,
.gso_segment = udp6_ufo_fragment,
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
}; };
...@@ -1570,10 +1568,14 @@ int __init udpv6_init(void) ...@@ -1570,10 +1568,14 @@ int __init udpv6_init(void)
{ {
int ret; int ret;
ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP); ret = inet6_add_offload(&udpv6_offload, IPPROTO_UDP);
if (ret) if (ret)
goto out; goto out;
ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP);
if (ret)
goto out_offload;
ret = inet6_register_protosw(&udpv6_protosw); ret = inet6_register_protosw(&udpv6_protosw);
if (ret) if (ret)
goto out_udpv6_protocol; goto out_udpv6_protocol;
...@@ -1582,6 +1584,8 @@ int __init udpv6_init(void) ...@@ -1582,6 +1584,8 @@ int __init udpv6_init(void)
out_udpv6_protocol: out_udpv6_protocol:
inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP); inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
out_offload:
inet6_del_offload(&udpv6_offload, IPPROTO_UDP);
goto out; goto out;
} }
...@@ -1589,4 +1593,5 @@ void udpv6_exit(void) ...@@ -1589,4 +1593,5 @@ void udpv6_exit(void)
{ {
inet6_unregister_protosw(&udpv6_protosw); inet6_unregister_protosw(&udpv6_protosw);
inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP); inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
inet6_del_offload(&udpv6_offload, IPPROTO_UDP);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment