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 +42/−0
- net-spider-rpl.cabal +4/−4
- src/NetSpider/RPL.hs +2/−0
- src/NetSpider/RPL/Combined.hs +32/−17
- src/NetSpider/RPL/ContikiNG.hs +40/−6
- src/NetSpider/RPL/DAO.hs +33/−13
- src/NetSpider/RPL/DIO.hs +45/−23
- src/NetSpider/RPL/FindingID.hs +5/−5
- test/NetSpider/RPL/ContikiNGSpec.hs +38/−1
- test/data/syslog_inf_rank.log +6/−0
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