nettle-openflow-0.1: src/Nettle/OpenFlow/Packet.hs
{-# LANGUAGE CPP, DisambiguateRecordFields, RecordWildCards #-}
module Nettle.OpenFlow.Packet (
-- * Sending packets
PacketOut (..)
, bufferedPacketOut
, unbufferedPacketOut
, receivedPacketOut
, BufferID
-- * Packets not handled by a switch
, PacketInfo (..)
, PacketInReason (..)
, NumBytes
, bufferedAtSwitch
) where
import qualified Data.ByteString.Lazy as B
import Nettle.OpenFlow.Port
import Nettle.OpenFlow.Action
import Data.Word
import Data.Maybe (isJust)
-- | A switch can be remotely commanded to send a packet. The packet
-- can either be a packet buffered at the switch, in which case the
-- bufferID is provided, or it can be specified explicitly by giving
-- the packet data.
data PacketOut
= PacketOut {
bufferIDData :: Either BufferID B.ByteString, -- ^either a buffer ID or the data itself
inPort :: Maybe PortID, -- ^the port at which the packet received, for the purposes of processing this command
actions :: ActionSequence -- ^actions to apply to the packet
} deriving (Eq,Show)
-- |A switch may buffer a packet that it receives.
-- When it does so, the packet is assigned a bufferID
-- which can be used to refer to that packet.
type BufferID = Word32
-- | Constructs a @PacketOut@ value for a packet buffered at a switch.
bufferedPacketOut :: BufferID -> Maybe PortID -> ActionSequence -> PacketOut
bufferedPacketOut bufID inPort actions =
PacketOut { bufferIDData = Left bufID
, inPort = inPort
, actions = actions
}
-- | Constructs a @PacketOut@ value for an unbuffered packet, including the packet data.
unbufferedPacketOut :: B.ByteString -> Maybe PortID -> ActionSequence -> PacketOut
unbufferedPacketOut pktData inPort actions =
PacketOut { bufferIDData = Right pktData
, inPort = inPort
, actions = actions
}
-- | Constructs a @PacketOut@ value that processes the packet referred to by the @PacketInfo@ value
-- according to the specified actions.
receivedPacketOut :: PacketInfo -> ActionSequence -> PacketOut
receivedPacketOut (PacketInfo {..}) actions =
case bufferID of
Nothing -> unbufferedPacketOut packetData (Just receivedOnPort) actions
Just bufID -> bufferedPacketOut bufID (Just receivedOnPort) actions
-- | A switch receives packets on its ports. If the packet matches
-- some flow rules, the highest priority rule is executed. If no
-- flow rule matches, the packet is sent to the controller. When
-- packet is sent to the controller, the switch sends a message
-- containing the following information.
data PacketInfo
= PacketInfo {
bufferID :: Maybe BufferID, -- ^buffer ID if packet buffered
packetLength :: NumBytes, -- ^full length of frame
receivedOnPort :: PortID, -- ^port on which frame was received
reasonSent :: PacketInReason, -- ^reason packet is being sent
packetData :: B.ByteString -- ^ethernet frame, includes full packet only if no buffer ID
} deriving (Show,Eq,Ord)
-- |A PacketInfo message includes the reason that the message
-- was sent, namely either there was no match, or there was
-- a match, and that match's actions included a Sent-To-Controller
-- action.
data PacketInReason = NotMatched | ExplicitSend deriving (Show,Read,Eq,Ord,Enum)
-- | The number of bytes in a packet.
type NumBytes = Integer
bufferedAtSwitch :: PacketInfo -> Bool
bufferedAtSwitch = isJust . bufferID