summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2004-05-14 03:57:17 +0000
committerwpaul <wpaul@FreeBSD.org>2004-05-14 03:57:17 +0000
commit6a0eb38f305490176accb3c1b7b30b7c4c3d224d (patch)
treeacf57da54960cf7c1a7e07a08e28c5f569478068 /sys/netinet6
parent49e7c87fded2320a906d60c882d3ada168a4326c (diff)
downloadFreeBSD-src-6a0eb38f305490176accb3c1b7b30b7c4c3d224d.zip
FreeBSD-src-6a0eb38f305490176accb3c1b7b30b7c4c3d224d.tar.gz
Fix a bug which I discovered recently while doing IPv6 testing at
Wind River. In the IPv4 output path, one of the tests in ip_output() checks how many slots are actually available in the interface output queue before attempting to send a packet. If, for example, we need to transmit a packet of 32K bytes over an interface with an MTU of 1500, we know it's going to take about 21 fragments to do it. If there's less than 21 slots left in the output queue, there's no point in transmitting anything at all: IP does not do retransmission, so sending only some of the fragments would just be a waste of bandwidth. (In an extreme case, if you're sending a heavy stream of fragmented packets, you might find yourself sending nothing by the first fragment of all your packets.) So if ip_output() notices there's not enough room in the output queue to send the frame, it just dumps the packet and returns ENOBUFS to the app. It turns out ip6_output() lacks this code. Consequently, this caused the netperf UDPIPV6_STREAM test to produce very poor results with large write sizes. This commit adds code to check the remaining space in the output queue and junk fragmented packets if they're too big to be sent, just like with IPv4. (I can't imagine anyone's running an NFS server using UDP over IPv6, but if they are, this will likely make them a lot happier. :)
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/ip6_output.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index 5e0105c..b955f40 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -1044,6 +1044,7 @@ skip_ipsec2:;
u_char nextproto;
struct ip6ctlparam ip6cp;
u_int32_t mtu32;
+ int qslots = ifp->if_snd.ifq_maxlen - ifp->if_snd.ifq_len;
/*
* Too large for the destination or interface;
@@ -1068,6 +1069,17 @@ skip_ipsec2:;
goto bad;
}
+ /*
+ * Verify that we have any chance at all of being able to queue
+ * the packet or packet fragments
+ */
+ if (qslots <= 0 || ((u_int)qslots * (mtu - hlen)
+ < tlen /* - hlen */)) {
+ error = ENOBUFS;
+ ip6stat.ip6s_odropped++;
+ goto bad;
+ }
+
mnext = &m->m_nextpkt;
/*
OpenPOWER on IntegriCloud