libyang icon indicating copy to clipboard operation
libyang copied to clipboard

Prefix is empty when handling identityref (libyang 2.1.144)

Open optimden opened this issue 2 years ago • 3 comments

Hello! I discovered the following problem on the libyang version 2.1.144. Other related libs versions: libnetconf2 - 2.1.38 sysrepo - 2.2.33 netopeer2 - 2.1.49 We sent get-config into the running datastore on the whole yang tree. Saved received config, and then send edit-config with content of this file to the candidate datastore. And got error in a response:

<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:9947300b-a5cf-4add-983d-7f266fdda739">
     <rpc-error>
       <error-type>application</error-type>
       <error-tag>operation-failed</error-tag>
       <error-severity>error</error-severity>
       <error-message xml:lang="en">Invalid identityref "match-all-filter" value - identity not found in module "ietf-netconf". (Data location "/bbf-qos-classifiers:classifiers/classifier-entry[name='initclss-eth0_0-0']/filter-operation".)</error-message>
     </rpc-error>
     <rpc-error>
       <error-type>application</error-type>
       <error-tag>operation-failed</error-tag>
       <error-severity>error</error-severity>
       <error-message xml:lang="en">User callback failed.</error-message>
     </rpc-error>
   </rpc-reply>

I discovered, that we handle identityref in function identityref_str2ident. But problem is that during handling the next part of xml:

<bbf-qos-cls:filter-operation>match-all-filter<bbf-qos-cls:filter-operation>

we got only:

match-all-filter<bbf-qos-cls:filter-operation>

as "value" parameter of identityref_str2ident function. Then we try to parse prefix from value inside it:

for (prefix_len = 0; (prefix_len < value_len) && (value[prefix_len] != ':'); ++prefix_len) {}
if (prefix_len < value_len) {
    id_name = &value[prefix_len + 1];
    id_len = value_len - (prefix_len + 1);
} else {
    prefix_len = 0;
    id_name = value;
    id_len = value_len; 
}

Of course, we can find nothing before we rich value_len and set prefix_len to 0. Then we have the same stacktrace into identityref_str2ident:

lyplg_type_identity_module
    |
ly_xml_resolve_prefix(ctx, NULL, 0, prefix_data)   <--- go here by switch condition

I see, that even if we found prefix, we never try find real matching between it and prefixes, which are stored in prefix_data set. We hardcode NULL as second paramter instead of pass prefix parameter, and 0 instead of real prefix_len.

optimden avatar Dec 20 '23 09:12 optimden

I do not know exactly where you get the data (it should not be netopeer2)

<bbf-qos-cls:filter-operation>match-all-filter<bbf-qos-cls:filter-operation>

but they are wrong if match-all-filter is from the bbf-qos-cls module. Based on what is said in RFC 7950:

   An identityref is lexically represented as the referred identity's
   qualified name as defined in XML-NAMES.  If the prefix is not
   present, the namespace of the identityref is the default namespace
   in effect on the element that contains the identityref value.

the default namespace is used, not the one of the prefix.

michalvasko avatar Dec 20 '23 10:12 michalvasko

I do not know exactly where you get the data (it should not be netopeer2)

<bbf-qos-cls:filter-operation>match-all-filter<bbf-qos-cls:filter-operation>

but they are wrong if match-all-filter is from the bbf-qos-cls module. Based on what is said in RFC 7950:

   An identityref is lexically represented as the referred identity's
   qualified name as defined in XML-NAMES.  If the prefix is not
   present, the namespace of the identityref is the default namespace
   in effect on the element that contains the identityref value.

the default namespace is used, not the one of the prefix.

Well, actually I have problem with applying deviation replace on default value. I have custom yang, which contains such deviation:

deviation "/bbf-qos-cls:classifiers/bbf-qos-cls:classifier-entry/bbf-qos-cls:filter-operation" {
        deviate replace {
            default "bbf-qos-cls:match-all-filter";
        }
    }

I imported modules using custom binary, which use sr_install_modules2 function from sysrepo. All is okey, but as a result i see, that startup datastore file bbf-qos-classifiers.yang in /etc/sysrepo/data/ contains value "match-all-filter" without any prefix. So, the default value for bbf-qos-cls:filter-operation was changed from "match-any-filter". But prefix is absent. And it's the reason of error:

Invalid identityref "match-all-filter" value - identity not found in module "ietf-netconf"

Behaviour on the previous versions of libyang, sysrepo and netopeer was such, that i have match-all-filter in startup datastore with prefix after applying deviation. I examined, that inside "sr_install_modules2" sysrepo function I go through the following stacktrace: sr_install_modules2 | _sr_install_modules | sr_lycc_update_data | lyd_validate_all <--- validation for a startup datastore | lyd_new_implicit_r <--- here I had been stopped by condition that: (struct lysc_node *)iter->name == "filter-operation". I checked, that i still have here for (struct lysc_node_leaf *)iter->dflt value "bbf-qos-classifiers:math-all-filter". But it seems, that this full name prefix will be removed further before printing this value via libyang to startup datastore file. Can you please reproduce such scenario and help to investigate the root cause?

optimden avatar Dec 22 '23 08:12 optimden

That is all fine, the value match-all-filter is correct in XML such as

<filter-operation xmlns="urn:bbf:yang:bbf-qos-classifiers">match-all-filter<filter-operation>

because it simply inherits the default namespace. That is why I have asked (and am asking again) how exactly did you get the XML data that are not using a default namespace but a prefixed namespace instead? Those are the only problem.

michalvasko avatar Jan 02 '24 10:01 michalvasko