Skip to content

Commit

Permalink
[all] otns2 follow-up to properly configure operational dataset (open…
Browse files Browse the repository at this point in the history
  • Loading branch information
EskoDijk committed Jun 10, 2024
1 parent b7a83bc commit 9db070e
Show file tree
Hide file tree
Showing 13 changed files with 161 additions and 69 deletions.
20 changes: 0 additions & 20 deletions etc/cli-scripts/ot-script-example.cli

This file was deleted.

29 changes: 29 additions & 0 deletions etc/cli-scripts/ot-script-example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#
# Example OT node CLI script, which can be passed to otns using the -ot-script parameter.
#

script:
ftd: |
# Active Dataset parameters
# This only works for an FTD (e.g. type 'router' or 'fed')
dataset init new
dataset networkname Test\ Network
dataset panid 0x1234
dataset channel 15
dataset networkkey 998877665544332211ffeeddccbbaa00
dataset commit active
# Some extra settings - differ from usual setup.
routerselectionjitter 10
mtd: |
networkkey 998877665544332211ffeeddccbbaa00
all: |
# Some extra settings - differ from usual setup.
ccathreshold -80
txpower 10
# Autostart the node
ifconfig up
thread start
2 changes: 1 addition & 1 deletion openthread
Submodule openthread updated 3150 files
4 changes: 2 additions & 2 deletions otns_main/otns_main.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,9 @@ func createSimulation(simId int, ctx *progctx.ProgCtx) (*simulation.Simulation,
simcfg.Id = simId
if len(args.InitScriptName) > 0 {
if args.InitScriptName == "none" {
simcfg.NewNodeConfig.InitScript = []string{} // zero lines of init-script
simcfg.NewNodeScripts = &simulation.YamlScriptConfig{}
} else {
simcfg.NewNodeConfig.InitScript, err = simulation.ReadNodeScript(args.InitScriptName)
simcfg.NewNodeScripts, err = simulation.ReadNodeScript(args.InitScriptName)
if err != nil {
return nil, err
}
Expand Down
9 changes: 7 additions & 2 deletions pylibs/otns/cli/OTNS.py
Original file line number Diff line number Diff line change
Expand Up @@ -937,20 +937,25 @@ def set_networkkey(self, nodeid: int, key: str) -> None:
"""
self.node_cmd(nodeid, f'networkkey {key}')

def config_dataset(self, nodeid: int, panid: int = None, networkkey: str = None, network_name: str = None,
def config_dataset(self, nodeid: int, channel: int = None, panid: int = None, extpanid: str = None, networkkey: str = None, network_name: str = None,
dataset='active'):
"""
Configure the active/pending dataset
:param nodeid: target node ID
:param channel: the channel number.
:param panid: the Pan ID.
:param networkkey: the network key
:param extpanid: the Extended PAN ID.
:param networkkey: the network key (REQUIRED)
:param network_name: the network name
"""
assert dataset in ('active', 'pending'), dataset

self.node_cmd(nodeid, 'dataset clear')

if channel is not None:
self.node_cmd(nodeid, f'dataset channel {channel}')

if panid is not None:
self.node_cmd(nodeid, f'dataset panid 0x{panid:04x}')

Expand Down
20 changes: 18 additions & 2 deletions pylibs/unittests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ def testWithOTNS(self):
"""
make sure OTNS works in with-statement
"""
self.tearDown()
self.ns.close()

with OTNS(otns_args=['-log', 'debug']) as ns:
self.assertEqual(OTNS.DEFAULT_SIMULATE_SPEED, ns.speed)
Expand Down Expand Up @@ -663,7 +663,7 @@ def testCmdCommand(self):
self.assertEqual(0, len(output))

def testRandomSeedSetting(self):
self.tearDown()
self.ns.close()
nodes = range(1,6)

# create a new OTNS with 'seed' parameter.
Expand Down Expand Up @@ -878,6 +878,22 @@ def testSendUdpCoap(self):
for a in addrs:
self.assertFalse(a.startswith("ff13")) # see Go simulation.SendMcastPrefix

def testLoadOtScript(self):
self.ns.close()

with OTNS(otns_args=['-ot-script', './etc/cli-scripts/ot-script-example.yaml', '-log', 'debug']) as ns:
self.ns = ns
ns.web()
ns.speed = 2
ns.add('router')
ns.go(10)
ns.add('router')
ns.add('router')
ns.add('med')
ns.add('fed')
ns.go(100)
self.assertFormPartitions(1)


if __name__ == '__main__':
unittest.main()
12 changes: 7 additions & 5 deletions pylibs/unittests/test_commissioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
class CommissioningTests(OTNSTestCase):

def setUp(self) -> None:
self.ns = OTNS(otns_args=['-ot-script', 'none', '-log', 'debug'])
self.ns = OTNS(otns_args=['-ot-script', 'none', '-log', 'debug', '-pcap', 'wpan-tap'])
self.ns.speed = float('inf')

def testRawNoSetup(self):
Expand All @@ -57,21 +57,23 @@ def testRawSetup(self):
# n1 with full dataset becomes Leader.
ns.node_cmd(n1, "dataset init new")
ns.node_cmd(n1, "dataset panid 0xface")
ns.node_cmd(n1, "dataset extpanid dead00beef00cafe")
ns.node_cmd(n1, "dataset networkkey 00112233445566778899aabbccddeeff")
ns.node_cmd(n1, "dataset networkname test")
ns.node_cmd(n1, "dataset channel 15")
ns.node_cmd(n1, "dataset commit active")
ns.ifconfig_up(n1)
ns.thread_start(n1)

# n2, n3 with partial dataset will scan channels to find n1.
# This can take some time.
# n2, n3 with partial dataset - if channel not given - will scan channels to find n1.
# This can take some time and may fail even then (FIXME: find cause).
# To prevent this failure, channel is provided here.
for id in (n2, n3):
ns.config_dataset(id, panid=0xface, network_name="test", networkkey="00112233445566778899aabbccddeeff")
ns.config_dataset(id, channel=15, panid=0xface, extpanid="dead00beef00cafe", network_name="test", networkkey="00112233445566778899aabbccddeeff")
ns.ifconfig_up(id)
ns.thread_start(id)

self.go(250)
self.go(300)
self.assertFormPartitions(1)

def testCommissioning(self):
Expand Down
3 changes: 3 additions & 0 deletions simulation/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ func (node *Node) runScript(cfg []string) error {
}

for _, cmd := range cfg {
if len(cmd) == 0 || strings.HasPrefix(strings.TrimSpace(cmd), "#") {
continue // skip empty lines and comments
}
if node.CommandResult() != nil {
return node.CommandResult()
}
Expand Down
71 changes: 53 additions & 18 deletions simulation/node_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ package simulation

import (
"fmt"
"math"
"os"
"path/filepath"
"strings"

"github.com/openthread/ot-ns/logger"
"github.com/openthread/ot-ns/prng"
. "github.com/openthread/ot-ns/types"
"math"
)

const (
Expand All @@ -47,18 +47,38 @@ const (
versionLatestTag = "v14"
)

// defaultNodeInitScript is an array of commands, sent to a new node by default (unless changed).
var defaultNodeInitScript = []string{
"networkname " + DefaultNetworkName,
"networkkey " + DefaultNetworkKey,
// defaultFtdInitScript is an array of commands, sent to a new FTD node by default (unless changed).
var defaultFtdInitScript = []string{
"dataset init new",
fmt.Sprintf("dataset networkname %s", DefaultNetworkName),
fmt.Sprintf("dataset networkkey %s", DefaultNetworkKey),
fmt.Sprintf("dataset panid 0x%x", DefaultPanid),
fmt.Sprintf("dataset channel %d", DefaultChannel),
fmt.Sprintf("dataset extpanid %s", DefaultExtPanid),
fmt.Sprintf("dataset meshlocalprefix %s", DefaultMeshLocalPrefix),
fmt.Sprintf("dataset pskc %s", DefaultPskc),
//"routerselectionjitter 1", // jitter can be set to '1' to speed up network formation for realtime tests.
"dataset commit active",
}

// defaultMtdInitScript is an array of commands, sent to a new MTD node by default (unless changed).
// because the MTD doesn't support 'dataset init new', an alternative way is needed to configure the
// active dataset. Another alternative (not used here) is 'dataset init tlvs 0e0800000000000100...' with
// the full dataset in hex format.
var defaultMtdInitScript = []string{
fmt.Sprintf("networkkey %s", DefaultNetworkKey),
fmt.Sprintf("panid 0x%x", DefaultPanid),
fmt.Sprintf("channel %d", DefaultChannel),
//"routerselectionjitter 1", // jitter can be set to '1' to speed up network formation for realtime tests.
fmt.Sprintf("extpanid %s", DefaultExtPanid),
}

// defaultAllInitScript is an array of commands, sent to any type of new node (as last script commands).
var defaultAllInitScript = []string{
"ifconfig up",
"thread start",
}

// defaultBrScript is an array of commands, sent to a new BR by default (unless changed).
// defaultBrScript is an array of additional commands, sent to a new BR by default (unless changed).
var defaultBrScript = []string{
"routerselectionjitter 1", // BR wants to become Router early on.
"routerdowngradethreshold 33", // BR never wants to downgrade.
Expand Down Expand Up @@ -141,11 +161,20 @@ func DefaultNodeConfig() NodeConfig {
RadioRange: defaultRadioRange,
ExecutablePath: "",
Restore: false,
InitScript: defaultNodeInitScript,
InitScript: []string{},
RandomSeed: 0, // 0 means not specified, i.e. truly unpredictable.
}
}

func DefaultNodeScripts() *YamlScriptConfig {
return &YamlScriptConfig{
Mtd: strings.Join(defaultMtdInitScript, "\n"),
Ftd: strings.Join(defaultFtdInitScript, "\n"),
Br: strings.Join(defaultBrScript, "\n"),
All: strings.Join(defaultAllInitScript, "\n"),
}
}

// NodeConfigFinalize finalizes the configuration for a new Node before it's used to create it. This is not
// mandatory to call, but a convenience method for the caller to avoid setting all details itself.
func (s *Simulation) NodeConfigFinalize(nodeCfg *NodeConfig) {
Expand All @@ -166,18 +195,24 @@ func (s *Simulation) NodeConfigFinalize(nodeCfg *NodeConfig) {
nodeCfg.RandomSeed = prng.NewNodeRandomSeed()
}

// for a BR, do extra init steps to set prefix/routes/etc.
if nodeCfg.IsBorderRouter {
nodeCfg.InitScript = append(nodeCfg.InitScript, defaultBrScript...)
}
// build node init-script
if !nodeCfg.IsRaw {
if nodeCfg.IsBorderRouter { // for a BR, do extra init steps to set prefix/routes/etc.
nodeCfg.InitScript = append(nodeCfg.InitScript, s.cfg.NewNodeScripts.BuildBrScript()...)
} else if nodeCfg.IsMtd {
nodeCfg.InitScript = append(nodeCfg.InitScript, s.cfg.NewNodeScripts.BuildMtdScript()...)
} else {
nodeCfg.InitScript = append(nodeCfg.InitScript, s.cfg.NewNodeScripts.BuildFtdScript()...)
}

// for SSED, do extra CSL init command.
if nodeCfg.Type == SSED {
cslScript := defaultCslScript
if len(nodeCfg.Version) > 0 && nodeCfg.Version <= "v13" {
cslScript = defaultLegacyCslScript // older nodes use different parameter unit
// for SSED, do extra CSL init command.
if nodeCfg.Type == SSED {
cslScript := defaultCslScript
if len(nodeCfg.Version) > 0 && nodeCfg.Version <= "v13" {
cslScript = defaultLegacyCslScript // older nodes use different parameter unit
}
nodeCfg.InitScript = append(nodeCfg.InitScript, cslScript...)
}
nodeCfg.InitScript = append(nodeCfg.InitScript, cslScript...)
}

// for Wifi interferer, run specific script.
Expand Down
29 changes: 13 additions & 16 deletions simulation/nodescript_parser.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022-2023, The OTNS Authors.
// Copyright (c) 2022-2024, The OTNS Authors.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -28,24 +28,21 @@ package simulation

import (
"fmt"
"io/ioutil"
"strings"
"os"
"gopkg.in/yaml.v3"
)

func ReadNodeScript(fn string) ([]string, error) {
script, err := ioutil.ReadFile(fn)
func ReadNodeScript(fn string) (*YamlScriptConfig, error) {
b, err := os.ReadFile(fn)
if err != nil {
err = fmt.Errorf("could not read OT node script file: %s (%w)", fn, err)
return []string{}, err
err = fmt.Errorf("could not load script config file '%s': %v", fn, err)
return nil, err
}
linesToFilter := strings.Split(string(script), "\n")
linesFiltered := make([]string, 0)
for _, line := range linesToFilter {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "#") || strings.HasPrefix(line, "//") || line == "" {
continue
}
linesFiltered = append(linesFiltered, line)
cfgFile := YamlConfigFile{}
err = yaml.Unmarshal(b, &cfgFile)
if err != nil {
err = fmt.Errorf("error in YAML file: %v", err)
return nil, err
}
return linesFiltered, nil
return &cfgFile.ScriptConfig, nil
}
4 changes: 2 additions & 2 deletions simulation/simulation_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,19 @@ import (

const (
DefaultChannel = 11
DefaultChannelMask = 0x07fff800
DefaultExtPanid = "dead00beef00cafe"
DefaultMeshLocalPrefix = "fdde:ad00:beef:0::"
DefaultNetworkKey = "00112233445566778899aabbccddeeff"
DefaultNetworkName = "otns"
DefaultPanid = 0xface
DefaultPskc = "3aa55f91ca47d1e4e71a08cb35e91591"
DefaultSecurityPolicy = "672 onrc"
)

type Config struct {
ExeConfig ExecutableConfig
ExeConfigDefault ExecutableConfig
NewNodeConfig NodeConfig
NewNodeScripts *YamlScriptConfig
Speed float64
ReadOnly bool
Realtime bool
Expand All @@ -69,6 +68,7 @@ func DefaultConfig() *Config {
ExeConfig: DefaultExecutableConfig,
ExeConfigDefault: DefaultExecutableConfig,
NewNodeConfig: DefaultNodeConfig(),
NewNodeScripts: DefaultNodeScripts(),
Speed: 1,
ReadOnly: false,
Realtime: false,
Expand Down
Loading

0 comments on commit 9db070e

Please sign in to comment.