Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3336288a authored by Vlad Yasevich's avatar Vlad Yasevich Committed by David S. Miller
Browse files

ipv6: Switch to using new offload infrastructure.



Switch IPv6 protocol to using the new GRO/GSO calls and data.

Signed-off-by: default avatarVlad Yasevich <vyasevic@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bca49f84
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -54,14 +54,6 @@ struct inet6_protocol {
			       struct inet6_skb_parm *opt,
			       u8 type, u8 code, int offset,
			       __be32 info);

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

	unsigned int	flags;	/* INET6_PROTO_xxx */
};

+11 −11
Original line number Diff line number Diff line
@@ -701,14 +701,14 @@ EXPORT_SYMBOL_GPL(ipv6_opt_accepted);

static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
{
	const struct inet6_protocol *ops = NULL;
	const struct net_offload *ops = NULL;

	for (;;) {
		struct ipv6_opt_hdr *opth;
		int len;

		if (proto != NEXTHDR_HOP) {
			ops = rcu_dereference(inet6_protos[proto]);
			ops = rcu_dereference(inet6_offloads[proto]);

			if (unlikely(!ops))
				break;
@@ -736,7 +736,7 @@ static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
static int ipv6_gso_send_check(struct sk_buff *skb)
{
	const struct ipv6hdr *ipv6h;
	const struct inet6_protocol *ops;
	const struct net_offload *ops;
	int err = -EINVAL;

	if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
@@ -747,7 +747,7 @@ static int ipv6_gso_send_check(struct sk_buff *skb)
	err = -EPROTONOSUPPORT;

	rcu_read_lock();
	ops = rcu_dereference(inet6_protos[
	ops = rcu_dereference(inet6_offloads[
		ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]);

	if (likely(ops && ops->gso_send_check)) {
@@ -765,7 +765,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
{
	struct sk_buff *segs = ERR_PTR(-EINVAL);
	struct ipv6hdr *ipv6h;
	const struct inet6_protocol *ops;
	const struct net_offload *ops;
	int proto;
	struct frag_hdr *fptr;
	unsigned int unfrag_ip6hlen;
@@ -792,7 +792,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,

	proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
	rcu_read_lock();
	ops = rcu_dereference(inet6_protos[proto]);
	ops = rcu_dereference(inet6_offloads[proto]);
	if (likely(ops && ops->gso_segment)) {
		skb_reset_transport_header(skb);
		segs = ops->gso_segment(skb, features);
@@ -825,7 +825,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
					 struct sk_buff *skb)
{
	const struct inet6_protocol *ops;
	const struct net_offload *ops;
	struct sk_buff **pp = NULL;
	struct sk_buff *p;
	struct ipv6hdr *iph;
@@ -852,7 +852,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,

	rcu_read_lock();
	proto = iph->nexthdr;
	ops = rcu_dereference(inet6_protos[proto]);
	ops = rcu_dereference(inet6_offloads[proto]);
	if (!ops || !ops->gro_receive) {
		__pskb_pull(skb, skb_gro_offset(skb));
		proto = ipv6_gso_pull_exthdrs(skb, proto);
@@ -860,7 +860,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
		skb_reset_transport_header(skb);
		__skb_push(skb, skb_gro_offset(skb));

		ops = rcu_dereference(inet6_protos[proto]);
		ops = rcu_dereference(inet6_offloads[proto]);
		if (!ops || !ops->gro_receive)
			goto out_unlock;

@@ -915,7 +915,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,

static int ipv6_gro_complete(struct sk_buff *skb)
{
	const struct inet6_protocol *ops;
	const struct net_offload *ops;
	struct ipv6hdr *iph = ipv6_hdr(skb);
	int err = -ENOSYS;

@@ -923,7 +923,7 @@ static int ipv6_gro_complete(struct sk_buff *skb)
				 sizeof(*iph));

	rcu_read_lock();
	ops = rcu_dereference(inet6_protos[NAPI_GRO_CB(skb)->proto]);
	ops = rcu_dereference(inet6_offloads[NAPI_GRO_CB(skb)->proto]);
	if (WARN_ON(!ops || !ops->gro_complete))
		goto out_unlock;

+35 −3
Original line number Diff line number Diff line
@@ -549,14 +549,44 @@ static const struct inet6_protocol nodata_protocol = {
	.flags		=	INET6_PROTO_NOPOLICY,
};

static int ipv6_exthdrs_offload_init(void)
{
	int ret;

	ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING);
	if (!ret)
		goto out;

	ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS);
	if (!ret)
		goto out_rt;

out:
	return ret;

out_rt:
	inet_del_offload(&rthdr_offload, IPPROTO_ROUTING);
	goto out;
}

static void ipv6_exthdrs_offload_exit(void)
{
	inet_del_offload(&rthdr_offload, IPPROTO_ROUTING);
	inet_del_offload(&rthdr_offload, IPPROTO_DSTOPTS);
}

int __init ipv6_exthdrs_init(void)
{
	int ret;

	ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING);
	ret = ipv6_exthdrs_offload_init();
	if (ret)
		goto out;

	ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING);
	if (ret)
		goto out_offload;

	ret = inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
	if (ret)
		goto out_rthdr;
@@ -567,10 +597,12 @@ int __init ipv6_exthdrs_init(void)

out:
	return ret;
out_rthdr:
	inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
out_destopt:
	inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
out_rthdr:
	inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
out_offload:
	ipv6_exthdrs_offload_exit();
	goto out;
};

+10 −7
Original line number Diff line number Diff line
@@ -2066,10 +2066,6 @@ static const struct inet6_protocol tcpv6_protocol = {
	.early_demux	=	tcp_v6_early_demux,
	.handler	=	tcp_v6_rcv,
	.err_handler	=	tcp_v6_err,
	.gso_send_check	=	tcp_v6_gso_send_check,
	.gso_segment	=	tcp_tso_segment,
	.gro_receive	=	tcp6_gro_receive,
	.gro_complete	=	tcp6_gro_complete,
	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
};

@@ -2116,10 +2112,14 @@ int __init tcpv6_init(void)
{
	int ret;

	ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP);
	ret = inet6_add_offload(&tcpv6_offload, IPPROTO_TCP);
	if (ret)
		goto out;

	ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP);
	if (ret)
		goto out_offload;

	/* register inet6 protocol */
	ret = inet6_register_protosw(&tcpv6_protosw);
	if (ret)
@@ -2131,10 +2131,12 @@ int __init tcpv6_init(void)
out:
	return ret;

out_tcpv6_protocol:
	inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
out_tcpv6_protosw:
	inet6_unregister_protosw(&tcpv6_protosw);
out_tcpv6_protocol:
	inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
out_offload:
	inet6_del_offload(&tcpv6_offload, IPPROTO_TCP);
	goto out;
}

@@ -2143,4 +2145,5 @@ void tcpv6_exit(void)
	unregister_pernet_subsys(&tcpv6_net_ops);
	inet6_unregister_protosw(&tcpv6_protosw);
	inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
	inet6_del_offload(&tcpv6_offload, IPPROTO_TCP);
}
+8 −3
Original line number Diff line number Diff line
@@ -1438,8 +1438,6 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
static const struct inet6_protocol udpv6_protocol = {
	.handler	=	udpv6_rcv,
	.err_handler	=	udpv6_err,
	.gso_send_check =	udp6_ufo_send_check,
	.gso_segment	=	udp6_ufo_fragment,
	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
};

@@ -1570,10 +1568,14 @@ int __init udpv6_init(void)
{
	int ret;

	ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP);
	ret = inet6_add_offload(&udpv6_offload, IPPROTO_UDP);
	if (ret)
		goto out;

	ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP);
	if (ret)
		goto out_offload;

	ret = inet6_register_protosw(&udpv6_protosw);
	if (ret)
		goto out_udpv6_protocol;
@@ -1582,6 +1584,8 @@ int __init udpv6_init(void)

out_udpv6_protocol:
	inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
out_offload:
	inet6_del_offload(&udpv6_offload, IPPROTO_UDP);
	goto out;
}

@@ -1589,4 +1593,5 @@ void udpv6_exit(void)
{
	inet6_unregister_protosw(&udpv6_protosw);
	inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
	inet6_del_offload(&udpv6_offload, IPPROTO_UDP);
}