瀏覽代碼

ipv6: Add new offload registration infrastructure.

Create a new data structure for IPv6 protocols that holds GRO/GSO
callbacks and a new array to track the protocols that register GRO/GSO.

Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Vlad Yasevich 12 年之前
父節點
當前提交
8ca896cfdd
共有 5 個文件被更改,包括 45 次插入0 次删除
  1. 4 0
      include/net/protocol.h
  2. 8 0
      net/ipv6/exthdrs.c
  3. 21 0
      net/ipv6/protocol.c
  4. 7 0
      net/ipv6/tcp_ipv6.c
  5. 5 0
      net/ipv6/udp.c

+ 4 - 0
include/net/protocol.h

@@ -84,6 +84,7 @@ struct net_offload {
 	struct sk_buff	      **(*gro_receive)(struct sk_buff **head,
 	struct sk_buff	      **(*gro_receive)(struct sk_buff **head,
 					       struct sk_buff *skb);
 					       struct sk_buff *skb);
 	int			(*gro_complete)(struct sk_buff *skb);
 	int			(*gro_complete)(struct sk_buff *skb);
+	unsigned int		flags;	/* Flags used by IPv6 for now */
 };
 };
 
 
 /* This is used to register socket interfaces for IP protocols.  */
 /* This is used to register socket interfaces for IP protocols.  */
@@ -109,6 +110,7 @@ extern const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS];
 
 
 #if IS_ENABLED(CONFIG_IPV6)
 #if IS_ENABLED(CONFIG_IPV6)
 extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
 extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
+extern const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS];
 #endif
 #endif
 
 
 extern int	inet_add_protocol(const struct net_protocol *prot, unsigned char num);
 extern int	inet_add_protocol(const struct net_protocol *prot, unsigned char num);
@@ -121,6 +123,8 @@ extern void	inet_unregister_protosw(struct inet_protosw *p);
 #if IS_ENABLED(CONFIG_IPV6)
 #if IS_ENABLED(CONFIG_IPV6)
 extern int	inet6_add_protocol(const struct inet6_protocol *prot, unsigned char num);
 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_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 int	inet6_register_protosw(struct inet_protosw *p);
 extern void	inet6_unregister_protosw(struct inet_protosw *p);
 extern void	inet6_unregister_protosw(struct inet_protosw *p);
 #endif
 #endif

+ 8 - 0
net/ipv6/exthdrs.c

@@ -531,11 +531,19 @@ static const struct inet6_protocol rthdr_protocol = {
 	.flags		=	INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
 	.flags		=	INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
 };
 };
 
 
+static const struct net_offload rthdr_offload = {
+	.flags		=	INET6_PROTO_GSO_EXTHDR,
+};
+
 static const struct inet6_protocol destopt_protocol = {
 static const struct inet6_protocol destopt_protocol = {
 	.handler	=	ipv6_destopt_rcv,
 	.handler	=	ipv6_destopt_rcv,
 	.flags		=	INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
 	.flags		=	INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
 };
 };
 
 
+static const struct net_offload dstopt_offload = {
+	.flags		=	INET6_PROTO_GSO_EXTHDR,
+};
+
 static const struct inet6_protocol nodata_protocol = {
 static const struct inet6_protocol nodata_protocol = {
 	.handler	=	dst_discard,
 	.handler	=	dst_discard,
 	.flags		=	INET6_PROTO_NOPOLICY,
 	.flags		=	INET6_PROTO_NOPOLICY,

+ 21 - 0
net/ipv6/protocol.c

@@ -26,6 +26,7 @@
 #include <net/protocol.h>
 #include <net/protocol.h>
 
 
 const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS] __read_mostly;
 const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS] __read_mostly;
+const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS] __read_mostly;
 
 
 int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol)
 int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol)
 {
 {
@@ -34,6 +35,13 @@ int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol
 }
 }
 EXPORT_SYMBOL(inet6_add_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.
  *	Remove a protocol from the hash tables.
  */
  */
@@ -50,3 +58,16 @@ int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol
 	return ret;
 	return ret;
 }
 }
 EXPORT_SYMBOL(inet6_del_protocol);
 EXPORT_SYMBOL(inet6_del_protocol);
+
+int inet6_del_offload(const struct net_offload *prot, unsigned char protocol)
+{
+	int ret;
+
+	ret = (cmpxchg((const struct net_offload **)&inet6_offloads[protocol],
+		       prot, NULL) == prot) ? 0 : -1;
+
+	synchronize_net();
+
+	return ret;
+}
+EXPORT_SYMBOL(inet6_del_offload);

+ 7 - 0
net/ipv6/tcp_ipv6.c

@@ -2073,6 +2073,13 @@ static const struct inet6_protocol tcpv6_protocol = {
 	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 };
 
 
+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,
+};
+
 static struct inet_protosw tcpv6_protosw = {
 static struct inet_protosw tcpv6_protosw = {
 	.type		=	SOCK_STREAM,
 	.type		=	SOCK_STREAM,
 	.protocol	=	IPPROTO_TCP,
 	.protocol	=	IPPROTO_TCP,

+ 5 - 0
net/ipv6/udp.c

@@ -1443,6 +1443,11 @@ static const struct inet6_protocol udpv6_protocol = {
 	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 };
 
 
+static const struct net_offload udpv6_offload = {
+	.gso_send_check =	udp6_ufo_send_check,
+	.gso_segment	=	udp6_ufo_fragment,
+};
+
 /* ------------------------------------------------------------------------ */
 /* ------------------------------------------------------------------------ */
 #ifdef CONFIG_PROC_FS
 #ifdef CONFIG_PROC_FS