cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
759
Views
0
Helpful
3
Replies

ydk-cpp query for a list of available interfaces can only return one value

EricMonson
Level 1
Level 1

-----  Update 5/22/2020 -------

 

Did some more debugging today. It appears that this is just a bug in the ydk-cpp codebase. What I've come to find out is that the yang to c++ code generator creates the following code for the InterfaceConfigurations constructor:

Cisco_IOS_XR_ifmgr_cfg_0.cpp
121 InterfaceConfigurations::InterfaceConfigurations() 122 : 123 interface_configuration(this, {"active", "interface_name"})

You'll notice that the key "interface-name" was modified to "interface_name". This is why the YList::build_key function only considers "active" as part of the key. The in value_str.cpp:298, the line: 'if (ylist_key == name_leaf_data.first)' ends up evaluating to 'if( "interface_name" == "interface-name")' ... which fails. This appears to be the root cause of the issue. I don't understand the code base well enough to know why the key was given an underscore instead of a hypen in the autogenerated code.

 

Any help would greatly be appreciated.

 

----- End Update --------------

 

 

Hi all,

 

I'm completely new to the NETCONF/YANG paradigm. I'm trying to get my feet wet just by doing a simple task of querying all the available interfaces off of an NCS55A2 (cisco_ios_xr 7.0.1). I'm trying to use the ydk-cpp framework for doing it. I'm using the following code:

 

NetconfServiceProvider provider{"ip_address", "username", "password", 830};
try   
{     
  auto intf_filter = make_shared<cisco_ios_xr::Cisco_IOS_XR_ifmgr_cfg::InterfaceConfigurations>();
  CrudService crud_service{};
  auto intf_read = crud_service.read( provider, *intf_filter );
  if(intf_read == nullptr)
  {
      cout << "=================================================="<<endl;
      cout << "No entries found"<<endl<<endl;
      cout << "=================================================="<<endl;
      return 0;
  }

  auto intf_read_ptr = dynamic_cast<cisco_ios_xr::Cisco_IOS_XR_ifmgr_cfg::InterfaceConfigurations*>(intf_read.get());
  cout << "Number of interfaces: " << intf_read_ptr->interface_configuration.len() << endl;

...

 

Since debugging is turned on, I see the following request go out to the networking element:

<?xml version="1.0"?>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
  <get>
    <filter>
      <interface-configurations xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"/>
    </filter>
  </get>
</rpc>

Beautiful. In addition to a whole log of debug logs, I see the following snippet come back:

 

<?xml version="1.0"?>
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
  <data>
    <interface-configurations xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg">
...
      <interface-configuration>
        <active>act</active>
        <interface-name>TenGigE0/0/0/0</interface-name>
        <shutdown/>
      </interface-configuration>
      <interface-configuration>
        <active>act</active>
        <interface-name>TenGigE0/0/0/1</interface-name>
        <shutdown/>
      </interface-configuration>
      <interface-configuration>
        <active>act</active>
        <interface-name>TenGigE0/0/0/2</interface-name>
        <shutdown/>
      </interface-configuration>
      <interface-configuration>
        <active>act</active>
        <interface-name>TenGigE0/0/0/3</interface-name>
        <shutdown/>
      </interface-configuration>
...

Again ... beautiful. It appears that I've pulled off the information that I wanted from the network device.

 

However, my debug cout statement always returns:

Number of interfaces: 1

 

In stepping through this, it appears that the YList object appends children in an interesting way. It builds a "key", which happens to be the very first leaf attribute returned by the query:

value_list.cpp
290 string
291 YList::build_key(shared_ptr<Entity> ep)
292 {
293     ostringstream value_buffer;
294     string key;
295     vector< pair<string, LeafData> > name_leaf_data_vector = ep->get_name_leaf_data();
296     for (auto ylist_key : ylist_key_names) {
297         for (auto name_leaf_data : name_leaf_data_vector) {
298             if (ylist_key == name_leaf_data.first) {
299                 key = value_buffer.str();
300                 if (key.length() > 0) {
301                     value_buffer << ",";
302                 }
303                 value_buffer << name_leaf_data.second.value;
304                 break;
305             }
306         }
307     }
308     key = value_buffer.str();
309     if (key.length() == 0) {
310         // No key list or no matching key, use internal counter
311         counter++;
312         value_buffer << counter;
313         key = value_buffer.str();
314     }
315     return key;
316 }

As you notice above from the query results, the first attribute returned is always: <active>act</active>

 

This means that every interface is hashed to the same key of "act" and as each one is added to the list, it overrides the previous one. This results in just being able to grab the very last interface reported by the device.

 

Am I doing something completely wrong. Sorry for the novice question. This really is the first time I've tried working with NETCONF / ydk-cpp.

 

Thanks in advance for any help you can provide.

Eric

1 Accepted Solution

Accepted Solutions

yangorelik
Spotlight
Spotlight

Hi Eric

Good catch!!

Indeed this is a bug. I have opened on your behalf GitHub issue #997. Please feel free to add any comments.

I found and fixed the bug and currently testing the YDK. I will get back to you, when the fix is ready for deployment.

Yan Gorelik
YDK Solutions

View solution in original post

3 Replies 3

yangorelik
Spotlight
Spotlight

Hi Eric

Good catch!!

Indeed this is a bug. I have opened on your behalf GitHub issue #997. Please feel free to add any comments.

I found and fixed the bug and currently testing the YDK. I will get back to you, when the fix is ready for deployment.

Yan Gorelik
YDK Solutions

Yan,

Thanks for jumping on that so quickly. I really appreciate you taking the time to fix this.

Eric

Hi Eric

I am glad to inform you that I fixed the issue, tested and committed the code to my private fork. 

In order to get the fix please follow this procedure:

# 1. Clone the git repository to your working space:
git clone https://github.com/ygorelik/ydk-gen.git -b 0.8.4.post1
cd ydk-gen

# 2. Generate and install libydk library (needs sudo access):
./generate.py --libydk -is

# 3. Generate and install Model API bundle package(s) for C++:
./generate.py --bundle profiles/bundles/<name-of-profile>.json --cpp -is

# 4. Recompile and run your application.

 Please let me know how it goes.

Yan Gorelik
YDK Solutions