Leaf list deletion

Hi,

we have leaf list defined as follows:
grouping community-set_config {
leaf community-set-name {
type eci-rpol:defined-name;
mandatory true;
}
leaf-list community-member {
type union {
type eci-bgp-types:bgp-std-community-type;
type eci-bgp-types:bgp-community-regexp-type;
type eci-bgp-types:bgp-well-known-community-type;
}
description
“members of the community set”;
}
}

We work with external DB.
When we configure comunity member as follows:
isim_Host1(config-community-set-inbal)# community-member iii
the following call back is being received:
TRACE CALL data set_elem(thandle=44, /routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-member, iii) --> CONFD_ACCUMULATE

when we delete the community member iii as follows:
isim_Host1(config-community-set-inbal)# no community-member iii
we receive the following callback:
TRACE CALL data delete(thandle=45,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-member) --> CONFD_ACCUMULATE

my question is - why we don’t receive the value iii for being delete?
since we can have more than one leaf-list element, how can we know which one the user intends to delete?

thanks
Inbal

If there is only one single value in a leaf-list and that value is deleted or all values in the leaf-list are deleted, ConfD will call the remove() callback for the leaf-list.

If there are more than one value and all values are not deleted in the leaf-list you don’t get a delete, i.e. ConfD does not call the remove() callback. Instead the set_elem() callback will be called by ConfD with the remaining values in the leaf-list after the delete.

Hi,

Thank you for your reply.
I tried to configure more than one value in my leaf list. I configured “iii” and then “aaa” and I see both in my debug command line, in the configure order.
#1
when I try to delete “aaa” I see the following call backs from tail-f and then the message in the confd cli is:
% No modifications to commit.
callbacks:
TRACE CALL data get_elem(thandle=116,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-member) (“iii”) --> CONFD_OK
TRACE CALL data get_elem(thandle=116,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-member) (“iii”) --> CONFD_OK
TRACE CALL data get_elem(thandle=116,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-set-name) (“inbal”) --> CONFD_OK
TRACE CALL data get_elem(thandle=116,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-member) (“iii”) --> CONFD_OK
TRACE CALL data get_elem(thandle=116,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-set-name) (“inbal”) --> CONFD_OK
TRACE CALL data get_elem(thandle=116,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-set-name) (“inbal”) --> CONFD_OK
TRACE CALL data get_elem(thandle=116,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-set-name) (“inbal”) --> CONFD_OK
TRACE CALL data get_elem(thandle=116,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-set-name) (“inbal”) --> CONFD_OK
TRACE CALL data get_elem(thandle=116,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-set-name) (“inbal”) --> CONFD_OK
TRACE CALL trans init(thandle=117,mode=“r”,db=running) --> CONFD_OK
TRACE CALL data get_elem(thandle=117,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-set-name) (“inbal”) --> CONFD_OK
TRACE CALL data get_elem(thandle=117,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-set-name) (“inbal”) --> CONFD_OK

Since there is only “get” and not “get next”, we return the first value - which is “iii”. then confd return that no modification is needed.
Should we return diffrently?

#2
when I try to delete “iii” the operation failed since it tries to delete. see the callbacks:
TRACE CALL trans init(thandle=103,mode=“rw”,db=cand) --> CONFD_OK
TRACE CALL trans init(thandle=101,mode=“rw”,db=running) --> CONFD_OK
TRACE CALL data get_elem(thandle=101,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-set-name) (“inbal”) --> CONFD_OK
TRACE CALL data get_elem(thandle=101,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-member) (“iii”) --> CONFD_OK
TRACE CALL trans prepare(thandle=103) --> CONFD_OK
TRACE CALL trans commit(thandle=103) --> CONFD_OK
TRACE CALL trans init(thandle=112,mode=“r”,db=running) --> CONFD_OK
TRACE CALL data get_elem(thandle=112,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-member) (“iii”) --> CONFD_OK
TRACE CALL data get_attrs(thandle=112,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-member) (NOEXISTS) --> CONFD_OK
TRACE CALL data get_elem(thandle=112,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-member) (“iii”) --> CONFD_OK
TRACE CALL trans finish(thandle=112) --> CONFD_OK
TRACE CALL data delete(thandle=101,/routing-policy/defined-sets/bgp-defined-sets/community-sets/community-set{inbal}/community-member) --> CONFD_ACCUMULATE
TRACE CALL trans prepare(thandle=101) --> CONFD_ERR
TRACE CALL trans finish(thandle=101) --> CONFD_OK

please see if you observe something wrong in the return values we send.

thanks
Inbal

Hello,

just to confirm, when returning leaf-list in get_elem, do you return it as confd_value_t of C_LIST type as described in ConfD User Guide (section confd_types)?

confd_value_t arr[5];
confd_value_t v;
int i;

for (i=0; i<5; i++)
     CONFD_SET_INT32(&arr[i], i);
CONFD_SET_LIST(&v, &arr[0], 5);

Hi,

That’s probably the problem…
we set the flag CONFD_DAEMON_FLAG_STRINGSONLY.
so we should CONFD_SET_STR for every configured leaf-list value and then in the end CONFD_SET_LIST?

thanks!
Inbal

In that case, I think you should crate C_LIST as you suggest and before returning it, convert it to the string
type. The string representation of leaf-list can be get with confd_val2str or confd_pp_value.
Also proper memory freeing should be done as you allocate strings into leaf-list.

Thanks.

I am not sure I understand the last guide you wrote regarding C_LIST .
In order to verify I am in the right way, please confirm I understand right.

usually we return the values as follows:
char* ReturnValue = READ FROM DB
confd_value_t value;
CONFD_SET_STR(&value, ReturnValue); //the name is part of the key
confd_data_reply_value(a_pTransaction, &value);

So now for leaf list I should:
confd_value_t arr[5];
confd_value_t value;
int i;

for (i=0; i<5; i++)
{
ReturnValue = READ FROM DB

 CONFD_SET_STR(&arr[i],ReturnValue);

}
CONFD_SET_LIST(&v, &arr[0], 5);
confd_data_reply_value(a_pTransaction, &value);

am I missing something? the memory free?

thanks
Inbal

Hi,

I tryed the code I wrote above.
I get the following error in confd_devel for “get_elem” of the leaf-list:
[<<“iii”>>,<<“zzz”>>] is not a valid value.
I think it is because I return value from type C_LIST and not value of type string.
I am not sure that confd_val2str is the one I should use.
please advise.
thanks
Inbal

I meant something like this:

confd_value_t arr[5];
confd_value_t lv, v;
int i;

for (i=0; i<5; i++)
{
   ReturnValue = READ FROM DB
   CONFD_SET_STR(&arr[i],ReturnValue);

}
CONFD_SET_LIST(&lv, &arr[0], 5);
confd_pp_value(buf, len, &lv)
CONFD_SET_STR(&v,buf);
confd_data_reply_value(a_pTransaction, &v);

First fill in leaf-list and then return string value in get_elem.
You can also create string without using C_LIST as long as you keep string format
returned by confd_pp_value(buf, &lv).

Hi,

Thanks, it seems to be working.
now on the opposite way, set_elem, I have question.
when I configure the first value “aaa”, it is all OK.
when I configure the second one “bbb” I receive the value as “aaa bbb”.
is it mean that every “set” I should delete the previos values and set them all one after the other?
Is it also a C_LIST converted to C_BUF (due to the StringOnly flag set), and I can somehow convert it to C_LIST and then take the values or only the last one?

please advise.
regards
Inbal

I assume yes, you are receiving leaf-list, which is internally one value which should be overwritten.

Note: this seems to have changed in ConfD 6.5
From 6.5 changelist

confd: The internal representation of leaf-lists has changed.
    Leaf-lists now behave similar to lists in terms of operations, i.e.,
    individual elements can now be created and deleted instead of
    setting/deleting the entire leaf-list as a single entity. Attributes
    can be set on individual leaf-list elements.

Hi,

when do you expect ConfD 6.5 version to be released?
I did not find your road map.
thanks
Inbal

ConfD 6.5 was already released on 10th October 2017.

Hi,

When confd 6.5 will be available for download at:
https://developer.cisco.com/site/confD/downloads/

Thanks,

Evyatar

OK, I’ll try to find out. Seems like confd-basic-6.5 is not yet available.

I got information that ConfD Basic is usually released few weeks after ConfD Premium. So please check from time to time the download page. Thank you.