Network Automation using YANG Models across XE, XR, & NX

YANG & RESTCONF


Configuring BGP on IOS-XE with openconfig-network-instance over RESTCONF


In this module we will explore configuring the CSR1kv using Openconfig BGP YANG models over RESTCONF. To learn more about RESTCONF on IOS-XE, check out the RESTCONF Programmable Interface guide for IOS-XE.

Configuring the IOS-XE Device

In this excercise, we will configure one EBGP peer on our CSRv device using YANG, RESTCONF, and the openconfig-network-instance YANG model. The openconfig-network-instance model is a superset of many route/switch concepts and was created to address some of the limitations of working with individual openconfig-* protocol specific models. To inspect the openconfig-network-instance model, go here.

To learn more about the history and how openconfig-network-instance ties in many route/switch concepts a unified fashion, refer to this IETF slide deck.

Create New Python File

Return to Visual Studio Code and create a new Python file called restconf_xe_bgp_conf.py. You can copy this file name below for ease.

restconf_xe_bgp_conf.py

Imports Required and Setup

Since we are performing our YANG modeling operations of RESTCONF, we will naturally use Python's requests library. The HTTPBasicAuth is imported to allow us to specify a username and password. The disable_warnings() call tells requests' underlying urllib3 to not warn about unsigned SSL certificates.

    
    # Using python request library for REST operations
    from requests.auth import HTTPBasicAuth
    import requests
    # disable warnings from SSL/TLS certificates
    requests.packages.urllib3.disable_warnings()
    

Check RESTCONF Capabilities

Similar to how ncclient can be used to check device capabilities, RESTCONF can be queried to return the list of YANG model capabilities that the device supports.

    
    response = requests.get(
        f"https://10.2.100.11/restconf/data/ietf-yang-library:modules-state",
        auth=HTTPBasicAuth('admin', 'cisco.123'),
        #headers=headers,
        verify=False)

    # Print out device capabilities.
    print(response.text)
    

Construct the REST Payload

Now that we have confirmed RESTCONF connectivity for getting data, let's build the Payload that we intend to use to configure BGP and add the neighbor.

    
    # RPC call that defines global level and neighbor level BGP peering information.
    rest_data = '''
                <network-instances>
                    <network-instance>
                    <name>default</name>
                    <protocols>
                        <protocol>
                        <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:BGP</identifier>
                        <name>65001</name>
                        <config>
                            <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:BGP</identifier>
                            <name>65001</name>
                        </config>
                        <bgp>
                            <global>
                            <config>
                                <as>65001</as>
                                <router-id>1.1.1.1</router-id>
                            </config>
                            </global>
                            <neighbors>
                            <neighbor>
                                <neighbor-address>10.1.1.2</neighbor-address>
                                <config>
                                <neighbor-address>10.1.1.2</neighbor-address>
                                <peer-as>65002</peer-as>
                                </config>
                                <ebgp-multihop>
                                <config>
                                    <enabled>false</enabled>
                                </config>
                                </ebgp-multihop>
                            </neighbor>
                            </neighbors>
                        </bgp>
                        </protocol>
                    </protocols>
                    </network-instance>
                </network-instances>
                '''
    

Sending the RESTCONF Payload

With the RESTCONF payload defined, we now need to send this data to the device using requests libraries patch() function. Note how we provide HTTPBasic auth headers.

    
    response = requests.patch(
        f"https://10.2.100.11/restconf/data/openconfig-network-instance:network-instances",
        auth=HTTPBasicAuth('admin', 'cisco.123'),
        verify=False,
        data=rest_data)
    

The Full Script

At this point, your script should look as follows:

    
    # Using python request library for REST operations
    from requests.auth import HTTPBasicAuth
    import requests
    # disable warnings from SSL/TLS certificates
    requests.packages.urllib3.disable_warnings()

    response = requests.get(
        f"https://10.2.100.11/restconf/data/ietf-yang-library:modules-state",
        auth=HTTPBasicAuth('admin', 'cisco.123'),
        #headers=headers,
        verify=False)

    # Print out device capabilities.
    print(response.text)

    # RPC call that defines global level and neighbor level BGP peering information.
    rest_data = '''
                <network-instances>
                    <network-instance>
                    <name>default</name>
                    <protocols>
                        <protocol>
                        <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:BGP</identifier>
                        <name>65001</name>
                        <config>
                            <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:BGP</identifier>
                            <name>65001</name>
                        </config>
                        <bgp>
                            <global>
                            <config>
                                <as>65001</as>
                                <router-id>1.1.1.1</router-id>
                            </config>
                            </global>
                            <neighbors>
                            <neighbor>
                                <neighbor-address>10.1.1.2</neighbor-address>
                                <config>
                                <neighbor-address>10.1.1.2</neighbor-address>
                                <peer-as>65002</peer-as>
                                </config>
                                <ebgp-multihop>
                                <config>
                                    <enabled>false</enabled>
                                </config>
                                </ebgp-multihop>
                            </neighbor>
                            </neighbors>
                        </bgp>
                        </protocol>
                    </protocols>
                    </network-instance>
                </network-instances>
                '''

    # Patch openconfig-network-instance with the updated BGP configuration.
    response = requests.patch(
        f"https://10.2.100.11/restconf/data/openconfig-network-instance:network-instances",
        auth=HTTPBasicAuth('admin', 'cisco.123'),
        verify=False,
        data=rest_data)
    

Execute Python Script

python3.6 restconf_xe_bgp_conf.py

Verify Configuration on CSRv

Your CSR's BGP configuration should look as follows:

    
Pod03-CSRv#show run | sec bgp
router bgp 65001
 bgp router-id 1.1.1.1
 bgp log-neighbor-changes
 bgp bestpath compare-routerid
 neighbor 10.1.1.2 remote-as 65002
 neighbor 10.1.1.2 transport path-mtu-discovery disable
 neighbor 10.1.1.2 transport connection-mode active
 neighbor 10.1.1.2 log-neighbor-changes
 neighbor 10.1.1.2 timers 30 90
Pod03-CSRv#
    

Use CURL to Query RESTCONF

To visually inspect that the configuration was applied, you can also use the unix tool curl to Query the openconfig-network-instance model.

        
        curl -v -k -u admin:cisco.123 https://10.2.100.11/restconf/data/openconfig-network-instance:network-instances/
        
    

You should observe something similar to the following:

    
    <network-instances xmlns="http://openconfig.net/yang/network-instance"  xmlns:oc-netinst="http://openconfig.net/yang/network-instance">
    <network-instance>
        <name>management</name>
        <config>
        <name>management</name>
        <type xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types">oc-ni-types:L3VRF</type>
        <enabled-address-families xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</enabled-address-families>
        </config>
        <state>
        <name>management</name>
        <type xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types">oc-ni-types:L3VRF</type>
        <enabled-address-families xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</enabled-address-families>
        </state>
        <interfaces>
        <interface>
            <id>GigabitEthernet1</id>
            <config>
            <id>GigabitEthernet1</id>
            <interface>GigabitEthernet1</interface>
            </config>
            <state>
            <id>GigabitEthernet1</id>
            <interface>GigabitEthernet1</interface>
            <associated-address-families xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</associated-address-families>
            </state>
        </interface>
        </interfaces>
        <tables>
        <table>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:DIRECTLY_CONNECTED</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
            <config>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:DIRECTLY_CONNECTED</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
            </config>
            <state>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:DIRECTLY_CONNECTED</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
            </state>
        </table>
        <table>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:STATIC</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
            <config>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:STATIC</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
            </config>
            <state>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:STATIC</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
            </state>
        </table>
        </tables>
        <protocols>
        <protocol>
            <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:BGP</identifier>
            <name>65001</name>
            <config>
            <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:BGP</identifier>
            <name>65001</name>
            </config>
            <bgp>
            <global>
            <state>
            <as>65001</as>
            </state>
            <graceful-restart>
            <config>
            <enabled>false</enabled>
            </config>
            <state>
            <enabled>false</enabled>
            </state>
        </graceful-restart>
        <route-selection-options>
        <config>
            <always-compare-med>false</always-compare-med>
        </config>
        <state>
            <always-compare-med>false</always-compare-med>
        </state>
        </route-selection-options>
    </global>
    </bgp>
    </protocol>
    <protocol>
    <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:STATIC</identifier>
    <name>DEFAULT</name>
    <config>
        <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:STATIC</identifier>
        <name>DEFAULT</name>
    </config>
    <static-routes>
        <static>
        <prefix>0.0.0.0/0</prefix>
        <config>
            <prefix>0.0.0.0/0</prefix>
        </config>
        <state>
            <prefix>0.0.0.0/0</prefix>
        </state>
        <next-hops>
            <next-hop>
            <index>10.0.249.1</index>
            <config>
                <index>10.0.249.1</index>
                <next-hop>10.0.249.1</next-hop>
            </config>
            <state>
                <index>10.0.249.1</index>
                <next-hop>10.0.249.1</next-hop>
            </state>
            </next-hop>
        </next-hops>
        </static>
    </static-routes>
    </protocol>
    <protocol>
    <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:DIRECTLY_CONNECTED</identifier>
    <name>DEFAULT</name>
    <config>
        <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:DIRECTLY_CONNECTED</identifier>
        <name>DEFAULT</name>
    </config>
    </protocol>
    </protocols>
    </network-instance>
    <network-instance>
    <name>default</name>
    <config>
        <name>default</name>
        <type xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types">oc-ni-types:DEFAULT_INSTANCE</type>
        <description>default-vrf [read-only]</description>
    </config>
    <state>
        <name>default</name>
        <type xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types">oc-ni-types:DEFAULT_INSTANCE</type>
        <description>default-vrf [read-only]</description>
    </state>
    <tables>
        <table>
        <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:DIRECTLY_CONNECTED</protocol>
        <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
        <config>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:DIRECTLY_CONNECTED</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
        </config>
        <state>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:DIRECTLY_CONNECTED</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
        </state>
        </table>
        <table>
        <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:DIRECTLY_CONNECTED</protocol>
        <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV6</address-family>
        <config>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:DIRECTLY_CONNECTED</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV6</address-family>
        </config>
        <state>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:DIRECTLY_CONNECTED</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV6</address-family>
        </state>
        </table>
        <table>
        <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:OSPF</protocol>
        <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
        <config>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:OSPF</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
        </config>
        <state>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:OSPF</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
        </state>
        </table>
        <table>
        <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:STATIC</protocol>
        <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
        <config>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:STATIC</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
        </config>
        <state>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:STATIC</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV4</address-family>
        </state>
        </table>
        <table>
        <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:STATIC</protocol>
        <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV6</address-family>
        <config>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:STATIC</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV6</address-family>
        </config>
        <state>
            <protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:STATIC</protocol>
            <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:IPV6</address-family>
        </state>
        </table>
    </tables>
    <protocols>
        <protocol>
        <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:BGP</identifier>
        <name>65001</name>
        <config>
            <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:BGP</identifier>
            <name>65001</name>
        </config>
        <bgp>
        <global>
        <config>
            <as>65001</as>
            <router-id>1.1.1.1</router-id>
        </config>
        <state>
            <as>65001</as>
            <router-id>1.1.1.1</router-id>
        </state>
        <graceful-restart>
        <config>
            <enabled>false</enabled>
        </config>
        <state>
            <enabled>false</enabled>
        </state>
        </graceful-restart>
        <route-selection-options>
        <config>
        <always-compare-med>false</always-compare-med>
        <external-compare-router-id>true</external-compare-router-id>
        </config>
        <state>
        <always-compare-med>false</always-compare-med>
        <external-compare-router-id>true</external-compare-router-id>
        </state>
    </route-selection-options>
    </global>
    <neighbors>
    <neighbor>
        <neighbor-address>10.1.1.2</neighbor-address>
        <config>
        <neighbor-address>10.1.1.2</neighbor-address>
        <peer-as>65002</peer-as>
        </config>
        <state>
        <neighbor-address>10.1.1.2</neighbor-address>
        <peer-as>65002</peer-as>
        <peer-type>EXTERNAL</peer-type>
        <messages>
        <sent>
            <UPDATE>0</UPDATE>
            <NOTIFICATION>0</NOTIFICATION>
        </sent>
        <received>
            <UPDATE>0</UPDATE>
            <NOTIFICATION>0</NOTIFICATION>
        </received>
        </messages>
        <queues>
        <input>0</input>
        <output>0</output>
        </queues>
    </state>
    <timers>
    <config>
        <hold-time>90.0</hold-time>
        <keepalive-interval>30.0</keepalive-interval>
        <minimum-advertisement-interval>30.0</minimum-advertisement-interval>
    </config>
    <state>
        <hold-time>90.0</hold-time>
        <keepalive-interval>30.0</keepalive-interval>
        <minimum-advertisement-interval>30.0</minimum-advertisement-interval>
    </state>
    </timers>
    <transport>
    <config>
    <mtu-discovery>false</mtu-discovery>
    <passive-mode>false</passive-mode>
    </config>
    <state>
    <mtu-discovery>false</mtu-discovery>
    <passive-mode>false</passive-mode>
    <local-port>0</local-port>
    <remote-port>0</remote-port>
    </state>
    </transport>
    <error-handling>
    <state>
    <treat-as-withdraw>true</treat-as-withdraw>
    </state>
    </error-handling>
    <logging-options>
    <config>
    <log-neighbor-state-changes>true</log-neighbor-state-changes>
    </config>
    <state>
    <log-neighbor-state-changes>true</log-neighbor-state-changes>
    </state>
    </logging-options>
    <ebgp-multihop>
    <config>
    <enabled>false</enabled>
    </config>
    <state>
    <enabled>false</enabled>
    </state>
    </ebgp-multihop>
    <route-reflector>
    <config>
    <route-reflector-client>false</route-reflector-client>
    </config>
    </route-reflector>
    <as-path-options>
    <config>
    <replace-peer-as>false</replace-peer-as>
    </config>
    </as-path-options>
    <add-paths>
    <config>
    <receive>false</receive>
    </config>
    </add-paths>
    </neighbor>
    </neighbors>
    </bgp>
    </protocol>
    <protocol>
    <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:OSPF</identifier>
    <name>100</name>
    <config>
        <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:OSPF</identifier>
        <name>100</name>
    </config>
    </protocol>
    <protocol>
    <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:STATIC</identifier>
    <name>DEFAULT</name>
    <config>
        <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:STATIC</identifier>
        <name>DEFAULT</name>
    </config>
    <static-routes>
        <static>
        <prefix>10.0.249.0/24</prefix>
        <config>
            <prefix>10.0.249.0/24</prefix>
        </config>
        <state>
            <prefix>10.0.249.0/24</prefix>
        </state>
        <next-hops>
            <next-hop>
            <index>GigabitEthernet1_10.0.249.1</index>
            <config>
                <index>GigabitEthernet1_10.0.249.1</index>
                <next-hop>10.0.249.1</next-hop>
            </config>
            <state>
                <index>GigabitEthernet1_10.0.249.1</index>
                <next-hop>10.0.249.1</next-hop>
            </state>
            <interface-ref>
            <config>
                <interface>GigabitEthernet1</interface>
            </config>
            <state>
                <interface>GigabitEthernet1</interface>
            </state>
            </interface-ref>
        </next-hop>
        </next-hops>
    </static>
    </static-routes>
    </protocol>
    <protocol>
    <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:DIRECTLY_CONNECTED</identifier>
    <name>DEFAULT</name>
    <config>
        <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:DIRECTLY_CONNECTED</identifier>
        <name>DEFAULT</name>
    </config>
    </protocol>
    </protocols>
    </network-instance>
    </network-instances>
    

Let's wrap-up the Python/Openconfig/YANG sections and move on to verifying the entire BGP topology and ensure all BGP peers are Established.