import Control.Monad import Control.Concurrent import Data.Serialize import Network.Socket hiding (recv) import Network.Socket.ByteString import Network.OpenFlow import Network.Info import System.Environment import Data.Bits import GHC.Word main :: IO () main = do addrinfos <- getAddrInfo (Just (defaultHints {addrFlags = [AI_PASSIVE]})) Nothing (Just "6633") let serveaddr = head addrinfos sock <- socket (addrFamily serveaddr) Stream defaultProtocol setSocketOption sock ReuseAddr 1 bindSocket sock (addrAddress serveaddr) listen sock 4 serveConns sock serveConns :: Socket -> IO () serveConns sock = forever $ do (csock, caddr) <- accept sock handshake csock flood csock _ <- forkIO $ handleSwitch csock caddr return () handshake :: Socket -> IO () handshake sock = do sendAll sock $ encode (OfpFrame (OfpHeader 1 0 0 0) (OfptHello [])) frame <- readOfpFrame sock putStrLn $ "RX: " ++ show frame sendAll sock $ encode (OfpFrame (OfpHeader 1 0 0 1) (OfptGetConfigRequest)) frame <- readOfpFrame sock putStrLn $ "RX: " ++ show frame sendAll sock $ encode (OfpFrame (OfpHeader 1 0 0 2) (OfptFeaturesRequest)) frame <- readOfpFrame sock putStrLn $ "RX: " ++ show frame handleSwitch :: Socket -> SockAddr -> IO () handleSwitch sock caddr = forever $ do frame <- readOfpFrame sock putStrLn $ "RX: " ++ show frame case frame of (OfpFrame (OfpHeader _ _ _ xid) (OfptEchoRequest dat)) -> do let resp = (OfpFrame (OfpHeader 1 0 0 xid) (OfptEchoReply dat)) sendAll sock $ encode resp putStrLn $ "TX: " ++ show resp (OfpFrame (OfpHeader _ _ _ xid) (OfptPacketIn (OfpPacketIn bid len inp reason dat))) -> do let resp = (OfpFrame (OfpHeader 1 0 0 xid) (OfptPacketOut (OfpPacketOut bid inp [(OfpOutput 6 0)] dat))) sendAll sock $ encode resp putStrLn $ "TX: " ++ show resp _ -> putStrLn " UNHANDLED" inp = 1 outp = 6 ofppController = 0xfffd ofppNone = 0xffff pri = 1 uint32max = 0xffffffff emptyMac = MAC 0x00 0x00 0x00 0x00 0x00 0x00 dlVlan' = 10 wc = [ OfpfwInPort, OfpfwDlVlan, OfpfwDlSrc, OfpfwDlDst, OfpfwDlType, OfpfwNwProto, OfpfwTpSrc, OfpfwTpDst, OfpfwNwSrc, OfpfwNwDst, OfpfwDlVlanPcp, OfpfwNwTos ] incrMac :: MAC -> Word64 -> MAC incrMac (MAC a b c d e f) v = MAC (fromIntegral $ (m `shiftR` 40) .&. 0xFF) (fromIntegral $ (m `shiftR` 32) .&. 0xFF) (fromIntegral $ (m `shiftR` 24) .&. 0xFF) (fromIntegral $ (m `shiftR` 16) .&. 0xFF) (fromIntegral $ (m `shiftR` 8) .&. 0xFF) (fromIntegral $ m .&. 0xFF) where m = v + fromIntegral ((a `shiftL` 40) .|. (b `shiftL` 32) .|. (c `shiftL` 24) .|. (d `shiftL` 16) .|. (e `shiftL` 8) .|. f) flood :: Socket -> IO() flood sock = flood' 4 0 where flood' 0 xid = putStrLn $ "done! xid=" ++ show xid flood' n xid = do let m = OfpMatch wc inp emptyMac (incrMac emptyMac n) dlVlan' 0 0 0 0 0 0 0 0 let fm = OfpFlowMod m 0 OfpfcAdd 65535 65535 pri uint32max outp OfpffSendFlowRem [(OfpOutput outp 0)] sendAll sock $ encode (OfpFrame (OfpHeader 1 0 0 xid) (OfptFlowMod fm)) putStrLn $ "TX: " ++ show n flood' (n-1) (xid+1)