From aceaa66903c4a3cb646a4a1efc8a32344def8cff Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Sat, 17 Jan 2015 16:48:00 +0000 Subject: [PATCH] refactor(ish) of special frame processing in udp frame handler - pull all special frame handling in one place - generalise the condition for detecting special frames - add some explanation --- router/ethernet_decoder.go | 6 ++--- router/router.go | 54 ++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/router/ethernet_decoder.go b/router/ethernet_decoder.go index 65051909..5e4b5bad 100644 --- a/router/ethernet_decoder.go +++ b/router/ethernet_decoder.go @@ -75,7 +75,7 @@ func (dec *EthernetDecoder) DropFrame() bool { return bytes.Equal(stpMACPrefix, dec.eth.DstMAC[:len(stpMACPrefix)]) } -func (dec *EthernetDecoder) IsPMTUVerify() bool { - return bytes.Equal(zeroMAC, dec.eth.SrcMAC) && - bytes.Equal(zeroMAC, dec.eth.DstMAC) +func (dec *EthernetDecoder) IsSpecial() bool { + return dec.eth.Length == 0 && dec.eth.EthernetType == layers.EthernetTypeLLC && + bytes.Equal(zeroMAC, dec.eth.SrcMAC) && bytes.Equal(zeroMAC, dec.eth.DstMAC) } diff --git a/router/router.go b/router/router.go index 2e132815..c89b168b 100644 --- a/router/router.go +++ b/router/router.go @@ -247,13 +247,38 @@ func (router *Router) handleUDPPacketFunc(dec *EthernetDecoder, po PacketSink) F dec.DecodeLayers(frame) decodedLen := len(dec.decoded) + + // Handle special frames produced internally (rather than + // captured/forwarded) by the remote router. + // + // We really shouldn't be decoding these above, since they are + // not genuine Ethernet frames. However, it is actually more + // efficient to do so, as we want to optimise for the common + // (i.e. non-special) frames. These always need decoding, and + // detecting special frames is cheaper post decoding than pre. + if decodedLen == 0 || (decodedLen == 1 && dec.IsSpecial()) { + if srcPeer != relayConn.Remote() || dstPeer != router.Ourself.Peer { + // A special frame not originating from the remote, or + // not for us? How odd; let's just drop it. + return nil + } + if frameLen == 0 { + relayConn.ReceivedHeartbeat(sender) + } else if frameLen == FragTestSize && bytes.Equal(frame, FragTest) { + relayConn.SendTCP(ProtocolFragmentationReceivedByte) + } else if frameLen == PMTUDiscoverySize && bytes.Equal(frame, PMTUDiscovery) { + } else if decodedLen == 1 { + frameLenBytes := []byte{0, 0} + binary.BigEndian.PutUint16(frameLenBytes, uint16(frameLen-EthernetOverhead)) + relayConn.SendTCP(Concat(ProtocolPMTUVerifiedByte, frameLenBytes)) + } + return nil + } + df := decodedLen == 2 && (dec.ip.Flags&layers.IPv4DontFragment != 0) if dstPeer != router.Ourself.Peer { // it's not for us, we're just relaying it - if decodedLen == 0 { - return nil - } if df { router.LogFrame("Relaying DF", frame, &dec.eth) } else { @@ -262,29 +287,6 @@ func (router *Router) handleUDPPacketFunc(dec *EthernetDecoder, po PacketSink) F return checkFrameTooBig(router.Ourself.Relay(srcPeer, dstPeer, df, frame, dec), srcPeer) } - if relayConn.Remote() == srcPeer { - if frameLen == 0 { - relayConn.ReceivedHeartbeat(sender) - return nil - } else if frameLen == FragTestSize && bytes.Equal(frame, FragTest) { - relayConn.SendTCP(ProtocolFragmentationReceivedByte) - return nil - } else if frameLen == PMTUDiscoverySize && bytes.Equal(frame, PMTUDiscovery) { - return nil - } - } - - if decodedLen == 0 { - return nil - } - - if dec.IsPMTUVerify() && relayConn.Remote() == srcPeer { - frameLenBytes := []byte{0, 0} - binary.BigEndian.PutUint16(frameLenBytes, uint16(frameLen-EthernetOverhead)) - relayConn.SendTCP(Concat(ProtocolPMTUVerifiedByte, frameLenBytes)) - return nil - } - srcMac := dec.eth.SrcMAC dstMac := dec.eth.DstMAC