#define _PROTOCOL_H
#include <linux/in6.h>
+#include <linux/skbuff.h>
#if IS_ENABLED(CONFIG_IPV6)
#include <linux/ipv6.h>
#endif
#define INET6_PROTO_NOPOLICY 0x1
#define INET6_PROTO_FINAL 0x2
-/* This should be set for any extension header which is compatible with GSO. */
-#define INET6_PROTO_GSO_EXTHDR 0x4
#endif
struct net_offload {
int (*gro_complete)(struct sk_buff *skb);
unsigned int flags; /* Flags used by IPv6 for now */
};
+/* This should be set for any extension header which is compatible with GSO. */
+#define INET6_PROTO_GSO_EXTHDR 0x1
/* This is used to register socket interfaces for IP protocols. */
struct inet_protosw {
extern const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS];
extern const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS];
+extern const struct net_offload __rcu *inet6_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);
#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
+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);
#endif /* _PROTOCOL_H */
ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
addrlabel.o \
route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \
- raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
+ raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o
ipv6-offload := ip6_offload.o tcpv6_offload.o udp_offload.o exthdrs_offload.o
ipv6-$(CONFIG_SYN_COOKIES) += syncookies.o
ipv6-objs += $(ipv6-y)
-ipv6-objs += $(ipv6-offload)
obj-$(CONFIG_INET6_AH) += ah6.o
obj-$(CONFIG_INET6_ESP) += esp6.o
obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
obj-$(CONFIG_IPV6_GRE) += ip6_gre.o
-obj-y += addrconf_core.o exthdrs_core.o output_core.o
+obj-y += addrconf_core.o exthdrs_core.o output_core.o protocol.o
+obj-y += $(ipv6-offload)
obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
#include <asm/uaccess.h>
#include <linux/mroute6.h>
-#include "ip6_offload.h"
MODULE_AUTHOR("Cast of dozens");
MODULE_DESCRIPTION("IPv6 protocol stack for Linux");
static int __init ipv6_packet_init(void)
{
- ipv6_offload_init();
dev_add_pack(&ipv6_packet_type);
return 0;
}
static void ipv6_packet_cleanup(void)
{
- ipv6_offload_cleanup();
dev_remove_pack(&ipv6_packet_type);
}
#endif
#include <asm/uaccess.h>
-#include "ip6_offload.h"
/*
* Parsing tlv encoded headers.
{
int ret;
- ret = ipv6_exthdrs_offload_init();
- if (ret)
- goto out;
-
ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING);
if (ret)
- goto out_offload;
+ goto out;
ret = inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
if (ret)
inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
out_rthdr:
inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
-out_offload:
- ipv6_exthdrs_offload_exit();
goto out;
};
void ipv6_exthdrs_exit(void)
{
- ipv6_exthdrs_offload_exit();
inet6_del_protocol(&nodata_protocol, IPPROTO_NONE);
inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
inet_del_offload(&rthdr_offload, IPPROTO_ROUTING);
goto out;
}
-
-void ipv6_exthdrs_offload_exit(void)
-{
- inet_del_offload(&rthdr_offload, IPPROTO_ROUTING);
- inet_del_offload(&rthdr_offload, IPPROTO_DSTOPTS);
-}
#include <linux/socket.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
+#include <linux/printk.h>
#include <net/protocol.h>
#include <net/ipv6.h>
.gro_complete = ipv6_gro_complete,
};
-void __init ipv6_offload_init(void)
+static int __init ipv6_offload_init(void)
{
+
+ if (tcpv6_offload_init() < 0)
+ pr_crit("%s: Cannot add TCP protocol offload\n", __func__);
+ if (udp_offload_init() < 0)
+ pr_crit("%s: Cannot add UDP protocol offload\n", __func__);
+ if (ipv6_exthdrs_offload_init() < 0)
+ pr_crit("%s: Cannot add EXTHDRS protocol offload\n", __func__);
+
dev_add_offload(&ipv6_packet_offload);
+ return 0;
}
-void ipv6_offload_cleanup(void)
-{
- dev_remove_offload(&ipv6_packet_offload);
-}
+fs_initcall(ipv6_offload_init);
#define __ip6_offload_h
int ipv6_exthdrs_offload_init(void);
-void ipv6_exthdrs_offload_exit(void);
-
int udp_offload_init(void);
-void udp_offload_cleanup(void);
-
int tcpv6_offload_init(void);
-void tcpv6_offload_cleanup(void);
-
-extern void ipv6_offload_init(void);
-extern void ipv6_offload_cleanup(void);
#endif
#include <linux/spinlock.h>
#include <net/protocol.h>
+#if IS_ENABLED(CONFIG_IPV6)
const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS] __read_mostly;
-const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS] __read_mostly;
+EXPORT_SYMBOL(inet6_protos);
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.
*/
return ret;
}
EXPORT_SYMBOL(inet6_del_protocol);
+#endif
+
+const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS] __read_mostly;
+
+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);
int inet6_del_offload(const struct net_offload *prot, unsigned char protocol)
{
#include <linux/crypto.h>
#include <linux/scatterlist.h>
-#include "ip6_offload.h"
static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb);
static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
{
int ret;
- ret = tcpv6_offload_init();
- if (ret)
- goto out;
-
ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP);
if (ret)
- goto out_offload;
+ goto out;
/* register inet6 protocol */
ret = inet6_register_protosw(&tcpv6_protosw);
inet6_unregister_protosw(&tcpv6_protosw);
out_tcpv6_protocol:
inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
-out_offload:
- tcpv6_offload_cleanup();
goto out;
}
unregister_pernet_subsys(&tcpv6_net_ops);
inet6_unregister_protosw(&tcpv6_protosw);
inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
- tcpv6_offload_cleanup();
}
{
return inet6_add_offload(&tcpv6_offload, IPPROTO_TCP);
}
-
-void tcpv6_offload_cleanup(void)
-{
- inet6_del_offload(&tcpv6_offload, IPPROTO_TCP);
-}
#include <linux/seq_file.h>
#include <trace/events/skb.h>
#include "udp_impl.h"
-#include "ip6_offload.h"
int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
{
{
int ret;
- ret = udp_offload_init();
- if (ret)
- goto out;
-
ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP);
if (ret)
- goto out_offload;
+ goto out;
ret = inet6_register_protosw(&udpv6_protosw);
if (ret)
out_udpv6_protocol:
inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
-out_offload:
- udp_offload_cleanup();
goto out;
}
{
inet6_unregister_protosw(&udpv6_protosw);
inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
- udp_offload_cleanup();
}
{
return inet6_add_offload(&udpv6_offload, IPPROTO_UDP);
}
-
-void udp_offload_cleanup(void)
-{
- inet6_del_offload(&udpv6_offload, IPPROTO_UDP);
-}