diff --git a/prog/weaver/main.go b/prog/weaver/main.go index d0ac8596..7b98dbb6 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -11,7 +11,6 @@ import ( "runtime" "strings" - "code.google.com/p/gopacket/layers" "github.com/davecheney/profile" "github.com/gorilla/mux" . "github.com/weaveworks/weave/common" @@ -192,15 +191,21 @@ func options() map[string]string { func logFrameFunc(debug bool) weave.LogFrameFunc { if !debug { - return func(prefix string, frame []byte, eth *layers.Ethernet) {} + return func(prefix string, frame []byte, dec *weave.EthernetDecoder) {} } - return func(prefix string, frame []byte, eth *layers.Ethernet) { + return func(prefix string, frame []byte, dec *weave.EthernetDecoder) { h := fmt.Sprintf("%x", sha256.Sum256(frame)) - if eth == nil { - log.Println(prefix, len(frame), "bytes (", h, ")") - } else { - log.Println(prefix, len(frame), "bytes (", h, "):", eth.SrcMAC, "->", eth.DstMAC) + parts := []interface{}{prefix, len(frame), "bytes (", h, ")"} + + if dec != nil { + parts = append(parts, dec.Eth.SrcMAC, "->", dec.Eth.DstMAC) + + if dec.DF() { + parts = append(parts, "(DF)") + } } + + log.Println(parts...) } } diff --git a/router/ethernet_decoder.go b/router/ethernet_decoder.go index 297a2011..036840c8 100644 --- a/router/ethernet_decoder.go +++ b/router/ethernet_decoder.go @@ -10,15 +10,15 @@ import ( ) type EthernetDecoder struct { - eth layers.Ethernet - ip layers.IPv4 + Eth layers.Ethernet + IP layers.IPv4 decoded []gopacket.LayerType parser *gopacket.DecodingLayerParser } func NewEthernetDecoder() *EthernetDecoder { dec := &EthernetDecoder{} - dec.parser = gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &dec.eth, &dec.ip) + dec.parser = gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &dec.Eth, &dec.IP) return dec } @@ -31,23 +31,23 @@ func (dec *EthernetDecoder) sendICMPFragNeeded(mtu int, sendFrame func([]byte) e opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true} - ipHeaderSize := int(dec.ip.IHL) * 4 // IHL is the number of 32-byte words in the header - payload := gopacket.Payload(dec.ip.BaseLayer.Contents[:ipHeaderSize+8]) + ipHeaderSize := int(dec.IP.IHL) * 4 // IHL is the number of 32-byte words in the header + payload := gopacket.Payload(dec.IP.BaseLayer.Contents[:ipHeaderSize+8]) err := gopacket.SerializeLayers(buf, opts, &layers.Ethernet{ - SrcMAC: dec.eth.DstMAC, - DstMAC: dec.eth.SrcMAC, - EthernetType: dec.eth.EthernetType}, + SrcMAC: dec.Eth.DstMAC, + DstMAC: dec.Eth.SrcMAC, + EthernetType: dec.Eth.EthernetType}, &layers.IPv4{ Version: 4, - TOS: dec.ip.TOS, + TOS: dec.IP.TOS, Id: 0, Flags: 0, FragOffset: 0, TTL: 64, Protocol: layers.IPProtocolICMPv4, - DstIP: dec.ip.SrcIP, - SrcIP: dec.ip.DstIP}, + DstIP: dec.IP.SrcIP, + SrcIP: dec.IP.DstIP}, &layers.ICMPv4{ TypeCode: 0x304, Id: 0, @@ -57,7 +57,7 @@ func (dec *EthernetDecoder) sendICMPFragNeeded(mtu int, sendFrame func([]byte) e return err } - log.Printf("Sending ICMP 3,4 (%v -> %v): PMTU= %v\n", dec.ip.DstIP, dec.ip.SrcIP, mtu) + log.Printf("Sending ICMP 3,4 (%v -> %v): PMTU= %v\n", dec.IP.DstIP, dec.IP.SrcIP, mtu) return sendFrame(buf.Bytes()) } @@ -68,10 +68,14 @@ var ( ) func (dec *EthernetDecoder) DropFrame() bool { - return bytes.Equal(stpMACPrefix, dec.eth.DstMAC[:len(stpMACPrefix)]) + return bytes.Equal(stpMACPrefix, dec.Eth.DstMAC[:len(stpMACPrefix)]) } 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) + return dec.Eth.Length == 0 && dec.Eth.EthernetType == layers.EthernetTypeLLC && + bytes.Equal(zeroMAC, dec.Eth.SrcMAC) && bytes.Equal(zeroMAC, dec.Eth.DstMAC) +} + +func (dec *EthernetDecoder) DF() bool { + return len(dec.decoded) == 2 && (dec.IP.Flags&layers.IPv4DontFragment != 0) } diff --git a/router/forwarder.go b/router/forwarder.go index 3c9ba0ed..cab1c0ff 100644 --- a/router/forwarder.go +++ b/router/forwarder.go @@ -77,6 +77,11 @@ func (conn *LocalConnection) Forward(df bool, frame *ForwardedFrame, dec *Ethern conn.Log("Cannot forward frame yet - awaiting contact") return nil } + + if dec != nil { + df = dec.DF() + } + // We could use non-blocking channel sends here, i.e. drop frames // on the floor when the forwarder is busy. This would allow our // caller - the capturing loop in the router - to read frames more @@ -105,11 +110,11 @@ func (conn *LocalConnection) Forward(df bool, frame *ForwardedFrame, dec *Ethern forwarderDF.Forward(frame) return nil } - conn.Router.LogFrame("Fragmenting", frame.frame, &dec.eth) + conn.Router.LogFrame("Fragmenting", frame.frame, dec) // We can't trust the stack to fragment, we have IP, and we // have a frame that's too big for the MTU, so we have to // fragment it ourself. - return fragment(dec.eth, dec.ip, effectivePMTU, frame, func(segFrame *ForwardedFrame) { + return fragment(dec.Eth, dec.IP, effectivePMTU, frame, func(segFrame *ForwardedFrame) { forwarderDF.Forward(segFrame) }) } diff --git a/router/local_peer.go b/router/local_peer.go index b9ea939b..930fbf1b 100644 --- a/router/local_peer.go +++ b/router/local_peer.go @@ -28,15 +28,15 @@ func NewLocalPeer(name PeerName, nickName string, router *Router) *LocalPeer { return peer } -func (peer *LocalPeer) Forward(dstPeer *Peer, df bool, frame []byte, dec *EthernetDecoder) error { - return peer.Relay(peer.Peer, dstPeer, df, frame, dec) +func (peer *LocalPeer) Forward(dstPeer *Peer, frame []byte, dec *EthernetDecoder) error { + return peer.Relay(peer.Peer, dstPeer, frame, dec) } -func (peer *LocalPeer) Broadcast(df bool, frame []byte, dec *EthernetDecoder) { - peer.RelayBroadcast(peer.Peer, df, frame, dec) +func (peer *LocalPeer) Broadcast(frame []byte, dec *EthernetDecoder) { + peer.RelayBroadcast(peer.Peer, frame, dec) } -func (peer *LocalPeer) Relay(srcPeer, dstPeer *Peer, df bool, frame []byte, dec *EthernetDecoder) error { +func (peer *LocalPeer) Relay(srcPeer, dstPeer *Peer, frame []byte, dec *EthernetDecoder) error { relayPeerName, found := peer.router.Routes.Unicast(dstPeer.Name) if !found { // Not necessarily an error as there could be a race with the @@ -50,27 +50,27 @@ func (peer *LocalPeer) Relay(srcPeer, dstPeer *Peer, df bool, frame []byte, dec log.Println("Unable to find connection to relay peer", relayPeerName) return nil } - return conn.(*LocalConnection).Forward(df, &ForwardedFrame{ + return conn.(*LocalConnection).Forward(false, &ForwardedFrame{ srcPeer: srcPeer, dstPeer: dstPeer, frame: frame}, dec) } -func (peer *LocalPeer) RelayBroadcast(srcPeer *Peer, df bool, frame []byte, dec *EthernetDecoder) { +func (peer *LocalPeer) RelayBroadcast(srcPeer *Peer, frame []byte, dec *EthernetDecoder) { nextHops := peer.router.Routes.Broadcast(srcPeer.Name) if len(nextHops) == 0 { return } for _, conn := range peer.ConnectionsTo(nextHops) { - err := conn.(*LocalConnection).Forward(df, &ForwardedFrame{ + err := conn.(*LocalConnection).Forward(false, &ForwardedFrame{ srcPeer: srcPeer, dstPeer: conn.Remote(), frame: frame}, dec) if err != nil { if ftbe, ok := err.(FrameTooBigError); ok { - log.Printf("dropping too big DF broadcast frame (%v -> %v): PMTU= %v\n", dec.ip.DstIP, dec.ip.SrcIP, ftbe.EPMTU) + log.Printf("dropping too big DF broadcast frame (%v -> %v): PMTU= %v\n", dec.IP.DstIP, dec.IP.SrcIP, ftbe.EPMTU) } else { log.Println(err) } diff --git a/router/router.go b/router/router.go index 9f9e626f..a85d1fb1 100644 --- a/router/router.go +++ b/router/router.go @@ -11,7 +11,6 @@ import ( "syscall" "time" - "code.google.com/p/gopacket/layers" . "github.com/weaveworks/weave/common" ) @@ -27,7 +26,7 @@ const ( // against brute-force attacks on the password when encryption is in // use. It is also a basic DoS defence. -type LogFrameFunc func(string, []byte, *layers.Ethernet) +type LogFrameFunc func(string, []byte, *EthernetDecoder) type Config struct { Port int @@ -151,7 +150,7 @@ func (router *Router) handleCapturedPacket(frameData []byte, dec *EthernetDecode if decodedLen == 0 { return } - srcMac := dec.eth.SrcMAC + srcMac := dec.Eth.SrcMAC srcPeer, found := router.Macs.Lookup(srcMac) // We need to filter out frames we injected ourselves. For such // frames, the srcMAC will have been recorded as associated with a @@ -165,17 +164,13 @@ func (router *Router) handleCapturedPacket(frameData []byte, dec *EthernetDecode if dec.DropFrame() { return } - dstMac := dec.eth.DstMAC + dstMac := dec.Eth.DstMAC dstPeer, found := router.Macs.Lookup(dstMac) if found && dstPeer == router.Ourself.Peer { return } - df := decodedLen == 2 && (dec.ip.Flags&layers.IPv4DontFragment != 0) - if df { - router.LogFrame("Forwarding DF", frameData, &dec.eth) - } else { - router.LogFrame("Forwarding", frameData, &dec.eth) - } + router.LogFrame("Forwarding", frameData, dec) + // at this point we are handing over the frame to forwarders, so // we need to make a copy of it in order to prevent the next // capture from overwriting the data @@ -186,11 +181,11 @@ func (router *Router) handleCapturedPacket(frameData []byte, dec *EthernetDecode // If we don't know which peer corresponds to the dest MAC, // broadcast it. if !found { - router.Ourself.Broadcast(df, frameCopy, dec) + router.Ourself.Broadcast(frameCopy, dec) return } - err := router.Ourself.Forward(dstPeer, df, frameCopy, dec) + err := router.Ourself.Forward(dstPeer, frameCopy, dec) if ftbe, ok := err.(FrameTooBigError); ok { err = dec.sendICMPFragNeeded(ftbe.EPMTU, po.WritePacket) } @@ -316,20 +311,13 @@ func (router *Router) handleUDPPacketFunc(relayConn *LocalConnection, dec *Ether return } - 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 df { - router.LogFrame("Relaying DF", frame, &dec.eth) - } else { - router.LogFrame("Relaying", frame, &dec.eth) - } - - err := router.Ourself.Relay(srcPeer, dstPeer, df, frame, dec) + router.LogFrame("Relaying", frame, dec) + err := router.Ourself.Relay(srcPeer, dstPeer, frame, dec) if ftbe, ok := err.(FrameTooBigError); ok { err = dec.sendICMPFragNeeded(ftbe.EPMTU, func(icmpFrame []byte) error { - return router.Ourself.Forward(srcPeer, false, icmpFrame, nil) + return router.Ourself.Forward(srcPeer, icmpFrame, nil) }) } @@ -337,21 +325,21 @@ func (router *Router) handleUDPPacketFunc(relayConn *LocalConnection, dec *Ether return } - srcMac := dec.eth.SrcMAC - dstMac := dec.eth.DstMAC + srcMac := dec.Eth.SrcMAC + dstMac := dec.Eth.DstMAC if router.Macs.Enter(srcMac, srcPeer) { log.Println("Discovered remote MAC", srcMac, "at", srcPeer) } if po != nil { - router.LogFrame("Injecting", frame, &dec.eth) + router.LogFrame("Injecting", frame, dec) checkWarn(po.WritePacket(frame)) } dstPeer, found = router.Macs.Lookup(dstMac) if !found || dstPeer != router.Ourself.Peer { - router.LogFrame("Relaying broadcast", frame, &dec.eth) - router.Ourself.RelayBroadcast(srcPeer, df, frame, dec) + router.LogFrame("Relaying broadcast", frame, dec) + router.Ourself.RelayBroadcast(srcPeer, frame, dec) } } }