netcore-1.0.0: src/Benchmark.hs
module Main (main) where
import Prelude hiding (init)
import Control.Monad
import qualified Data.Map as Map
import Frenetic.NetCore
import Frenetic.NetCore.Pretty
import Frenetic.NetCore.Types (size)
import Frenetic.TopoGen
import Frenetic.PolicyGen
import Frenetic.Slices.Compile
import Frenetic.Slices.VlanAssignment
import Frenetic.Slices.Slice
import Frenetic.Slices.Sat
import System.Console.GetOpt
import System.CPUTime
import System.Environment
import System.Exit
import Text.Printf
data GraphType = Fattree | Smallworld | Waxman
data PolicyType = ShortestPath | Multicast
data Options = Options {
optEdge :: Bool
, optAST :: Bool
, optTime :: Bool
, optIso :: Bool
, optComp :: Bool
, optGraph :: GraphType
, optPolicy :: PolicyType
, optNodes :: Int
, optHosts :: Int
}
defaultOptions :: Options
defaultOptions = Options {
optEdge = False
, optAST = False
, optTime = True
, optIso = False
, optComp = False
, optGraph = Smallworld
, optPolicy = ShortestPath
, optNodes = 20
, optHosts = 1
}
options :: [OptDescr (Options -> IO Options)]
options =
[
Option ['e'] ["edge"] (NoArg setEdge) "Use edge compiler"
, Option ['a'] ["ast"] (NoArg setAST) "Measure AST size"
, Option ['l'] ["time"] (NoArg setTime) "Time compilation"
, Option ['i'] ["isolation"] (NoArg setIso) "Time isolation validation"
, Option ['c'] ["compilation"] (NoArg setComp) "Time compilation validation"
, Option ['f'] ["fattree"] (NoArg setFattree) "Use fattree topology."
, Option ['s'] ["smallworld"] (NoArg setSmallworld) "Use small world random topology."
, Option ['w'] ["waxman"] (NoArg setWaxman) "Use Waxman random topology."
, Option ['p'] ["shortest"] (NoArg setShortest) "Use shortest path routing."
, Option ['m'] ["multicast"] (NoArg setMulticast) "Use multicast routing."
, Option ['n'] ["nodes"] (ReqArg readNodes "NODES") "Number of nodes to use."
, Option ['t'] ["hosts"] (ReqArg readHosts "HOSTS") "Number of hosts per switch."
, Option ['h'] ["help"] (NoArg showHelp) "print this help message"
]
setEdge :: Options -> IO Options
setEdge opt = return opt { optEdge = True }
setAST :: Options -> IO Options
setAST opt = return opt { optAST = True }
setTime :: Options -> IO Options
setTime opt = return opt { optTime = True }
setIso :: Options -> IO Options
setIso opt = return opt { optIso = True }
setComp :: Options -> IO Options
setComp opt = return opt { optComp = True }
setFattree :: Options -> IO Options
setFattree opt = return opt { optGraph = Fattree }
setSmallworld :: Options -> IO Options
setSmallworld opt = return opt { optGraph = Smallworld }
setWaxman :: Options -> IO Options
setWaxman opt = return opt { optGraph = Waxman }
setMulticast :: Options -> IO Options
setMulticast opt = return opt { optPolicy = Multicast }
setShortest :: Options -> IO Options
setShortest opt = return opt { optPolicy = ShortestPath }
readNodes :: String -> Options -> IO Options
readNodes arg opt = return opt { optNodes = read arg }
readHosts :: String -> Options -> IO Options
readHosts arg opt = return opt { optHosts = read arg }
showHelp _ = do
putStrLn (usageInfo "Usage Info" options)
exitSuccess
doWaxman Options {optNodes = nodes, optHosts = hosts} =
waxman nodes hosts 0.8 0.18
doSmallworld Options {optNodes = nodes, optHosts = hosts} =
smallworld nodes hosts (max 4 (nodes `quot` 3)) 0.3
doFattree _ = return fattree
start options = do
g <- case optGraph options of
Fattree -> doFattree
Smallworld -> doSmallworld
Waxman -> doWaxman
$ options
let policy = case optPolicy options of
ShortestPath -> shortestPath
Multicast -> multicast
$ g
let slice = (simpleSlice g matchNone) {egress = Map.empty}
let (compiled1, compiled2) =
if optEdge options then
-- Force them to be distinct by adding PoBottom to them. Edge
-- compilation relies on distinct (slice, policy) pairs.
let combined = [(slice, policy), (slice, policy <+> PoBottom)] in
let tagged = edge g combined in
let [c1, c2] = map (\(assignment, (slice, policy)) ->
edgeCompileSlice slice assignment policy)
tagged in
(c1, c2)
else
let c1 = compileSlice slice 1 policy in
let c2 = compileSlice slice 2 policy in
(c1, c2)
when (optTime options) $ do
start <- getCPUTime
let s = size compiled1
s `seq` return ()
finish <- getCPUTime
let diff = (fromIntegral (finish - start)) / (10^12)
printf "Compilation time: %0.3f sec\n" (diff :: Double)
let pSize = size policy
let cSize = size compiled1
when (optAST options) $
putStrLn $ "AST Size: " ++ show pSize ++ " -> " ++ show cSize
when (optIso options) $ do
start <- getCPUTime
sep <- separate g compiled1 compiled2
if not sep then
error "Not separate!"
else return ()
finish <- getCPUTime
let diff = (fromIntegral (finish - start)) / (10^12)
printf "Isolation time: %0.3f sec\n" (diff :: Double)
when (optComp options) $ do
start <- getCPUTime
sep <- compiledCorrectly g slice policy compiled1
if not sep then
error "Not correct!"
else return ()
finish <- getCPUTime
let diff = (fromIntegral (finish - start)) / (10^12)
printf "Correctness time: %0.3f sec\n" (diff :: Double)
main = do
rawArgs <- getArgs
let (args, unmatched, errors) = getOpt RequireOrder options rawArgs
opts <- foldl (>>=) (return defaultOptions) args
unless (null errors) $ do
mapM_ putStrLn errors
fail "invalid arguments"
start opts