aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/protocol.h11
-rw-r--r--net/ipv6/Makefile6
-rw-r--r--net/ipv6/af_inet6.c3
-rw-r--r--net/ipv6/exthdrs.c10
-rw-r--r--net/ipv6/exthdrs_offload.c6
-rw-r--r--net/ipv6/ip6_offload.c17
-rw-r--r--net/ipv6/ip6_offload.h8
-rw-r--r--net/ipv6/protocol.c20
-rw-r--r--net/ipv6/tcp_ipv6.c10
-rw-r--r--net/ipv6/tcpv6_offload.c5
-rw-r--r--net/ipv6/udp.c10
-rw-r--r--net/ipv6/udp_offload.c5
12 files changed, 36 insertions, 75 deletions
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 7019c1637848..2c90794c139d 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -25,6 +25,7 @@
25#define _PROTOCOL_H 25#define _PROTOCOL_H
26 26
27#include <linux/in6.h> 27#include <linux/in6.h>
28#include <linux/skbuff.h>
28#if IS_ENABLED(CONFIG_IPV6) 29#if IS_ENABLED(CONFIG_IPV6)
29#include <linux/ipv6.h> 30#include <linux/ipv6.h>
30#endif 31#endif
@@ -59,8 +60,6 @@ struct inet6_protocol {
59 60
60#define INET6_PROTO_NOPOLICY 0x1 61#define INET6_PROTO_NOPOLICY 0x1
61#define INET6_PROTO_FINAL 0x2 62#define INET6_PROTO_FINAL 0x2
62/* This should be set for any extension header which is compatible with GSO. */
63#define INET6_PROTO_GSO_EXTHDR 0x4
64#endif 63#endif
65 64
66struct net_offload { 65struct net_offload {
@@ -72,6 +71,8 @@ struct net_offload {
72 int (*gro_complete)(struct sk_buff *skb); 71 int (*gro_complete)(struct sk_buff *skb);
73 unsigned int flags; /* Flags used by IPv6 for now */ 72 unsigned int flags; /* Flags used by IPv6 for now */
74}; 73};
74/* This should be set for any extension header which is compatible with GSO. */
75#define INET6_PROTO_GSO_EXTHDR 0x1
75 76
76/* This is used to register socket interfaces for IP protocols. */ 77/* This is used to register socket interfaces for IP protocols. */
77struct inet_protosw { 78struct inet_protosw {
@@ -93,10 +94,10 @@ struct inet_protosw {
93 94
94extern const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS]; 95extern const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS];
95extern const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS]; 96extern const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS];
97extern const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS];
96 98
97#if IS_ENABLED(CONFIG_IPV6) 99#if IS_ENABLED(CONFIG_IPV6)
98extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS]; 100extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
99extern const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS];
100#endif 101#endif
101 102
102extern int inet_add_protocol(const struct net_protocol *prot, unsigned char num); 103extern 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);
109#if IS_ENABLED(CONFIG_IPV6) 110#if IS_ENABLED(CONFIG_IPV6)
110extern int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char num); 111extern int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char num);
111extern int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char num); 112extern int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char num);
112extern int inet6_add_offload(const struct net_offload *prot, unsigned char num);
113extern int inet6_del_offload(const struct net_offload *prot, unsigned char num);
114extern int inet6_register_protosw(struct inet_protosw *p); 113extern int inet6_register_protosw(struct inet_protosw *p);
115extern void inet6_unregister_protosw(struct inet_protosw *p); 114extern void inet6_unregister_protosw(struct inet_protosw *p);
116#endif 115#endif
116extern int inet6_add_offload(const struct net_offload *prot, unsigned char num);
117extern int inet6_del_offload(const struct net_offload *prot, unsigned char num);
117 118
118#endif /* _PROTOCOL_H */ 119#endif /* _PROTOCOL_H */
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index cdca302f395c..04a475df98ad 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_IPV6) += ipv6.o
7ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ 7ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
8 addrlabel.o \ 8 addrlabel.o \
9 route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ 9 route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \
10 raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ 10 raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
11 exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o 11 exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o
12 12
13ipv6-offload := ip6_offload.o tcpv6_offload.o udp_offload.o exthdrs_offload.o 13ipv6-offload := ip6_offload.o tcpv6_offload.o udp_offload.o exthdrs_offload.o
@@ -23,7 +23,6 @@ ipv6-$(CONFIG_PROC_FS) += proc.o
23ipv6-$(CONFIG_SYN_COOKIES) += syncookies.o 23ipv6-$(CONFIG_SYN_COOKIES) += syncookies.o
24 24
25ipv6-objs += $(ipv6-y) 25ipv6-objs += $(ipv6-y)
26ipv6-objs += $(ipv6-offload)
27 26
28obj-$(CONFIG_INET6_AH) += ah6.o 27obj-$(CONFIG_INET6_AH) += ah6.o
29obj-$(CONFIG_INET6_ESP) += esp6.o 28obj-$(CONFIG_INET6_ESP) += esp6.o
@@ -41,6 +40,7 @@ obj-$(CONFIG_IPV6_SIT) += sit.o
41obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o 40obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
42obj-$(CONFIG_IPV6_GRE) += ip6_gre.o 41obj-$(CONFIG_IPV6_GRE) += ip6_gre.o
43 42
44obj-y += addrconf_core.o exthdrs_core.o output_core.o 43obj-y += addrconf_core.o exthdrs_core.o output_core.o protocol.o
44obj-y += $(ipv6-offload)
45 45
46obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o 46obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index c84d5ba60cdd..7bafc51cda11 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -62,7 +62,6 @@
62 62
63#include <asm/uaccess.h> 63#include <asm/uaccess.h>
64#include <linux/mroute6.h> 64#include <linux/mroute6.h>
65#include "ip6_offload.h"
66 65
67MODULE_AUTHOR("Cast of dozens"); 66MODULE_AUTHOR("Cast of dozens");
68MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); 67MODULE_DESCRIPTION("IPv6 protocol stack for Linux");
@@ -707,14 +706,12 @@ static struct packet_type ipv6_packet_type __read_mostly = {
707 706
708static int __init ipv6_packet_init(void) 707static int __init ipv6_packet_init(void)
709{ 708{
710 ipv6_offload_init();
711 dev_add_pack(&ipv6_packet_type); 709 dev_add_pack(&ipv6_packet_type);
712 return 0; 710 return 0;
713} 711}
714 712
715static void ipv6_packet_cleanup(void) 713static void ipv6_packet_cleanup(void)
716{ 714{
717 ipv6_offload_cleanup();
718 dev_remove_pack(&ipv6_packet_type); 715 dev_remove_pack(&ipv6_packet_type);
719} 716}
720 717
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index a786a20ad823..473f628f9f20 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -48,7 +48,6 @@
48#endif 48#endif
49 49
50#include <asm/uaccess.h> 50#include <asm/uaccess.h>
51#include "ip6_offload.h"
52 51
53/* 52/*
54 * Parsing tlv encoded headers. 53 * Parsing tlv encoded headers.
@@ -502,13 +501,9 @@ int __init ipv6_exthdrs_init(void)
502{ 501{
503 int ret; 502 int ret;
504 503
505 ret = ipv6_exthdrs_offload_init();
506 if (ret)
507 goto out;
508
509 ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING); 504 ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING);
510 if (ret) 505 if (ret)
511 goto out_offload; 506 goto out;
512 507
513 ret = inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS); 508 ret = inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
514 if (ret) 509 if (ret)
@@ -524,14 +519,11 @@ out_destopt:
524 inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS); 519 inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
525out_rthdr: 520out_rthdr:
526 inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING); 521 inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
527out_offload:
528 ipv6_exthdrs_offload_exit();
529 goto out; 522 goto out;
530}; 523};
531 524
532void ipv6_exthdrs_exit(void) 525void ipv6_exthdrs_exit(void)
533{ 526{
534 ipv6_exthdrs_offload_exit();
535 inet6_del_protocol(&nodata_protocol, IPPROTO_NONE); 527 inet6_del_protocol(&nodata_protocol, IPPROTO_NONE);
536 inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS); 528 inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
537 inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING); 529 inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
diff --git a/net/ipv6/exthdrs_offload.c b/net/ipv6/exthdrs_offload.c
index 271bf4a97023..cf77f3abfd06 100644
--- a/net/ipv6/exthdrs_offload.c
+++ b/net/ipv6/exthdrs_offload.c
@@ -39,9 +39,3 @@ out_rt:
39 inet_del_offload(&rthdr_offload, IPPROTO_ROUTING); 39 inet_del_offload(&rthdr_offload, IPPROTO_ROUTING);
40 goto out; 40 goto out;
41} 41}
42
43void ipv6_exthdrs_offload_exit(void)
44{
45 inet_del_offload(&rthdr_offload, IPPROTO_ROUTING);
46 inet_del_offload(&rthdr_offload, IPPROTO_DSTOPTS);
47}
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 01cf9835a581..63d79d9005bd 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -12,6 +12,7 @@
12#include <linux/socket.h> 12#include <linux/socket.h>
13#include <linux/netdevice.h> 13#include <linux/netdevice.h>
14#include <linux/skbuff.h> 14#include <linux/skbuff.h>
15#include <linux/printk.h>
15 16
16#include <net/protocol.h> 17#include <net/protocol.h>
17#include <net/ipv6.h> 18#include <net/ipv6.h>
@@ -262,12 +263,18 @@ static struct packet_offload ipv6_packet_offload __read_mostly = {
262 .gro_complete = ipv6_gro_complete, 263 .gro_complete = ipv6_gro_complete,
263}; 264};
264 265
265void __init ipv6_offload_init(void) 266static int __init ipv6_offload_init(void)
266{ 267{
268
269 if (tcpv6_offload_init() < 0)
270 pr_crit("%s: Cannot add TCP protocol offload\n", __func__);
271 if (udp_offload_init() < 0)
272 pr_crit("%s: Cannot add UDP protocol offload\n", __func__);
273 if (ipv6_exthdrs_offload_init() < 0)
274 pr_crit("%s: Cannot add EXTHDRS protocol offload\n", __func__);
275
267 dev_add_offload(&ipv6_packet_offload); 276 dev_add_offload(&ipv6_packet_offload);
277 return 0;
268} 278}
269 279
270void ipv6_offload_cleanup(void) 280fs_initcall(ipv6_offload_init);
271{
272 dev_remove_offload(&ipv6_packet_offload);
273}
diff --git a/net/ipv6/ip6_offload.h b/net/ipv6/ip6_offload.h
index 4e88ddb52a2c..2e155c651b35 100644
--- a/net/ipv6/ip6_offload.h
+++ b/net/ipv6/ip6_offload.h
@@ -12,15 +12,7 @@
12#define __ip6_offload_h 12#define __ip6_offload_h
13 13
14int ipv6_exthdrs_offload_init(void); 14int ipv6_exthdrs_offload_init(void);
15void ipv6_exthdrs_offload_exit(void);
16
17int udp_offload_init(void); 15int udp_offload_init(void);
18void udp_offload_cleanup(void);
19
20int tcpv6_offload_init(void); 16int tcpv6_offload_init(void);
21void tcpv6_offload_cleanup(void);
22
23extern void ipv6_offload_init(void);
24extern void ipv6_offload_cleanup(void);
25 17
26#endif 18#endif
diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c
index f7c53a7d5cb0..22d1bd4670da 100644
--- a/net/ipv6/protocol.c
+++ b/net/ipv6/protocol.c
@@ -25,8 +25,9 @@
25#include <linux/spinlock.h> 25#include <linux/spinlock.h>
26#include <net/protocol.h> 26#include <net/protocol.h>
27 27
28#if IS_ENABLED(CONFIG_IPV6)
28const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS] __read_mostly; 29const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS] __read_mostly;
29const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS] __read_mostly; 30EXPORT_SYMBOL(inet6_protos);
30 31
31int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol) 32int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol)
32{ 33{
@@ -35,13 +36,6 @@ int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol
35} 36}
36EXPORT_SYMBOL(inet6_add_protocol); 37EXPORT_SYMBOL(inet6_add_protocol);
37 38
38int inet6_add_offload(const struct net_offload *prot, unsigned char protocol)
39{
40 return !cmpxchg((const struct net_offload **)&inet6_offloads[protocol],
41 NULL, prot) ? 0 : -1;
42}
43EXPORT_SYMBOL(inet6_add_offload);
44
45/* 39/*
46 * Remove a protocol from the hash tables. 40 * Remove a protocol from the hash tables.
47 */ 41 */
@@ -58,6 +52,16 @@ int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol
58 return ret; 52 return ret;
59} 53}
60EXPORT_SYMBOL(inet6_del_protocol); 54EXPORT_SYMBOL(inet6_del_protocol);
55#endif
56
57const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS] __read_mostly;
58
59int inet6_add_offload(const struct net_offload *prot, unsigned char protocol)
60{
61 return !cmpxchg((const struct net_offload **)&inet6_offloads[protocol],
62 NULL, prot) ? 0 : -1;
63}
64EXPORT_SYMBOL(inet6_add_offload);
61 65
62int inet6_del_offload(const struct net_offload *prot, unsigned char protocol) 66int inet6_del_offload(const struct net_offload *prot, unsigned char protocol)
63{ 67{
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 5bed594b429d..6c0f2526f3f1 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -71,7 +71,6 @@
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"
75 74
76static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); 75static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb);
77static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, 76static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
@@ -2007,13 +2006,9 @@ int __init tcpv6_init(void)
2007{ 2006{
2008 int ret; 2007 int ret;
2009 2008
2010 ret = tcpv6_offload_init();
2011 if (ret)
2012 goto out;
2013
2014 ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP); 2009 ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP);
2015 if (ret) 2010 if (ret)
2016 goto out_offload; 2011 goto out;
2017 2012
2018 /* register inet6 protocol */ 2013 /* register inet6 protocol */
2019 ret = inet6_register_protosw(&tcpv6_protosw); 2014 ret = inet6_register_protosw(&tcpv6_protosw);
@@ -2030,8 +2025,6 @@ out_tcpv6_protosw:
2030 inet6_unregister_protosw(&tcpv6_protosw); 2025 inet6_unregister_protosw(&tcpv6_protosw);
2031out_tcpv6_protocol: 2026out_tcpv6_protocol:
2032 inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); 2027 inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
2033out_offload:
2034 tcpv6_offload_cleanup();
2035 goto out; 2028 goto out;
2036} 2029}
2037 2030
@@ -2040,5 +2033,4 @@ void tcpv6_exit(void)
2040 unregister_pernet_subsys(&tcpv6_net_ops); 2033 unregister_pernet_subsys(&tcpv6_net_ops);
2041 inet6_unregister_protosw(&tcpv6_protosw); 2034 inet6_unregister_protosw(&tcpv6_protosw);
2042 inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); 2035 inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
2043 tcpv6_offload_cleanup();
2044} 2036}
diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c
index edeafedba470..3a27fe685c8e 100644
--- a/net/ipv6/tcpv6_offload.c
+++ b/net/ipv6/tcpv6_offload.c
@@ -91,8 +91,3 @@ int __init tcpv6_offload_init(void)
91{ 91{
92 return inet6_add_offload(&tcpv6_offload, IPPROTO_TCP); 92 return inet6_add_offload(&tcpv6_offload, IPPROTO_TCP);
93} 93}
94
95void tcpv6_offload_cleanup(void)
96{
97 inet6_del_offload(&tcpv6_offload, IPPROTO_TCP);
98}
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 013fef740d51..dfaa29b8b293 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -50,7 +50,6 @@
50#include <linux/seq_file.h> 50#include <linux/seq_file.h>
51#include <trace/events/skb.h> 51#include <trace/events/skb.h>
52#include "udp_impl.h" 52#include "udp_impl.h"
53#include "ip6_offload.h"
54 53
55int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) 54int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
56{ 55{
@@ -1472,13 +1471,9 @@ int __init udpv6_init(void)
1472{ 1471{
1473 int ret; 1472 int ret;
1474 1473
1475 ret = udp_offload_init();
1476 if (ret)
1477 goto out;
1478
1479 ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP); 1474 ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP);
1480 if (ret) 1475 if (ret)
1481 goto out_offload; 1476 goto out;
1482 1477
1483 ret = inet6_register_protosw(&udpv6_protosw); 1478 ret = inet6_register_protosw(&udpv6_protosw);
1484 if (ret) 1479 if (ret)
@@ -1488,8 +1483,6 @@ out:
1488 1483
1489out_udpv6_protocol: 1484out_udpv6_protocol:
1490 inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP); 1485 inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
1491out_offload:
1492 udp_offload_cleanup();
1493 goto out; 1486 goto out;
1494} 1487}
1495 1488
@@ -1497,5 +1490,4 @@ void udpv6_exit(void)
1497{ 1490{
1498 inet6_unregister_protosw(&udpv6_protosw); 1491 inet6_unregister_protosw(&udpv6_protosw);
1499 inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP); 1492 inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
1500 udp_offload_cleanup();
1501} 1493}
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index f964d2b366c8..979e4ab63a8b 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -115,8 +115,3 @@ int __init udp_offload_init(void)
115{ 115{
116 return inet6_add_offload(&udpv6_offload, IPPROTO_UDP); 116 return inet6_add_offload(&udpv6_offload, IPPROTO_UDP);
117} 117}
118
119void udp_offload_cleanup(void)
120{
121 inet6_del_offload(&udpv6_offload, IPPROTO_UDP);
122}