API for getting 'confd_cs_node*'

Hi,
I am looking for a API that would provide me with ‘confd_cs_node’ pointer to corresponding node represented by its ‘xml_tag’ structure for the below yang structure.

 notification new-route {
        description "Notification for new route";
        leaf name {
          description "Route name";
          type string;
        }
    
        leaf id {
          description "Route ID";
          type uint16;
        }
      }

  notification temp-alarm {
    description "Temperature threshold alarm";
    leaf message {
      description "Alarm message";
      type string;
    }

    leaf curr-temp {
      description "Current temperature";
      type uint16;
    }

    leaf thresh-temp {
      description "Threshold temperature";
      type uint16;
    }
  }

I have the xml_tag structure populated with correct values for ‘temp-alarm’. Now, I need the ‘confd_cs_node’ structure for that node.

The only API I see is ‘confd_find_cs_root’ which gives me the ‘confd_cs_node’ for ‘new-route’ node and since ‘temp-alarm’ is not a child of it, I cant traverse from there.

Is there any API to get the ‘confd_cs_node’ of the node specifies by the xml_tag directly ?

Thanks.

From the confd_lib_lib man page:

struct confd_cs_node *confd_find_cs_root(int ns);
When schema information is available to the library, this function returns the root of the tree representaton of the namespace given by ns, i.e. a pointer to the struct confd_cs_node for the (first) toplevel node. For namespaces that are augmented into other namespaces such that they do not have a toplevel node, this function returns NULL - the nodes of such a namespace are found below the augment target node(s) in other tree(s). See confd_types(3).
struct confd_cs_node *confd_find_cs_node(const confd_hkeypath_t *hkey- path, int len);
Utility function which finds the struct confd_cs_node corresponding to the len first elements of the hashed keypath. To make the search consider the full keypath, pass the len element from the confd_hkeypath_t structure (i.e. mykeypath->len). See confd_types(3).
struct confd_cs_node *confd_find_cs_node_child(const struct confd_cs_node *parent, struct xml_tag xmltag);
Utility function which finds the struct confd_cs_node corresponding to the child node given as xmltag. See confd_types(3).
struct confd_cs_node *confd_cs_node_cd(const struct confd_cs_node *start, const char *fmt, …);
Utility function which finds the resulting struct confd_cs_node given an (optional) starting node and a (relative or absolute) string keypath. I.e. this function navigates the tree in a manner corresponding to cdb_cd()/maapi_cd(). Note however that the confd_cs_node tree does not have a node correspond- ing to “/”. It is possible to pass start as NULL, in which case the path must be absolute (i.e. start with a “/”).
Since the key values are not relevant for the tree navigation, the key elements can be omitted, i.e. a “tagpath” can be used - if present, key elements are ignored, whether given in the {…} form or the CDB-only [N] form. See confd_types(3).
If the path can not be found, NULL is returned, confd_errno is set to CONFD_ERR_BADPATH, and confd_lasterr() can be used to retrieve a string that describes the reason for the failure.

One reference you can use is the print_modifications() in this example:

1 Like

There is no function to do exactly what you ask for, since the confd_cs_node tree lacks a “super-root” corresponding to “/”, which would have your struct xml_tag as a child that could be found with confd_find_cs_node_child(). But you can walk the toplevel nodes of the module/namespace by following the ‘next’ pointer in the node that you got with confd_find_cs_root(). I.e. you could have a function like (untested)

struct confd_cs_node *get_toplevel_node(struct xml_tag *tag)
{
    struct confd_cs_node *node = confd_find_cs_root(tag->ns);
    while (node != NULL) {
        if (node->tag == tag->tag && node->ns == tag->ns)
            return node;
        node = node->next;
    }
    return NULL;
}

Actually a slightly better version (returns NULL faster if the tag is wrong, since you can walk into a different module by following the ‘next’ pointer ) is (still untested)

struct confd_cs_node *get_toplevel_node(struct xml_tag *tag)
{
    struct confd_cs_node *node = confd_find_cs_root(tag->ns);
    while (node != NULL && node->ns == tag->ns) {
        if (node->tag == tag->tag)
            return node;
        node = node->next;
    }
    return NULL;
}
1 Like

Thanks Per.
I did something like that but did not have to iterate since I knew at what level my node would be present.

Good! Actually on second (third:-) thought, I realize that my answer was unnecessarily complex, focusing on your question rather than the actual problem: the simple way to find a given toplevel node is to use confd_cs_node_cd(), mentioned in cohult’s answer. E.g. for the ‘new-route’ notification, assuming that ‘new-route’ is unique at the top level: confd_cs_node_cd(NULL, “/new-route”). If it is not unique, you need to include the namespace prefix - can be a good idea to do that anyway for “future-proofing” (a module added at a later point may introduce new toplevel elements such that the one you want is no longer unique: confd_cs_node_cd(NULL, “/prefix:new-route”).