Series · Designing a Netconf Manager · Part 2 of 4

The library

Four layers in the RFC become four components: operations, session, RPC and transport, with the session at the centre.

2014 · 5 min read

RFC 6241 says NETCONF "provides mechanisms to install, manipulate, and delete the configuration of network devices", using XML for both data and messages, with operations realised as remote procedure calls. Tough language. Four plain points come out of it:

  • it is a configuration protocol;
  • it needs a connection to network devices, and so a session;
  • it uses XML as its base language;
  • its operations are RPCs, which are XML messages.

Although RFC 6241 is the reference, the library should stay as general as possible, so it can take future changes without a redesign.

Four layers, four components

The RFC describes NETCONF in four layers: secure transport, messages, operations and content. Content is outside the RFC's scope. The other three, plus the session the connection implies, give the library its four components.

Contentdata models (outside the RFC)(the client’s data)Operationsget, get-config, edit-config, …Operations enumMessagesRPC framing, XMLSession + RPCSecure TransportSSH, TLSSecure protocol interfaceNETCONF LAYERS (RFC 6241)LIBRARY COMPONENTS
Each layer of the protocol becomes one part of the library. The session is the centre: it owns the lifecycle and forms and parses RPCs.

Operations

The protocol defines nine operations: get, get-config, edit-config, copy-config, delete-config, lock, unlock, close-session and kill-session. Each has its own RPC form, which belongs to the RPC component. For the user of the library, they are simply an enumeration. The user names an operation; the library worries about the XML.

Session

A session is a semi-permanent dialogue between two communicating peers. Here it is the dialogue between the client and a network device, and the medium is NETCONF. So the session has to understand the protocol, which makes it the centre of the library.

A NETCONF session runs like this. The client opens a connection with NETCONF as the SSH subsystem, and the node immediately sends a hello listing its capabilities. The client replies with its own hello. Hello must be the first message from both sides; it is a handshake. Then the client sends requests (a get, say) and the node answers, as many times as needed while the session lives. Finally the client sends close-session, the node replies ok, and the session ends.

Newconnected, unusableCapability exchangehello ↔ helloOpenoperations allowedClosingclose-session sentClosedsession endedget, edit-config, … (repeat)
The session lifecycle. Hello must be the first message from both peers; only an open session accepts operations, as many as needed.

That gives the session four responsibilities:

  1. maintain the lifecycle;
  2. form RPC requests from an operation and its input;
  3. parse responses according to the RPC rules;
  4. keep session information.

Connections and security are not its concern; those belong to the socket and the secure transport.

Receiving needs one more thought. Requests can be formed in one go, because all the data is at hand. Responses arrive in chunks, because of how the lower layers work, so the session accumulates data until it has a complete RPC response. Helpfully, a session receives only one response at a time, so a single buffer and a flag saying whether the response is complete are enough. Once complete, it is handled according to the session state. A single class can do all this, though an interface or abstract class above it makes later changes easier.

RPC

An RPC is a structured XML message, in two families: requests and responses. Hello fits in as a hello request from the client and a hello response from the node. Each message (except hello) carries an RPC tag, a type tag and a message-id; the tag classifies it and the message-id makes it unique. Some need session data, and there are headers and footers that depend on the session.

RPCtag · type · message-idRPC requestRPC responseHelloGetGet configEdit configCopy configLockUnlockKill sessionClose sessionHelloOkDataError
One base RPC, two families. Factories form requests and parse responses, so the library’s user only ever names an operation.

Enumerations for request and response types, plus factories for forming and parsing, finish the component. It may look as if the RPC request types make the operations enumeration redundant. They don't. RPC formation stays private to the library; the user only says which operation to perform. That is why the session's request method takes an operation, not an RPC type.

Secure transport

What remains is securing the data and moving it over the network. Rather than design around SSH or TLS specifically, the library defines an abstract secure protocol: open the session, authenticate, encrypt outgoing data, decrypt incoming data, close. Generic input and output types keep it independent of any one implementation.

The gain is threefold. Any protocol can be added by implementing the interface and bridging to it. The library's users never change, because they only see the abstraction. And neither the NETCONF code nor the protocol code has to know about the other.

Sending and receiving bytes is a separate choice. The best answer is to offer both: a basic, extendable network implementation in the library (in Java, socket channels and NIO), with no restriction stopping the user from bringing their own.

Services and utilities

Two small families round it off. Services give structure to things like node information and logging. Utilities hold the static and factory helpers: NETCONF and library properties, general XML handling, security certificates.

A task that ties a session, a secure protocol and a socket together could live in the library. It is better left to the service layer, which has to manage resources its own way.

Next: the manager service.

Drafted in 2014
Updated for site in 2026