A profile is YAML (or JSON) describing one CPE model: parameter tree, periodic Inform paths, fleet metadata, generators, connection-request auth, and transfer behavior. The same profile drives both the TR-069 (CWMP) and TR-369 (USP) stacks; nothing in the schema is transport-specific.

A profile is either a single file (e.g. profile.yaml) or a directory of *.yaml / *.yml files that load in lexicographic order and merge into one tree. Use a directory when one file is getting unwieldy; group leaves by topic (deviceinfo.yaml, wifi.yaml, hosts.yaml).

This page is the exhaustive field reference. For introductions and worked examples, see:

Top-level blocks

deviceIdPaths:        # required
parameters:           # leaves
objects:              # multi-instance objects (table-shaped)
groups:               # single-instance prefix groupings
informParameters:     # per-event-code parameter lists for Inform builder
periodicInformPaths:  # leaves the per-CPE periodic Inform timer reads
generators:           # top-level generators list
fleet:                # fleet count + pools + serial pattern
connectionRequest:    # CR listener auth + throttle
transfer:             # Download / Upload TransferComplete defaults + faults
eventSchedule:        # Wall-clock latency for Reboot / FactoryReset / boot

Every block is optional except deviceIdPaths and at least one of parameters / objects / groups (you need to mount the four DeviceID leaves).

deviceIdPaths (required)

deviceIdPaths:
  manufacturer: Device.DeviceInfo.Manufacturer
  oui:          Device.DeviceInfo.ManufacturerOUI
  productClass: Device.DeviceInfo.ProductClass
  serialNumber: Device.DeviceInfo.SerialNumber

Names the four leaves the Inform builder reads to populate the <DeviceId> block. All four are required when the block is present; partial declarations reject. The simulator reads these paths from the tree at every Inform.

For TR-098 substitute the InternetGatewayDevice.DeviceInfo.* paths.

parameters

Individual leaf declarations.

Field Type Default Notes
path string (required) Absolute parameter path. May contain a single {i} token if instances is set.
type string xsd:string One of xsd:string, xsd:int, xsd:unsignedInt, xsd:boolean, xsd:dateTime, xsd:base64.
value string type-zero The leaf's initial value ("", "0", "false", …).
writable bool false Whether the ACS / Controller can SPV the leaf.
instances int (omitted) When path contains {i}, materializes N instances (Radio.1, Radio.2, …).
generator object (omitted) Inline value generator. See Generators.
parameters:
  - path: Device.WiFi.Radio.{i}.Channel
    type: xsd:unsignedInt
    instances: 2
    value: "{i}"          # → "1" / "2" at load time
    writable: true

objects (multi-instance tables)

Sugar over the verbose form. Declare the parent path once, list the children, set instances: N. The loader expands to {i}-templated leaves and registers AddTable so AddObject works.

Field Type Notes
path string Parent path without trailing {i}.
instances int Number of instances to materialize.
parameters list Each entry has the same fields as a top-level parameter, but path is relative to the parent.
objects:
  - path: Device.Hosts.Host
    instances: 5
    parameters:
      - path: IPAddress
        value: "192.168.1.{i}0"
      - path: HostName
        value: "host-{i}"
      - path: Active
        type: xsd:boolean
        value: "true"

groups (single-instance prefix grouping)

For containers that aren't tables. Same shape as objects but no instance numbering, no AddTable registration. Each child path is concatenated as prefix + "." + child.path.

groups:
  - prefix: Device.DeviceInfo.MemoryStatus
    parameters:
      - path: Total
        type: xsd:unsignedInt
        value: "262144"
      - path: Free
        type: xsd:unsignedInt
        value: "131072"

informParameters

Per-event-code parameter lists the Inform builder includes in the ParameterList. The simulator picks the right list per session via first-matching-event.

Key Triggered by
bootstrap 0 BOOTSTRAP (first session after factory reset / fresh process).
boot 1 BOOT (every subsequent process start).
periodic 2 PERIODIC (the scheduler tick).
valueChange 4 VALUE CHANGE (a tracked leaf mutated).
connectionRequest 6 CONNECTION REQUEST (CR listener fired).
informParameters:
  bootstrap:
    - Device.DeviceInfo.SoftwareVersion
    - Device.IP.Interface.2.IPv4Address.1.IPAddress
  periodic:
    - Device.Ethernet.Interface.1.Stats.BytesSent
  connectionRequest:
    - Device.DeviceInfo.UpTime

Every path referenced here must exist in the tree; the loader rejects references to undefined leaves.

periodicInformPaths

Names the two leaves the periodic Inform timer reads.

Field Type Constraints
interval string Path of an xsd:unsignedInt writable leaf, in seconds.
enable string Path of an xsd:boolean writable leaf.
periodicInformPaths:
  interval: Device.ManagementServer.PeriodicInformInterval
  enable:   Device.ManagementServer.PeriodicInformEnable

When omitted, the simulator exits after the bootstrap Inform (unless --cr-bind-addr keeps it alive). See Periodic Inform Scheduler.

generators (top-level)

Generators may be declared inline on a parameter or in a top-level generators: list. Inline is preferred so the leaf and its mutator stay co-located. Use the top-level form when you want a generator that doesn't fit neatly inside an objects: / groups: block.

generators:
  - path: Device.WAN.Stats.BytesSent
    type: counter
    interval: 30s
    min: 0
    max: 4294967295
    step: 12500000
    jitter: 0.2
Field Used by Notes
path all Absolute path to a writable leaf.
type all counter / drift / enum / uptime / wallclock.
interval all Tick cadence. Go duration syntax (30s, 5m, …).
min counter, drift Lower bound.
max counter, drift Upper bound.
step counter Bytes-per-tick before jitter.
jitter counter Uniform fraction (0.2 = ±20%).
stepMax drift Max |delta| per tick.
values enum List of strings to cycle / pick from.
mode enum cycle (default) or random.

The same fields work in the inline form. See Value Generators for full validation rules and behavior.

fleet

Fleet metadata, named address pools, serial pattern.

Field Type Default Notes
count int 1 Number of CPEs to spawn. 0 and 1 both mean single-CPE.
serialPattern string {base}-{i} Template applied to each CPE's SerialNumber leaf. Recognized: {base} (the value: of the SerialNumber leaf), {i} (1-based instance), {i:N} (zero-padded).
pools map {} Named per-CPE allocators referenced from any leaf via {name}.

Pool entry:

Field Used by Notes
type all ipv4 / ipv6 / ipv6prefix.
cidr ipv4, ipv6 Source range.
super ipv6prefix Operator-side super-prefix.
sublen ipv6prefix Per-CPE sub-prefix length.
fleet:
  count: 100
  serialPattern: "TEST-{i:04}"
  pools:
    wan_ipv4:
      type: ipv4
      cidr: "203.0.113.0/24"
    wan_ipv6:
      type: ipv6
      cidr: "2001:db8:1::/64"
    delegated_prefix:
      type: ipv6prefix
      super: "2001:db8:cafe::/48"
      sublen: 56

Pool capacity is checked at load. fleet.count: 1001 against a /24 (capacity 254) rejects with a precise error. See Multi-CPE Fleets for the full placeholder list.

connectionRequest

CR listener auth scheme and throttle window.

Field Type Notes
scheme string "" / basic / digest.
realm string Required when scheme != "". Sent verbatim in the WWW-Authenticate challenge.
throttleWindow string Go duration. 0s / omitted disables throttling. TR-069 §3.2.2 default is 5s.
usernameParameter string Tree path the listener reads per request to get the expected username. Required when scheme != "".
passwordParameter string Tree path for the expected password. Required when scheme != "".
connectionRequest:
  scheme: digest
  realm: cpe-sim
  throttleWindow: 5s
  usernameParameter: Device.ManagementServer.ConnectionRequestUsername
  passwordParameter: Device.ManagementServer.ConnectionRequestPassword

See Connection Request Listener for full behavior.

transfer

Default delay and per-FileType fault injection for the Download and Upload RPC handlers.

Field Type Notes
defaultDelay string Go duration the simulator waits before firing TransferComplete. Falls back to a code-level constant when zero / omitted.
faults map Keyed by FileType (e.g. 1 Firmware Upgrade Image). Each entry carries code (BBF fault code, e.g. 9010) and string (fault string).
transfer:
  defaultDelay: 2s
  faults:
    "1 Firmware Upgrade Image":
      code: 9010
      string: "Download failure: server unreachable"

When the ACS issues a Download whose FileType matches a faults key, the handler fires TransferComplete with the configured fault code and string. Useful for testing how an ACS handles failed firmware pushes.

eventSchedule

Wall-clock latency between selected CWMP events and the simulated CPE's matching outbound Inform. Models the time a real CPE spends rebooting, factory-resetting, or booting up before the ACS sees the post-event Inform.

Field Type Notes
rebootDelay duration Time between a Reboot RPC ack and the post-reboot Inform. The deferred Inform carries [1 BOOT, M Reboot] (the wire shape a real CPE produces after rebooting). Repeat Reboot RPCs supersede the in-flight schedule.
factoryResetDelay duration Time between a FactoryReset RPC ack and the post-reset Inform. The deferred Inform carries [1 BOOT, 0 BOOTSTRAP] (BOOTSTRAP is re-armed by ResetBootstrap inside onReset). Errors from the deferred onReset are logged only — they cannot surface to the ACS because the FactoryResetResponse has already been sent.
bootDelay duration Time between process start and the per-CPE bootstrap Inform. The fleet still bootstraps in parallel; every CPE waits the same delay independently.
eventSchedule:
  rebootDelay: 30s
  factoryResetDelay: 60s
  bootDelay: 5s

All three fields are optional. Zero / unset preserves the simulator's existing immediate behavior (RPC handlers run their effect synchronously; the bootstrap Inform fires the moment the process starts). Negative values reject at load time.

rebootDelay > 0 or factoryResetDelay > 0 keeps the process alive long enough for the deferred Inform to fire (daemon mode). bootDelay alone preserves one-shot mode (the deferred bootstrap fires, then the process exits).

Strict load-time validation

The loader rejects loudly. Every error names the source file and offending key:

  • Unknown YAML keys at any level (KnownFields = true).
  • Path templates malformed or containing {i} more than once.
  • instances: N on a non-{i} path.
  • Inform parameters referencing paths that don't exist in the tree.
  • periodicInformPaths leaves with the wrong type or non-writable.
  • connectionRequest with scheme set but missing realm / usernameParameter / passwordParameter.
  • eventSchedule durations that don't parse via Go's time.ParseDuration, or that parse to a negative value.
  • fleet.pools with a CIDR that doesn't parse, an IPv6 prefix length lower than the super-prefix length, or capacity smaller than fleet.count.
  • Generators on the wrong leaf type (counter on a string, drift on an unsigned int).
  • Two generators targeting the same path (top-level + inline on the same leaf).
  • Two profile files in directory mode declaring the same singleton block (fleet, transfer, connectionRequest, periodicInformPaths, deviceIdPaths).

Fail-fast at load beats per-CPE failure mid-bootstrap.