From 8663e02aba154e04679c9bb1665af52021d32547 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 15 Nov 2012 08:49:17 +0000 Subject: 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 Signed-off-by: David S. Miller --- net/ipv6/tcpv6_offload.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 net/ipv6/tcpv6_offload.c (limited to 'net/ipv6/tcpv6_offload.c') diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c new file mode 100644 index 00000000000..edeafedba47 --- /dev/null +++ b/net/ipv6/tcpv6_offload.c @@ -0,0 +1,98 @@ +/* + * IPV6 GSO/GRO offload support + * Linux INET6 implementation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * TCPv6 GSO/GRO support + */ +#include +#include +#include +#include +#include "ip6_offload.h" + +static int tcp_v6_gso_send_check(struct sk_buff *skb) +{ + const struct ipv6hdr *ipv6h; + struct tcphdr *th; + + if (!pskb_may_pull(skb, sizeof(*th))) + return -EINVAL; + + ipv6h = ipv6_hdr(skb); + th = tcp_hdr(skb); + + th->check = 0; + skb->ip_summed = CHECKSUM_PARTIAL; + __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr); + return 0; +} + +static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, + struct sk_buff *skb) +{ + const struct ipv6hdr *iph = skb_gro_network_header(skb); + __wsum wsum; + __sum16 sum; + + switch (skb->ip_summed) { + case CHECKSUM_COMPLETE: + if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr, + skb->csum)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + } +flush: + NAPI_GRO_CB(skb)->flush = 1; + return NULL; + + case CHECKSUM_NONE: + wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr, + skb_gro_len(skb), + IPPROTO_TCP, 0)); + sum = csum_fold(skb_checksum(skb, + skb_gro_offset(skb), + skb_gro_len(skb), + wsum)); + if (sum) + goto flush; + + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + } + + return tcp_gro_receive(head, skb); +} + +static int tcp6_gro_complete(struct sk_buff *skb) +{ + const struct ipv6hdr *iph = ipv6_hdr(skb); + struct tcphdr *th = tcp_hdr(skb); + + th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb), + &iph->saddr, &iph->daddr, 0); + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; + + return tcp_gro_complete(skb); +} + +static const struct net_offload tcpv6_offload = { + .gso_send_check = tcp_v6_gso_send_check, + .gso_segment = tcp_tso_segment, + .gro_receive = tcp6_gro_receive, + .gro_complete = tcp6_gro_complete, +}; + +int __init tcpv6_offload_init(void) +{ + return inet6_add_offload(&tcpv6_offload, IPPROTO_TCP); +} + +void tcpv6_offload_cleanup(void) +{ + inet6_del_offload(&tcpv6_offload, IPPROTO_TCP); +} -- cgit v1.2.3-70-g09d2 From c6b641a4c6b32f39db678c2441cb1ef824110d74 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 15 Nov 2012 08:49:22 +0000 Subject: ipv6: Pull IPv6 GSO registration out of the module Sing GSO support is now separate, pull it out of the module and make it its own init call. Remove the cleanup functions as they are no longer called. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/protocol.h | 11 ++++++----- net/ipv6/Makefile | 6 +++--- net/ipv6/af_inet6.c | 3 --- net/ipv6/exthdrs.c | 10 +--------- net/ipv6/exthdrs_offload.c | 6 ------ net/ipv6/ip6_offload.c | 17 ++++++++++++----- net/ipv6/ip6_offload.h | 8 -------- net/ipv6/protocol.c | 20 ++++++++++++-------- net/ipv6/tcp_ipv6.c | 10 +--------- net/ipv6/tcpv6_offload.c | 5 ----- net/ipv6/udp.c | 10 +--------- net/ipv6/udp_offload.c | 5 ----- 12 files changed, 36 insertions(+), 75 deletions(-) (limited to 'net/ipv6/tcpv6_offload.c') diff --git a/include/net/protocol.h b/include/net/protocol.h index 7019c163784..2c90794c139 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -25,6 +25,7 @@ #define _PROTOCOL_H #include +#include #if IS_ENABLED(CONFIG_IPV6) #include #endif @@ -59,8 +60,6 @@ struct inet6_protocol { #define INET6_PROTO_NOPOLICY 0x1 #define INET6_PROTO_FINAL 0x2 -/* This should be set for any extension header which is compatible with GSO. */ -#define INET6_PROTO_GSO_EXTHDR 0x4 #endif struct net_offload { @@ -72,6 +71,8 @@ struct net_offload { int (*gro_complete)(struct sk_buff *skb); unsigned int flags; /* Flags used by IPv6 for now */ }; +/* This should be set for any extension header which is compatible with GSO. */ +#define INET6_PROTO_GSO_EXTHDR 0x1 /* This is used to register socket interfaces for IP protocols. */ struct inet_protosw { @@ -93,10 +94,10 @@ struct inet_protosw { extern const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS]; extern const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS]; +extern const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS]; #if IS_ENABLED(CONFIG_IPV6) extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS]; -extern const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS]; #endif extern int inet_add_protocol(const struct net_protocol *prot, unsigned char num); @@ -109,10 +110,10 @@ extern void inet_unregister_protosw(struct inet_protosw *p); #if IS_ENABLED(CONFIG_IPV6) extern int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char num); extern int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char num); -extern int inet6_add_offload(const struct net_offload *prot, unsigned char num); -extern int inet6_del_offload(const struct net_offload *prot, unsigned char num); extern int inet6_register_protosw(struct inet_protosw *p); extern void inet6_unregister_protosw(struct inet_protosw *p); #endif +extern int inet6_add_offload(const struct net_offload *prot, unsigned char num); +extern int inet6_del_offload(const struct net_offload *prot, unsigned char num); #endif /* _PROTOCOL_H */ diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index cdca302f395..04a475df98a 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_IPV6) += ipv6.o ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ addrlabel.o \ route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ - raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ + raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o ipv6-offload := ip6_offload.o tcpv6_offload.o udp_offload.o exthdrs_offload.o @@ -23,7 +23,6 @@ ipv6-$(CONFIG_PROC_FS) += proc.o ipv6-$(CONFIG_SYN_COOKIES) += syncookies.o ipv6-objs += $(ipv6-y) -ipv6-objs += $(ipv6-offload) obj-$(CONFIG_INET6_AH) += ah6.o obj-$(CONFIG_INET6_ESP) += esp6.o @@ -41,6 +40,7 @@ obj-$(CONFIG_IPV6_SIT) += sit.o obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o obj-$(CONFIG_IPV6_GRE) += ip6_gre.o -obj-y += addrconf_core.o exthdrs_core.o output_core.o +obj-y += addrconf_core.o exthdrs_core.o output_core.o protocol.o +obj-y += $(ipv6-offload) obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index c84d5ba60cd..7bafc51cda1 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -62,7 +62,6 @@ #include #include -#include "ip6_offload.h" MODULE_AUTHOR("Cast of dozens"); MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); @@ -707,14 +706,12 @@ static struct packet_type ipv6_packet_type __read_mostly = { static int __init ipv6_packet_init(void) { - ipv6_offload_init(); dev_add_pack(&ipv6_packet_type); return 0; } static void ipv6_packet_cleanup(void) { - ipv6_offload_cleanup(); dev_remove_pack(&ipv6_packet_type); } diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index a786a20ad82..473f628f9f2 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -48,7 +48,6 @@ #endif #include -#include "ip6_offload.h" /* * Parsing tlv encoded headers. @@ -502,13 +501,9 @@ int __init ipv6_exthdrs_init(void) { int ret; - ret = ipv6_exthdrs_offload_init(); - if (ret) - goto out; - ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING); if (ret) - goto out_offload; + goto out; ret = inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS); if (ret) @@ -524,14 +519,11 @@ 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; }; void ipv6_exthdrs_exit(void) { - ipv6_exthdrs_offload_exit(); inet6_del_protocol(&nodata_protocol, IPPROTO_NONE); inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS); inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING); diff --git a/net/ipv6/exthdrs_offload.c b/net/ipv6/exthdrs_offload.c index 271bf4a9702..cf77f3abfd0 100644 --- a/net/ipv6/exthdrs_offload.c +++ b/net/ipv6/exthdrs_offload.c @@ -39,9 +39,3 @@ out_rt: inet_del_offload(&rthdr_offload, IPPROTO_ROUTING); goto out; } - -void ipv6_exthdrs_offload_exit(void) -{ - inet_del_offload(&rthdr_offload, IPPROTO_ROUTING); - inet_del_offload(&rthdr_offload, IPPROTO_DSTOPTS); -} diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 01cf9835a58..63d79d9005b 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -262,12 +263,18 @@ static struct packet_offload ipv6_packet_offload __read_mostly = { .gro_complete = ipv6_gro_complete, }; -void __init ipv6_offload_init(void) +static int __init ipv6_offload_init(void) { + + if (tcpv6_offload_init() < 0) + pr_crit("%s: Cannot add TCP protocol offload\n", __func__); + if (udp_offload_init() < 0) + pr_crit("%s: Cannot add UDP protocol offload\n", __func__); + if (ipv6_exthdrs_offload_init() < 0) + pr_crit("%s: Cannot add EXTHDRS protocol offload\n", __func__); + dev_add_offload(&ipv6_packet_offload); + return 0; } -void ipv6_offload_cleanup(void) -{ - dev_remove_offload(&ipv6_packet_offload); -} +fs_initcall(ipv6_offload_init); diff --git a/net/ipv6/ip6_offload.h b/net/ipv6/ip6_offload.h index 4e88ddb52a2..2e155c651b3 100644 --- a/net/ipv6/ip6_offload.h +++ b/net/ipv6/ip6_offload.h @@ -12,15 +12,7 @@ #define __ip6_offload_h int ipv6_exthdrs_offload_init(void); -void ipv6_exthdrs_offload_exit(void); - int udp_offload_init(void); -void udp_offload_cleanup(void); - int tcpv6_offload_init(void); -void tcpv6_offload_cleanup(void); - -extern void ipv6_offload_init(void); -extern void ipv6_offload_cleanup(void); #endif diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c index f7c53a7d5cb..22d1bd4670d 100644 --- a/net/ipv6/protocol.c +++ b/net/ipv6/protocol.c @@ -25,8 +25,9 @@ #include #include +#if IS_ENABLED(CONFIG_IPV6) const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS] __read_mostly; -const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS] __read_mostly; +EXPORT_SYMBOL(inet6_protos); int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol) { @@ -35,13 +36,6 @@ int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol } EXPORT_SYMBOL(inet6_add_protocol); -int inet6_add_offload(const struct net_offload *prot, unsigned char protocol) -{ - return !cmpxchg((const struct net_offload **)&inet6_offloads[protocol], - NULL, prot) ? 0 : -1; -} -EXPORT_SYMBOL(inet6_add_offload); - /* * Remove a protocol from the hash tables. */ @@ -58,6 +52,16 @@ int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol return ret; } EXPORT_SYMBOL(inet6_del_protocol); +#endif + +const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS] __read_mostly; + +int inet6_add_offload(const struct net_offload *prot, unsigned char protocol) +{ + return !cmpxchg((const struct net_offload **)&inet6_offloads[protocol], + NULL, prot) ? 0 : -1; +} +EXPORT_SYMBOL(inet6_add_offload); int inet6_del_offload(const struct net_offload *prot, unsigned char protocol) { diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 5bed594b429..6c0f2526f3f 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -71,7 +71,6 @@ #include #include -#include "ip6_offload.h" static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, @@ -2007,13 +2006,9 @@ int __init tcpv6_init(void) { int ret; - ret = tcpv6_offload_init(); - if (ret) - goto out; - ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP); if (ret) - goto out_offload; + goto out; /* register inet6 protocol */ ret = inet6_register_protosw(&tcpv6_protosw); @@ -2030,8 +2025,6 @@ out_tcpv6_protosw: inet6_unregister_protosw(&tcpv6_protosw); out_tcpv6_protocol: inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); -out_offload: - tcpv6_offload_cleanup(); goto out; } @@ -2040,5 +2033,4 @@ void tcpv6_exit(void) unregister_pernet_subsys(&tcpv6_net_ops); inet6_unregister_protosw(&tcpv6_protosw); inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); - tcpv6_offload_cleanup(); } diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c index edeafedba47..3a27fe685c8 100644 --- a/net/ipv6/tcpv6_offload.c +++ b/net/ipv6/tcpv6_offload.c @@ -91,8 +91,3 @@ int __init tcpv6_offload_init(void) { return inet6_add_offload(&tcpv6_offload, IPPROTO_TCP); } - -void tcpv6_offload_cleanup(void) -{ - inet6_del_offload(&tcpv6_offload, IPPROTO_TCP); -} diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 013fef740d5..dfaa29b8b29 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -50,7 +50,6 @@ #include #include #include "udp_impl.h" -#include "ip6_offload.h" int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) { @@ -1472,13 +1471,9 @@ int __init udpv6_init(void) { int ret; - ret = udp_offload_init(); - if (ret) - goto out; - ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP); if (ret) - goto out_offload; + goto out; ret = inet6_register_protosw(&udpv6_protosw); if (ret) @@ -1488,8 +1483,6 @@ out: out_udpv6_protocol: inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP); -out_offload: - udp_offload_cleanup(); goto out; } @@ -1497,5 +1490,4 @@ void udpv6_exit(void) { inet6_unregister_protosw(&udpv6_protosw); inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP); - udp_offload_cleanup(); } diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index f964d2b366c..979e4ab63a8 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c @@ -115,8 +115,3 @@ int __init udp_offload_init(void) { return inet6_add_offload(&udpv6_offload, IPPROTO_UDP); } - -void udp_offload_cleanup(void) -{ - inet6_del_offload(&udpv6_offload, IPPROTO_UDP); -} -- cgit v1.2.3-70-g09d2 From f191a1d17f227032c159e5499809f545402b6dc6 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 15 Nov 2012 08:49:23 +0000 Subject: net: Remove code duplication between offload structures Move the offload callbacks into its own structure. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/linux/netdevice.h | 10 +++++++--- include/net/protocol.h | 10 +++------- net/core/dev.c | 14 +++++++------- net/ipv4/af_inet.c | 42 ++++++++++++++++++++++++------------------ net/ipv6/ip6_offload.c | 28 +++++++++++++++------------- net/ipv6/tcpv6_offload.c | 10 ++++++---- net/ipv6/udp_offload.c | 6 ++++-- 7 files changed, 66 insertions(+), 54 deletions(-) (limited to 'net/ipv6/tcpv6_offload.c') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 61bc8483031..e46c830c88d 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1515,15 +1515,19 @@ struct packet_type { struct list_head list; }; -struct packet_offload { - __be16 type; /* This is really htons(ether_type). */ +struct offload_callbacks { struct sk_buff *(*gso_segment)(struct sk_buff *skb, netdev_features_t features); int (*gso_send_check)(struct sk_buff *skb); struct sk_buff **(*gro_receive)(struct sk_buff **head, struct sk_buff *skb); int (*gro_complete)(struct sk_buff *skb); - struct list_head list; +}; + +struct packet_offload { + __be16 type; /* This is really htons(ether_type). */ + struct offload_callbacks callbacks; + struct list_head list; }; #include diff --git a/include/net/protocol.h b/include/net/protocol.h index 2c90794c139..047c0476c0a 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -29,6 +29,7 @@ #if IS_ENABLED(CONFIG_IPV6) #include #endif +#include /* This is one larger than the largest protocol value that can be * found in an ipv4 or ipv6 header. Since in both cases the protocol @@ -63,13 +64,8 @@ struct inet6_protocol { #endif struct net_offload { - 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; /* Flags used by IPv6 for now */ + struct offload_callbacks callbacks; + unsigned int flags; /* Flags used by IPv6 for now */ }; /* This should be set for any extension header which is compatible with GSO. */ #define INET6_PROTO_GSO_EXTHDR 0x1 diff --git a/net/core/dev.c b/net/core/dev.c index cf843a256cc..cf105e886cc 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2102,16 +2102,16 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, rcu_read_lock(); list_for_each_entry_rcu(ptype, &offload_base, list) { - if (ptype->type == type && ptype->gso_segment) { + if (ptype->type == type && ptype->callbacks.gso_segment) { if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) { - err = ptype->gso_send_check(skb); + err = ptype->callbacks.gso_send_check(skb); segs = ERR_PTR(err); if (err || skb_gso_ok(skb, features)) break; __skb_push(skb, (skb->data - skb_network_header(skb))); } - segs = ptype->gso_segment(skb, features); + segs = ptype->callbacks.gso_segment(skb, features); break; } } @@ -3533,10 +3533,10 @@ static int napi_gro_complete(struct sk_buff *skb) rcu_read_lock(); list_for_each_entry_rcu(ptype, head, list) { - if (ptype->type != type || !ptype->gro_complete) + if (ptype->type != type || !ptype->callbacks.gro_complete) continue; - err = ptype->gro_complete(skb); + err = ptype->callbacks.gro_complete(skb); break; } rcu_read_unlock(); @@ -3598,7 +3598,7 @@ enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) rcu_read_lock(); list_for_each_entry_rcu(ptype, head, list) { - if (ptype->type != type || !ptype->gro_receive) + if (ptype->type != type || !ptype->callbacks.gro_receive) continue; skb_set_network_header(skb, skb_gro_offset(skb)); @@ -3608,7 +3608,7 @@ enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) NAPI_GRO_CB(skb)->flush = 0; NAPI_GRO_CB(skb)->free = 0; - pp = ptype->gro_receive(&napi->gro_list, skb); + pp = ptype->callbacks.gro_receive(&napi->gro_list, skb); break; } rcu_read_unlock(); diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 9f2e7fd8bea..d5e5a054123 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1276,8 +1276,8 @@ static int inet_gso_send_check(struct sk_buff *skb) rcu_read_lock(); ops = rcu_dereference(inet_offloads[proto]); - if (likely(ops && ops->gso_send_check)) - err = ops->gso_send_check(skb); + if (likely(ops && ops->callbacks.gso_send_check)) + err = ops->callbacks.gso_send_check(skb); rcu_read_unlock(); out: @@ -1326,8 +1326,8 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, rcu_read_lock(); ops = rcu_dereference(inet_offloads[proto]); - if (likely(ops && ops->gso_segment)) - segs = ops->gso_segment(skb, features); + if (likely(ops && ops->callbacks.gso_segment)) + segs = ops->callbacks.gso_segment(skb, features); rcu_read_unlock(); if (!segs || IS_ERR(segs)) @@ -1379,7 +1379,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, rcu_read_lock(); ops = rcu_dereference(inet_offloads[proto]); - if (!ops || !ops->gro_receive) + if (!ops || !ops->callbacks.gro_receive) goto out_unlock; if (*(u8 *)iph != 0x45) @@ -1420,7 +1420,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, skb_gro_pull(skb, sizeof(*iph)); skb_set_transport_header(skb, skb_gro_offset(skb)); - pp = ops->gro_receive(head, skb); + pp = ops->callbacks.gro_receive(head, skb); out_unlock: rcu_read_unlock(); @@ -1444,10 +1444,10 @@ static int inet_gro_complete(struct sk_buff *skb) rcu_read_lock(); ops = rcu_dereference(inet_offloads[proto]); - if (WARN_ON(!ops || !ops->gro_complete)) + if (WARN_ON(!ops || !ops->callbacks.gro_complete)) goto out_unlock; - err = ops->gro_complete(skb); + err = ops->callbacks.gro_complete(skb); out_unlock: rcu_read_unlock(); @@ -1563,10 +1563,12 @@ static const struct net_protocol tcp_protocol = { }; static const struct net_offload tcp_offload = { - .gso_send_check = tcp_v4_gso_send_check, - .gso_segment = tcp_tso_segment, - .gro_receive = tcp4_gro_receive, - .gro_complete = tcp4_gro_complete, + .callbacks = { + .gso_send_check = tcp_v4_gso_send_check, + .gso_segment = tcp_tso_segment, + .gro_receive = tcp4_gro_receive, + .gro_complete = tcp4_gro_complete, + }, }; static const struct net_protocol udp_protocol = { @@ -1577,8 +1579,10 @@ static const struct net_protocol udp_protocol = { }; static const struct net_offload udp_offload = { - .gso_send_check = udp4_ufo_send_check, - .gso_segment = udp4_ufo_fragment, + .callbacks = { + .gso_send_check = udp4_ufo_send_check, + .gso_segment = udp4_ufo_fragment, + }, }; static const struct net_protocol icmp_protocol = { @@ -1667,10 +1671,12 @@ static int ipv4_proc_init(void); static struct packet_offload ip_packet_offload __read_mostly = { .type = cpu_to_be16(ETH_P_IP), - .gso_send_check = inet_gso_send_check, - .gso_segment = inet_gso_segment, - .gro_receive = inet_gro_receive, - .gro_complete = inet_gro_complete, + .callbacks = { + .gso_send_check = inet_gso_send_check, + .gso_segment = inet_gso_segment, + .gro_receive = inet_gro_receive, + .gro_complete = inet_gro_complete, + }, }; static int __init ipv4_offload_init(void) diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 63d79d9005b..f26f0da7f09 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -70,9 +70,9 @@ static int ipv6_gso_send_check(struct sk_buff *skb) ops = rcu_dereference(inet6_offloads[ ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]); - if (likely(ops && ops->gso_send_check)) { + if (likely(ops && ops->callbacks.gso_send_check)) { skb_reset_transport_header(skb); - err = ops->gso_send_check(skb); + err = ops->callbacks.gso_send_check(skb); } rcu_read_unlock(); @@ -113,9 +113,9 @@ 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_offloads[proto]); - if (likely(ops && ops->gso_segment)) { + if (likely(ops && ops->callbacks.gso_segment)) { skb_reset_transport_header(skb); - segs = ops->gso_segment(skb, features); + segs = ops->callbacks.gso_segment(skb, features); } rcu_read_unlock(); @@ -173,7 +173,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, rcu_read_lock(); proto = iph->nexthdr; ops = rcu_dereference(inet6_offloads[proto]); - if (!ops || !ops->gro_receive) { + if (!ops || !ops->callbacks.gro_receive) { __pskb_pull(skb, skb_gro_offset(skb)); proto = ipv6_gso_pull_exthdrs(skb, proto); skb_gro_pull(skb, -skb_transport_offset(skb)); @@ -181,7 +181,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, __skb_push(skb, skb_gro_offset(skb)); ops = rcu_dereference(inet6_offloads[proto]); - if (!ops || !ops->gro_receive) + if (!ops || !ops->callbacks.gro_receive) goto out_unlock; iph = ipv6_hdr(skb); @@ -220,7 +220,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, csum = skb->csum; skb_postpull_rcsum(skb, iph, skb_network_header_len(skb)); - pp = ops->gro_receive(head, skb); + pp = ops->callbacks.gro_receive(head, skb); skb->csum = csum; @@ -244,10 +244,10 @@ static int ipv6_gro_complete(struct sk_buff *skb) rcu_read_lock(); ops = rcu_dereference(inet6_offloads[NAPI_GRO_CB(skb)->proto]); - if (WARN_ON(!ops || !ops->gro_complete)) + if (WARN_ON(!ops || !ops->callbacks.gro_complete)) goto out_unlock; - err = ops->gro_complete(skb); + err = ops->callbacks.gro_complete(skb); out_unlock: rcu_read_unlock(); @@ -257,10 +257,12 @@ out_unlock: static struct packet_offload ipv6_packet_offload __read_mostly = { .type = cpu_to_be16(ETH_P_IPV6), - .gso_send_check = ipv6_gso_send_check, - .gso_segment = ipv6_gso_segment, - .gro_receive = ipv6_gro_receive, - .gro_complete = ipv6_gro_complete, + .callbacks = { + .gso_send_check = ipv6_gso_send_check, + .gso_segment = ipv6_gso_segment, + .gro_receive = ipv6_gro_receive, + .gro_complete = ipv6_gro_complete, + }, }; static int __init ipv6_offload_init(void) diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c index 3a27fe685c8..2ec6bf6a0aa 100644 --- a/net/ipv6/tcpv6_offload.c +++ b/net/ipv6/tcpv6_offload.c @@ -81,10 +81,12 @@ static int tcp6_gro_complete(struct sk_buff *skb) } static const struct net_offload tcpv6_offload = { - .gso_send_check = tcp_v6_gso_send_check, - .gso_segment = tcp_tso_segment, - .gro_receive = tcp6_gro_receive, - .gro_complete = tcp6_gro_complete, + .callbacks = { + .gso_send_check = tcp_v6_gso_send_check, + .gso_segment = tcp_tso_segment, + .gro_receive = tcp6_gro_receive, + .gro_complete = tcp6_gro_complete, + }, }; int __init tcpv6_offload_init(void) diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index 979e4ab63a8..8e01c44a987 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c @@ -107,8 +107,10 @@ out: return segs; } static const struct net_offload udpv6_offload = { - .gso_send_check = udp6_ufo_send_check, - .gso_segment = udp6_ufo_fragment, + .callbacks = { + .gso_send_check = udp6_ufo_send_check, + .gso_segment = udp6_ufo_fragment, + }, }; int __init udp_offload_init(void) -- cgit v1.2.3-70-g09d2