[NETCONF-744] Read whole leaf-list using get/get-config RPC Created: 26/Nov/20  Updated: 12/May/21  Resolved: 12/May/21

Status: Resolved
Project: netconf
Component/s: netconf
Affects Version/s: Aluminium
Fix Version/s: Aluminium SR4, 1.13.2

Type: Bug Priority: High
Reporter: Jaroslav Tóth Assignee: Jaroslav Tóth
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Hi,

I tried to read whole leaf-list using plain SSH and chunking mechanism. Example ("extraIpPorts" is described by leaf-list):

#528
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="m-291">
    <get>
        <filter xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:type="subtree">
            <confdConfig xmlns="http://tail-f.com/ns/confd_dyncfg/1.0">
                <netconf>
                    <transport>
                        <ssh>
                            <extraIpPorts/>
                        </ssh>
                    </transport>
                </netconf>
            </confdConfig>
        </filter>
    </get>
</rpc>
##
#304
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="m-291"><data><confdConfig xmlns="http://tail-f.com/ns/confd_dyncfg/1.0"><netconf><transport><ssh><extraIpPorts>:::2022</extraIpPorts></ssh></transport></netconf></confdConfig></data></rpc-reply>
##

Device accepted such request and successfully returned RPC response with one leaf-list entry. I also tried different request which would return whole leaf-lists with multiple entries. Everything seems to work as expected (I tested reading of leaf-list on the ConfD device).

However, I cannot build the similar subtree filter using NETCONF that would point to the whole leaf-list.

My attempts to build subtree filter that would point to "netconf-state/capabilities/capability" leaf-list (ietf-netconf-monitoring module):

#1

final YangInstanceIdentifier targetYiid = YangInstanceIdentifier.create(
 toId(NetconfState.QNAME),
 toId(Capabilities.QNAME),
 toId(QName.create(Capabilities.QNAME, "capability")));

Built GET RPC ('capability' entity is skipped):

<rpc message-id="m-0" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <get>
 <filter xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:type="subtree">
 <netconf-state xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring">
 <capabilities/>
 </netconf-state>
 </filter>
 </get>
</rpc>

#2

final YangInstanceIdentifier targetYiid = YangInstanceIdentifier.create(
 toId(NetconfState.QNAME),
 toId(Capabilities.QNAME),
 new NodeWithValue<>(QName.create(Capabilities.QNAME, "capability"), null));

Built GET RPC ('capability' entity is again skipped):

<rpc message-id="m-0" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <get>
 <filter xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:type="subtree">
 <netconf-state xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring">
 <capabilities/>
 </netconf-state>
 </filter>
 </get>
</rpc>

#3

final YangInstanceIdentifier targetYiid = YangInstanceIdentifier.create(
                toId(NetconfState.QNAME),
                toId(Capabilities.QNAME),
                toId(QName.create(Capabilities.QNAME, "capability")),
                new NodeWithValue<>(QName.create(Capabilities.QNAME, "capability"), null));

Error: 

[main] WARN org.opendaylight.netconf.util.NetconfUtil - Unable to set namespace context, falling back to setPrefix()
java.lang.UnsupportedOperationException
	at java.xml/com.sun.xml.internal.stream.writers.XMLDOMWriterImpl.setNamespaceContext(XMLDOMWriterImpl.java:158)
	at org.opendaylight.netconf.util.NetconfUtil$NamespaceSetter.forFactory(NetconfUtil.java:83)
	at org.opendaylight.netconf.util.NetconfUtil.<clinit>(NetconfUtil.java:118)
	at org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.<clinit>(NetconfMessageTransformUtil.java:121)
	at org.opendaylight.netconf.sal.connect.netconf.schema.mapping.NetconfMessageTransformer.<clinit>(NetconfMessageTransformer.java:99)
	at org.opendaylight.netconf.sal.connect.netconf.schema.mapping.NetconfMessageTransformerTest.getTransformer(NetconfMessageTransformerTest.java:490)
	at org.opendaylight.netconf.sal.connect.netconf.schema.mapping.NetconfMessageTransformerTest.setUp(NetconfMessageTransformerTest.java:202)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
java.lang.NullPointerException
	at java.base/java.util.Objects.requireNonNull(Objects.java:221)
	at org.opendaylight.yangtools.concepts.AbstractCodec.serialize(AbstractCodec.java:34)
	at org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamWriterUtils.serialize(XMLStreamWriterUtils.java:116)
	at org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamWriterUtils.encodeValue(XMLStreamWriterUtils.java:82)
	at org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamWriterUtils.encodeValue(XMLStreamWriterUtils.java:56)
	at org.opendaylight.yangtools.yang.data.codec.xml.SchemaAwareXMLStreamNormalizedNodeStreamWriter.encodeValue(SchemaAwareXMLStreamNormalizedNodeStreamWriter.java:53)
	at org.opendaylight.yangtools.yang.data.codec.xml.SchemaAwareXMLStreamNormalizedNodeStreamWriter.encodeValue(SchemaAwareXMLStreamNormalizedNodeStreamWriter.java:38)
	at org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamNormalizedNodeStreamWriter.writeValue(XMLStreamNormalizedNodeStreamWriter.java:132)
	at org.opendaylight.yangtools.yang.data.codec.xml.SchemaAwareXMLStreamNormalizedNodeStreamWriter.scalarValue(SchemaAwareXMLStreamNormalizedNodeStreamWriter.java:161)
	at org.opendaylight.netconf.util.StreamingContext$LeafListEntry.streamToWriter(StreamingContext.java:393)
	at org.opendaylight.netconf.util.StreamingContext$AbstractComposite.streamToWriter(StreamingContext.java:167)
	at org.opendaylight.netconf.util.StreamingContext$AbstractComposite.streamToWriter(StreamingContext.java:167)
	at org.opendaylight.netconf.util.StreamingContext$AbstractComposite.streamToWriter(StreamingContext.java:167)
	at org.opendaylight.netconf.util.NetconfUtil.writeFilter(NetconfUtil.java:217)
	at org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toFilterStructure(NetconfMessageTransformUtil.java:233)
	at org.opendaylight.netconf.sal.connect.netconf.schema.mapping.NetconfMessageTransformerTest.getLeafListFieldsTest(NetconfMessageTransformerTest.java:1071)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)

Testing was done from "NetconfMessageTransformerTest" unit tests.

My questions:

  1. From the quick analysis, I think the source of the issue is in the SchemaAwareXMLStreamNormalizedNodeStreamWriter YANG-TOOLs class that just skips the empty leaf-list and doesn't serialize it. Is behaviour of SchemaAwareXMLStreamNormalizedNodeStreamWriter correct?
  2. Why reading of whole leaf-list using NETCONF is not allowed, if it is it is supported by devices? Is there some RFC sheet that denies such scenario?
  3. Where to fix this bug (if it is a bug)? Possible solution: creation of custom XML stream writer that also serializes empty leaf-lists and will be used only by NETCONF.

Regards,
Jaroslav

 


Generated at Wed Feb 07 20:15:47 UTC 2024 using Jira 8.20.10#820010-sha1:ace47f9899e9ee25d7157d59aa17ab06aee30d3d.