Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

NAME management and commanded address

Once a control function owns an address, the network is not done with it. A configuration tool may need to move that node to a specific address, or change some of its NAME fields so two otherwise-identical units can be told apart. These are the network-management operations that sit on top of the basic claim. This tutorial explains the commanded-address message, the NAME-management negotiation, and how a correct node behaves when its address is commanded, contested, or violated.

This page is the sibling of Address claim. That page owns the basic claim — power-up, the contention window, NAME arbitration, and the self-configure walk. Read it first. This page assumes the node has already claimed an address and covers what happens after.

Why this exists

The basic claim answers one question: “which address does each NAME get when everyone powers up at once?” It does not answer the operational questions a real machine raises later:

  • A service tool wants every ECU at a known, documented address so a wiring diagram or a diagnostic script can find it. The claim alone gives addresses that can drift between power cycles.
  • Two physically identical implements hang off the same bus. Their NAMEs collide on every field except the per-unit identity number. The integrator needs to set an instance field on one of them so the rest of the network can address each independently.
  • A generic ECU ships with a placeholder function and is configured into its real role at install time.

Commanded address and NAME management are the standardized, in-band ways to do all of this without reflashing firmware. Both are optional capabilities in ISO 11783-5: a node may support neither, one, or both, and may guard them behind a source check or a proprietary security step. machbus gives you the protocol machinery to respond correctly when you choose to support them.

Mental model

Think of three actors and two messages.

 commanding CF (tool/bridge)            target CF (your node)
 ─────────────────────────             ─────────────────────
        │  commanded-address (NAME + new SA)  │
        │ ──────────────────────────────────►│  is the NAME mine?
        │                                     │  yes ─► re-claim at new SA
        │  ◄───────── address-claimed ────────│
        │                                     │
        │  name-mgmt: set pending (fields)    │
        │ ──────────────────────────────────►│  identity unchanged? store it
        │  ◄────────── ACK / NACK ────────────│
        │  name-mgmt: adopt pending           │
        │ ──────────────────────────────────►│  swap NAME ─► re-claim
        │  ◄───────── address-claimed ────────│

Two ideas carry the whole topic. First, address and identity are separable. Commanded address changes only the label; the NAME is untouched. NAME management changes the identity; the address is then re-negotiated from scratch. Second, every accepted change ends in a fresh address claim. Whenever a node moves address or adopts a new NAME, it must re-run the claim and win an address before it resumes normal traffic — exactly the handshake from Address claim.

Anatomy: the two messages

machbus carries these on two distinct PGNs, exposed as net::pgn_defs::PGN_COMMANDED_ADDRESS and net::pgn_defs::PGN_NAME_MANAGEMENT.

Commanded address

The commanded-address payload is nine bytes: the eight-byte NAME of the node being commanded, followed by one byte holding the address it should move to. The NAME acts as the addressee — a commanding CF must already know which NAME it wants to relocate, because the source address it sends to could have drifted between the decision and the command.

NameManager::handle_commanded_address(msg, our_name) decodes this for you and applies four guards before it accepts anything:

GuardRejected whenWhy
PGN matchmsg.pgn is not the commanded-address PGNWrong message entirely.
Source sanitysource is the null or broadcast addressA command must come from a real claimed node.
Lengthpayload is not exactly nine bytesMalformed; not a valid command.
Target matchthe carried NAME is not our_nameThe command is for some other node.
Address rangethe new address is above MAX_ADDRESS (0xFD)0xFE/0xFF are reserved and never claimable.

If all guards pass, the method returns Some(new_address) and fires on_commanded_address. It does not move you on its own — applying the address and re-claiming is the caller’s job, because only the caller owns the CF state.

NAME management

The NAME-management message is a fixed wire shape: a one-byte mode, eight NAME bytes, a one-byte NACK reason, and padding, encoded to a canonical 17-byte payload. machbus models it as net::NameManagementMsg:

#![allow(unused)]
fn main() {
pub struct NameManagementMsg {
    pub mode: NameMgmtMode,
    pub name_data: [u8; 8],
    pub nack_reason: NameNackReason,
}
}

NameManagementMsg::encode and NameManagementMsg::decode move between this struct and the wire bytes. decode is strict: it rejects non-canonical lengths, unknown modes, invalid NACK reason codes, and any padding byte that is not 0xFF. NameManagementMsg::for_name(mode, name) is the convenient constructor, and msg.name() extracts the carried NAME.

The NAME-management modes

The mode byte selects which of nine operations a frame represents. machbus enumerates them as net::NameMgmtMode:

ModeDirectionMeaning
RequestCurrenttool → node“Tell me the NAME you are using right now.”
RequestCurrentResponsenode → toolThe current NAME, answering the above.
SetPendingtool → node“Stage this NAME; do not adopt it yet.”
RequestPendingtool → node“Tell me the NAME you have staged.”
RequestPendingResponsenode → toolThe staged NAME, answering the above.
AdoptPendingtool → node“Make the staged NAME your current NAME and re-claim.”
Acknowledgenode → toolA set or adopt succeeded.
NegativeAcknowledgenode → toolA request was refused; carries a reason.
RequestAddressClaimtool → bus“If your NAME matches, send your address claim.”

The shape of a configuration session is: query the current NAME, stage one or more field changes with SetPending, optionally read back what was staged with RequestPending, then trigger the swap with AdoptPending. The node keeps running under its current NAME the whole time it has a pending one staged; nothing changes on the bus until adoption.

How machbus answers each mode

NameManager::handle_name_management(msg, current_name) is the responder. It ignores frames from the null or broadcast source, decodes the payload, and dispatches by mode. It always emits the on_name_management event for observability, and returns the reply to send (if any):

Incoming modemachbus reply
RequestCurrentRequestCurrentResponse carrying current_name.
SetPendingAcknowledge if accepted, else NegativeAcknowledge.
RequestPendingRequestPendingResponse if one is staged, else NACK PendingNotSet.
AdoptPendingAcknowledge if a pending NAME existed, else NACK PendingNotSet.
all response/ack modes, RequestAddressClaimno reply — observed only.

The last row is deliberate. Acknowledgements and responses are observed but never answered, so two machbus nodes can never fall into a response-to-response loop where each one replies to the other’s reply forever. Those frames also never mutate the pending NAME.

The one rule that constrains a SetPending

NameManager::set_pending(current_identity, new_name) enforces the single invariant the standard places on NAME changes: the identity number must not change. Every other field — instances, function, device class, industry group, even the self-configurable bit — can be re-commanded, but the per-unit identity number is fixed at manufacture and stays put. If a SetPending carries a NAME whose identity number differs from the node’s current one, machbus rejects it with NegativeAcknowledge and reason InvalidItems, and stages nothing.

NACK reasons as behavior

When machbus refuses an operation it answers with NegativeAcknowledge and a net::NameNackReason. Read each one as “what the node is telling the tool to do differently”:

ReasonWhat it means in practice
SecurityThe node will not accept this change from this source. The tool must authenticate or come from an allowed CF (a bridge or service tool).
InvalidItemsOne or more commanded fields are not allowed to change — in machbus, attempting to change the identity number.
ConflictThe node cannot take on what the change implies (it cannot perform the requested function, or cannot be self-configurable as asked).
ChecksumThe integrity check that guards against an addressee mismatch did not match.
PendingNotSetA RequestPending or AdoptPending arrived but nothing is staged. machbus returns this for both.
OtherA catch-all when none of the above fit.

Self-configurable address ranges

When a self-configurable node loses arbitration, it must pick another address to try. ISO 11783-5 narrows the choice: a self-configurable node draws its retry candidates from the dynamic range (the upper region of the address space), and should prefer the lower part of that range before reaching into addresses that double as preferred slots for other functions. A node with an assigned preferred address may also fall back to that preferred address.

machbus walks candidates in AddressClaimer. After a loss it calls an internal find_next_address that steps linearly from the contested address, skips the node’s own preferred address (it was just contested), and skips any address it has already seen claimed by someone else. The claimer remembers occupied addresses from every peer claim it observes, so a saturated network does not make it cycle onto slots it already knows are taken. If the walk exhausts every claimable address, the node transitions to the failed state and announces cannot-claim from the null address — the same dead end the claim page describes, reached through a fuller search.

Two practical consequences:

  • Pick a preferred address inside the range appropriate for your function so the very first attempt usually succeeds and the walk never runs.
  • Do not configure the null or broadcast address as a local preferred source address. machbus treats that as unclaimable at startup and takes the cannot-claim path instead of briefly advertising an unusable address.
  • After a node settles on a new address, that address should become its initial address for the next power-up. Persisting it (see Advanced) is what keeps the network stable across restarts instead of re-shuffling every boot.

Contention and address-violation handling

There are two distinct “someone wants my address” situations, and they are not the same.

Contention during a claim. Another node sends an address-claimed for an address you are claiming. This is the normal arbitration path: lower NAME wins, the loser self-configures or fails. AddressClaimer::handle_claim owns this and it is covered in Address claim.

Address violation after a claim. You are already the owner, online and sending, and you observe some other message using your source address — not an address claim, just ordinary traffic from a node that thinks the address is its. A correct node does not stay quiet. It re-announces its claim to the whole bus so the network re-converges on the true owner, and it raises the corresponding diagnostic condition so a tool can see that two nodes are fighting over one address. The wrong response is to keep transmitting as if nothing happened, which leaves the bus with an ambiguous owner.

The closely related failure is a duplicate NAME: two distinct devices present the same NAME on different source addresses. Arbitration has no tie-breaker for equal NAMEs, so it cannot resolve this. AddressClaimer::handle_duplicate_name treats it as fatal for the local node: it goes offline, transitions to the failed state, drops to the null address, and emits a single cannot-claim announcement rather than continuing under an identity the bus cannot distinguish. The cure is upstream — make the identity numbers differ — not on the wire.

Doing it with machbus

There are two layers, mirroring the claim page.

The session facade owns the NAME-management responder when you plug the NameManagement plugin. It registers a callback on the NAME-management PGN, drains incoming frames each pump, and runs NameManager::handle_name_management for you. When a reply is produced it sends it; when an AdoptPending is accepted it applies the new NAME to your control function and restarts address claiming automatically — you do not have to re-sequence the claim by hand. The shape is:

#![allow(unused)]
fn main() {
// Illustrative shape — reacting to a tool adopting a new NAME for this node.
ctrl.with_mut::<NameManagement, _>(|nm| {
    nm.manager_mut().on_name_changed.subscribe(|new_name| {
        // The session will re-claim under `new_name`; persist it if you want
        // it to survive the next power cycle.
    });
});
}

The plugin is a responder: it answers a commanding CF. Driving the commanding side (sending SetPending/AdoptPending to other nodes) is an application concern you build on top of the raw send API.

The low-level manager (for tests and embedded control)

net::NameManager is the pure, stateless-by-design helper. You feed it decoded Messages and route its replies yourself:

#![allow(unused)]
fn main() {
// Illustrative shape — not a compiled example.
let mut mgr = NameManager::new();

// A tool commands us to move to 0x42.
if let Some(new_addr) = mgr.handle_commanded_address(&msg, our_name) {
    cf.set_address(new_addr);
    // re-run the claim at new_addr (see the address-claim tutorial)
}

// A tool runs a NAME-management exchange.
if let Some(reply) = mgr.handle_name_management(&msg, current_name) {
    net.send(PGN_NAME_MANAGEMENT, &reply.msg.encode(),
             self_cf, reply.destination, Priority::Default)?;
}
}

The manager tracks only the pending NAME. set_pending, adopt_pending, has_pending, and pending_name give you direct control for unit tests, and adopt_pending returns the adopted NAME and fires on_name_changed so the caller knows it now owes a re-claim.

Events and responsibilities

EventFired byYour responsibility
on_commanded_addresshandle_commanded_addressApply the new address and re-claim. The session does this for you.
on_name_changedadopt_pendingThe current NAME is now the adopted one; re-claim under it and persist it.
on_name_managementevery received NM frameObserve/log. Do not reply from here — the manager already decides replies.

The rule that never bends, same as the claim page: after any commanded move or NAME adoption, do not resume normal traffic until you have successfully claimed an address again. The address you were commanded to, or the identity you adopted, is not yours until the claim confirms it.

Edge cases and failures

  • Commanded to an occupied address. The command is accepted and you re-claim at the new address — but the claim can still lose if a lower NAME already owns it. The correct end state is whatever the claim yields, not blind occupation. A node that cannot take the commanded address re-announces its current address instead.
  • Commanded to a reserved address. handle_commanded_address returns None for any address above MAX_ADDRESS, so 0xFE/0xFF are silently ignored.
  • NACKed name change. A SetPending that touches the identity number, or that the node will not accept from this source, comes back as a NegativeAcknowledge. The pending state is left untouched; nothing was staged.
  • Adopt with nothing staged. AdoptPending when no pending NAME exists NACKs with PendingNotSet and changes nothing. adopt_pending consumes the pending NAME, so a second adopt also fails — adoption is one-shot.
  • Response/violation storms. Because machbus never replies to ack or response modes, a bus full of NM responses cannot drag your node into an ever-escalating reply loop. Likewise a real violation triggers exactly one re-announce per detection, not a continuous stream.
  • Stale source address. A node can claim a new address between a tool deciding to command it and the command arriving. Commanded address sidesteps this by addressing the NAME, not the source; NAME management guards the same race with an integrity check that surfaces as the Checksum NACK reason.

Advanced

  • Multi-CF ECUs. One physical ECU may host several control functions, each with its own NAME and its own address. Commanded address and NAME management are per-CF: model each control function separately and run a NameManager per CF. Never try to share one address between two of them.
  • Configuration tools and security. Supporting these messages is optional, and the standard explicitly lets a manufacturer accept them only from a bridge or service tool, or behind a proprietary security check. If your product is a responder, decide who you accept commands from before shipping, and answer unauthorized requests with the Security NACK reason rather than silently obeying.
  • Persistence across power cycles. When a node moves address — by losing arbitration, by self-configuring, or by command — that new address is meant to become the initial address it tries next boot. machbus does not own your non-volatile storage; persist the address (and an adopted NAME) yourself from the on_address_claimed and on_name_changed events so the network comes back up in the same shape it settled into.
  • Fine control vs the bare codecs. The NameManagement plugin is right for applications: it pumps, replies, applies adopted NAMEs, and re-claims for you. The bare NameManager is right for tests and tightly controlled embedded loops where you route every frame and own every state transition.

Validate locally

make test

The library tests exercise the responder end to end: request-current, set-pending with matching and mismatched identity, request-pending when set and unset, adoption and double-adoption, malformed and overlong payloads, response modes that must not loop, and commanded-address targeting us, targeting someone else, with a reserved address, and with short or overlong payloads. For the basic claim and self-configure walk that these operations re-trigger, run the address-claim example:

make run EXAMPLE=address_claim

What this proves / does not prove

Proves: in software, machbus decodes and answers NAME-management and commanded-address traffic by the rules above, refuses identity changes and unstaged adoptions, never loops on responses, and re-claims after any accepted move or NAME change.

Does not prove: real-hardware timing, interoperability with a specific third-party tool or ECU, or any conformance or certification claim. Supporting these optional messages on a shipping product still needs official standards, real hardware, and interoperability evidence. machbus ships no certification.

See also