net: Add net protocol offload registration infrustructure
authorVlad Yasevich <vyasevic@redhat.com>
Thu, 15 Nov 2012 08:49:12 +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 IPv4 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/ipv4/af_inet.c
net/ipv4/protocol.c

index 929528c..d8ecb17 100644 (file)
@@ -77,6 +77,15 @@ struct inet6_protocol {
 #define INET6_PROTO_GSO_EXTHDR 0x4
 #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);
+};
+
 /* This is used to register socket interfaces for IP protocols.  */
 struct inet_protosw {
        struct list_head list;
@@ -96,6 +105,7 @@ struct inet_protosw {
 #define INET_PROTOSW_ICSK      0x04  /* Is this an inet_connection_sock? */
 
 extern const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS];
+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];
@@ -103,6 +113,8 @@ extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
 
 extern int     inet_add_protocol(const struct net_protocol *prot, unsigned char num);
 extern int     inet_del_protocol(const struct net_protocol *prot, unsigned char num);
+extern int     inet_add_offload(const struct net_offload *prot, unsigned char num);
+extern int     inet_del_offload(const struct net_offload *prot, unsigned char num);
 extern void    inet_register_protosw(struct inet_protosw *p);
 extern void    inet_unregister_protosw(struct inet_protosw *p);
 
index 4c99c5f..3918d86 100644 (file)
@@ -1566,6 +1566,13 @@ static const struct net_protocol tcp_protocol = {
        .netns_ok       =       1,
 };
 
+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,
+};
+
 static const struct net_protocol udp_protocol = {
        .handler =      udp_rcv,
        .err_handler =  udp_err,
@@ -1575,6 +1582,11 @@ static const struct net_protocol udp_protocol = {
        .netns_ok =     1,
 };
 
+static const struct net_offload udp_offload = {
+       .gso_send_check = udp4_ufo_send_check,
+       .gso_segment = udp4_ufo_fragment,
+};
+
 static const struct net_protocol icmp_protocol = {
        .handler =      icmp_rcv,
        .err_handler =  ping_err,
index 8918eff..0f9d09f 100644 (file)
@@ -29,6 +29,7 @@
 #include <net/protocol.h>
 
 const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS] __read_mostly;
+const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS] __read_mostly;
 
 /*
  *     Add a protocol handler to the hash tables
@@ -41,6 +42,13 @@ int inet_add_protocol(const struct net_protocol *prot, unsigned char protocol)
 }
 EXPORT_SYMBOL(inet_add_protocol);
 
+int inet_add_offload(const struct net_offload *prot, unsigned char protocol)
+{
+       return !cmpxchg((const struct net_offload **)&inet_offloads[protocol],
+                       NULL, prot) ? 0 : -1;
+}
+EXPORT_SYMBOL(inet_add_offload);
+
 /*
  *     Remove a protocol from the hash tables.
  */
@@ -57,3 +65,16 @@ int inet_del_protocol(const struct net_protocol *prot, unsigned char protocol)
        return ret;
 }
 EXPORT_SYMBOL(inet_del_protocol);
+
+int inet_del_offload(const struct net_offload *prot, unsigned char protocol)
+{
+       int ret;
+
+       ret = (cmpxchg((const struct net_offload **)&inet_offloads[protocol],
+                      prot, NULL) == prot) ? 0 : -1;
+
+       synchronize_net();
+
+       return ret;
+}
+EXPORT_SYMBOL(inet_del_offload);