skip to content

A NETCONF client stages a BGP neighbour with no remote AS in the candidate datastore; when does the server enforce the YANG must and mandatory rules, and what does the client see?

level: seniorimportance: should knowfreq 12%

answer

  1. three enforcement windows
  2. parse, edit, validate
  3. candidate waits for commit or validate
  4. a type restriction fails earlier

basics

~20 s

For the candidate datastore, YANG must, mandatory, unique and min/max-elements are checked at commit or validate, not on each edit-config; type, key and when errors surface while the payload is parsed. Running is validated after every edit.

solid answer

~40 s

RFC 7950 §8.3 names three windows. While parsing the payload the server checks types (`invalid-value`, with the restriction's own message and app tag), missing keys (`missing-element`), two cases of one choice (`bad-element`) and nodes whose `when` is false (`unknown-element`). Validation covers `must`, `mandatory`, `unique`, `min-elements`/`max-elements` and references: for running or startup it runs at the end of every `<edit-config>` or `<copy-config>`, for the candidate only at `<commit>` or `<validate>`. So the neighbour without `peer-as` sits in the candidate with `<ok/>` replies; `<validate>` or `<commit>` then returns `<rpc-error>`, and for the hold-time `must` that is `operation-failed` with its `error-app-tag` and `error-message`. Running is never touched, because it MUST always be valid. RESTCONF has no such staging: each edit is applied to running, or committed at once, so it must be valid by itself.

code

xml · 10 lines
xml
<rpc-reply message-id="103"
           xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <rpc-error>
    <error-type>application</error-type>
    <error-tag>operation-failed</error-tag>
    <error-severity>error</error-severity>
    <error-app-tag>hold-time-too-short</error-app-tag>
    <error-message>hold-time must be 0 or at least 3 seconds</error-message>
  </rpc-error>
</rpc-reply>

go deeper

for a junior

Recall that a candidate configuration is only fully checked when it is validated or committed, while running is checked on every edit.

for a middle

Name the three windows — parsing, edit-config processing, validation — and which constraints fall into each, with the error tags a client receives.

for a senior

Use the timing in tooling: stage related changes in the candidate, send RESTCONF entries whole, branch on error-app-tag, and expect type errors before must errors.

for a principal

Design models and pipelines together: rules a client should hit early belong in types, cross-node rules in must, and change workflows must fit servers with and without a candidate.

## Three windows in RFC 7950 RFC 7950 §8.3 says a NETCONF server enforces constraints on configuration data in three windows. Which window a rule falls into decides when the client hears about a mistake. | Window | What is checked | Reply | |---|---|---| | Payload parsing | leaf values against their type, including `range`, `length` and `pattern` | `invalid-value`, with that restriction's own `error-app-tag` and `error-message` if any | | Payload parsing | every key leaf present in each list entry | `missing-element` | | Payload parsing | data for at most one case of a choice | `bad-element` | | Payload parsing | no data for a node whose `when` is false | `unknown-element` | | `<edit-config>` processing | deletes of missing data, creates of existing data, writes to a node whose `when` is false | `unknown-element` for the `when` case | | Validation | `must`, `unique`, `mandatory`, `min-elements`, `max-elements`, referential integrity | `operation-failed` with `must-violation`, `data-not-unique`, `too-few-elements`, `too-many-elements` or the model's own `error-app-tag` | ## When validation runs §8.3.3 makes the timing of the last window depend on the target datastore: - **running** or **startup**: at the end of every `<edit-config>` or `<copy-config>`. RFC 7950 §8.1 also says the running datastore MUST always be valid, so an edit that would break a rule is refused and running is left as it was. - **candidate**: enforcement is delayed until a `<commit>` or `<validate>` takes place. In between, the candidate may hold a configuration that is not yet valid. ## The BGP neighbour in the candidate The model requires `peer-as` with `mandatory true` and rejects a hold time of 1 or 2 seconds with a `must` that carries `error-app-tag "hold-time-too-short"`. Follow one session: 1. An `<edit-config>` to the candidate creates neighbour 198.51.100.7 with no `peer-as`. Parsing passes — the key is present — and validation is deferred, so the reply is `<ok/>`. 2. A second `<edit-config>` sets `hold-time` to 2. Still `<ok/>`: the rule is a `must`, so it waits too. 3. A `<validate>` of the candidate fails. For the `must`, the `<rpc-error>` looks like the code example; whether the same reply also lists the missing `peer-as` is up to the server. 4. The client adds `peer-as 64496`, sets `hold-time` to 90 and sends `<commit>`. Validation passes and running changes in one step. Had the hold-time rule been a `range "0 | 3..65535"` on the leaf's type, step 2 would already have failed with `invalid-value`, because type restrictions are checked as the payload is parsed, whatever the target datastore. ## RESTCONF has no staging area RFC 8040 says that when the server supports `:writable-running`, RESTCONF edits go straight to running; when it supports only `:candidate`, the candidate is committed to running immediately after each successful edit. Either way every RESTCONF request has to leave a valid configuration behind, so the neighbour must arrive in one request with its `peer-as` and a legal hold time. RESTCONF's error body carries the same `error-tag`, `error-app-tag` and `error-message` fields. ## Operational consequences - **Stage multi-node changes in the candidate.** On a server without one, send everything a `must` relates in a single `<edit-config>`, or the first half is refused. - **Test without applying.** With the `:validate:1.1` capability, `<edit-config>` accepts `<test-option>`: `test-then-set` (the default), `set`, or `test-only`. RFC 6241 only promises that the test checks at least for syntax errors, so how deep it goes is the server's choice. - **Match on the app tag.** Automation should branch on `error-app-tag`; `error-message` is text for a human. - **Put single-leaf rules in the type.** A model author who wants the earliest possible error uses a type restriction for a rule about one leaf and keeps `must` for rules across nodes. - **Conceptual, not literal.** RFC 7950 lets a server enforce these rules without an XPath engine; what is normative is the outcome and its timing, not how the server computes it. - **Watch shared candidates.** RFC 8040 commits everything in the candidate, including another session's unfinished edits, when a RESTCONF edit lands on a candidate-only server, so a half-staged NETCONF change can be validated — and refused — at an unexpected moment. ## Why the specification splits it this way Type checks need only the value in hand, so a server can make them as it reads the request. Rules such as `must`, `unique`, `mandatory` and the element counts look across the whole tree: whether a neighbour has a remote AS, or whether two names collide, is only meaningful once every change in the request — or, for the candidate, every change in the session — has been applied. Deferring them to validation is what lets a client build a complex configuration in several steps without passing through an invalid intermediate state in running.

  • Why would a range on the hold-time type report the same mistake earlier than the must does?
    A `range` is a type restriction, and RFC 7950 checks type restrictions while parsing the RPC payload, whatever the target datastore, answering `invalid-value` with the range's own `error-message` and `error-app-tag`. A `must` is a validation constraint, so on the candidate it waits for `<commit>` or `<validate>`.
  • How can a NETCONF client check an edit to the running datastore without applying it?
    If the server advertises `:validate:1.1`, the client sends `<edit-config>` with `<test-option>test-only</test-option>`; the default is `test-then-set`, which validates and then applies. RFC 6241 only guarantees that the test checks at least for syntax errors, so whether every model constraint is evaluated depends on the server.
  • Through RESTCONF, why can't the client create the neighbour in one request and add its remote AS in the next?
    RFC 8040 applies each RESTCONF edit to running, or to the candidate followed by an immediate commit, so every request must leave a valid configuration. A neighbour without its mandatory `peer-as` is refused, so the whole entry — address, remote AS, a legal hold time — has to arrive in one request.

saying these in an interview costs you the question

  • Every YANG constraint is checked as soon as edit-config touches the candidate.
  • A failed must at commit leaves the bad neighbour half-applied in running.
  • A range violation also waits for commit when the target is the candidate.
  • RESTCONF lets a client stage an incomplete entry and fix it in the next request.
  • test-only is guaranteed to evaluate every must and mandatory rule in the model.