NETCONF

NETCONF protocol sessions, RPC operations, and YANG model-driven configuration management.

Enable NETCONF on IOS-XE

Enable NETCONF-YANG subsystem — listens on TCP port 830
Switch(config)# netconf-yang
Switch(config)# netconf-yang feature candidate-datastore

candidate-datastore enables the candidate config — edit without affecting running until you commit. Without it, edit-config writes directly to running (which is the default IOS-XE behavior).

Verify NETCONF is running
Switch# show netconf-yang sessions
Switch# show netconf-yang sessions detail
Switch# show platform software yang-management process

YANG Models

NETCONF is the transport. YANG is the data model that defines the structure. IOS-XE supports three model families:

  • IETF models — ietf-interfaces, ietf-ip, ietf-routing. Standards-based, multi-vendor.

  • OpenConfig models — openconfig-interfaces, openconfig-bgp. Vendor-neutral, opinionated.

  • Cisco native models — Cisco-IOS-XE-native, Cisco-IOS-XE-interfaces-oper. Full device coverage, IOS-XE specific.

List available YANG models on the device
Switch# show netconf-yang datastores

Or retrieve capabilities via a NETCONF session (the server sends them in the <hello> message).

ncclient — Python NETCONF Client

Connect and retrieve running config
from ncclient import manager
import xmltodict

m = manager.connect(
    host="10.50.1.10",
    port=830,
    username="admin",
    password="<PASSWORD>",
    hostkey_verify=False
)

# Get full running config
config = m.get_config(source="running")
print(config)
Get specific data with a subtree filter — retrieve only interfaces
filter_xml = """
<filter xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>
</filter>
"""

result = m.get_config(source="running", filter=filter_xml)
print(result)
Edit config — change an interface description
edit_xml = """
<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
    <interface>
      <name>GigabitEthernet1</name>
      <description>Uplink to Core</description>
    </interface>
  </interfaces>
</config>
"""

m.edit_config(target="running", config=edit_xml)

Candidate Datastore Workflow

If candidate-datastore is enabled, use the lock-edit-validate-commit pattern:

with manager.connect(...) as m:
    # Lock candidate to prevent concurrent edits
    m.lock(target="candidate")

    # Edit candidate (not running)
    m.edit_config(target="candidate", config=edit_xml)

    # Validate before committing
    m.validate(source="candidate")

    # Commit candidate to running
    m.commit()

    # Unlock
    m.unlock(target="candidate")

This is the same workflow as Junos or any NETCONF device with candidate support. The advantage: you can build up multiple changes, validate them together, and commit atomically.

XPath Filters vs Subtree Filters

Subtree filter — XML structure matching
# Get only Loopback interfaces
filter_xml = """
<filter>
  <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
    <interface>
      <type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">
        ianaift:softwareLoopback
      </type>
    </interface>
  </interfaces>
</filter>
"""
XPath filter — more concise, requires device support
filter_xpath = "/interfaces/interface[type='ianaift:softwareLoopback']"
result = m.get_config(source="running", filter=("xpath", filter_xpath))

Not all IOS-XE versions support XPath filters. Subtree filters always work.

Raw NETCONF via SSH

Connect directly to the NETCONF subsystem — useful for debugging
ssh -p 830 admin@10.50.1.10 -s netconf

The device sends its <hello> with capabilities. Send your <hello> back, then issue RPC operations. Each message ends with ]]>]]> (NETCONF 1.0) or chunked framing (1.1).

Operational Data (get vs get-config)

  • get-config — retrieves configuration data only (what you configured).

  • get — retrieves configuration AND operational/state data (counters, status, neighbors).

# Get operational interface data -- counters, oper-status
oper_filter = """
<filter>
  <interfaces-state xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>
</filter>
"""
result = m.get(filter=oper_filter)

Verification and Troubleshooting

Switch# show netconf-yang sessions                 (1)
Switch# show netconf-yang statistics               (2)
Switch# debug netconf-yang level debug             (3)
1 Active NETCONF sessions with session ID and user
2 RPC counts — in/out, errors, notifications
3 Full NETCONF message trace — very verbose, lab only