From 5a0deeb636063a42b48f064b475a3899fde57c34 Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Sun, 15 Apr 2012 05:00:49 +0200 Subject: Net: distinguishing between faulty and not active interfaces --- src/Plugins/Monitors/Net.hs | 106 ++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 64 deletions(-) diff --git a/src/Plugins/Monitors/Net.hs b/src/Plugins/Monitors/Net.hs index 96a68c3..768907c 100644 --- a/src/Plugins/Monitors/Net.hs +++ b/src/Plugins/Monitors/Net.hs @@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Plugins.Monitors.Net --- Copyright : (c) 2011 Jose Antonio Ortega Ruiz +-- Copyright : (c) 2011, 2012 Jose Antonio Ortega Ruiz -- (c) 2007-2010 Andrea Rossato -- License : BSD-style (see LICENSE) -- @@ -22,15 +22,9 @@ import Data.Time.Clock (UTCTime, getCurrentTime, diffUTCTime) import qualified Data.ByteString.Lazy.Char8 as B -data OperState = Up | Down - deriving (Eq, Show, Read) - data NetDev = NA - | ND { netDev :: String - , netRx :: Float - , netTx :: Float - , netOperState :: OperState - } deriving (Eq,Show,Read) + | NI String + | ND String Float Float deriving (Eq,Show,Read) type NetDevRef = IORef (NetDev, UTCTime) @@ -39,55 +33,38 @@ netConfig = mkMConfig ": KB|KB" -- template ["dev", "rx", "tx", "rxbar", "txbar"] -- available replacements --- Given a list of indexes, take the indexed elements from a list. -getNElements :: [Int] -> [a] -> [a] -getNElements ns as = map (as!!) ns - --- Split into words, with word boundaries indicated by the given predicate. --- Drops delimiters. Duplicates 'Data.List.Split.wordsBy'. --- --- > map (wordsBy (`elem` " :")) ["lo:31174097 31174097", "eth0: 43598 88888"] --- --- will become @[["lo","31174097","31174097"], ["eth0","43598","88888"]]@ -wordsBy :: (a -> Bool) -> [a] -> [[a]] -wordsBy f s = case dropWhile f s of - [] -> [] - s' -> w : wordsBy f s'' where (w, s'') = break f s' - -readNetDev :: [String] -> NetDev -readNetDev [] = NA -readNetDev xs = - ND (head xs) (r (xs !! 1)) (r (xs !! 2)) Down - where r s | s == "" = 0 - | otherwise = read s / 1024 - - -parseOperState :: String -> OperState -parseOperState state | state == "down" = Down - | otherwise = Up - -fillOperState :: NetDev -> IO NetDev -fillOperState (ND d r t _) = do - operstate <- B.readFile $ "/sys/class/net/" ++ d ++ "/operstate" - return (ND d r t (parseOperState $ (B.unpack . head . B.lines) operstate)) - -fillOperState NA = return NA - -fileNet :: IO [NetDev] -fileNet = do - devs <- netParser `fmap` B.readFile "/proc/net/dev" - mapM fillOperState devs +isUp :: String -> IO Bool +isUp d = do + operstate <- B.readFile $ "/sys/class/net/" ++ d ++ "/operstate" + return $ "up" == (B.unpack . head . B.lines) operstate + +readNetDev :: [String] -> IO NetDev +readNetDev (d:x:y:_) = do + up <- isUp d + return (if up then ND d (r x) (r y) else NI d) + where r s | s == "" = 0 + | otherwise = read s / 1024 + +readNetDev _ = return NA + +netParser :: B.ByteString -> IO [NetDev] +netParser = mapM (readNetDev . splitDevLine) . readDevLines + where readDevLines = drop 2 . B.lines + splitDevLine = selectCols . wordsBy (`elem` " :") . B.unpack + selectCols cols = map (cols!!) [0,1,9] + wordsBy f s = case dropWhile f s of + [] -> [] + s' -> w : wordsBy f s'' where (w, s'') = break f s' findNetDev :: String -> IO NetDev findNetDev dev = do - nds <- fileNet - case filter (\d -> netDev d == dev) nds of + nds <- B.readFile "/proc/net/dev" >>= netParser + case filter isDev nds of x:_ -> return x _ -> return NA - -netParser :: B.ByteString -> [NetDev] -netParser = - map (readNetDev . getNElements [0,1,9] . wordsBy (`elem` " :") . B.unpack) . drop 2 . B.lines + where isDev (ND d _ _) = d == dev + isDev (NI d) = d == dev + isDev NA = False formatNet :: Float -> Monitor (String, String) formatNet d = do @@ -100,13 +77,13 @@ formatNet d = do printNet :: NetDev -> Monitor String printNet nd = - case nd of - ND d r t o -> case o of - Up -> do (rx, rb) <- formatNet r - (tx, tb) <- formatNet t - parseTemplate [d,rx,tx,rb,tb] - Down -> return "" - NA -> return "" + case nd of + ND d r t -> do + (rx, rb) <- formatNet r + (tx, tb) <- formatNet t + parseTemplate [d,rx,tx,rb,tb] + NI _ -> return "" + NA -> return "N/A" parseNet :: NetDevRef -> String -> IO NetDev parseNet nref nd = do @@ -116,10 +93,11 @@ parseNet nref nd = do writeIORef nref (n1, t1) let scx = realToFrac (diffUTCTime t1 t0) scx' = if scx > 0 then scx else 1 - netRate f da db = takeDigits 2 $ (f db - f da) / scx' - diffRate NA _ = NA - diffRate _ NA = NA - diffRate da db = ND nd (netRate netRx da db) (netRate netTx da db) (netOperState db) + rate da db = takeDigits 2 $ (db - da) / scx' + diffRate (ND d ra ta) (ND _ rb tb) = ND d (rate ra rb) (rate ta tb) + diffRate (NI d) _ = NI d + diffRate _ (NI d) = NI d + diffRate _ _ = NA return $ diffRate n0 n1 runNet :: NetDevRef -> String -> [String] -> Monitor String -- cgit v1.2.3