diff --git a/router/fastdp.go b/router/fastdp.go index e3043370..31ba9d7b 100644 --- a/router/fastdp.go +++ b/router/fastdp.go @@ -443,8 +443,10 @@ func (fastdp *FastDatapath) getVxlanVportID(udpPort int) (odp.VportID, error) { pk := flowKeysToPacketKey(fks) var zeroMAC MAC if pk.SrcMAC == zeroMAC && pk.DstMAC == zeroMAC { - return vxlanSpecialPacketFlowOp{fastdp, srcPeer, - &net.UDPAddr{ + return vxlanSpecialPacketFlowOp{ + fastdp: fastdp, + srcPeer: srcPeer, + sender: &net.UDPAddr{ IP: net.IP(tunKey.Ipv4Src[:]), Port: udpPort, }, @@ -477,6 +479,7 @@ func (fastdp *FastDatapath) extractPeers(tunnelID [8]byte) (*Peer, *Peer) { } type vxlanSpecialPacketFlowOp struct { + NonDiscardingFlowOp fastdp *FastDatapath srcPeer *Peer sender *net.UDPAddr @@ -765,7 +768,7 @@ func (fwd *fastDatapathForwarder) Forward(key ForwardPacketKey) FlowOp { remoteIP, err := ipv4Bytes(fwd.remoteAddr.IP) if err != nil { log.Error(err) - return nil + return DiscardingFlowOp{} } var sta odp.SetTunnelAction @@ -1134,6 +1137,7 @@ func (fastdp *FastDatapath) takeDecoder(lock *fastDatapathLock) *EthernetDecoder } type odpActionsFlowOp struct { + NonDiscardingFlowOp fastdp *FastDatapath actions []odp.Action } @@ -1157,22 +1161,15 @@ func (fop odpActionsFlowOp) Process(frame []byte, dec *EthernetDecoder, checkWarn(fastdp.dp.Execute(frame, nil, fop.actions)) } -type nopFlowOp struct{} - -func (nopFlowOp) Process([]byte, *EthernetDecoder, bool) { - // A nopFlowOp just provides a hint about flow creation, it - // doesn't send anything -} - // A vetoFlowCreationFlowOp flags that no flow should be created type vetoFlowCreationFlowOp struct { - nopFlowOp + DiscardingFlowOp } // A odpFlowKeyFlowOp adds a FlowKey to the resulting flow type odpFlowKeyFlowOp struct { + DiscardingFlowOp key odp.FlowKey - nopFlowOp } func odpFlowKey(key odp.FlowKey) FlowOp { diff --git a/router/flow.go b/router/flow.go index f2f5c791..7ca1caa2 100644 --- a/router/flow.go +++ b/router/flow.go @@ -27,6 +27,24 @@ type FlowOp interface { // The broadcast parameter is a hint whether the packet is // being broadcast. Process(frame []byte, dec *EthernetDecoder, broadcast bool) + + // Does the FlowOp discard the packet? + Discards() bool +} + +type DiscardingFlowOp struct{} + +func (DiscardingFlowOp) Process([]byte, *EthernetDecoder, bool) { +} + +func (DiscardingFlowOp) Discards() bool { + return true +} + +type NonDiscardingFlowOp struct{} + +func (NonDiscardingFlowOp) Discards() bool { + return false } type MultiFlowOp struct { @@ -36,16 +54,14 @@ type MultiFlowOp struct { func NewMultiFlowOp(broadcast bool, ops ...FlowOp) *MultiFlowOp { mfop := &MultiFlowOp{broadcast: broadcast} - mfop.Add(ops...) + for _, op := range ops { + mfop.Add(op) + } return mfop } -func (mfop *MultiFlowOp) Add(ops ...FlowOp) { - for _, op := range ops { - if op != nil { - mfop.ops = append(mfop.ops, op) - } - } +func (mfop *MultiFlowOp) Add(op FlowOp) { + mfop.ops = append(mfop.ops, op) } func (mfop *MultiFlowOp) Process(frame []byte, dec *EthernetDecoder, @@ -55,6 +71,16 @@ func (mfop *MultiFlowOp) Process(frame []byte, dec *EthernetDecoder, } } +func (mfop *MultiFlowOp) Discards() bool { + for _, op := range mfop.ops { + if !op.Discards() { + return false + } + } + + return true +} + func FlattenFlowOp(fop FlowOp) []FlowOp { return collectFlowOps(nil, fop) } diff --git a/router/overlay.go b/router/overlay.go index 168cb9f3..824a2b39 100644 --- a/router/overlay.go +++ b/router/overlay.go @@ -127,7 +127,7 @@ func (NullOverlay) AddFeaturesTo(map[string]string) { } func (NullOverlay) Forward(ForwardPacketKey) FlowOp { - return nil + return DiscardingFlowOp{} } func (NullOverlay) Stop() { diff --git a/router/pcap.go b/router/pcap.go index cddc366e..848870be 100644 --- a/router/pcap.go +++ b/router/pcap.go @@ -9,6 +9,8 @@ import ( ) type Pcap struct { + NonDiscardingFlowOp + iface *net.Interface bufSz int @@ -131,7 +133,7 @@ func (p *Pcap) sniff(readHandle *pcap.Handle, consumer BridgeConsumer) { continue } - if fop := consumer(dec.PacketKey()); fop != nil { + if fop := consumer(dec.PacketKey()); !fop.Discards() { // 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 diff --git a/router/router.go b/router/router.go index 6c877c57..73ea1673 100644 --- a/router/router.go +++ b/router/router.go @@ -114,12 +114,12 @@ func (router *Router) handleCapturedPacket(key PacketKey) FlowOp { // we are seeing a frame we injected ourself. That // shouldn't happen, but discard it just in case. log.Errorln("Captured frame from MAC (", srcMac, ") associated with another peer", conflictPeer) - return nil + return DiscardingFlowOp{} } // Discard STP broadcasts if key.DstMAC == [...]byte{0x01, 0x80, 0xC2, 0x00, 0x00, 0x00} { - return nil + return DiscardingFlowOp{} } dstMac := net.HardwareAddr(key.DstMAC[:]) @@ -130,7 +130,7 @@ func (router *Router) handleCapturedPacket(key PacketKey) FlowOp { // it's likely to be broadcasting the packet to all // ports. So if it happens, just drop the packet to // avoid warnings if we try to forward it. - return nil + return DiscardingFlowOp{} case nil: // If we don't know which peer corresponds to the dest // MAC, broadcast it. @@ -223,14 +223,14 @@ func (router *Router) relay(key ForwardPacketKey) FlowOp { // Not necessarily an error as there could be a race with the // dst disappearing whilst the frame is in flight log.Println("Received packet for unknown destination:", key.DstPeer) - return nil + return DiscardingFlowOp{} } conn, found := router.Ourself.ConnectionTo(relayPeerName) if !found { // Again, could just be a race, not necessarily an error log.Println("Unable to find connection to relay peer", relayPeerName) - return nil + return DiscardingFlowOp{} } return conn.(*LocalConnection).Forward(key) @@ -239,7 +239,7 @@ func (router *Router) relay(key ForwardPacketKey) FlowOp { func (router *Router) relayBroadcast(srcPeer *Peer, key PacketKey) FlowOp { nextHops := router.Routes.Broadcast(srcPeer.Name) if len(nextHops) == 0 { - return nil + return DiscardingFlowOp{} } op := NewMultiFlowOp(true) diff --git a/router/sleeve.go b/router/sleeve.go index 374b34ef..676d73c7 100644 --- a/router/sleeve.go +++ b/router/sleeve.go @@ -427,12 +427,13 @@ func (fwd *sleeveForwarder) ErrorChannel() <-chan error { } type curriedForward struct { + NonDiscardingFlowOp fwd *sleeveForwarder key ForwardPacketKey } func (fwd *sleeveForwarder) Forward(key ForwardPacketKey) FlowOp { - return curriedForward{fwd, key} + return curriedForward{fwd: fwd, key: key} } func (f curriedForward) Process(frame []byte, dec *EthernetDecoder,