ipv6: Add new offload registration infrastructure.
authorVlad Yasevich <vyasevic@redhat.com>
Thu, 15 Nov 2012 08:49:13 +0000 (08:49 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 15 Nov 2012 22:36:17 +0000 (17:36 -0500)
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>
include/net/protocol.h
net/ipv6/exthdrs.c
net/ipv6/protocol.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c

index d8ecb17b12315ead4eb09962cd25a69cd0baede6..637e1bb6a76ef0e92d723dae2d11db96f050a5d3 100644 (file)
@@ -84,6 +84,7 @@ struct net_offload {
        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 */
 };
 
 /* 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)
 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);
@@ -121,6 +123,8 @@ 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
index f005acc58b2aad4db9119e307b45d4029f2bc159..cb6f0828ca44a32019c729cb0d6a4befaf060475 100644 (file)
@@ -531,11 +531,19 @@ static const struct inet6_protocol rthdr_protocol = {
        .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 = {
        .handler        =       ipv6_destopt_rcv,
        .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 = {
        .handler        =       dst_discard,
        .flags          =       INET6_PROTO_NOPOLICY,
index 053082dfc93e1f9d0c98e26e9c083fc384ed06d5..f7c53a7d5cb05c3f3e0a892f15922db687fc80aa 100644 (file)
@@ -26,6 +26,7 @@
 #include <net/protocol.h>
 
 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)
 {
@@ -34,6 +35,13 @@ 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.
  */
@@ -50,3 +58,16 @@ int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol
        return ret;
 }
 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);
index c73d0ebde9c8eee55e35204dad161f6dd320e2ed..6884a95be433a070b41a41f36f40501f83d19af6 100644 (file)
@@ -2073,6 +2073,13 @@ static const struct inet6_protocol tcpv6_protocol = {
        .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 = {
        .type           =       SOCK_STREAM,
        .protocol       =       IPPROTO_TCP,
index fc9997260a6bc5b841aafc4f3b57cf11ff7ec404..3ad44e1765033e832badf898e4bd3eda7e1d66d1 100644 (file)
@@ -1443,6 +1443,11 @@ static const struct inet6_protocol udpv6_protocol = {
        .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