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>
This commit is contained in:
Vlad Yasevich 2012-11-15 08:49:13 +00:00 committed by David S. Miller
parent de27d001d1
commit 8ca896cfdd
5 changed files with 45 additions and 0 deletions

View File

@ -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

View File

@ -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,

View File

@ -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);

View File

@ -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,

View File

@ -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