OpenDaylight

11 posts

Both OpenDaylight and Cisco IOS XR now support the OpenConfig YANG models (for BGP both ODL and XR support the 2015-10-09 revision).

 

In this post I will show how to create a BGP session from ODL to XR using the OpenConfig YANG models.  ODL will be configured using RESTCONF.  XR will be configured using RESTCONF to ODL and NETCONF from ODL to XR (but equally you could use NETCONF, or for some platforms RESTCONF, direct to XR).

 

Note this is a work in progress - currently seeing some issues with the XR config part (I believe this is to do with https://bugs.opendaylight.org/show_bug.cgi?id=7506).    If you have already configured BGP on XR and already have at least one neighbor then it ought to work, but you won't be able to configure BGP from scratch.

 

First off ODL needs to be running the odl-bgpcep-bgp, odl-netconf-all, odl-restconf-all and odl-netconf-connector-all features.

 

XR then needs to be configured as a NETCONF server.  So you'll need to have configured:

ssh server v2

ssh server netconf vrf default

netconf-yang agent ssh

 

(and you'll need to have done "crypto key generate rsa" from the admin mode)

 

You'll also have to have mounted XR from ODL using NETCONF (see other blog posts for that).

 

In the below I'll assume that ODL is running on the localhost and that XR has been mounted as "XR"

 

So - let's configure ODL.

 

do a RESTCONF PUT to:

 

http://localhost:8181/restconf/config/openconfig-network-instance:network-instances/network-instance/global-bgp/protocols/protocol/openconfig-policy-types:BGP/example-bgp-rib/bgp/global

 

with a body of e.g.:

{

  "bgp-openconfig-extensions:global": {

    "afi-safis": {

      "afi-safi": [

        {

          "afi-safi-name": "openconfig-bgp-types:IPV4-UNICAST"

        },

        {

          "afi-safi-name": "openconfig-bgp-types:IPV6-UNICAST"

        }

      ]

    },

    "config": {

      "as": 65504,

      "router-id": "10.195.94.43"

    }

  }

}

 

the full list of supported AFI/SAFI names (as of ODL Boron) is:

1) openconfig-bgp-types:IPV4-UNICAST

2) openconfig-bgp-types:IPV6-UNICAST

3) openconfig-bgp-types:IPV4-LABELLED-UNICAST

4) openconfig-bgp-types:IPV6-LABELLED-UNICAST

5) openconfig-bgp-types:L3VPN-IPV4-UNICAST

6) openconfig-bgp-types:L3VPN-IPV6-UNICAST

7) openconfig-bgp-types:L2VPN-EVPN

8) bgp-openconfig-extensions:LINKSTATE

9) bgp-openconfig-extensions:IPV4-FLOW

10) bgp-openconfig-extensions:IPV6-FLOW

11) bgp-openconfig-extensions:IPV4-L3VPN-FLOW

12) bgp-openconfig-extensions:IPV6-L3VPN-FLOW

 

so now the RIB is set up.

 

next step is to add a peer:

 

do a RESTCONF POST to:

 

http://localhost:8181/restconf/config/openconfig-network-instance:network-instances/network-instance/global-bgp/protocols/protocol/openconfig-policy-types:BGP/example-bgp-rib/bgp-openconfig-extensions:bgp/neighbors

 

with a body of e.g:

 

{

  "bgp-openconfig-extensions:neighbor": [

    {

      "neighbor-address": "10.195.94.68",

      "timers": {

        "config": {

          "connect-retry": 10,

          "keepalive-interval": 30,

          "hold-time": 180,

          "minimum-advertisement-interval": 30

        }

      },

      "afi-safis": {

        "afi-safi": [

          {

            "afi-safi-name": "openconfig-bgp-types:IPV4-UNICAST"

          },

          {

            "afi-safi-name": "openconfig-bgp-types:IPV6-UNICAST"

          }

        ]

      },

      "route-reflector": {

        "config": {

          "route-reflector-client": false

        }

      },

      "transport": {

        "config": {

          "remote-port": 179,

          "mtu-discovery": false,

          "passive-mode": false

        }

      },

      "config": {

        "send-community": "NONE",

        "peer-as": 65504,

        "route-flap-damping": false,

        "peer-type": "INTERNAL"

      }

    }

  ]

}

 

If you need to advertise routes from ODL to XR you'll also want to set up the application peer.  For this you can do a POST to the same URL above (http://localhost:8181/restconf/config/openconfig-network-instance:network-instances/network-instance/global-bgp/protocols/protocol/openconfig-policy-types:BGP/example-bgp-rib/bgp-openconfig-extensions:bgp/neighbors) with a body of e.g:

 

{

  "bgp-openconfig-extensions:neighbor": [

    {

      "neighbor-address": "10.195.94.40",

      "config": {

        "peer-group": "application-peers"

      }

    }

  ]

}

 

So now we're ready to configure XR.

 

First let's configure the RIB.  So do a POST to:

 

http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/XR/yang-ext:mount/openconfig-bgp:bgp/global

 

with a body of e.g.:

 

{

  "global": {

    "config": {

      "as": 65504,

      "router-id": "10.195.94.67"

    },

    "afi-safis": {

      "afi-safi": [

        {

          "afi-safi-name": "openconfig-bgp-types:ipv4-unicast"

        },

        {

          "afi-safi-name": "openconfig-bgp-types:ipv6-unicast"

        }

      ]

    }

  }

}

 

(this won't work until that bug noted above is fixed)

 

So now we can add ODL as a peer on XR.  So do a POST to:

 

http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/XR/yang-ext:mount/openconfig-bgp:bgp/neighbors


with a body of e.g:


{

  "neighbor": [

    {

      "neighbor-address": "10.195.94.43",

        "config": {

          "peer-as": 65504,

          "neighbor-address": "10.195.94.43"

        },

        "afi-safis": {

          "afi-safi": [

            {

              "afi-safi-name": "openconfig-bgp-types:ipv4-unicast",

              "config": {

                "enabled": true,

                "afi-safi-name": "openconfig-bgp-types:ipv4-unicast"

              }

            },

            {

              "afi-safi-name": "openconfig-bgp-types:ipv6-unicast",

              "config": {

              "enabled": true,

                "afi-safi-name": "openconfig-bgp-types:ipv6-unicast"

              }

            }

          ]

        }

    }

  ]

}

 

(again this won't work until that bug noted above is fixed - or at least not if this is XR's first BGP neighbor)

 

at this point BGP ought to come up...

venue.JPG“It Just Got Real” was the theme of OpenDaylight Summit 2016, and it rang true throughout the entire summit. A great group of developers and end users came together to celebrate the accomplishments brought forth in the most recent release, Boron; share successes and lessons learned deploying OpenDaylight at large scale; and chart a course for making OpenDaylight even more solid and feature rich in the next release, Carbon. From start to finish, it was humbling and heartening to be a part of such a diverse group of talented and motivated individuals coming together to work passionately yet constructively on the networking platform that is OpenDaylight.

 

The summit opened Monday with a set of in depth tutorials and workshops. Two that I managed to catch where the FD.io Mini Summit and a series of sessions that focused on OpenStack and OpenDaylight Integration. One particularly encouraging aspect of the integration was the coming together or what had been multiple project specific NetVirt implementations into a single NetVirt project within OpenDaylight. Now we have a single project to which to contribute new functionality and enhancements.

 

The main conference was Tuesday and Wednesday. Neela Jacques, OpenDaylight Executive Director, kicked things off with his inspiring overview of the state of OpenDaylight. He highlighted several large and successful deployments of OpenDaylight, including those by AT&T, Comcast, TenCent. In speaking of the growing maturity and success of the project, he unveiled its “Secret Sauce”, its “Developer/User Intimacy and Collaboration”. devs.JPG

 

To hear more about how Tencent is using OpenDaylight, check out this keynote presentation by Tom Bie, VP Tencent.

In a later session, Brian Freeman went into more details on its Enhanced Control, Orchestration, Management and Policy (ECOMP) platform, a project AT&T plans to open source soon. It is based on OpenDaylight and serves as a great example of the power and flexibility gained by using YANG models not only for modeling network devices but also for modeling network services. att.png


Throughout the course of the conference, we enjoyed sharing with you all the open source applications we have built on top of OpenDaylight. OpenDaylight is truly a great platform for building a wide range of application, including networking aware apps and apps for IoT, as we demonstrated in our booth. In case you missed it or if you want to get your hands on the code, check out our OpenDaylight Apps page.


Near the end of the main conference agenda, I had the opportunity and pleasure to share with the OpenDaylight community the work that is going on in MEF Forum to standardize Lifecycle Service Orchestration (LSO) through the definition of a set of interface points and corresponding APIs. I teamed up with Pascal Menezes, MEF CTO, to deliver this talk and a call to action to the to the OpenDaylight Community to join us in our upcoming LSO Hackathon at MEF16.

 

OpenDaylight within Reference Implementation for Next Generation Network Services

talk.png


As the main conference wrapped up, the Developer Forum kicked into high gear. Wednesday night we had some fun and got to know one another better at a social event at a local bowling alley. I now know I am even worse at bowling than when I last bowled 10+ years ago. But not worry, I was in good company with much of the OpenDaylight Community. It is a good thing this group is better at coding than bowling. Of course, Neela, who must have had a hand in the selection of the venue, thrashed us all as he threw one strike after another.

 

Thursday witnessed the OpenDaylight Community asking itself hard questions, admitting its shortcoming, and demanding better of itself for the benefit of the OpenDaylight project and its growing community. For me, this brought things full circle to the keynote that kicked off the summit and the developer/user intimacy and collaboration of the OpenDaylight Community. I invite those of you who have not yet experienced OpenDaylight yet to dive in and get involved. I am pretty sure you will like what you find on personal, technical, and professional levels. I used what I learned at the summit to submit by first patch. It was reviewed, accepted, and integrated earlier this week - hurray!

 

For access to slides and recordings of all the session delivered by myself and my colleagues at this year’s summit, including tutorials on NETCONF/YANG and on BGP and PCEP, an introduction to FD.io, Composing Fast Data Stacks with OpenDaylight and OpenStack in OPNFV, and more, check out OpenDaylight Summit 2016 Presentations.

Screen Shot 2016-09-21 at 11.25.04 AM.png

Image compliments of http://events.linuxfoundation.org/events/opendaylight-summit

 

The OpenDaylight Summit is next week, September 26-29. Whether you are new to OpenDaylight, an experienced end user, a developer of network applications, or a core contributor to the OpenDaylight project itself, you will find a wealth of rewarding opportunities to learn, share, and network. I certainly plan to be there along with several other developers and experts from Cisco. We look forward to sharing what we know about OpenDaylight with you and are excited to learn from you and others as well. Here are some highlights.

 

Monday, September 26 - Tutorials


You can find more info here.

 

Tuesday - Wednesday, September 27-28, Main Conference

 

Tuesday

 

Wednesday

 

Wednesday - Thursday, September 28-29, Carbon Developer Design Summit


  • The developer community comes together to discuss designs and plans for the upcoming OpenDaylight release - Carbon.
  • Please note: Registration to the Summit (main conference) is required in order to attend the Developer Design Summit.
  • You can find more info here.

 

I will be around all week, including the tutorials and the design summit. I hope to see you there.

Get more info, including access to the complete schedule and registration site here.

for the basics of this please see my earlier blog post.

 

There are a couple of gotchas though mounting XR 6.0.x from ODL:

 

a) you need ODL Beryllium-SR2 or later as there was a bug in earlier versions where ODL would fail to handle the deviation that XR 6.0 and later announces against ietf-netconf-monitoring (because it's a basic NETCONF capability rather than a generic YANG model).

 

b) XR will initially fail to mount until you fix a YANG model issue in the cache.  There's a model (called Cisco-IOS-XR-wd-cfg.yang in XRv and ASR9K, and Cisco-IOS-XR-watchd-cfg.yang in XR9000v - and presumably other "Calvados"-based platforms) which imports Cisco-IOS-XR-config-mda-cfg.yang twice with 2 different prefixes.   That's not an error vs RFC6020 so I've raised a bug - 6249 - against ODL Yangtools to get it fixed.   At any rate the workaround for now is:

 

     (1) attempt to mount the device using RESTCONF.  This will fail.

     (2) go into the “cache/schema” directory under distribution-karaf-0.4.2-beryllium-SR2

     (3) edit the file “Cisco-IOS-XR-watchd-cfg@2015-11-09.yang” or "Cisco-IOS-XR-wd-cfg@2015-11-09.yang"

     (4) delete the line "  import Cisco-IOS-XR-config-mda-cfg { prefix "a1"; }” (be sure not to delete the line with a prefix of "node")

     (5) unmount the device using RESTCONF.

     (6) re-mount the device using RESTCONF.  This time it should succeed.

 

I've posted a bunch of scripts etc. to https://github.com/CiscoDevNet/opendaylight-setup

 

following the instructions there should enable you to get a Linux VM up and running with ODL (either directly, or using Vagrant).

 

I've focussed for now on NETCONF/YANG, BGP-LS and PCE-P as southbounds and with IOS XR as the NETCONF server.

 

The setup ought to work with local XR nodes, with VIRL, or with dCloud.

This is a short introduction to the opendaylight-startup-archetype which is the easiest way to get started writing an OpenDaylight MD-SAL application. An archetype creates a maven project from a template, giving you a working project to start from.

mvn archetype:generate \
-DarchetypeGroupId=org.opendaylight.controller \
-DarchetypeArtifactId=opendaylight-startup-archetype \
-DarchetypeVersion=1.0.3-Lithium-SR3 \
-DarchetypeRepository=http://nexus.opendaylight.org/content/repositories/opendaylight.release/
-DarchetypeCatalog=http://nexus.opendaylight.org/content/repositories/opendaylight.release/archetype-catalog.xml

Follow the prompts to set the project parameters. When I ran the archetype I called my project demoproject so the snippets I use will always reference demoproject. Let me explain the structure of the generated project and the purpose of each part.

 

Note that the default value for the 'version' property is 1.0-SNAPSHOT. This causes problems when you want to install the project into an OpenDaylight release such as Lithium-SR3 because it is configured to ignore snapshots. If you set the 'version' property to 1.0 then the generated artifacts will work.

 

This is the structure of the generated project:

api  # contains the YANG model for your project
  |-- src/main/yang/demoproject.yang
  `-- pom.xml
impl # contains the project implementation
  |-- src/main/java
  | |-- com/cisco/impl/DemoProvider.java
  | `-- org/.../demoproject/impl/rev141210/DemoModule.java # Your module init class
  |-- src/main/yang/demoproject-impl.yang # YANG definition for your module config
  |-- src/main/config/default-config.xml  # Your module config file
  `-- pom.xml
features # contains the feature definition for Karaf
  |-- src/main/features/features.xml # defines features that can be installed in karaf
  `-- pom.xml
artifacts # maven project that includes all artifacts required by project
  `-- pom.xml # references demoproject-api, demoproject-impl, demoproject-features
karaf # maven project that builds an OpenDaylight karaf distribution
  `-- pom.xml # includes odl-demoproject-ui in the list of karaf local features

Without changing anything in the generated project, you can build the project and then run the generated Karaf distribution:

% cd demoproject
% mvn install
% ./karaf/target/assembly/bin/karaf

    ________                      ________                .__  .__      .__    __     
    \_____  \ ______  ____  ____ \______ \ _____  ___.__.|  | |__| ____ |  |___/  |_   
    /  |  \\____ \_/ __ \ /    \ |    |  \\__  \<  |  ||  | |  |/ ___\|  |  \  __\   
    /    |    \  |_> >  ___/|  |  \|    `  \/ __ \\___  ||  |_|  / /_/  >  Y  \  |     
    \_______  /  __/ \___  >___|  /_______  (____  / ____||____/__\___  /|___|  /__|     
            \/|__|        \/    \/        \/    \/\/            /_____/      \/         
                                                                                   

Hit '<tab>' for a list of available commands
and '[cmd] --help' for help on a specific command.
Hit '<ctrl-d>' or type 'system:shutdown' or 'logout' to shutdown OpenDaylight.

opendaylight-user@root>feature:list | grep demoproject
odl-demoproject-api  | 1.0-SNAPSHOT | x  | odl-demoproject-1.0-SNAPSHOT | OpenDaylight :: demoproject :: api
odl-demoproject      | 1.0-SNAPSHOT | x  | odl-demoproject-1.0-SNAPSHOT | OpenDaylight :: demoproject
odl-demoproject-rest | 1.0-SNAPSHOT | x  | odl-demoproject-1.0-SNAPSHOT | OpenDaylight :: demoproject :: REST
odl-demoproject-ui  | 1.0-SNAPSHOT | x  | odl-demoproject-1.0-SNAPSHOT | OpenDaylight :: demoproject :: UI

As you can see, there are 4 features instlalled in karaf from my project. These features are define in the features.xml file. Features are a karaf concept that make it easier to install multiple OSGi bundles and their dependencies. A features.xml file is a "Feature Repository" which can contain multiple feature definitions. Here is the features.xml file with inline comments:

<?xml version="1.0" encoding="UTF-8"?>
<features name="odl-demoproject-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
  <!--
    Karaf features are defined in repositories. In order to reference a feature, you first need to
    declare its repository location. Repositories are just feature definition files that are stored
    in a Maven repo.
  -->
  <repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
  <repository>mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features</repository>
  <repository>mvn:org.opendaylight.controller/features-restconf/${mdsal.version}/xml/features</repository>
  <!--
    The odl-demoproject-api feature references the odl-yangtools-models as a dependency and
    adds the demoproject-api bundle. This feature just installs the model into karaf.
  -->
  <feature name='odl-demoproject-api' version='${project.version}' description='OpenDaylight :: demoproject :: api'>
    <feature version='${yangtools.version}'>odl-yangtools-models</feature>
    <bundle>mvn:com.cisco/demoproject-api/${project.version}</bundle>
  </feature>
  <!--
    The odl-demoproject feature references mdsal and the odl-demoproject-api features.
    It adds the demoproject-impl bundle. It also adds a configfile that tells OpenDaylight how
    to start this feature.
  -->
  <feature name='odl-demoproject' version='${project.version}' description='OpenDaylight :: demoproject'>
    <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
    <feature version='${project.version}'>odl-demoproject-api</feature>
    <bundle>mvn:com.cisco/demoproject-impl/${project.version}</bundle>
    <configfile finalname="${configfile.directory}/demoproject.xml">mvn:com.cisco/demoproject-impl/${project.version}/xml/config</configfile>
  </feature>
  <!--
    This feature references the odl-demoproject and odl-restconf features.
    It ensures that the necessary features get installed to allow you to call your application via RESTCONF
  -->
  <feature name='odl-demoproject-rest' version='${project.version}' description='OpenDaylight :: demoproject :: REST'>
    <feature version="${project.version}">odl-demoproject</feature>
    <feature version="${mdsal.version}">odl-restconf</feature>
  </feature>
  <!--
    This feature references the odl-demoproject-rest feature and also MD-SAL apidocs and xsql features.
    It ensures that the necessary features get installed to allow API doc UI to work for your project.
  -->
  <feature name='odl-demoproject-ui' version='${project.version}' description='OpenDaylight :: demoproject :: UI'>
    <feature version="${project.version}">odl-demoproject-rest</feature>
    <feature version="${mdsal.version}">odl-mdsal-apidocs</feature>
    <feature version="${mdsal.version}">odl-mdsal-xsql</feature>
  </feature>
</features>

You can install your application into a separate OpenDaylight runtime such as the Lithium-SR3 distribution. The maven project builds a Karaf "kar" file in features/target/demoproject-features-1.0.kar which can be copied into the karaf deploy directory:

% cp demoproject/features/target/demoproject-features-1.0.kar distribution-karaf-0.3.3-Lithium-SR3/deploy

Note that the OpenDaylight Lithium-SR3 distribution is configured to ignore snapshots so it is important that your project does not have a version like 1.0-SNAPSHOT.

Screen Shot 2016-01-31 at 9.53.37 PM.pngCisco is a founding member, leading contributor, and passionate supporter of the OpenDaylight open source project. OpenDaylight is an open source platform for building programmable, software-defined networks. Back in April 2013, Cisco made headlines and jump started the project by contributing its ONE Controller. Even more important is the ongoing involvement and support by Cisco contributors at all levels of the project, e.g. on the Board of Directors, members of the Technical Steering Committee, project leads, code contributors, code reviewers, and organizers of boot camps and hackathons.

 

The latest evidence of Cisco’s commitment to OpenDaylight is the newly launched OpenDaylight microsite on DevNet. The microsite exists to help developers like you quickly and easily grasp what OpenDaylight is all about, Cisco’s role in the OpenDaylight community, and Cisco products and platforms that help you build your own applications and solutions on top of OpenDaylight.

 

Here are some examples of what you will find on the microsite:

  • learning labs that walk you through an introduction to OpenDaylight
  • recordings of talks on various topics related to OpenDaylight  given by Cisco experts at recent conferences
  • sample application and source code that illustration what you can do with OpenDaylight and how to use its programmatic interfaces
  • sandbox environments in which you can experiment with OpenDaylight on your own
  • a community of enthusiastic experts with whom you can discuss ideas and get answers to your burning questions about Cisco’s contributions to and use of OpenDaylight

 

Better still, we encourage you to come see us in the DevNet Zone at CiscoLive Berlin, February 15-19, where we have a full lineup of OpenDaylight related content, including the following sessions:

Screen Shot 2016-02-01 at 1.11.56 PM.png

  • Using BGP, PCE-P and BMP with the OpenDaylight [DevNet-1251]
  • OpenDaylight: 2 Workload Orchestrators, One Policy [DevNet-1250]
  • Introduction to YANG Data Models and Their Use in OpenDaylight [DevNet-1083]
  • OpenStack and OpenDaylight, the Evolving Relationship in Cloud Networking [DevNet-1105]
  • SDN WAN Apps Developments [DevNet-1090]
  • DevNet Workshop: Open SDN Controller [DevNet-1676]
  • Service Chaining Verification [DevNet-1084]

 

You can also count on hands on demos in the DevNet Zone that showcase OpenDaylight solutions and give you access to OpenDaylight experts on site.

 

Register today! Multiple registration options are available. The Explorer Pass gives you access to the DevNet Zone the entire week.

So first off you need to install kvm/qemu 2.0 or better.

 

then create a separate .vmdk file for each XRv or CSR1Kv instance (as config etc. will be written to the files they need to be read/write and be separate files per virtual router).

 

A script for running XRv will look something like:

 

sudo qemu-system-x86_64 -daemonize -display none -enable-kvm -machine accel=kvm -smp cores=2 -m 4096 \

  -hda /home/xrvr/xrvr-images/XRv.vmdk \

  -serial telnet::9101,server,nowait -serial telnet::9102,server,nowait \

  -net nic,model=virtio,vlan=0,macaddr=00:22:00:ff:0A:00 -net tap,vlan=0,script=/etc/qemu-ifup \

  -net nic,model=virtio,vlan=1,macaddr=00:22:00:ff:0A:01 -net socket,vlan=1,listen=127.0.0.1:10000 \

  -net nic,model=virtio,vlan=4,macaddr=00:22:00:ff:0A:02 -net socket,vlan=2,connect=127.0.0.1:20000


Note the following:


1) KVM/QEMU needs to run as sudo

2) you need to be daemonized/no display (as this will run in the background)

3) you need KVM machine accel enabled (or performance will suck royally)

4) for XRv I find dual cores and 4G of RAM works well.  CSR1Kv seems ok with 2G and one core.

5) you need to supply two local telnet ports for console and aux.

6) the first vNIC on XRv will be MgmtEth0/0/CPU0/0.  The others will be GigabitEthernet0/0/0/0, GigabitEthernet0/0/0/1 etc.  On CSR1Kv the NICs are numbered GigabitEthernet1, GigabitEthernet2 and so on.

7) using -net tap creates a bridged interface.  there should already be a qemu-ifup script for br0.  We typically set the host up to bind an address to br0 and then bind br0 to eth0.  Then the management IPs for the XRv nodes can be on the same subnet as the host.

8) listen/connect are for TCP connections between devices.  For those you need to start the "listen" end before the "connect" end.   There's also an option to use multicast but that seems to have issues (e.g. with packets being sent back to the host that sent them).  I generally find it easiest to have a priority order of nodes and to start them in reverse priority (so the first node only listens and the last one only connects).

 

when you start an XRv node for the first time you need to assign login credentials to it.  You'll also find (once it finishes configuring itself) that the interfaces are all disabled and that there's no other config.  So you need to go into the config, unshut all the interfaces and add an address to the management interface before you can start loading up configs using TFTP etc.

 

when you start a CSR1Kv node for the first time it has cisco/cisco login credentials, no config, and all interfaces shut.  so again you'll need to add credentials, unshut the interfaces, and add an IP to GigabitEthernet1.   Of course on CSR1Kv you need to "wr mem" to apply any config changes.



First off we need to distinguish between the OpenDaylight and Cisco OSC API structure.

 

In OpenDaylight the restconf API is at http://controller-ip:8181/restconf  (replace controller-ip with your own controller's IP!)

 

In Cisco Open SDN Controller (OSC) the restconf API is at https://controller-ip/controller/restconf

 

So then there are 3 types of restconf data:

1) config - at restconf/config

2) operational (state data) - at restconf/operational

3) RPCs - at restconf/operations

 

The next thing to be aware of is that whenever you see a URL component (i.e. text between two slashes) that has a colon in then that data is interpreted as yang-module:top-level-data-item.

 

In this post I will focus on working with network topologies (and in particular on the NETCONF topology/inventory and how we can use that to configure the controller itself), but the basic ideas here are applicable to other parts of the restconf API.

 

All topology/inventory is under network-topology:network-topology.   If you look at network-topology.yang you will see it has a top level container called "network-topology".    Note that there are 2 versions of network-topology.yang in ODL - network-topology@2013-07-12.yang  and network-topology@2013-10-21.yang.  These correspond to draft-clemm-netmod-yang-network-topo-00 and draft-clemm-netmod-yang-network-topo-01.   Those drafts have now expired - the current equivalent is draft-ietf-i2rs-yang-network-topo-01.  Once that makes it to RFC we'd expect ODL to support it.

 

So e.g. to get all operational topologies you can go to "...restconf/operational/network-topology:network-topology"

 

The network-topology container in network-topology.yang contains a list called "topology".    To get a list entry in RESTCONF you need to give the list name and then a value for the list key.   The key to the topology list is the topology ID.  So, for example to get the NETCONF inventory in Lithium or later you need to add "/topology/topology-netconf" to the URL above.

 

(Note that in Hydrogen and Helium the NETCONF inventory was at opendaylight-inventory:nodes and that still works in Lithium, but will no longer work from Beryllium).

 

Note that each individual topology may augment the base IETF topology model.  So e.g. for PCE-P there's a yang model - network-topology-pcep.yang which augments the topology with PCE-P specific attributes and which adds 3 RPCs for add-lsp, update-lsp and remove-lsp.  So e.g. to add an LSP you can POST to "..restconf/operations/network-topology:network-topology/topology/pcep-topology/add-lsp" with the appropriate body.

 

So in the topology-netconf case the next thing to do is generally to select the node from the topology.    A topology contains a list of nodes and a list of links.   The list of nodes is called "node" and the key is the node-ID.  So to access e.g. the OpenDaylight config subsystem you add "/node/controller-config".

 

The OpenDaylight config subsystem is a special case of a netconf node.  It is part of OpenDaylight itself and it listens on port 1830.  So if you do a “netstat -an” on your ODL instance you ought to see a local connection on port 1830.

 

OpenDaylight also listens on port 830 but provides only limited model support there.

 

You can also configure ODL to listen on port 2830 if you enable the feature odl-netconf-mdsal.   In that instance ODL exposes the same set of models over NETCONF as over RESTCONF.

 

Now for any netconf node if you want to access models exposed by that node over RESTCONF you need to add “/yang-ext:mount”.

 

so if you go to ../restconf/operational/network-topology:network-topology/topollogy/topology-netconf/node/controller-config you will see all the models exposed by the config subsystem.

 

from the above URL you can see that the config subsystem exposes the "config" model.   That model has a top level container called modules.  So now you can add "/config:modules".

 

The modules container contains a list of “module” with a key of “type name”.  so you need to add something of the form “/module/type/name” to select a specific module (in RESTCONF when a list has multiple keys you put slashes between them).    One challenge here is that the type is typically defined in a different module somewhere.

 

so for example if you want to get the configuration of the ODL BGP RIB then the the type is "rib-impl" but it's defined in odl-bgp-rib-impl-cfg.yang.  We typically call our own RIB "example-bgp-rib" (that's the name given in the 41-bgp-example.xml file).  So you need to add "/module/odl-bgp-rib-impl-cfg:rib-impl/example-bgp-rib"

 

So the final URL is ../restconf/config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules/module/odl-bgp-rib-impl-cfg:rib-impl/example-bgp-rib".  (Note this is config, not operational).

 

Easy, wasn't it?

 

Not if you want to modify that RIB you need to do a PUT to that same URL with a modified body.  POST worked for Hydrogen/Helium but as of Lithium it's only possible to use POST to add new data, not to modify existing data.

First off ensure you have a "new" XRv or ASR9K load (XR 6.0 or later) and a "new" ODL (Beryllium or later).


Then ensure ODL is running the BGP and PCEP features (by doing "feature:install odl-bgpcep-bgp-all" and "feature:install odl-bgpcep-pcep-all").

 

Configure BGP on ODL.  You have two options here:

  • modify ~/etc/opendaylight/karaf/41-bgp-example.xml.
    • change the local BGP RIB info.  Search for "example-bgp-rib" and change the "local-as" and "bgp-rib-id" values to be your local AS and ODL's IP address.
    • add the peer for XRv (one of your XRv nodes needs to be the BGP speaker).  Look for the "example-bgp-peer" module, remove the comments around it, and edit the IP address.
    • (optionally).  If you want XR to be in a different ASN to ODL then add "<peer-role>ebgp</peer-role>" and "<remote-as>XXX</remote-as>" (replacing "XXX" with XR's ASN).
    • (optionally).  If you want ODL to listen on port 179 (so it can accept inbound connections from XR) then search for "binding-port" and modify the port to be 179 instead of 1790.  Note that you'll need to run ODL as root for this to work.
    • do an rm -rf on ODL's ~/data and ~/etc/opendaylight/current directories and restart ODL for the changes to take effect.
  • PUTting the config from e.g. postman.


1) PUT the RIB:  So e.g. PUT to http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules/module/odl-bgp-rib-impl-cfg:rib-impl/example-bgp-rib with:

{ "module" : [

        {

            "type": "odl-bgp-rib-impl-cfg:rib-impl",

            "name": "example-bgp-rib",

            "odl-bgp-rib-impl-cfg:bgp-rib-id": "10.0.0.1",

            "odl-bgp-rib-impl-cfg:bgp-dispatcher": {

                "type": "odl-bgp-rib-impl-cfg:bgp-dispatcher",

                "name": "global-bgp-dispatcher"

            },

            "odl-bgp-rib-impl-cfg:extensions": {

                "type": "odl-bgp-rib-spi-cfg:extensions",

                "name": "global-rib-extensions"

            },

            "odl-bgp-rib-impl-cfg:tcp-reconnect-strategy": {

                "type": "protocol-framework:reconnect-strategy-factory",

                "name": "example-reconnect-strategy-factory"

            },

            "odl-bgp-rib-impl-cfg:rib-id": "example-bgp-rib",

            "odl-bgp-rib-impl-cfg:session-reconnect-strategy": {

                "type": "protocol-framework:reconnect-strategy-factory",

                "name": "example-reconnect-strategy-factory"

            },

            "odl-bgp-rib-impl-cfg:local-table": [

                {

                    "type": "odl-bgp-rib-impl-cfg:bgp-table-type",

                    "name": "ipv4-unicast"

                },

                {

                    "type": "odl-bgp-rib-impl-cfg:bgp-table-type",

                    "name": "ipv6-unicast"

                },

                {

                    "type": "odl-bgp-rib-impl-cfg:bgp-table-type",

                    "name": "linkstate"

                },

                {

                    "type": "odl-bgp-rib-impl-cfg:bgp-table-type",

                    "name": "ipv4-flowspec"

                },

                {

                    "type": "odl-bgp-rib-impl-cfg:bgp-table-type",

                    "name": "ipv6-flowspec"

                },

                {

                    "type": "odl-bgp-rib-impl-cfg:bgp-table-type",

                    "name": "labeled-unicast"

                }

            ],

            "odl-bgp-rib-impl-cfg:data-provider": {

                "type": "opendaylight-md-sal-binding:binding-async-data-broker",

                "name": "pingpong-binding-data-broker"

            },

            "odl-bgp-rib-impl-cfg:dom-data-provider": {

                "type": "opendaylight-md-sal-dom:dom-async-data-broker",

                "name": "pingpong-broker"

            },

            "odl-bgp-rib-impl-cfg:codec-tree-factory": {

                "type": "opendaylight-md-sal-binding:binding-codec-tree-factory",

                "name": "runtime-mapping-singleton"

            },

            "odl-bgp-rib-impl-cfg:local-as": 64496

        }

    ]

}

(remember to change the IP address for the bgp-rib-id, and if needed the local-as)

(also note that for ODL Beryllium and later the "flowspec" stanza is replaced by separate "ipv4-flowspec" and "ipv6-flowspec" stanzas, though of course you only need to include the address families you plan to use.  The same applies to the peer config below).

 

2) PUT the peer - as above only one of the XR nodes needs to speak BGP.  Note that you only need to enable the address families that you wish to use (they are listed under "advertized-table").


So e.g. PUT to http://localhost:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules/module/odl-bgp-rib-impl-cfg:bgp-peer/example-bgp-peer with:

{ "module" : [

        {

            "type": "odl-bgp-rib-impl-cfg:bgp-peer",

            "name": "example-bgp-peer",

            "odl-bgp-rib-impl-cfg:host":"10.0.0.2",

            "odl-bgp-rib-impl-cfg:initiate-connection": true,

            "odl-bgp-rib-impl-cfg:rib": {

                "type": "odl-bgp-rib-impl-cfg:rib-instance",

                "name": "example-bgp-rib"

            },

            "odl-bgp-rib-impl-cfg:peer-registry": {

                "type": "odl-bgp-rib-impl-cfg:bgp-peer-registry",

                "name": "global-bgp-peer-registry"

            },

            "odl-bgp-rib-impl-cfg:advertized-table": [

                {

                    "type": "odl-bgp-rib-impl-cfg:bgp-table-type",

                    "name": "ipv4-unicast"

                },

                {

                    "type": "odl-bgp-rib-impl-cfg:bgp-table-type",

                    "name": "linkstate"

                }

            ]

        }

    ]

}

(again remember to change the IP address for the host)

 

Now configure BGP on XRv.  So e.g.

 

router bgp 64496

bgp router-id 10.0.0.2

address-family link-state link-state

!

neighbor 10.0.0.1

  remote-as 64496

  address-family link-state link-state

!

 

Ensure XRv also has ISIS or OSPF routes distributed into BGP-LS using the following command within ISIS or OSPF:

 

distribute bgp-ls

 

Now verify that the BGP session comes up.  In ODL you ought to be able to do a GET on e.g.: http://localhost:8181/restconf/operational/network-topology:network-topology/topology/example-linkstate-topology and see BGP-LS topology info.


Now configure PCE-P on all of your XRv instances.  under "mpls traffic-eng" you want something like:


pce

  peer ipv4 10.0.0.1

  !

  stateful-client

  instantiation

  delegation

  !

!

auto-tunnel pcc

  tunnel-id min 101 max 200


Note that for PCE-P to come up your ODL instance will need to be able to route back to the loopback addresses in your XRv network.  If those are e.g. in 192.168.0.0/24 then go to the ODL host and do something like:


sudo route add -net 192.168.0.0/24 gw 10.0.0.2


if you want this to persist after a reboot then edit /etc/network/interfaces (this is assuming Ubuntu) and add:


up route add -net 192.168.0.0/24 gw 10.0.0.2


Alternatively you can configure XR to use a different source interface for PCE-P using "mpls traffic-eng pce peer source ipv4 a.b.c.d" and selecting e.g. the address of the management interface.


Then check PCE-P has come up on ODL by looking at e.g. http://localhost:8181/restconf/operational/network-topology:network-topology/topology/pcep-topology.  You should see a list of PCE-P nodes.  If not then look for ESTABLISHED inbound connections to port 4189 on the ODL host and if they're missing then verify you can ping the router loopbacks and that there are no filters in e.g. iptables blocking inbound connections.


Having done all this you can start adding LSPs etc.

 

There are two modes for PCE-P LSPs

 

Firstly the LSP may be configured in XR and delegated to PCE-P.  So the LSP will be configured something like:

 

interface tunnel-te1

ipv4 unnumbered Loopback0

signalled-name foo

autoroute announce

!

destination 192.168.0.4

pce

  delegation

!

!

 

So then the LSP can be brought up by using the update-lsp RPC (http://localhost:8181/restconf/operations/network-topology-pcep/update-lsp):

 

{

    "input" : {

        "node" : "pcc://192.168.0.1",

        "name" : "foo",

        "network-topology-ref": "/network-topology:network-topology/network-topology:topology[network-topology:topology-id=\"pcep-topology\"]",

        "arguments": {

            "lsp": {

                "administrative": "true",

                "delegate": "true"

            },

            "ero" : {

                "subobject" : [

                    {

                        "loose" : "false",

                        "ip-prefix" : { "ip-prefix" : "192.168.99.2/32" }

                    },

                    {

                        "loose" : "false",

                        "ip-prefix" : { "ip-prefix" : "192.168.0.4/32" }

                    }

                ]

            }

        }

    }

}

 

(note that there will be one sub-object per link the LSP traverses - using the address of the far end of the link - plus one for the loopback address of the egress router).

 

The response to the RPC should be empty (i.e. '{ "output": {} }').

 

Once you have done this the LSP should be visible under the PCC in the pcep-topology, or by doing a "show mpls traffic-eng tunnels" in XR.

 

Alternatively the LSP may be created/deleted dynamically by ODL using the add-lsp RPC (http://localhost:8181/restconf/operations/network-topology-pcep/add-lsp):

 

{

    "input": {

        "node": "pcc://192.168.0.1",

        "name": "bar",

        "network-topology-ref": "/network-topology:network-topology/network-topology:topology[network-topology:topology-id=\"pcep-topology\"]",

        "arguments": {

            "odl-pcep-ietf-stateful07:lsp" : {

                "delegate" : "true",

                "administrative" : "true"

            },

            "endpoints-obj": {

                "ipv4": {

                    "source-ipv4-address": "192.168.0.1",

                    "destination-ipv4-address": "192.168.0.4"

                }

            },

            "ero" : {

                "subobject" : [

                    {

                        "loose" : "false",

                        "ip-prefix" : {

                            "ip-prefix" : "192.168.99.2/32"

                        }

                    },

                    {

                        "loose" : "false",

                        "ip-prefix" : {

                            "ip-prefix" : "192.168.0.4/32"

                        }

                    }

                ]

            }

        }

    }

}

 

Again the LSP should then be visible in the pcep-topology and in XR.  In XR the tunnel number will be in the range given in the MPLS-TE config for dynamic tunnels.

 

you can still update the LSP (e.g. to change path or to add bandwidth) using update-lsp:

 

{

    "input" : {

        "node" : "pcc://192.168.0.1",

        "name" : "bar",

        "network-topology-ref": "/network-topology:network-topology/network-topology:topology[network-topology:topology-id=\"pcep-topology\"]",

        "arguments": {

            "lsp": {

                "administrative": "true",

                "delegate": "true"

            },

            "bandwidth": {

                "bandwidth": "QvoAAA=="

            },

            "ero" : {

                "subobject" : [

                    {

                        "loose" : "false",

                        "ip-prefix" : { "ip-prefix" : "192.168.99.2/32" }

                    },

                    {

                        "loose" : "false",

                        "ip-prefix" : { "ip-prefix" : "192.168.0.2/32" }

                    }

                ]

            }

        }

    }

}

 

(note that a full ERO must still be given even if not changing the path).

 

you can then delete the LSP if required using the remove-lsp RPC (http://localhost:8181/restconf/operations/network-topology-pcep/remove-lsp):

 

{

    "input" : {

        "node" : "pcc://192.168.0.1",

        "name" : "bar",

        "network-topology-ref": "/network-topology:network-topology/network-topology:topology[network-topology:topology-id=\"pcep-topology\"]"

    }

}

 

Note that one constraint with ODL is that dynamically-generated LSPs don't support autoroute (as autoroute isn't part of the standard).  But there are Cisco-proprietary extensions available (e.g. in Cisco OSC) to enable that.  E.g. include the following within "arguments", "lsp":

 

                    "tlvs" : {

                        "vs-tlv" : {

                            "enterprise-number" : 9,

                            "pcep-cisco-specific:fcid" : 1

                        }

                    }

 

(you'll also need to configure "mpls traffic-eng pce stateful-client cisco-extension" on XR)

 

Enjoy!

First ensure that you're running XR 5.3 or later.


Then ensure that in XR you've done "crypto key generate dsa" and that your config contains:

 

netconf-yang agent

     ssh

!

ssh server v2

ssh server netconf port 830

 

note that on XR 5.3.0 you'll see:

 

ssh server v2

ssh server netconf port 830

netconf-yang agent ssh

 

Then use Postman or RESTClient to POST to http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/controller-config/yang-ext:mount/config:modules:

 

{

    "config:module": [

        {

            "type": "odl-sal-netconf-connector-cfg:sal-netconf-connector",

            "name": "xrv",

            "odl-sal-netconf-connector-cfg:address": "172.23.29.125",

            "odl-sal-netconf-connector-cfg:port": 830,

            "odl-sal-netconf-connector-cfg:username": "cisco",

            "odl-sal-netconf-connector-cfg:password": "cisco",

            "odl-sal-netconf-connector-cfg:tcp-only": false,

            "odl-sal-netconf-connector-cfg:binding-registry": {

                "type": "opendaylight-md-sal-binding:binding-broker-osgi-registry",

                "name": "binding-osgi-broker"

            },

            "odl-sal-netconf-connector-cfg:between-attempts-timeout-millis": 2000,

            "odl-sal-netconf-connector-cfg:processing-executor": {

                "type": "threadpool:threadpool",

                "name": "global-netconf-processing-executor"

            },

            "odl-sal-netconf-connector-cfg:max-connection-attempts": 0,

            "odl-sal-netconf-connector-cfg:sleep-factor": 1.5,

            "odl-sal-netconf-connector-cfg:client-dispatcher": {

                "type": "odl-netconf-cfg:netconf-client-dispatcher",

                "name": "global-netconf-dispatcher"

            },

            "odl-sal-netconf-connector-cfg:dom-registry": {

                "type": "opendaylight-md-sal-dom:dom-broker-osgi-registry",

                "name": "dom-broker"

            },

            "odl-sal-netconf-connector-cfg:event-executor": {

                "type": "netty:netty-event-executor",

                "name": "global-event-executor"

            },

            "odl-sal-netconf-connector-cfg:connection-timeout-millis": 20000

        }

    ]

}

 

note that you'll need to change the IP address above - and potentially the name, port, username and password.

 

also note that for Cisco OSC the URL is different:

 

https://localhost/controller/restconf/config/opendaylight-inventory:nodes/node/controller-config/yang-ext:mount/config:modules.

 

and also note that from Lithium this is also available at:

 

http://localhost8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/controller-config/yang-ext:mount/config:modules

 

and finally note that from Beryllium the older "opendaylight-inventory" will no longer be supported.


One thing to remember for ODL is you need the right set of features installed to get ODL to connect to its own NETCONF NBI for config and to then be able to connect to XR.  odl-mdsal-broker, odl-restconf and odl-netconf-connector-ssh should suffice.  For Cisco OSC those features will all be pre-installed.

 

After you post the config you can then do a GET to:

 

http://localhost:8181/restconf/operational/opendaylight-inventory:nodes/node/xrv  (assuming your XR node is called xrv) to check that the node has mounted ok (it may take a few seconds to mount).

 

once XR mounts you should see something like:

 

{

}