05-21-2020 04:21 PM - edited 05-22-2020 08:19 AM
----- 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
Solved! Go to Solution.
05-22-2020 12:28 PM
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.
05-22-2020 12:28 PM
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.
05-26-2020 05:15 AM
Yan,
Thanks for jumping on that so quickly. I really appreciate you taking the time to fix this.
Eric
05-26-2020 11:22 AM
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.
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide