pay attention to EMSGSIZE errors when sending pmtu verification packets

and drop the pmtu accordingly
This way, when we actually *do* get pmtu info from the network/kernel
we can discover the correct pmtu much more quickly. Especially in the
absence of other traffic, forwarding of which was previously the only
place where we'd check for EMSGSIZE.

Fixes #12
This commit is contained in:
Matthias Radestock committed 2014-08-26 21:05:13 +01:00
1 parent fa5a5f46b4
commit c6a796675d
1 file changed
+23 -10
+23 -10
View File
@@ -70,15 +70,29 @@ func (conn *LocalConnection) forwarderLoop(forwardCh <-chan *ForwardedFrame, sto
var pmtuVerifyTick <-chan time.Time
var clientPMTU int
maxPayload := pmtu - UDPOverhead
calculateClientPMTU := func(ftbe FrameTooBigError) {
maxPayload = ftbe.PMTU - UDPOverhead
clientPMTU = maxPayload - enc.PacketOverhead() - enc.FrameOverhead() - EthernetOverhead
}
updateClientPMTU := func() {
conn.setClientPMTU(clientPMTU)
pmtuVerifyFrame := &ForwardedFrame{
srcPeer: conn.local,
dstPeer: conn.remote,
frame: make([]byte, clientPMTU+EthernetOverhead)}
for cnt := 0; cnt < 10; cnt += 1 {
enc.AppendFrame(pmtuVerifyFrame)
udpSender.Send(enc.Bytes())
for gotNewPMTU := true; gotNewPMTU; {
conn.setClientPMTU(clientPMTU)
pmtuVerifyFrame := &ForwardedFrame{
srcPeer: conn.local,
dstPeer: conn.remote,
frame: make([]byte, clientPMTU+EthernetOverhead)}
gotNewPMTU = false
for cnt := 0; cnt < 10; cnt += 1 {
enc.AppendFrame(pmtuVerifyFrame)
err := udpSender.Send(enc.Bytes())
if err != nil {
if ftbe, ok := err.(FrameTooBigError); ok {
calculateClientPMTU(ftbe)
gotNewPMTU = true
break
}
}
}
}
pmtuVerifyTick = time.After(PMTUVerifyTimeout)
}
@@ -94,8 +108,7 @@ func (conn *LocalConnection) forwarderLoop(forwardCh <-chan *ForwardedFrame, sto
err := udpSender.Send(enc.Bytes())
if err != nil {
if ftbe, ok := err.(FrameTooBigError); ok {
maxPayload = ftbe.PMTU - UDPOverhead
clientPMTU = maxPayload - enc.PacketOverhead() - enc.FrameOverhead() - EthernetOverhead
calculateClientPMTU(ftbe)
updateClientPMTU()
} else if PosixError(err) == syscall.ENOBUFS {
// TODO handle this better