openflow-0.3.0: src/Network/Data/OpenFlow/Action.hs
{-# LANGUAGE BangPatterns #-}
module Network.Data.OpenFlow.Action (
-- * Actions
Action (..)
, ActionType (..)
, PseudoPort (..)
, MaxLenToSendController
, VendorID
, QueueID
-- * Action sequences
, ActionSequence(..)
, actionSequenceToList
, actionSequenceSizeInBytes
, sendOnPort, phyPort, sendOnInPort, flood, drop, allPhysicalPorts, processNormally, sendToController, processWithTable
, setVlanVID, setVlanPriority, stripVlanHeader, setEthSrcAddr, setEthDstAddr
, setIPSrcAddr, setIPDstAddr
, setIPToS
, setTransportSrcPort
, setTransportDstPort
, enqueue
, vendorAction
) where
import Prelude hiding (drop)
import Network.Data.OpenFlow.Port
import Network.Data.Ethernet.EthernetAddress
import Network.Data.Ethernet.EthernetFrame
import Network.Data.IPv4.IPAddress
import Network.Data.IPv4.IPPacket
import Data.Word
import Data.Monoid
-- |The supported switch actions are denoted with these symbols.
data ActionType = OutputToPortType
| SetVlanVIDType
| SetVlanPriorityType
| StripVlanHeaderType
| SetEthSrcAddrType
| SetEthDstAddrType
| SetIPSrcAddrType
| SetIPDstAddrType
| SetIPTypeOfServiceType
| SetTransportSrcPortType
| SetTransportDstPortType
| EnqueueType
| VendorActionType
deriving (Show,Read,Eq,Ord,Enum)
-- | Each flow table entry contains a list of actions that will
-- be executed when a packet matches the entry.
-- Specification: @ofp_action_header@ and all @ofp_action_*@ structures.
data Action
= SendOutPort !PseudoPort -- ^send out given port
| SetVlanVID VLANID -- ^set the 802.1q VLAN ID
| SetVlanPriority VLANPriority -- ^set the 802.1q priority
| StripVlanHeader -- ^strip the 802.1q header
| SetEthSrcAddr EthernetAddress -- ^set ethernet source address
| SetEthDstAddr EthernetAddress -- ^set ethernet destination address
| SetIPSrcAddr IPAddress -- ^set IP source address
| SetIPDstAddr IPAddress -- ^set IP destination address
| SetIPToS IPTypeOfService -- ^IP ToS (DSCP field)
| SetTransportSrcPort TransportPort -- ^set TCP/UDP source port
| SetTransportDstPort TransportPort -- ^set TCP/UDP destination port
| Enqueue {
enqueuePort :: PortID, -- ^port the queue belongs to
queueID :: QueueID -- ^where to enqueue the packets
} -- ^output to queue
| VendorAction VendorID [Word8]
deriving (Show,Eq,Ord)
-- | A @PseudoPort@ denotes the target of a forwarding
-- action.
data PseudoPort = Flood -- ^send out all physical ports except input port and those disabled by STP
| PhysicalPort PortID -- ^send out physical port with given id
| InPort -- ^send packet out the input port
| AllPhysicalPorts -- ^send out all physical ports except input port
| ToController MaxLenToSendController -- ^send to controller
| NormalSwitching -- ^process with normal L2/L3 switching
| WithTable -- ^process packet with flow table
deriving (Show,Read, Eq, Ord)
-- | A send to controller action includes the maximum
-- number of bytes that a switch will send to the
-- controller.
type MaxLenToSendController = Word16
type VendorID = Word32
type QueueID = Word32
-- | Sequence of actions, represented as finite lists. The Monoid instance of
-- lists provides methods for denoting the do-nothing action (@mempty@) and for concatenating action sequences @mconcat@.
-- type ActionSequence = [Action]
data ActionSequence = ActionSequence !Int ![Action]
deriving (Show, Eq, Ord)
instance Monoid ActionSequence where
mempty = drop
mappend (ActionSequence s1 a1) (ActionSequence s2 a2) = ActionSequence (s1 + s2) (a1 ++ a2)
actionSequenceToList :: ActionSequence -> [Action]
actionSequenceToList (ActionSequence _ as) = as
actionSequenceSizeInBytes :: ActionSequence -> Int
actionSequenceSizeInBytes (ActionSequence !sz _) = sz
-- | send p is a packet send action.
send :: PseudoPort -> ActionSequence
send p = ActionSequence 8 [SendOutPort p]
sendOnPort :: PortID -> ActionSequence
sendOnPort = phyPort
phyPort :: PortID -> ActionSequence
phyPort p = ActionSequence 8 [SendOutPort $ PhysicalPort p]
{-# INLINE phyPort #-}
sendOnInPort, flood, drop, allPhysicalPorts, processNormally, processWithTable :: ActionSequence
sendOnInPort = send InPort
flood = send Flood
drop = ActionSequence 0 []
allPhysicalPorts = send AllPhysicalPorts
processNormally = send NormalSwitching
processWithTable = send WithTable
sendToController :: MaxLenToSendController -> ActionSequence
sendToController maxlen = send (ToController maxlen)
setVlanVID :: VLANID -> ActionSequence
setVlanVID vlanid = ActionSequence 8 [SetVlanVID vlanid]
setVlanPriority :: VLANPriority -> ActionSequence
setVlanPriority x = ActionSequence 8 [SetVlanPriority x]
stripVlanHeader :: ActionSequence
stripVlanHeader = ActionSequence 8 [StripVlanHeader]
setEthSrcAddr :: EthernetAddress -> ActionSequence
setEthSrcAddr addr = ActionSequence 16 [SetEthSrcAddr addr]
setEthDstAddr :: EthernetAddress -> ActionSequence
setEthDstAddr addr =ActionSequence 16 [SetEthDstAddr addr]
setIPSrcAddr :: IPAddress -> ActionSequence
setIPSrcAddr addr = ActionSequence 8 [SetIPSrcAddr addr]
setIPDstAddr :: IPAddress -> ActionSequence
setIPDstAddr addr = ActionSequence 8 [SetIPDstAddr addr]
setIPToS :: IPTypeOfService -> ActionSequence
setIPToS tos = ActionSequence 8 [SetIPToS tos]
setTransportSrcPort :: TransportPort -> ActionSequence
setTransportSrcPort port = ActionSequence 8 [SetTransportSrcPort port]
setTransportDstPort :: TransportPort -> ActionSequence
setTransportDstPort port = ActionSequence 8 [SetTransportDstPort port]
enqueue :: PortID -> QueueID -> ActionSequence
enqueue portid queueid = ActionSequence 16 [Enqueue portid queueid]
vendorAction :: VendorID -> [Word8] -> ActionSequence
vendorAction vid bytes = ActionSequence (length bytes + 8) [VendorAction vid bytes]