Skip to contentSkip to conversation

ipv6: Enable enough of the code to handle GSO when disabled.

PATCH Superseded Vlad Yasevich 1 participant 1 message Oct 11, 2012 1 message not in the archive

Subsystems (5)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw

PATCH 1/1 ipv6: Enable enough of the code to handle GSO when disabled.

When a guest using virtio is attempting to use IPv6 on a host where IPv6 module is administratively disabled, the tcp bulk thransfer rate drops down to 10kbps. The problem is that when IPv6 is disabled, none of the protocol handlers are registered. When the guest attempts to send an IPv6 packet with GSO (which is the default), this packet is dropped by the host stack because there are no gso handlers registered. Thus a retransmit is triggerd for ever GSO packet, reducing the transfer rate.

This patch attempts to solve this by enabling just enough code that GSO is correctly processed. However, I should point out that if IPv6 is simply blacklisted or not build for the kernel, this problem will still persist.

This problem also exists for AF_PACKET sockets, so it is not limited to guests using virtio.

---
 include/linux/ipv6.h  |    1 +
 include/net/ipv6.h    |    5 +++
 net/ipv6/af_inet6.c   |   69 +++++++++++++++++++++++++++++++++++++++++++++---
 net/ipv6/ip6_input.c  |    5 +++
 net/ipv6/reassembly.c |   11 +++++--
 net/ipv6/tcp_ipv6.c   |    9 +++++-
 net/ipv6/udp.c        |    6 +++-
 7 files changed, 95 insertions(+), 11 deletions(-)
include/linux/ipv6.h +1 -0
index 0b94e91..1d5e061 100644
@@ -176,6 +176,7 @@ struct ipv6_devconf {
 };
 
 struct ipv6_params {
+	__s32 disable_ipv6_mod;
 	__s32 disable_ipv6;
 	__s32 autoconf;
 };
include/net/ipv6.h +5 -0
index 979bf6c..cda75b4 100644
@@ -550,6 +550,11 @@ extern int			ipv6_rcv(struct sk_buff *skb,
 					 struct packet_type *pt,
 					 struct net_device *orig_dev);
 
+extern int			ipv6_rcv_stub(struct sk_buff *skb, 
+					 struct net_device *dev, 
+					 struct packet_type *pt,
+					 struct net_device *orig_dev);
+
 extern int			ip6_rcv_finish(struct sk_buff *skb);
 
 /*
net/ipv6/af_inet6.c +64 -5

102 lines not on this page · raw message

net/ipv6/ip6_input.c +5 -0
index a52d864..3e86ec3 100644
@@ -74,6 +74,11 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
 		return NET_RX_DROP;
 	}
 
+	if (ipv6_defaults.disable_ipv6_mod) {
+		kfree_skb(skb);
+		return NET_RX_DROP;
+	}
+
 	rcu_read_lock();
 
 	idev = __in6_dev_get(skb->dev);
net/ipv6/reassembly.c +8 -3
index da8a4e3..71a0e61 100644
@@ -705,6 +705,9 @@ int __init ipv6_frag_init(void)
 	if (ret)
 		goto out;
 
+	if (ipv6_defaults.disable_ipv6_mod)
+		goto out;
+
 	ret = ip6_frags_sysctl_register();
 	if (ret)
 		goto err_sysctl;
@@ -734,8 +737,10 @@ err_sysctl:
 
 void ipv6_frag_exit(void)
 {
-	inet_frags_fini(&ip6_frags);
-	ip6_frags_sysctl_unregister();
-	unregister_pernet_subsys(&ip6_frags_ops);
+	if (!ipv6_defaults.disable_ipv6_mod) {
+		inet_frags_fini(&ip6_frags);
+		ip6_frags_sysctl_unregister();
+		unregister_pernet_subsys(&ip6_frags_ops);
+	}
 	inet6_del_protocol(&frag_protocol, IPPROTO_FRAGMENT);
 }
net/ipv6/tcp_ipv6.c +7 -2
index 49c8903..ebb297c 100644
@@ -2109,6 +2109,9 @@ int __init tcpv6_init(void)
 	if (ret)
 		goto out;
 
+	if (ipv6_defaults.disable_ipv6_mod)
+		goto out;
+
 	/* register inet6 protocol */
 	ret = inet6_register_protosw(&tcpv6_protosw);
 	if (ret)
@@ -2129,7 +2132,9 @@ out_tcpv6_protosw:
 
 void tcpv6_exit(void)
 {
-	unregister_pernet_subsys(&tcpv6_net_ops);
-	inet6_unregister_protosw(&tcpv6_protosw);
+	if (!ipv6_defaults.disable_ipv6_mod) {
+		unregister_pernet_subsys(&tcpv6_net_ops);
+		inet6_unregister_protosw(&tcpv6_protosw);
+	}
 	inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
 }
net/ipv6/udp.c +5 -1
index fc99972..2e8dddb 100644
@@ -1569,6 +1569,9 @@ int __init udpv6_init(void)
 	if (ret)
 		goto out;
 
+	if (ipv6_defaults.disable_ipv6_mod)
+		goto out;
+
 	ret = inet6_register_protosw(&udpv6_protosw);
 	if (ret)
 		goto out_udpv6_protocol;
@@ -1582,6 +1585,7 @@ out_udpv6_protocol:
 
 void udpv6_exit(void)
 {
-	inet6_unregister_protosw(&udpv6_protosw);
+	if (!ipv6_defaults.disable_ipv6_mod)
+		inet6_unregister_protosw(&udpv6_protosw);
 	inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
 }
Signature · 1 line
1.7.7.6