packages feed

net-spider-rpl 0.1.0.0 → 0.2.0.0

raw patch · 10 files changed

+247/−69 lines, 10 filesdep −net-spider-pangraphdep ~net-spider

Dependencies removed: net-spider-pangraph

Dependency ranges changed: net-spider

Files

ChangeLog.md view
@@ -1,5 +1,47 @@ # Revision history for net-spider-rpl +## 0.2.0.0  -- 2019-07-15++* [BREAKING CHANGE] Type class instances from net-spider-pangraph are+  removed. This is because++    1. `NetSpider.GraphML.Writer` from net-spider can be used to+       format SnapshotGraphs into GraphML+    2. net-spider-pangraph has relatively a heavy dependency set+    3. `NetSpider.Pangraph.ToAttributes` typeclass instance can be+       easily implemented by `NetSpider.Pangraph.attributesFromGraphML`.++* Add `NetSpider.GraphML.ToAttributes` instance to RPL data types so+  that SnapshotGraphs can be formatted to GraphML.++### Combined module++* Add `SnapshotGraphCombined` type synonym.+* `combineNodes` now prefers the input node with the latest timestamp+  as the basis of the result.++### ContikiNG module++* Bug fix for DIO entries including the infinite rank.+* Add detailed doc to `parseFile`.++### DAO module++* Add `SnapshotGraphDAO` type synonym.+* Add `daoDefQuery` function.+* Fix writer and parser of `dao_route_num` attribute.++### DIO module++* Add `SnapshotGraphDIO` type synonym.+* Add `dioDefQuery` function.++### FindingID module++* Add `NetSpider.GraphML.Writer.ToNodeID` intance to `FindingID` and+  `IPv6ID`.++ ## 0.1.0.0  -- 2019-05-03  * First version. Released on an unsuspecting world.
net-spider-rpl.cabal view
@@ -1,5 +1,5 @@ name:                   net-spider-rpl-version:                0.1.0.0+version:                0.2.0.0 author:                 Toshio Ito <debug.ito@gmail.com> maintainer:             Toshio Ito <debug.ito@gmail.com> license:                BSD3@@ -13,7 +13,8 @@                         test/data/cooja.log,                         test/data/syslog_root.log,                         test/data/syslog_nonroot.log,-                        test/data/syslog_sr_tables.log+                        test/data/syslog_sr_tables.log,+                        test/data/syslog_inf_rank.log homepage:               https://github.com/debug-ito/net-spider bug-reports:            https://github.com/debug-ito/net-spider/issues @@ -33,8 +34,7 @@   build-depends:        base >=4.11.1.0 && <4.13,                         aeson >=1.3.1.1 && <1.5,                         greskell >=0.2.3.0 && <0.3,-                        net-spider >=0.3.0.0 && <0.4,-                        net-spider-pangraph >=0.1.0.0 && <0.2,+                        net-spider >=0.3.1.0 && <0.4,                         text >=1.2.3.1 && <1.3,                         ip >=1.3.0 && <1.5,                         hashable >=1.2.7.0 && <1.3,
src/NetSpider/RPL.hs view
@@ -6,6 +6,7 @@ -- -- This module defines NetSpider data model and utility for RPL -- networks.+-- For usage example, see [an example program](https://github.com/debug-ito/net-spider/tree/master/net-spider-rpl-example/src/NetSpider/RPL/Example.hs). -- -- RPL ( [IPv6 Routing Protocol for Low-Power and Lossy Networks, RFC 6550](https://tools.ietf.org/html/rfc6550) ) -- is a routing protocol for small wireless devices. Each node@@ -46,6 +47,7 @@ -- files generated by Contiki-NG applications. -- [Contiki-NG](http://contiki-ng.org/) is a tiny operating system for -- wireless devices that supports RPL.+-- module NetSpider.RPL        ( module NetSpider.RPL.FindingID,          module NetSpider.RPL.DIO,
src/NetSpider/RPL/Combined.hs view
@@ -9,29 +9,31 @@ -- "NetSpider.RPL.DAO") graphs. module NetSpider.RPL.Combined   ( -- * Functions+    combineGraphs,     combineNodes,     combineLinks,-    combineGraphs,     -- * Types+    SnapshotGraphCombined,     CombinedNode(..),     CombinedLink(..),     combinedLinkType   ) where  import Data.Bifunctor (bimap, second)+import Data.List (sortOn, reverse) import Data.Semigroup (Semigroup(..)) import Data.Maybe (isJust) import Data.Monoid (Monoid(..), First(..)) import GHC.Exts (groupWith)-import qualified NetSpider.Pangraph as Pan+import qualified NetSpider.GraphML.Writer as GraphML import NetSpider.Snapshot-  ( SnapshotNode, SnapshotLink,-    nodeId, nodeAttributes+  ( SnapshotNode, SnapshotLink, SnapshotGraph,+    nodeId, nodeAttributes, nodeTimestamp   )  import NetSpider.RPL.FindingID (FindingID(..), FindingType(..), IPv6ID, ipv6Only)-import NetSpider.RPL.DIO (DIONode, MergedDIOLink)-import NetSpider.RPL.DAO (DAONode, DAOLink)+import NetSpider.RPL.DIO (DIONode, MergedDIOLink, SnapshotGraphDIO)+import NetSpider.RPL.DAO (DAONode, DAOLink, SnapshotGraphDAO)  -- | Node attributes combining 'DIONode' and 'DAONode'. data CombinedNode =@@ -53,25 +55,29 @@   mappend a b = a <> b   mempty = CombinedNode Nothing Nothing -instance Pan.ToAttributes CombinedNode where-  toAttributes cn = (Pan.toAttributes $ attrsDIO cn)-                    ++ (Pan.toAttributes $ attrsDAO cn)+instance GraphML.ToAttributes CombinedNode where+  toAttributes cn = (GraphML.toAttributes $ attrsDIO cn)+                    ++ (GraphML.toAttributes $ attrsDAO cn)  -- | Link attribute combining 'MergedDIOLink' and 'DAOLink'. data CombinedLink = CombinedDIOLink MergedDIOLink                   | CombinedDAOLink DAOLink                   deriving (Show,Eq,Ord) -instance Pan.ToAttributes CombinedLink where+instance GraphML.ToAttributes CombinedLink where   toAttributes (CombinedDIOLink ll) =-    ("link_type", "dio") : Pan.toAttributes ll-  toAttributes (CombinedDAOLink sl) =-    ("link_type", "dao") : Pan.toAttributes sl+    ("link_type", GraphML.AttrString "dio") : GraphML.toAttributes ll+  toAttributes (CombinedDAOLink ll) =+    ("link_type", GraphML.AttrString "dao") : GraphML.toAttributes ll  combinedLinkType :: CombinedLink -> FindingType combinedLinkType (CombinedDIOLink _) = FindingDIO combinedLinkType (CombinedDAOLink _) = FindingDAO +-- | Combine DIO and DAO 'SnapshotNode's. Attributes from 'DIONode'+-- and 'DAONode' for the same 'IPv6ID' are combined into one+-- 'CombinedNode'. Timestamp of a combined 'SnapshotNode' is the+-- latest timestamp of input nodes for that 'IPv6ID'. combineNodes :: [SnapshotNode FindingID DIONode]              -> [SnapshotNode FindingID DAONode]              -> [SnapshotNode IPv6ID CombinedNode]@@ -79,8 +85,9 @@   where     fromDIO = bimap ipv6Only (\ln -> CombinedNode (Just ln) Nothing)     fromDAO = bimap ipv6Only (\sn -> CombinedNode Nothing (Just sn))-    concatNodes nodes = map merge $ groupWith nodeId nodes+    concatNodes nodes = map (merge . sortByTimestamp) $ groupWith nodeId nodes       where+        sortByTimestamp = reverse . sortOn nodeTimestamp         merge [] = error "Empty group should not happen."         merge group_nodes@(head_node : _) =           case mmerged_attr of@@ -95,6 +102,9 @@             mmerged_attr = mconcat $ map nodeAttributes group_nodes             hasNodeAttr n = isJust $ nodeAttributes n +-- | Convert DIO and DAO links into combined links. Despite its name,+-- this function does not combine input links. It just make one+-- combined link from each of the input links. combineLinks :: [SnapshotLink FindingID MergedDIOLink]              -> [SnapshotLink FindingID DAOLink]              -> [SnapshotLink IPv6ID CombinedLink]@@ -103,8 +113,13 @@     fromDIO = bimap ipv6Only (\ll -> CombinedDIOLink ll)     fromDAO = bimap ipv6Only (\sl -> CombinedDAOLink sl) -combineGraphs :: ([SnapshotNode FindingID DIONode], [SnapshotLink FindingID MergedDIOLink])-              -> ([SnapshotNode FindingID DAONode], [SnapshotLink FindingID DAOLink])-              -> ([SnapshotNode IPv6ID CombinedNode], [SnapshotLink IPv6ID CombinedLink])+-- | 'SnapshotGraph' combining DIO and DAO networks.+type SnapshotGraphCombined = SnapshotGraph IPv6ID CombinedNode CombinedLink++-- | Combine DIO and DAO graphs into the combined graph, using+-- 'combineNodes' and 'combineLinks'.+combineGraphs :: SnapshotGraphDIO+              -> SnapshotGraphDAO+              -> SnapshotGraphCombined combineGraphs (dio_ns, dio_ls) (dao_ns, dao_ls) =   (combineNodes dio_ns dao_ns, combineLinks dio_ls dao_ls)
src/NetSpider/RPL/ContikiNG.hs view
@@ -42,7 +42,7 @@ import NetSpider.RPL.FindingID (FindingID(FindingID), FindingType(..)) import NetSpider.RPL.IPv6 (isLinkLocal, setPrefix, getPrefix) import qualified NetSpider.RPL.DIO as DIO-import NetSpider.RPL.DIO (FoundNodeDIO, dioLinkState)+import NetSpider.RPL.DIO (FoundNodeDIO, dioLinkState, Rank) import qualified NetSpider.RPL.DAO as DAO import NetSpider.RPL.DAO (FoundNodeDAO) @@ -60,13 +60,31 @@     extract [] = Nothing     extract ((a,_) : _) = Just a +runParser' :: Parser a+           -> String -- ^ error message+           -> String -- ^ input+           -> Parser a+runParser' p err input =+  case runParser p input of+    Nothing -> fail err+    Just a -> return a+ -- | Read and parse a log file from a Contiki-NG application to make -- 'FoundNodeDIO' and 'FoundNodeDAO'. --+-- Currently this parser function supports logs from \"rpl-lite\"+-- module only.+-- -- It assumes that each line of log file has prefix, and that the -- prefix contains timestamp information. You have to pass the parser -- for the prefix to this function. For example, if you read a log -- file generated by Cooja simulator, use 'pCoojaLogHead'' parser.+--+-- One 'FoundNodeDIO' object is parsed from one block of log lines+-- from the rpl module. On the other hand, one or more 'FoundNodeDAO'+-- objects are parsed from one block of log lines from the rpl+-- module. The 'FoundNodeDAO' objects generated from the same log+-- block share the same timestamp. parseFile :: Parser Timestamp -- ^ Parser for log prefix           -> FilePath -- ^ File to read           -> IO ([FoundNodeDIO], [FoundNodeDAO])@@ -152,7 +170,7 @@         Nothing -> return Nothing         Just line ->           case runParser ((Left <$> pEnd) <|> (Right <$> pBody)) line of-            Nothing -> return Nothing+            Nothing -> throwIO $ ParseError ("Parse error at line: " <> line)             Just (Left _) -> return $ Just $ reverse acc             Just (Right body) -> go (body : acc) @@ -276,13 +294,29 @@ pExpectChar :: Char -> Parser Bool pExpectChar exp_c = fmap (== Just exp_c) $ optional P.get +pNeighborAndRank :: Parser (IPv6, Rank)+pNeighborAndRank = spaced <|> non_spaced+  where+    spaced = do+      addr <- pMaybeCompactAddress+      P.skipSpaces+      rank <- pNum+      void $ P.string ", "+      return (addr, rank)+    non_spaced = do+      -- Rank is so large that there is no space between the address and rank.+      -- This case happens when the rank is 5 digits.+      addr_and_rank <- P.munch isAddressChar+      void $ P.string ", "+      let (addr_str, rank_str) = splitAt (length addr_and_rank - 5) addr_and_rank+      addr <- runParser' pMaybeCompactAddress ("Failed to parse address:" <> addr_str) addr_str+      rank <- runParser' pNum ("Failed to parser rank:" <> rank_str) rank_str+      return (addr, rank)+ pDIONeighbor :: Parser (IPv6, DIO.DIOLink) pDIONeighbor = do   void $ P.string "nbr: "-  neighbor_addr <- pMaybeCompactAddress-  P.skipSpaces-  neighbor_rank <- pNum-  void $ P.string ", "+  (neighbor_addr, neighbor_rank) <- pNeighborAndRank   P.skipSpaces   metric <- pNum   void $ P.string " => "
src/NetSpider/RPL/DAO.hs view
@@ -8,9 +8,11 @@ module NetSpider.RPL.DAO   ( -- * Types     FoundNodeDAO,+    SnapshotGraphDAO,     DAONode(..),     DAOLink(..),-    -- * Unifier+    -- * Query+    daoDefQuery,     daoUnifierConf   ) where @@ -21,13 +23,15 @@ import Control.Applicative ((<$>), (<*>)) import Data.Aeson (ToJSON(..)) import Data.Greskell-  ( parseOneValue+  ( parseOneValue, parseListValues   ) import Data.Greskell.Extra (writePropertyKeyValues)+import Data.Maybe (listToMaybe) import NetSpider.Found (FoundNode) import NetSpider.Graph (NodeAttributes(..), LinkAttributes(..))-import qualified NetSpider.Pangraph as Pan-import NetSpider.Pangraph.Atom (toAtom, Atom)+import qualified NetSpider.GraphML.Writer as GraphML+import qualified NetSpider.Query as Query+import NetSpider.Snapshot (SnapshotGraph) import NetSpider.Unify (UnifyStdConfig, lsLinkAttributes, latestLinkSample) import qualified NetSpider.Unify as Unify @@ -36,6 +40,10 @@ -- | 'FoundNode' for a network described by DAOs. type FoundNodeDAO = FoundNode FindingID DAONode DAOLink +-- | 'SnapshotGraph' for a network described by DAOs. This is what you+-- get by 'daoDefQuery'.+type SnapshotGraphDAO = SnapshotGraph FindingID DAONode DAOLink+ -- | Node attributes about DAO. data DAONode =   DAONode@@ -53,16 +61,19 @@ instance NodeAttributes DAONode where   writeNodeAttributes dn = writePropertyKeyValues pairs     where-      pairs = [ ("dao_route_num", toJSON $ daoRouteNum dn)-              ]-  parseNodeAttributes ps = DAONode <$> parseOneValue "dao_route_num" ps+      pairs =+        case daoRouteNum dn of+          Nothing -> []+          Just n -> [("dao_route_num", toJSON n)]+  parseNodeAttributes ps = fmap (DAONode . listToMaybe) $ parseListValues "dao_route_num" ps -instance Pan.ToAttributes DAONode where-  toAttributes dn = +instance GraphML.ToAttributes DAONode where+  toAttributes dn =     case daoRouteNum dn of       Nothing -> []-      Just p -> [("dao_route_num", toAtom $ p)]+      Just p -> [("dao_route_num", GraphML.AttrInt $ fromIntegral $ p)] + -- | Link attributes about DAO. -- -- In Storing mode of RPL, a 'DAOLink' represents a link between the@@ -87,9 +98,18 @@               ]   parseLinkAttributes ps = DAOLink <$> parseOneValue "path_lifetime_sec" ps -instance Pan.ToAttributes DAOLink where-  toAttributes dl = [ ("path_lifetime_sec", toAtom $ pathLifetimeSec dl) ]+instance GraphML.ToAttributes DAOLink where+  toAttributes dl = [ ("path_lifetime_sec", GraphML.AttrInt $ fromIntegral $ pathLifetimeSec dl) ] --- | 'UnifyStdConfig' for RPL DAO data.+-- | Default 'Query.Query' for DAO nodes.+daoDefQuery :: [FindingID] -- ^ 'Query.startsFrom' field.+            -> Query.Query FindingID DAONode DAOLink DAOLink+daoDefQuery start =+  (Query.defQuery start)+  { Query.startsFrom = start,+    Query.unifyLinkSamples = Unify.unifyStd daoUnifierConf+  }++-- | 'UnifyStdConfig' for RPL DAO data. Used in 'defQuery'. daoUnifierConf :: UnifyStdConfig FindingID DAONode DAOLink DAOLink () daoUnifierConf = Unify.defUnifyStdConfig { Unify.negatesLinkSample = \_ _ -> False }
src/NetSpider/RPL/DIO.hs view
@@ -8,6 +8,7 @@ module NetSpider.RPL.DIO   ( -- * Types     FoundNodeDIO,+    SnapshotGraphDIO,     DIONode(..),     DIOLink(..),     dioLinkState,@@ -16,7 +17,8 @@     NeighborType(..),     neighborTypeToText,     neighborTypeFromText,-    -- * Unifier+    -- * Query+    dioDefQuery,     dioUnifierConf   ) where @@ -33,8 +35,9 @@ import Data.Word (Word32) import NetSpider.Found (FoundNode, LinkState(..)) import NetSpider.Graph (NodeAttributes(..), LinkAttributes(..))-import qualified NetSpider.Pangraph as Pan-import NetSpider.Pangraph.Atom (toAtom, Atom)+import qualified NetSpider.GraphML.Writer as GraphML+import qualified NetSpider.Query as Query+import NetSpider.Snapshot (SnapshotGraph) import NetSpider.Unify (UnifyStdConfig, lsLinkAttributes, latestLinkSample) import qualified NetSpider.Unify as Unify @@ -43,6 +46,10 @@ -- | 'FoundNode' for a network described by DIOs. type FoundNodeDIO = FoundNode FindingID DIONode DIOLink +-- | 'SnapshotGraph' for a network described by DIOs. This is what you+-- get by 'dioDefQuery'.+type SnapshotGraphDIO = SnapshotGraph FindingID DIONode MergedDIOLink+ -- | RPL rank type Rank = Word @@ -70,9 +77,9 @@                            <$> parseOneValue "rank" ps                            <*> parseOneValue "dio_interval" ps -instance Pan.ToAttributes DIONode where-  toAttributes ln = [ ("rank", toAtom $ rank ln),-                      ("dio_interval", toAtom $ dioInterval ln)+instance GraphML.ToAttributes DIONode where+  toAttributes ln = [ ("rank", GraphML.AttrInt $ fromIntegral $ rank ln),+                      ("dio_interval", GraphML.AttrInt $ fromIntegral $ dioInterval ln)                     ]  -- | Classification of RPL neighbors.@@ -147,19 +154,17 @@     PreferredParent -> LinkToTarget     _ -> LinkUnused -toAttributesPrefix :: Atom -> DIOLink -> [Pan.Attribute]-toAttributesPrefix prefix ll = -  [ (prefix <> "neighbor_type", toAtom $ neighborTypeToText $ neighborType ll),-    (prefix <> "neighbor_rank", toAtom $ neighborRank ll)-  ]-  ++-  ( case metric ll of-      Nothing -> []-      Just metric_val -> [(prefix <> "metric", toAtom metric_val)]-  )--instance Pan.ToAttributes DIOLink where-  toAttributes = toAttributesPrefix ""+instance GraphML.ToAttributes DIOLink where+  toAttributes ll = [ ("neighbor_type", GraphML.AttrString $ neighborTypeToText $ neighborType ll),+                      ("neighbor_rank", GraphML.AttrInt $ fromIntegral $ neighborRank ll)+                    ]+                    ++ at_metric+    where+      at_metric =+        case metric ll of+          Nothing -> []+          Just m -> [("metric", GraphML.AttrInt $ fromIntegral m)]+                      -- | Link attributes merging two 'DIOLink's from the two end nodes -- of the link.@@ -170,7 +175,24 @@   }   deriving (Show,Eq,Ord) --- | 'UnifyStdConfig' for RPL DIO data+withKeyPrefix :: Monoid k+              => k+              -> [(k, v)]+              -> [(k, v)]+withKeyPrefix prefix = map prependPrefix+  where+    prependPrefix (k, v) = (prefix <> k, v)++-- | Default 'Query.Query' for DIO nodes.+dioDefQuery :: [FindingID] -- ^ 'Query.startsFrom' field.+         -> Query.Query FindingID DIONode DIOLink MergedDIOLink+dioDefQuery start =+  (Query.defQuery start)+  { Query.startsFrom = start,+    Query.unifyLinkSamples = Unify.unifyStd dioUnifierConf+  }++-- | 'UnifyStdConfig' for RPL DIO data. Used in 'defQuery'. dioUnifierConf :: UnifyStdConfig FindingID DIONode DIOLink MergedDIOLink () dioUnifierConf = Unify.UnifyStdConfig                  { Unify.makeLinkSubId = const (),@@ -197,11 +219,11 @@       where         main_ll = lsLinkAttributes main_link -instance Pan.ToAttributes MergedDIOLink where+instance GraphML.ToAttributes MergedDIOLink where   toAttributes ml =-    toAttributesPrefix "source_" (fromSource ml)+    (withKeyPrefix "source_" $ GraphML.toAttributes $ fromSource ml)     ++     ( case fromDest ml of         Nothing -> []-        Just dl -> toAttributesPrefix "dest_" dl+        Just dl -> withKeyPrefix "dest_" $ GraphML.toAttributes dl     )
src/NetSpider/RPL/FindingID.hs view
@@ -33,7 +33,7 @@ import GHC.Generics (Generic) import Net.IPv6 (IPv6(..)) import qualified Net.IPv6 as IPv6-import NetSpider.Pangraph.Atom (ToAtom(..))+import NetSpider.GraphML.Writer (ToNodeID(..))  -- | Type of local finding. data FindingType = FindingDIO@@ -107,8 +107,8 @@       ft = findingType fid       addr_id = IPv6ID $ nodeAddress fid -instance ToAtom FindingID where-  toAtom = toAtom . idToText+instance ToNodeID FindingID where+  toNodeID = idToText  -- | 'IPv6' address with additional type-class instances. newtype IPv6ID = IPv6ID { unIPv6ID :: IPv6 }@@ -136,8 +136,8 @@ instance FromGraphSON IPv6ID where   parseGraphSON gv = parseIPv6IDFromText =<< parseGraphSON gv -instance ToAtom IPv6ID where-  toAtom = toAtom . ipv6ToText+instance ToNodeID IPv6ID where+  toNodeID = ipv6ToText  -- | Extract 'IPv6ID' from 'FindingID'. ipv6Only :: FindingID -> IPv6ID
test/NetSpider/RPL/ContikiNGSpec.hs view
@@ -256,4 +256,41 @@       (got_dios, got_daos) <- parseFile pHead "test/data/syslog_sr_tables.log"       got_dios `shouldBe` [exp_dio1, exp_dio2]       got_daos `shouldMatchList` exp_daos-+    specify "syslog_inf_rank" $ do+      let exp_dio =+            FoundNode+            { subjectNode = fromJust $ idFromText "dio://[fd00::aaa:bbbb:bcc:1008]",+              foundAt = fromEpochMillisecond 1551104666000,+              nodeAttributes = DIO.DIONode { DIO.rank = 65535, DIO.dioInterval = 12 },+              neighborLinks = exp_links+            }+          exp_links =+            [ FoundLink+              { targetNode = fromJust $ idFromText "dio://[fd00::aaa:bbbb:bcc:100a]",+                linkState = LinkUnused,+                linkAttributes = DIO.DIOLink { DIO.neighborType = DIO.OtherNeighbor,+                                               DIO.neighborRank = 492,+                                               DIO.metric = Just 601+                                             }+              },+              FoundLink+              { targetNode = fromJust $ idFromText "dio://[fd00::aaa:bbbb:9221:d51a]",+                linkState = LinkUnused,+                linkAttributes = DIO.DIOLink { DIO.neighborType = DIO.OtherNeighbor,+                                               DIO.neighborRank = 422,+                                               DIO.metric = Just 601+                                             }+              },+              FoundLink+              { targetNode = fromJust $ idFromText "dio://[fd00::aaa:bbbb:bcc:d5e8]",+                linkState = LinkUnused,+                linkAttributes = DIO.DIOLink { DIO.neighborType = DIO.OtherNeighbor,+                                               DIO.neighborRank = 65535,+                                               DIO.metric = Just 133+                                             }+              }+            ]+          pHead = pSyslogHead 2019 Nothing+      (got_dios, got_daos) <- parseFile pHead "test/data/syslog_inf_rank.log"+      got_dios `shouldBe` [exp_dio]+      got_daos `shouldMatchList` []
+ test/data/syslog_inf_rank.log view
@@ -0,0 +1,6 @@+Feb 25 14:24:26 host-name tag[14621]: [WARN: RPL       ] no parent, scheduling periodic DIS, will leave if no parent is found+Feb 25 14:24:26 host-name tag[14621]: [INFO: RPL       ] nbr: own state, addr fd00::aaa:bbbb:bcc:1008, DAG state: initialized, MOP 1 OCP 1 rank 65535 max-rank 2041, dioint 12, nbr count 3 (Parent switch)+Feb 25 14:24:26 host-name tag[14621]: [INFO: RPL       ] nbr: fe80::aaa:bbbb:bcc:100a  492,   601 =>  1093 --  8    f  (last tx 0 min ago, better since 0 min)+Feb 25 14:24:26 host-name tag[14621]: [INFO: RPL       ] nbr: fe80::aaa:bbbb:9221:d51a  422,   601 =>  1023 --  8    f  (last tx 0 min ago, better since 0 min)+Feb 25 14:24:26 host-name tag[14621]: [INFO: RPL       ] nbr: fe80::aaa:bbbb:bcc:d5e865535,   133 => 65535 --  5    f  (last tx 0 min ago)+Feb 25 14:24:26 host-name tag[14621]: [INFO: RPL       ] nbr: end of list