{-# LANGUAGE DeriveGeneric #-} module Network.Data.OpenFlow.Port ( Port (..) , PortID , SpanningTreePortState (..) , PortConfigAttribute (..) , PortFeature (..) , PortFeatures , PortMod (..) , PortStatus , PortStatusUpdateReason (..) , portCapacity , portAttributeOn , portAttributeOff , isPhysicalPort , isPhysicalPortID ) where import Data.Word import Data.Map (Map) import qualified Data.Map as Map import Network.Data.Ethernet.EthernetAddress import Data.Aeson import GHC.Generics -- ^ A switch receives and sends packets on a port; The Port data type models attributes of a physical port. data Port = Port { portID :: PortID, -- ^value datapath associates with a physical port portName :: String, -- ^human-readable interface name portAddress :: EthernetAddress, -- ^the Ethernet address of the port portConfig :: [PortConfigAttribute], -- ^describes spanning tree and administrative settings portLinkDown :: Bool, -- ^describes whether the link is down portSTPState :: SpanningTreePortState, -- ^describes spanning tree state portCurrentFeatures :: Maybe PortFeatures, -- ^port's current features portAdvertisedFeatures :: Maybe PortFeatures, -- ^features advertised by port portSupportedFeatures :: Maybe PortFeatures, -- ^features supported by port portPeerFeatures :: Maybe PortFeatures -- ^features advertised by peer } deriving (Show,Read,Eq, Ord, Generic) instance ToJSON Port instance FromJSON Port type PortID = Word16 data SpanningTreePortState = STPListening | STPLearning | STPForwarding | STPBlocking deriving (Show,Read,Eq,Ord,Enum, Generic) instance ToJSON SpanningTreePortState instance FromJSON SpanningTreePortState -- | Possible behaviors of a physical port. Specification: -- @ofp_port_config@. data PortConfigAttribute = PortDown -- ^port is administratively down | STPDisabled -- ^disable 802.1D spanning tree on this port | OnlySTPackets -- ^drop all packets except 802.1D spanning tree packets | NoSTPackets -- ^drop received 802.1D STP packets | NoFlooding -- ^do not include this port when flooding | DropForwarded -- ^drop packets forwarded to port | NoPacketInMsg -- ^do not send packet-in messages for this port deriving (Show,Read,Eq,Ord,Enum, Generic) instance ToJSON PortConfigAttribute instance FromJSON PortConfigAttribute -- | Possible port features. Specification @ofp_port_features@. data PortFeature = Rate10MbHD -- ^10 Mb half-duplex rate support | Rate10MbFD -- ^10 Mb full-duplex rate support | Rate100MbHD -- ^100 Mb half-duplex rate support | Rate100MbFD -- ^100 Mb full-duplex rate support | Rate1GbHD -- ^1 Gb half-duplex rate support | Rate1GbFD -- ^1 Gb full-duplex rate support | Rate10GbFD -- ^10 Gb full-duplex rate support | Copper | Fiber | AutoNegotiation | Pause | AsymmetricPause deriving (Show,Read,Eq, Ord, Generic) instance ToJSON PortFeature instance FromJSON PortFeature -- | Set of 'PortFeature's. Specification: bitmap of members in @enum -- ofp_port_features@. type PortFeatures = [PortFeature] -- | The max bandwidth in Mbps. portCapacity :: Port -> Maybe Double portCapacity port = maybe Nothing f $ portCurrentFeatures port where f features | elem Rate10MbHD features = Just 10 | elem Rate10MbFD features = Just 10 | elem Rate100MbHD features = Just 100 | elem Rate100MbFD features = Just 100 | elem Rate1GbHD features = Just 1000 | elem Rate1GbFD features = Just 1000 | elem Rate10GbFD features = Just 10000 | otherwise = Nothing -- |A port can be configured with a @PortMod@ message. data PortMod = PortModRecord { portNumber :: PortID, -- ^ port number of port to modify hwAddr :: EthernetAddress, -- ^ hardware address of the port -- (redundant with the port number above; both are required) attributesToSet :: Map PortConfigAttribute Bool -- ^ attributes mapped to true will be set on, -- attributes mapped to false will be turned off, -- and attributes missing will be unchanged } deriving (Show,Read,Eq) -- | The @PortStatus@ represents information regarding -- a change to a port state on a switch. type PortStatus = (PortStatusUpdateReason, Port) -- | The reason that a port status update message -- was sent. data PortStatusUpdateReason = PortAdded | PortDeleted | PortModified deriving (Show,Read,Eq,Ord,Enum) portAttributeOn :: PortID -> EthernetAddress -> PortConfigAttribute -> PortMod portAttributeOn pid addr attr = PortModRecord pid addr (Map.singleton attr True) portAttributeOff :: PortID -> EthernetAddress -> PortConfigAttribute -> PortMod portAttributeOff pid addr attr = PortModRecord pid addr (Map.singleton attr False) isPhysicalPort :: Port -> Bool isPhysicalPort = isPhysicalPortID . portID isPhysicalPortID :: PortID -> Bool isPhysicalPortID pid = pid <= 0xff00