skip to content

A RESTCONF JSON body sets the ietf-interfaces type leaf to plain ethernetCsmacd and is rejected; how must RFC 7951 encode identityref values?

level: seniorimportance: should knowfreq 7%

answer

  1. values have namespaces too
  2. compare the identity's module with the leaf's
  3. the module name, never an XML prefix
  4. instance-identifier follows the member-name rule

basics

~20 s

An identityref value is a string naming the identity, qualified module:identity with the defining module's name whenever the identity lives in a different module from the leaf, so ietf-interfaces' type takes "iana-if-type:ethernetCsmacd", not the bare name or an XML prefix.

solid answer

~40 s

RFC 7951 Section 6.8 encodes an `identityref` as a string naming an identity. If the identity is defined in a module other than the one defining the leaf, the namespace-qualified form `module:identity` MUST be used; if they share a module, either form is allowed. The `type` leaf is in `ietf-interfaces` while `ethernetCsmacd` is defined in `iana-if-type`, so `"iana-if-type:ethernetCsmacd"` is required. The test compares the identity's module with the leaf's, not the leaf's parent, so the member-name rule does not carry over. The qualifier is the module name: values copied from XML or a `when` expression carry a prefix such as `ianaift`, which JSON does not recognise. `instance-identifier` values, including `error-path`, qualify their first node and every module change.

go deeper

for a junior

Remember that some JSON values, not only member names, carry a module:name qualifier, and that interface types come from iana-if-type.

for a middle

Explain the identityref test, identity module versus leaf module, and how it differs from the member-name rule and from instance-identifier paths.

for a senior

Debug a rejected body by spotting a bare foreign identity or a copied XML prefix, read error-path correctly, and normalise identity strings before comparing.

for a principal

Decide how your automation resolves identities and their derivations from the schema, so identities added by new modules do not break consumers.

## Values can carry namespaces too RFC 7951's member-name rule puts module names on JSON **keys**. Two YANG types also need a namespace inside the **value**: - an **`identityref`**, whose value names a YANG **identity**, an abstract, extensible tag that any module can derive new values from; - an **`instance-identifier`**, whose value is a path to a node in the data tree. Identities are the reason the first rule exists. The `type` leaf of an interface in `ietf-interfaces` (RFC 8343) is `identityref { base interface-type; }`, and the actual values, such as `ethernetCsmacd`, are defined in a different module, `iana-if-type`. Identity names are unique only within their module, so a bare name does not say which module's identity is meant. ## The identityref rule RFC 7951 Section 6.8: | Where the identity is defined | Encoding | |---|---| | a module **other than** the module defining the leaf | qualified form **MUST** be used: `"iana-if-type:ethernetCsmacd"` | | the **same** module as the leaf | simple or qualified are both permitted: `"alternative"` or `"example-jukebox:alternative"` | ```json { "ietf-interfaces:interfaces": { "interface": [ { "name": "eth0", "type": "iana-if-type:ethernetCsmacd", "enabled": true } ] } } ``` So the rejected body most likely sent `"type": "ethernetCsmacd"`. Three habits produce that mistake: 1. **Carrying over the member-name rule.** Member names are qualified only where a node's module differs from its *parent's*. The identityref test is different: it compares the *identity's* module with the *leaf's* module. A leaf sitting happily among same-module siblings still needs a qualified value if its identity comes from elsewhere. 2. **Copying from XML.** In the XML encoding an identityref is an XML qualified name (RFC 7950 §9.10.3) whose prefix is whatever `xmlns` declaration is in scope, for example `ianaift:ethernetCsmacd` with `xmlns:ianaift` bound to the module's namespace URI. That prefix is local to the document. RFC 7951 always uses the **module name**. 3. **Copying from the YANG module.** An augmentation example in RFC 8343 writes `when "if:type = 'ianaift:ethernetCsmacd'"`, using the prefixes its `import` statements declare. Those prefixes are scoped to the module text; `"ianaift:ethernetCsmacd"` in a JSON body names a module that does not exist. ## The same value in both encodings | Encoding | Value written | What the qualifier is | |---|---|---| | XML | `ianaift:ethernetCsmacd` | a prefix the document binds with `xmlns:ianaift` to the module's namespace URI; the writer may choose any prefix | | JSON | `iana-if-type:ethernetCsmacd` | the module's name, fixed by the module itself, with no declaration needed | The XML prefix is only meaningful together with its `xmlns` binding, which JSON has nowhere to put; that is why RFC 7951 chose the one stable identifier every module has, its name. Converting a body between the two encodings therefore means rewriting identityref values, not just the structure, and RFC 7951 Section 3 notes that such conversion needs the YANG model to be available. ## The parsing side: accept both forms Because the same-module case permits either spelling, a server may answer a `GET` with `"genre": "example-jukebox:alternative"` while another client wrote `"alternative"`; RFC 8040's own jukebox example uses the qualified form for a same-module identity. A client that compares identity strings literally will see false differences. Normalise first: resolve a bare name to the leaf's own module, then compare `module:identity` pairs. Also remember an identity check may involve derivation: a value is valid if it is derived from the leaf's base, and derived identities are often defined in yet another module. ## instance-identifier values RFC 7951 Section 6.11 applies the member-name logic, not the identityref logic, to paths inside values: - the leftmost (top-level) node is always qualified; - every later node, **including node names inside predicates**, is qualified only if its module differs from its parent's. The RFC's example is `/ietf-interfaces:interfaces/interface[name='eth0']/ietf-ip:ipv4/ip`: `interfaces`, `interface` and `name` come from `ietf-interfaces`, while `ipv4` and `ip` come from `ietf-ip`, which augments the interface entry. The place most RESTCONF users meet this is the **`error-path`** of an `ietf-restconf:errors` body. It is an `instance-identifier`, so in a JSON reply it uses module names in this form (RFC 8072 shows one), whereas the XML reply in RFC 8040 binds `xmlns` prefixes. It is also not the same syntax as the request URI, which writes list keys after `=` rather than in predicates. ## What to do about it - Look up where each identity is **defined**, not where its base lives, and qualify with that module's name. - Never reuse prefixes from XML documents or YANG source in JSON values. - When reading, accept both forms for same-module identities and compare after normalising. - When an encoding error comes back, read `error-path` with the instance-identifier rules above to find the offending leaf.

  • Why can a RESTCONF client not compare identityref strings from server replies literally?
    Because RFC 7951 permits both the simple and the qualified form when the identity is defined in the same module as the leaf. One server may return `"example-jukebox:alternative"` and another `"alternative"` for the same value. Compare after resolving a bare name to the leaf's module, so both become the same `module:identity` pair.
  • Why does RFC 7951 refuse a bare identity name when the identity comes from another module?
    Identity names are unique only inside the module that defines them, and identities derived from one base can be defined by any module that imports it. A bare `ethernetCsmacd` under a leaf whose own module does not define it leaves the decoder no reliable way to know which module was meant, so Section 6.8 makes the module-qualified form mandatory there.

saying these in an interview costs you the question

  • An identityref value is qualified only where the parent node's module changes
  • The identityref qualifier is the prefix from the YANG import, such as ianaift
  • A bare identity name always works because the base identity fixes the module
  • Servers always return identityref values in one fixed form, so string compares are safe
  • JSON instance-identifier values bind XML namespace prefixes, like the XML encoding