YANG Data Nodes

This section describes the basic design of a YANG data tree that represents instances of various object nodes that the client or the server can create.

Data Trees

A YumaPro data tree is a representation of some subset of all possible object instances that a server is maintaining within a configuration database or other structure.

Each data tree starts with a 'root' container, and any child nodes represent top-level YANG module data nodes that exist within the server.

Each configuration database maintains its own copy (and version) of the data tree. There is only one object tree, however, and all data trees use the same object tree for reference.

Not all object types have a corresponding node within a data tree. Only 'real' data nodes are present. Object nodes that are used as meta-data to organize the object tree (E.g., choice, augment) are not present. The following table lists the object types and whether each one is found in a data tree.

Object Types in the Data Tree

OBJ_TYP_ANYXML

Yes

OBJ_TYP_CONTAINER

Yes

OBJ_TYP_CONTAINER (ncx:root)

Yes

OBJ_TYP_LEAF

Yes

OBJ_TYP_LEAF_LIST

Yes

OBJ_TYP_LIST

Yes

OBJ_TYP_CHOICE

No

OBJ_TYP_CASE

No

OBJ_TYP_USES

No

OBJ_TYP_REFINE

No

OBJ_TYP_AUGMENT

No

OBJ_TYP_RPC

No

OBJ_TYP_RPCIO

No

OBJ_TYP_NOTIF

No

Child Data Nodes

The design used for the storage of child nodes has changed over time.

Old Design

../_images/old_val_tree.png

New Design

../_images/new_val_tree.png

The old design required the entire child list to be searched when adding a new entry.

The new design uses a queue of object headers. First the correct object header is found, then the instance of that object is found. YANG lists are now stored in an AVL tree (using libdict hb_tree).

The server will maintain the order or instances given in the <edit-config> or startup configuration. It will maintain YANG schema order so the objects will be returned in the correct order according to the YANG module.

The val_set_index_chain function MUST be called before val_add_child for a list

Sometimes server or SIL code creates data. In order to create a list, the following steps must be followed

  1. Create the list node, e.g., with val_new_value()

  2. Create the key leafs and add them to the parent with val_child_add

  3. Create the list index chain with val_gen_index_chain

  4. Add the list node to its parent with val_child_add

status_t val_child_add(val_value_t *child, val_value_t *parent)

Add a child value node to a parent value node.

Replaces val_add_child

Parameters
  • child -- node to store in the parent

  • parent -- complex value node with a child header Q

Returns

status; node is only added if status is NO_ERR

status_t val_child_add_force(val_value_t *child, val_value_t *parent)

Add a child value node to a parent value node Force add even if Tree Insersion fails.

Parameters
  • child -- node to store in the parent

  • parent -- complex value node with a child header Q

Returns

status; node is only added if status is NO_ERR

status_t val_child_insert(val_value_t *child, val_value_t *current, val_value_t *parent, op_insertop_t insert_op)

Insert a child value node into a parent value node before or after the specified node.

Parameters
  • child -- node to store in the parent

  • current -- last node that was stored in the parent (may be NULL)

  • parent -- complex value node with a childQ

  • insert_op -- insert operation enum (first, last, before, after)

Returns

status

Data Node Types

The 'ncx_btype_t' enumeration in ncx/ncxtypes.h is used within each val_value_t to quickly identify which variant of the data node structure is being used.

ncx_btype_t

enum ncx_btype_t

enumeration of the built-in NCX types These types cannot be overridden and cannot be imported

Values:

enumerator NCX_BT_NONE

No type has been set yet.

  • The val_new_value() function has been called but no specific init function has been called to set the base type.

enumerator NCX_BT_ANY

The node is a YANG 1.0 'anyxml' node.

  • Type is deprecated. Use anydata instead.

  • When the client or server parses an 'anyxml' object, it will be converted to containers and strings.

  • This type should not be used directly.

  • WIll be converted to (or replaced by) a container

enumerator NCX_BT_BITS

YANG bits data type.

  • Uses ncx_list_t (string list) for implementation

enumerator NCX_BT_ENUM

YANG enumeration data type.

  • Uses enum name string in implementation

  • The 'value' number is not currently used

enumerator NCX_BT_EMPTY

YANG empty data type.

  • Uses boolean always set to true in implementation

  • If boolean set to false then may not mean not-present

enumerator NCX_BT_BOOLEAN

YANG boolean data type.

  • Uses boolean in implementation

enumerator NCX_BT_INT8

YANG int8 data type.

  • Uses int32 in implementation

enumerator NCX_BT_INT16

YANG int16 data type.

  • Uses int32 in implementation

enumerator NCX_BT_INT32

YANG int32 data type.

  • Uses int32 in implementation

enumerator NCX_BT_INT64

YANG int64 data type.

  • Uses int64 in implementation

enumerator NCX_BT_UINT8

YANG uint8 data type.

  • Uses int32 in implementation

enumerator NCX_BT_UINT16

YANG uint16 data type.

  • Uses int32 in implementation

enumerator NCX_BT_UINT32

YANG uint32 data type.

  • Uses int32 in implementation

enumerator NCX_BT_UINT64

YANG uint64 data type.

  • Uses uint64 in implementation

enumerator NCX_BT_DECIMAL64

YANG decimal64 data type.

  • Uses struct in implementation

enumerator NCX_BT_FLOAT64

Hidden double type, used just for XPath.

  • If the HAS_FLOAT define is false, then this type will be implemented as a string, not a double.

enumerator NCX_BT_STRING

YANG 'string' type.

  • There are also some YumaPro extensions that are used with this data type for special strings.

  • The server needs to know if a string contains XML prefixes or not, and there are several flavors to automatate processing of each one correctly.

enumerator NCX_BT_BINARY

YANG binary data type.

  • Uses struct in implementation

  • YANG uses base64 encoding for binary strings

enumerator NCX_BT_INSTANCE_ID

YANG instance-identifier data type.

  • Uses xpath:1.0 string in implementation

enumerator NCX_BT_UNION

YANG 'union' data type.

  • This is a meta-type.

  • When the client or server parses a value, it will resolve the union to one of the data types defined within the union.

  • An unresolved union will use the string type

enumerator NCX_BT_LEAFREF

YANG 'leafref' data type.

  • This is a meta-type.

  • The client or server will resolve this data type to the type of the actual 'pointed-at' leaf that is being referenced.

enumerator NCX_BT_IDREF

YANG identityref data type.

  • Uses struct in implementation, pointer to ncx_identity_t

  • YANG uses qualified-name encoding for identityref strings

  • The standards are not clear how to encode identityref in all protocols

enumerator NCX_BT_SLIST

ncx:xsdlist extension (internal, deprecated)

  • uses ncx_list_t, not limited to string sub-type

  • supports deprecated ncx:xsdlist string

enumerator NCX_BT_CONTAINER

YANG container node.

enumerator NCX_BT_CHOICE

YANG choice.

  • This is a meta-type and placeholder.

  • It does not appear in the data tree.

  • Not really used!

enumerator NCX_BT_CASE

YANG case.

  • This is a meta-type and placeholder.

  • It does not appear in the data tree.

  • Not really used!

enumerator NCX_BT_LIST

YANG list instance node.

enumerator NCX_BT_ANYDATA

The node is a YANG 1.1 'anydata' node.

  • When the client or server parses an 'anydata' object, it will be converted to containers and strings.

  • This type should not be used directly.

  • WIll be converted to (or replaced by) a container

enumerator NCX_BT_EXTERN

Internal 'external' data type, used in server and yangcli-pro.

  • It indicates that the content is actually in an external file.

  • Not a real type, points fo file for contents

enumerator NCX_BT_INTERN

Internal 'buffer' data type, used in server and yangcli-pro.

  • The content is actually stored verbatim in an internal buffer.

  • Not a real type, string buffer for contents.

The following table describes the different enumeration values:

YumaPro Data Types (ncx_btype_t)

NCX_BT_NONE

No type has been set yet. The val_new_value() function has been called but no specific init function has been called to set the base type.

NCX_BT_ANY

The node is a YANG 'anyxml' node. When the client or server parses an 'anyxml' object, it will be converted to containers and strings. This type should not be used directly.

NCX_BT_BITS

YANG 'bits' data type

NCX_BT_ENUM

YANG 'enumeration' data type

NCX_BT_EMPTY

YANG 'empty' data type

NCX_BT_BOOLEAN

YANG 'boolean' data type

NCX_BT_INT8

YANG 'int8' data type

NCX_BT_INT16

YANG 'int16' data type

NCX_BT_INT32

YANG 'int32' data type

NCX_BT_INT64

YANG 'int64' data type

NCX_BT_UINT8

YANG 'uint8' data type

NCX_BT_UINT16

YANG 'uint16' data type

NCX_BT_UINT32

YANG 'uint32' data type

NCX_BT_UINT64

YANG 'uint64' data type

NCX_BT_DECIMAL64

YANG 'decimal64' data type

NCX_BT_FLOAT64

Hidden double type, used just for XPath. If the HAS_FLOAT #define is false, then this type will be implemented as a string, not a double.

NCX_BT_STRING

YANG 'string' type. There are also some YumaPro extensions that are used with this data type for special strings. The server needs to know if a string contains XML prefixes or not, and there are several flavors to automate processing of each one correctly.

NCX_BT_BINARY

YANG 'binary' data type

NCX_BT_INSTANCE_ID

YANG 'instance-identifier' data type

NCX_BT_UNION

YANG 'union' data type. This is a meta-type. When the client or server parses a value, it will resolve the union to one of the data types defined within the union.

NCX_BT_LEAFREF

YANG 'leafref' data type. This is a meta-type. The client or server will resolve this data type to the type of the actual 'pointed-at' leaf that is being referenced.

NCX_BT_IDREF

YANG 'identityref' data type

NCX_BT_SLIST

XSD list data type (ncx:xsdlist extension)

NCX_BT_CONTAINER

YANG container

NCX_BT_CHOICE

YANG choice. This is a meta-type and placeholder. It does not appear in the data tree.

NCX_BT_CASE

YANG case. This is a meta-type and placeholder. It does not appear in the data tree.

NCX_BT_LIST

YANG list

NCX_BT_EXTERN

Internal 'external' data type, used in yangcli-pro. It indicates that the content is actually in an external file.

NCX_BT_INTERN

Internal 'buffer' data type, used in yangcli-pro. The content is actually stored verbatim in an internal buffer.

YumaPro Data Node Edit Variables (val_editvars_t)

There is a temporary data structure which is attached to a data node while editing operations are in progress, called "val_editvars_t". This structure is used by the functions in agt/agt_val.c to manipulate the value tree nodes during an <edit-config>, <copy-config>, <load-config>, or <commit> operation.

The SIL callback functions may wish to refer to the fields in this data structure. There is also a SIL cookie field to allow data to be transferred from one callback stage to the later stages. For example, if an edit operation caused the device instrumentation to reserve some memory, then this cookie could store that pointer.

The following typedef is used to define the val_editvars_t structure:

struct val_editvars_t

one set of edit-in-progress variables for one value node

Public Members

struct val_value_t_ *curparent

these fields are only used in modified values before they are actually added to the config database (TBD: move into struct) curparent == parent of curnode for merge

track the real parent

op_insertop_t insertop

YANG insert operation.

xmlChar *insertstr

saved value or key attr

struct xpath_pcb_t_ *insertxpcb

key attr for insert

struct val_value_t_ *insertval

back-ptr if before or after

val_insert_mode_t insert_mode

insert mode requested

uint8 silprio

2nd SIL priority for server

boolean operset

nc:operation here

void *pcookie

user pointer cookie

int icookie

user integer cookie

boolean is_move

TRUE if YPATCH MOVE operation.

boolean skip_sil_partial

TRUE is skip_sil_partial needed.

The following fields within the 'val_editvars_t' are highlighted:

val_editvars_t Fields

curparent

A 'new' node will use this field to remember the parent of the 'current' value. This is needed to support the YANG insert operation.

editop

The effective edit operation for this node.

insertop

The YANG insert operation, if any.

insertstr

The YANG 'value' or 'key' attribute value string, used to support the YANG insert operation.

insertxpcb

XPath parser control block for the insert 'key' expression, if needed. Used to support the YANG insert operation.

insertval

Back pointer to the value node to insert ahead of, or behind, if needed. Used to support the 'before' and 'after' modes of the YANG insert operation.

iskey

TRUE if this is a key leaf. FALSE otherwise.

operset

TRUE if there was an nc:operation attribute found in this node; FALSE if the 'editop' is derived from its parent.

pcookie

SIL user pointer cookie. Not used by the server. Reserved for SIL callback code.

icookie

SIL user integer cookie. Not used by the server. Reserved for SIL callback code.

val_value_t

The val_value_t data structure is used to maintain the internal representation of all NETCONF databases, non-configuration data available with the <get> operation, all RPC operation input and output parameters, and all notification contents.

Warning

Do not access fields directly! Use val.h macros or access functions in val.h and val_util.h

The following typedef is used to define a value node:

struct val_value_t

one value to match one type

Public Members

dlq_hdr_t qhdr

queue header to insert in dlq_hdr list

struct obj_template_t_ *obj

common fields

bptr to object def

typ_def_t *typdef

bptr to typdef if leaf

const xmlChar *name

back pointer to elname

the dname field is moved to

val_extra_t and only used when the value is constructed from dummy objects or no objects at all

struct val_value_t_ *parent

back-ptr to parent if any

struct val_child_hdr_t_ *hdr

back-ptr to own child_hdr

val_extra_t *val_extra

val extra fields only needed about 25% of the time

uint32 flags

internal status flags

xmlns_id_t nsid

namespace ID for this node

ncx_btype_t btyp

base type of this value

ncx_data_class_t dataclass

config or state data

time_t last_modified

last_modified and etag fields used for filtered retrieval and YANG-API If-Match type of conditional editing

ncx_etag_t etag

ETag for RESTCONF.

dlq_hdr_t *metaQ

YANG does not support user-defined meta-data but NCX does.

The <edit-config>, <get> and <get-config> operations use attributes in the RPC parameters, the metaQ is still used

The ncx:metadata extension allows optional attributes to be added to object nodes for anyxml, leaf, leaf-list, list, and container nodes. The config property will be inherited from the object that contains the metadata

This is used mostly for RPC input parameters and is strongly discouraged. Full edit-config support is not provided for metadata Q of val_value_t

val_editvars_t *editvars

value editing variables the editvars will only be malloced while edit is in progress

edit-vars from attrs

op_editop_t editop

needed for all edits

status_t res

validation result

dlq_hdr_t *indexQ

this field used in NCX_BT_LIST only ??? when is it ncx_filptr_t ???

Q of val_index_t or ncx_filptr_t

ncx_owner_id_t owner_id

set if the owners are being stored and this is a data node in the running config

ncx_nmda_origin_t nmda_origin

NMDA origin enum.

union val_value_t::v_ v
union v_

union of all the NCX-specific sub-types note that the following invisible constructs should never show up in this struct:

Public Members

dlq_hdr_t child_hdrQ

complex types have a Q of val_value_t representing the child nodes with values

changed from Q of val_value_t to a Q of val_child_hdr_t

ncx_num_t num

Numeric data types:

ncx_str_t str

String data types:

val_idref_t idref

NCX_BT_IDREF.

ncx_binary_t binary

NCX_BT_BINARY.

ncx_list_t list

NCX_BT_BITS, NCX_BT_SLIST.

boolean boo

NCX_BT_EMPTY, NCX_BT_BOOLEAN.

ncx_enum_t enu

NCX_BT_UNION, NCX_BT_ENUM.

xmlChar *fname

NCX_BT_EXTERN.

xmlChar *intbuff

NCX_BT_INTERN.

The following table highlights the fields in this data structure.

val_value_t Fields

qhdr

Internal queue header to allow a value node to be stored in a queue. A complex node maintains a child queue of val_value_t nodes.

obj

Back pointer to the object template for this data node

typdef

Back pointer to the typedef structure if this is a leaf or leaf-list node.

name

Back pointer to the name string for this node

parent

Back pointer to the parent of this node, if any

nsid

Namespace ID for this node. This may not be the same as the object node namespace ID, E.g., anyxml child node contents will override the generic object namespace.

btyp

The ncx_btype_t base type enumeration for this node. This is the final resolved value, in the event the object type is not a final resolved base type.

flags

Internal flags field. Do not access directly.

dataclass

Internal config or non-config enumeration

metaQ

Queue of val_value_t structures that represent any meta-variables (XML attributes) found for this data node. For example, the NETCONF filter 'type' and 'select' attributes are defined for the <filter> element in yuma-netconf.yang.

editvars

Pointer to the malloced edit variables structure for this data node. This node will be freed (and NULL value) when the edit variables are not in use.

res

Internal validation result status for this node during editing or parsing.

indexQ

Queue of internal data structures used during parsing and filtering streamed output.

val_extra

Pointer to extra data if needed

v

Union of different internal fields, depending on the 'btyp' field value.

v.childQ

Queue of val_value_t child nodes, if this is a complex node.

v.num

ncx_num_t for all numeric data types

v.str

Malloced string value for the string data type

v.idref

Internal data structure for the YANG identityref data type

v.binary

Internal data structure for the YANG binary data type

v.list

Internal data structure for YANG bits and NCX xsdlist data types

v.boo

YANG boolean data type

v.enu

Internal data structure for YANG enumeration data type

v.fname

File name for NCX 'external' data type

v.intbuff

Malloced buffer for 'internal' data type

YumaPro Data Nodes (Extra) (val_extra_t)

The val_extra_t data structure is used to maintain the fields that are internal and rarely used by the server have been moved from val_value_t to a new data structure called "val_extra_t".

The following typedef is used to define the extra data used for value node processing

struct val_extra_t

extra information not used very often within a val_value_t

Public Members

xmlChar *dname

malloced value name used rarely if obj_get_name not correct this can happen if val_value_t trees are constructed by SIL code from generic objects; This is NOT RECOMMENDED Use val_init_from_template using correct obj_template_t instead

malloced name if needed

void *getcb

Used by Agent only: GET1 callback for virtualval if this field is non-NULL, then the entire value node is actually a placeholder for a dynamic read-only object and all read access is done via this callback function; the real data type is getcb_fn_t *.

struct val_value_t_ *virtualval

if this field is non-NULL, then a malloced value struct representing the real value retrieved by val_get_virtual_value, is cached here for <get>/<get-config>

time_t cachetime

timestamp for virtual val timeout

struct xpath_pcb_t_ *xpathpcb

this field is for NCX_BT_LEAFREF NCX_BT_INSTANCE_ID, or tagged ncx:xpath value stored in v union as a string

plock_cb_t *plock[VAL_MAX_PLOCKS]

back-ptr to the partial locks that are held against this node

dlq_hdr_t *dataruleQ

back-ptr to the data access control rules that reference this node

Q of obj_xpath_ptr_t

xmlChar *varexpr

malloced pointer to the variable expression found if this val node is part of a data template.

The actual value in union v_ MUST be ignored if varexpr string is non-NULL!!

struct xpath_aio_cb_t_ *aiocb

Used by xpath_aio.c and agt_xpath.c to keep track of the parent of a top AIO val_value_ tree.

This is a backptr.

ncx_sm_mpid_t *mpid

malloced Moint Point ID struct if found in parsing

The following table highlights the fields in this data structure:

Note: Do not access fields directly! Use val.h macros or access functions in val.h and val_util.h

val_extra_t Fields

dname

Malloced name string if the client or server changed the name of this node, so the object node name is not being used. This is used for anyxml processing (and other things) to allow generic objects (container, string, empty, etc.) to be used to represent the contents of an 'anyxml' node.

getcb

Internal server callback function pointer. Used only if this is a 'virtual' node, and the actual value node contents are generated by a SIL callback function instead of being stored in the node itself.

virtualval

The temporary cached virtual node value, if the getcb pointer is non-NULL.

cachetime

The timestamp used to cache for a virtualval

xpathpcb

XPath parser control block, used if this value contains some sort of XPath string or instance-identifier. For example, the XML namespace ID mappings are stored, so the XML prefix map generated for the <rpc-reply> will contain and reuse the proper namespace attributes, as needed.

plock

Array of [1] for supporting <partial-lock> operation

dataruleQ

pointer to malloced queue for NACM data rule support

varexpr

malloced string containing variable string for replacement

val_value_t Access Macros

There are a set of macros defined to access the fields within a val_value_t structure.

These should be used instead of accessing the fields directly. There are also functions defined as well. These macros are provided in addition the the access functions for quick access to the actual node value. These macros must only be used when the base type ('btyp') field has been properly set and known by the SIL code. Some auto-generated SIL code uses these macros.

The following table summarized the val_value_t macros that are defined in ncx/val.h:

VAL_OBJ(V)

Access object template of the value

VAL_TYPE(V)

Access base type of the value

VAL_HDR(V)

Access child header pointer of the value

VAL_TYPDEF(V)

Access type definition of the value

VAL_NSID(V)

Access namespace ID value

VAL_NAME(V)

Access name value

VAL_RES(V)

Access resource enumeration value

VAL_BOOL(V)

Access value for NCX_BT_BOOLEAN

VAL_EMPTY(V)

Access value for NCX_BT_EMPTY

VAL_DOUBLE(V)

Access value for NCX_BT_FLOAT64

VAL_STRING(V)

Access value for NCX_BT_STRING

VAL_BINARY(V)

Access value for NCX_BT_BINARY

VAL_ENU(V)

Access entire ncx_enum_t structure for NCX_BT_ENUM

VAL_ENUM(V)

Access enumeration integer value for NCX_BT_ENUM

VAL_ENUM_NAME(V)

Access enumeration name string for NCX_BT_ENUM

VAL_FLAG(V)

Deprecated: use VAL_BOOL instead

VAL_LONG(V)

Access NCX_BT_INT64 value

VAL_INT(V)

Access NCX_BT_INT32 value

VAL_INT8(V)

Access NCX_BT_INT8 value

VAL_INT16(V)

Access NCX_BT_INT16 value

VAL_INT32(V)

Access NCX_BT_INT32 value

VAL_INT64(V)

Access NCX_BT_INT64 value

VAL_STR(V)

Deprecated: use VAL_STRING instead

VAL_INSTANCE_ID(V)

Access NCX_BT_INSTANCE_ID value

VAL_IDREF(V)

Access entire val_idref_t structure for NCX_BT_IDREF

VAL_IDREF_NSID(V)

Access the identityref namespace ID for NCX_BT_IDREF

VAL_IDREF_NAME(V)

Access the identityref name string for NCX_BT_IDREF

VAL_UINT(V)

Access the NCX_BT_UINT32 value

VAL_UINT8(V)

Access the NCX_BT_UINT8 value

VAL_UINT16(V)

Access the NCX_BT_UINT16 value

VAL_UINT32(V)

Access the NCX_BT_UINT32 value

VAL_UINT64(V)

Access the NCX_BT_UINT64 value

VAL_ULONG(V)

Access the NCX_BT_UINT64 value

VAL_DEC64(V)

Access the ncx_dec64 structure for NCX_BT_DEC64

VAL_DEC64_DIGITS(V)

Access the number of digits for NCX_BT_DEC64

VAL_DEC64_ZEROES(V)

Access the number of zeros for NCX_BT_DEC64

VAL_LIST(V)

Access the ncx_list_t structure for NCX_BT_LIST

VAL_BITS

Access the ncx_list_t structure for NCX_BT_BITS. (Same as VAL_LIST)

val_value_t Access Functions

The file ncx/val.h contains many API functions so that object properties do not have to be accessed directly. In addition, the file ncx/val_util.h contains more (high-level) utility functions. The following table highlights the most commonly used functions. Refer to the H files for a complete definition of each API function.

val_value_t Access Functions

val_new_value

Malloc a new value node with type NCX_BT_NONE.

val_init_complex

Initialize a malloced value node as one of the complex data types.

val_init_virtual

Initialize a malloced value node as a virtual node (provide a 'get' callback function).

val_init_from_template

Initialize a malloced value node using an object template. This is the most common form of the init function used by SIL callback functions.

val_free_value

Clean and free a malloced value node.

val_set_name

Set or replace the value node name.

val_force_dname

Set (or reset) the name of a value struct . Set all descendant nodes as well Force dname to be used, not object name backptr.

val_set_qname

Set or replace the value node namespace ID and name.

val_string_ok

Check if the string value is valid for the value node object type.

val_string_ok_errinfo

Check if the string value is valid for the value node object type, and provide the error information to use if it is not OK.

val_binary_ok_errinfo

Retrieve the YANG custom error info if any. Check a binary string to make sure the value is valid base64 if the value came from raw RPC XML, and if its CLI input then do validation as for binary sting . Retrieve the configured error info struct if any error.

val_list_ok

Check if the list value is valid for the value node object type.

val_list_ok_errinfo

Check if the list value is valid for the value node object type, and provide the error information to use if it is not OK.

val_enum_ok

Check if the enumeration value is valid for the value node object type.

val_enum_ok_errinfo

Check if the enumeration value is valid for the value node object type, and provide the error information to use if it is not OK.

val_bit_ok

Check if the bits value is valid for the value node object type.

val_idref_ok

Check if the identityref value is valid for the value node object type.

val_parse_idref

Convert a string to an internal QName string into its various parts and find the identity struct that is being referenced (if available).

val_range_ok

Check a number to see if it is in range or not . Could be a number or size range.

val_range_ok_errinfo

Check a number to see if it is in range or not . Could be a number or size range. Returns error info record on error exit.

val_pattern_ok

Check a string against all the patterns in a big AND expression.

val_pattern_ok_errinfo

Check a string against all the patterns in a big AND expression. Returns error info record on error exit.

val_simval_ok

Check if the smple value is valid for the value node object type.

val_simval_ok_errinfo

Check if the simple value is valid for the value node object type, and provide the error information to use if it is not OK.

val_union_ok

Check a union to make sure the string is valid.

val_union_ok_errinfo

Check a union to make sure the string is valid. Returns error info record on error exit.

val_union_ok_ex

Check a union to make sure the string is valid based on the specified typdef.

val_union_ok_full

Check a union to make sure the string is valid based on the specified typdef, and convert the string to an NCX internal format . Use context and root nodes to evaluate XPath for leafref and instance-identifier types.

val_get_metaQ

Get the meta Q header for the value.

val_get_first_meta

Get the first meta-variable (XML attribute value) for a value node.

val_get_next_meta

Get the next meta-variable (XML attribute value) for a value node.

val_meta_empty

Check if the metaQ is empty for the value node.

val_find_meta

Find the specified meta-variable in a value node.

val_meta_match

Return true if the corresponding attribute exists and has the same value.

val_metadata_inst_count

Get the number of instances of the specified attribute.

val_dump_value

Debug function to print the contents of any value node.

val_dump_value_ex

Debug function to print the contents of any value node, with extended parameters to control the output.

val_dump_value_max

Debug function to print the contents of any value node, with full control of the output parameters.

val_set_string

Set a malloced value node as a generic string value. Used instead of val_init_from_template.

val_set_string2

Set a malloced value node as a specified string type. Used instead of val_init_from_template.

val_set_binary

Set and decode base64 value . Set an initialized val_value_t as a binary type.

val_reset_empty

Recast an already initialized value as an NCX_BT_EMPTY clean a value and set it to empty type used by yangcli-pro to delete leafs.

val_set_simval

Set a malloced value node as a specified simple type. Used instead of val_init_from_template.

val_make_simval

Create and set a val_value_t as a simple type same as val_set_simval, but malloc the value first.

val_set_simval_str

Set a malloced value node as a specified simple type. Used instead of val_init_from_template. Use a counted string value instead of a zero-terminated string value.

val_make_string

Create a complete malloced generic string value node.

val_merge

Merge source val into destination value (! MUST be same type !) . Any meta vars in source are also merged into destination . This function is not used to merge complex objects For simple types only!

val_clone

Clone a value node.

val_clone2

Clone a specified val_value_t structure and sub-trees but not the editvars.

val_clone_test

Clone a value node with a 'test' callback function to prune certain descendant nodes during the clone procedure.

val_clone_config_data

Clone a value node but skip all the non-configuration descendant nodes.

val_replace

Replace a specified val_value_t structure and sub-trees. This can be destructive to the source 'val' parameter !

val_replace_str

Replace a specified val_value_t structure with a string type.

val_fast_replace_string

Replace a specified val_value_t structure with a string type . Reuse everything -- just set the val->v.str field

val_add_child

Add a child value node to a parent value node.

Simply makes a new last child!!!

Does not check siblings!!!

Relies on val_set_canonical_order

To modify existing entries, use val_add_child_sorted instead!!

val_add_child2

Add a child value node to a parent value node.

val_add_child_sorted

Add a child value node to a parent value node in the proper place

val_insert_child

Insert a child value node into a specific spot into a parent value node.

val_remove_child

Remove a child value node from its parent.

val_swap_child

Replace a child node within its parent with a different value node.

val_first_child_match

Match a child node name; Used for partial command completion in yangcli-pro.

val_first_child_match_fast

Get the first instance of the corresponding child node. Object pointers must be from the same tree!!!

val_next_child_match

Match the next child node name; Used for partial command completion in yangcli-pro.

val_next_child_same

Get the next instance of the corresponding child node.

val_get_first_child

Get the first child value node.

val_get_next_child

Get the next child value node.

val_find_child

Find a specific child value node.

val_find_child_fast

Find the first instance of the specified child node.

val_find_child_obj

Find the first instance of the specified child node . Use the object template pointer to match the object.

val_find_child_que

Find the first instance of the specified child node in the specified child Q.

val_find_next_child

Find the next occurrence of a specified child node.

val_find_next_child_fast

Find the next instance of the specified child node . Use the curchild->obj pointer to find next child of this type . Assumes childQ is sorted and all instances of 'curchild' are already grouped together.

val_first_child_name

Get the first corresponding child node instance, by name find first -- really for resolve index function.

val_first_child_qname

Get the first corresponding child node instance, by Qname.

val_next_child_qname

Get the next corresponding child node instance, by Qname.

val_first_child_string

Find first name value pair . Get the first corresponding child node instance, by name and by string value. Child node must be a base type of

NCX_BT_STRING

NCX_BT_INSTANCE_ID

NCX_BT_LEAFREF

val_get_first_terminal_child

Get the child node only if obj_is_terminal(obj) is true.

val_get_next_terminal_child

Get the next child node only if obj_is_terminal(obj) is true.

val_match_child

Match a potential partial node name against the child node names, and return the first match found, if any.

val_match_child_count

Match the first instance of the specified child node . Return the total number of matches.

val_child_cnt

Get the number of child nodes within a parent node.

val_child_inst_cnt

Get the corresponding child instance count by name . Get instance count -- for instance qualifier checking.

val_get_child_inst_id

Get the instance ID for this child node within the parent context.

val_liststr_count

Get the number of strings within an NCX_BT_LIST value node.

val_index_match

Check if 2 value list nodes have the same set of key leaf values.

val_compare

Compare 2 value nodes

val_compare_ex

Compare 2 value nodes with extra parameters.

val_compare_to_string

Compare a value node to a string value instead of another value node.

val_compare_to_string_len

Compare a val_value_t structure value contents to a string . Provide a max-length to compare.

val_sprintf_simval_nc

Output the value node as a string into the specified buffer.

val_make_sprintf_string

Malloc a buffer and fill it with a zero-terminated string representation of the value node.

val_resolve_scoped_name

Find a descendant node within a value node, from a relative path expression.

val_has_content

Return TRUE if the value node has any content; FALSE if an empty XML element could represent its value.

val_has_index

Return TRUE if the value node is a list with a key statement.

val_get_first_index

Get the first index node for the specified list value node.

val_get_next_index

Get the next index node for the specified list value node.

val_get_index_count

Get the number of index nodes in this val.

val_set_extern

Set a malloced value node as an NCX_BT_EXTERN internal data type.

val_set_intern

Set a malloced value node as an NCX_BT_INTERN internal data type.

val_fit_oneline

Return TRUE if the value node should fit on 1 display line; Sometimes a guess is made instead of determining the exact value. XML namespace declarations generated during XML output can cause this function value to sometimes be wrong.

val_create_allowed

Return TRUE if the NETCONF create operation is allowed for the specified value node.

val_delete_allowed

Return TRUE if the NETCONF delete operation is allowed for the specified value node.

val_is_config_data

Return TRUE if the value node represents configuration data.

val_is_virtual

Check if the specified value is a virtual value , such that a 'get' callback function is required to access the real value contents.

val_get_virtual_value

Get the value for a virtual node from its 'get' callback function.

val_is_default

Return TRUE if the value node is set to its YANG default value.

val_is_real

Check if a value node is a real node or one of the abstract node types.

val_get_parent_nsid

Get the namespace ID for the parent value node of a specified child node.

val_instance_count

Get the number of occurrences of the specified child value node within a parent value node.

val_instance_count_fast

Count the number of instances of the specified object name in the parent value structure. This only checks the first level under the parent, not the entire subtree.

val_instance_count_fast2

Count the number of instances of the specified object name in the parent value structure. This only checks the first level under the parent, not the entire subtree . Starts with the startval passed in.

val_need_quotes

Return TRUE if the printed string representation of a value node needs quotes (because it contains some whitespace or special characters).

val_all_whitespace

Check if a string is all whitespace.

val_any_whitespace

Check if a string has any whitespace chars.

val_get_dirty_flag

Check if a value node has been altered by an RPC operation, but this edit has not been finalized yet.

val_get_nest_level

Get the current numeric nest level of the specified value node.

val_get_mod_name

Get the module name for the specified value node.

val_get_mod_prefix

Get the module prefix string for the specified value node.

val_get_nsid

Get the namespace ID for the specified value node.

val_change_nsid

Change the namespace ID for the specified value node and all of its descendants.

val_set_pcookie

Set the SIL pointer cookie in the value node editvars structure.

val_set_icookie

Set the SIL integer cookie in the value node editvars structure.

val_get_pcookie

Get the SIL pointer cookie in the value node editvars structure.

val_get_icookie

Get the SIL integer cookie in the value node editvars structure.

val_get_typdef

Get the typedef structure for a leaf or leaf-list value node.

val_move_children

Move all the child nodes of one complex value node to another complex value node.

val_set_canonical_order

Re-order the descendant nodes of a value node so they are in YANG order. Does not change the relative order of system-ordered lists and leaf-lists.

val_gen_index_chain

Generate the internal key leaf lookup chain for a list value node..

val_add_defaults

Generate the leafs that have default values.

val_instance_check

Check a value node against its template to see if the correct number of descendant nodes are present.

val_get_choice_first_set

Get the first real node that is present for a conceptual choice statement.

val_get_choice_next_set

Get the next real node that is present for a conceptual choice statement.

val_choice_is_set

Return TRUE if some real data node is present for a conceptual choice statement.

val_get_first_key

Get the first key record if this is a list with a key-stmt.

val_get_last_key

Get the last key record if this is a list with a key-stmt.

val_get_next_key

Get the next key record if this is a list with a key-stmt.

val_get_prev_key

Get the previous key record if this is a list with a key-stmt.

val_remove_key

Remove a key pointer because the key is invalid . Free the key pointer.

val_new_child_val

Create a child node during an edit operation. Used by the server. SIL code does not need to maintain the value tree.

val_gen_instance_id

Malloc and generate the YANG instance-identifier string for the value node.

val_check_obj_when

Check if an object node has any 'when' statements, and if so, evaluate the XPath condition(s) against the value tree to determine if the object should be considered present or not.

val_check_child_conditional

Check if a child object node has any FALSE 'if-feature' or 'when' statements.

val_is_mandatory

Check if the child object node is currently mandatory or optional.

val_get_xpathpcb

Access the XPath parser control block for this value node, if any.

val_make_simval_obj

Malloc and fill in a value node from an object template and a value string.

val_set_simval_obj

Fill in a value node from an object template and a value string.

val_find_bit

Check if a bits value contains the specified bit name

val_find_bit_name

Get the name of the bit from a bits value that corresponds to the specified bit position

val_find_enum_name

Get the name of the enum from an enumeration value that corresponds to the specified 'value' number

val_sprintf_etag

Write the Entity Tag for the value to the specified buffer.

val_get_last_modified

Get the last_modified field.

val_has_children

Determine if there are any child nodes for this val.

val_delete_children

Check if the value is a complex type and if so then delete all child nodes.

val_clean_value

Clean a static val_value_t structure.

val_get_yang_typename

Get the YANG type name for this value node if there is one.

val_is_value_set

Check if a value has been set by a client . It has to be initialized and not set by default to return true.

val_idref_derived_from

Check the specified valnode is derived from the specified identity.

val_get_sil_priority

Get the secondary SIL priority; zero if not found.

val_has_conditional_value

YANG 1.1:

Check the value that must be properly set to see if it is conditional on any if-feature-stmts.

val_convert_leafref

Convert a value of type NCX_BT_LEAFREF to the value that the final leafref is pointing at.

Data Tree Handling Examples

YANG data trees are instances of YANG schema nodes. There are various API functions that can be used to manipulate a desired Data node. They differ widely the operation that you need to perform. This section contains simple examples that will illustrate how to manage different YANG node types.

Include Files For Data Nodes

The following H files need to be included in a C file to use APIs to access data nodes.

H File

Description

agt.h

Core agent utilities and agt_profile

agt_util.h

Agent utility functions

cfg.h

Configuration datastore utilities

ncx.h

YANG module utilities

ncxconst.h

Global constants

ncxtypes.h

Module and other code data structures

obj.h

YANG object template APIs

val.h

Main val_value_t access functions

val_child.h

Child access functions

val_util.h

Additional val_value_t access functions

  • These files are (and others) are automatically included in auto-generated SIL and SIL-SA code.

  • If using in another file, remember to include all YumaPro H files after procdefs.h.

  • The libxml2 file xmlstring.h is usually included before all YumaPro files.

  • All YumaPro headers are self-compiling, so it is OK to include them in alphabetical order (after procdefs.h)

For example:

#include <xmlstring.h>
#include "procdefs.h"
#include "agt.h"
#include "agt_util.h"
#include "cfg.h"
#include "ncx.h"
#include "ncxconst.h"
#include "ncxtypes.h"
#include "obj.h"
#include "val.h"
#include "val_child.h"
#include "val_util.h"

Creating and Deleting Data Nodes

Many APIs in this section return a malloced structure representing a YANG data node. The val_value_t typedef is used for this purpose.

New Value Node

val_value_t *val_new_value(void)

Malloc and initialize the fields in a val_value_t.

Returns

pointer to the malloced and initialized struct or NULL if an error

/* create an uninitialized value node */
val_value_t *val = val_new_value();
if (val == NULL) {
    return ERR_INTERNAL_MEM;
}

Initialize a Value Node

void val_init_from_template(val_value_t *val, struct obj_template_t_ *obj)

Initialize a value node from its object template.

This is the normal init function to call MUST CALL val_new_value FIRST

Parameters
  • val -- pointer to the initialized value struct to bind

  • obj -- object template to use

/* initialize a value node */
val_init_from_template(val, obj);

Free a Value Node

void val_free_value(val_value_t *val)

Scrub the memory in a val_value_t by freeing all the sub-fields and then freeing the entire struct itself.

The struct must be removed from any queue it is in before this function is called.

Parameters

val -- val_value_t to delete

/* clean and free a value node and all its descendants */
val_free_value(val);

Leaf Examples

The following examples show how to construct a simple leaf data node. These APIs can all be used for a leaf-list value as well.

String Value With Leaf Object Template

The most common and generic API function to construct the data node from a string value. The val_make_simval_obj API requires the child object template.

val_value_t *val_make_simval_obj(obj_template_t *obj, const xmlChar *valstr, status_t *res)

Create and set a val_value_t as a simple type from an object template instead of individual fields Calls val_make_simval with the object settings.

This API is the preferred method to create a leaf in SIL or SIL-SA code. This will use correct settings from the object template

Parameters
  • obj -- object template to use

  • valstr -- simple value encoded as a string

  • res -- address of return status

Return values

*res -- return status

Returns

pointer to malloced and filled in val_value_t struct NULL if some error

obj_template_t *leafobj =
    obj_find_child(parentobj, modname, objname);
if (leafobj == NULL) {
      /* report an error or do not try to generate the leaf */
      return ERR_NCX_DEF_NOT_FOUND;
}

/* construct a leaf val_vale tree regardless of its type */
status_t res = NO_ERR;
val_value_t *any_type_leaf =
     val_make_simval_obj(leafobj, (const xmlChar *)"8", &res);

String Value With Parent Object Template

The "agt_make_leaf" family of API functions look up the child object and make the child leaf in one step.

val_value_t *agt_make_leaf(obj_template_t *parentobj, const xmlChar *leafname, const xmlChar *leafstrval, status_t *res)

make a string val_value_t struct for a specified leaf or leaf-list

This is a main API for SIL and SIL-SA code to construct return data for GET2 callbacks.

See also

agt_make_leaf2

Parameters
  • parentobj -- parent object to find child leaf object

  • leafname -- name of leaf to find (namespace hardwired)

  • leafstrval -- string version of value to set for leaf

  • res -- address of return status

Return values

*res -- return status

Returns

malloced value struct or NULL if some error

/* construct any type leaf using string representation */
status_t res = NO_ERR;
val_value_t *string_leaf =
    agt_make_leaf(parentobj,
                  leafname,
                  (const xmlChar *)"example value",
                  &res);

There are additional APIs that allow a leaf to be created from an internal data type other than a string, such as a numeric type.

Integer Types

In order to construct a data node with integer types, the following API function can be used:

val_value_t *agt_make_int_leaf(obj_template_t *parentobj, const xmlChar *leafname, int32 leafval, status_t *res)

make an int32 val_value_t struct for a specified leaf or leaf-list

This is a main API for SIL and SIL-SA code to construct return data for GET2 callbacks.

See also

agt_make_int_leaf2

Parameters
  • parentobj -- parent object to find child leaf object

  • leafname -- name of leaf to find (namespace hardwired)

  • leafval -- integer number value for leaf

  • res -- address of return status

Return values

*res -- return status

Returns

malloced value struct or NULL if some error

/* construct a uint32 type leaf */
status_t res = NO_ERR;
val_value_t *string_leaf =
    agt_make_uint_leaf(parentobj,
                       leafname,
                       (uint32)32,
                       &res);
val_value_t *agt_make_uint_leaf(obj_template_t *parentobj, const xmlChar *leafname, uint32 leafval, status_t *res)

make a uint32 val_value_t struct for a specified leaf or leaf-list

This is a main API for SIL and SIL-SA code to construct return data for GET2 callbacks.

See also

agt_make_uint_leaf2

Parameters
  • parentobj -- parent object to find child leaf object

  • leafname -- name of leaf to find (namespace hardwired)

  • leafval -- number value for leaf

  • res -- address of return status

Return values

*res -- return status

Returns

malloced value struct or NULL if some error

/* construct a uint32 type leaf */
status_t res = NO_ERR;
val_value_t *value =
    agt_make_int_leaf(parentobj,
                      leafname,
                      (int32)32,
                       &res);
val_value_t *agt_make_uint64_leaf(obj_template_t *parentobj, const xmlChar *leafname, uint64 leafval, status_t *res)

make a uint64 val_value_t struct for a specified leaf or leaf-list

This is a main API for SIL and SIL-SA code to construct return data for GET2 callbacks.

See also

agt_make_uint64_leaf2

Parameters
  • parentobj -- parent object to find child leaf object

  • leafname -- name of leaf to find (namespace hardwired)

  • leafval -- uint64 number value for leaf

  • res -- address of return status

Return values

*res -- return status

Returns

malloced value struct or NULL if some error

/* construct a uint64 type leaf */
status_t res = NO_ERR;
val_value_t *value =
    agt_make_uint64_leaf(parentobj,
                         leafname,
                         (uint64)64,
                          &res);
val_value_t *agt_make_int64_leaf(obj_template_t *parentobj, const xmlChar *leafname, int64 leafval, status_t *res)

make an int64 val_value_t struct for a specified leaf or leaf-list

This is a main API for SIL and SIL-SA code to construct return data for GET2 callbacks.

See also

agt_make_int64_leaf2

Parameters
  • parentobj -- parent object to find child leaf object

  • leafname -- name of leaf to find (namespace hardwired)

  • leafval -- int64 number value for leaf

  • res -- address of return status

Return values

*res -- return status

Returns

malloced value struct or NULL if some error

/* construct a int64 type leaf */
status_t res = NO_ERR;
val_value_t *value =
    agt_make_int64_leaf(parentobj,
                        leafname,
                        (int64)64,
                         &res);

Boolean Type

In order to construct a data node with boolean type, the following API function can be used.

val_value_t *agt_make_boolean_leaf(obj_template_t *parentobj, const xmlChar *modname, const xmlChar *leafname, boolean boolval, status_t *res)

make a val_value_t struct for a specified leaf or leaf-list (NCX_BT_BOOL)

Parameters
  • parentobj -- parent object to find child leaf object

  • modname -- name of module defining leaf (may be NULL to pick parent)

  • leafname -- name of leaf to find (namespace hardwired)

  • boolval -- boolean value for leaf

  • res -- address of return status

Return values

*res -- return status

Returns

malloced value struct or NULL if some error

/* construct a boolean type leaf */
status_t res = NO_ERR;
val_value_t *string_leaf =
    agt_make_boolean_leaf(parentobj,
                          modname,
                          leafname,
                          boolval,
                          &res);

Empty Type

In order to construct a data node with empty type, the following API function can be used.

val_value_t *agt_make_empty_leaf(obj_template_t *parentobj, const xmlChar *modname, const xmlChar *leafname, boolean boolval, status_t *res)

make a val_value_t struct for a specified leaf or leaf-list (NCX_BT_EMPTY)

Parameters
  • parentobj -- parent object to find child leaf object

  • modname -- name of module defining leaf (may be NULL to pick parent)

  • leafname -- name of leaf to find (namespace hardwired)

  • boolval -- ignored boolean value for leaf

  • res -- address of return status

Return values

*res -- return status

Returns

malloced value struct or NULL if some error

/* construct a boolean type leaf */
status_t res = NO_ERR;
val_value_t *string_leaf =
    agt_make_empty_leaf(parentobj,
                        modname,
                        leafname,
                        boolval,
                        &res);

Bits Type

The easiest way to create a leaf or leaf-list with the YANG bits data type is to create a string somehow with the bit values that should be set. This example uses the leaf object template and the 'val_make_simval_obj' API.

#include "val_util.h"
#include "status.h"

status_t res = NO_ERR;
val_value_t *retval =
    val_make_simval_obj(leafobj,
                        (const xmlChar *)"bit1 bit3 bit5",
                        &res);
if ((retval != NULL) && (res == NO_ERR)) {
    /* retval is malloced and valid, ready to use */
    // ...
} else {
    // res should be some error only if retval is also NULL
}

It is also possible to construct a bits leaf or leaf-list from the 'ncx_bits_t' which is really 'ncx_list_t'.

  • First the ncx_list_t is constructed or referenced from within another val_value_t or other data structure.

  • Next the agt_make_bits_leaf API is used with the parent object not the child leaf object.

val_value_t *agt_make_bits_leaf(obj_template_t *parentobj, const xmlChar *modname, const xmlChar *leafname, const ncx_list_t *listval, status_t *res)

make a val_value_t struct for a specified leaf or leaf-list (NCX_BT_BITS or NCX_BT_SLIST)

Parameters
  • parentobj -- parent object to find child leaf object

  • modname -- name of module defining leaf (may be NULL to pick parent)

  • leafname -- name of leaf to find (namespace hardwired)

  • listval -- bits value for leaf

  • res -- address of return status

Return values

*res -- return status

Returns

malloced value struct or NULL if some error

#include "agt_util.h"
#include "ncx_list.h"
#include "status.h"

/* construct a bits leaf from another bits leaf */
status_t res = NO_ERR;
const ncx_list_t *bits = &(VAL_BITS(anotherleafval));
val_value_t *string_leaf =
    agt_make_bits_leaf(parentobj,
                       modname,
                       leafname,
                       bits,
                       &res);

To check if any bit is set in a val_value_t using the bits type, refer to the following code example for a server CLI parameter:

/* Process --log-backtrace-stream */
val = val_find_child_fast(parentval, nsid, NCX_EL_LOGBT_STREAM);
if (val && val->res == NO_ERR) {
    ncx_list_t *bits = &VAL_BITS(val);

    if (ncx_string_in_list((const xmlChar *)"logfile", bits)) {
        log_set_backtrace_logfile();
    }
    if (ncx_string_in_list((const xmlChar *)"stderr", bits)) {
        log_set_backtrace_stderr();
    }
    if (ncx_string_in_list((const xmlChar *)"stdout", bits)) {
        log_set_backtrace_stdout();
    }
    if (ncx_string_in_list((const xmlChar *)"syslog", bits)) {
        log_set_backtrace_syslog();
    }
    if (ncx_string_in_list((const xmlChar *)"vendor", bits)) {
        log_set_backtrace_vendor();
    }
}

Identityref Type

The 'identityref' data type in YANG is used to select a specific YANG identity for its value, which must match the identityref 'base' statements in the identityref type.

module foo {
   // ...
   prefix f;

   identity idbase;

   identity val1 {
     base idbase;
   }
   identity val2 {
     base idbase;
   }
   identity val2 {
     base idbase;
   }

   leaf idref1 {
     type identityref {
       // values val1, val2, val3 allowed
       base idbase;
     }
   }
}

The 'val_idref_t' struct is used to define a reference to an identity.

struct val_idref_t

one QName for the NCX_BT_IDREF value

Public Members

xmlns_id_t nsid

namespace ID

xmlChar *name

if nsid == INV_ID then this is entire QName

ncx_identity_t *identity

ID back-ptr if found.

An identityref leaf can be created in 2 steps with these APIs:

  • Create a val_idref_t struct

  • Invoke the agt_make_idref_leaf API function

val_value_t *agt_make_idref_leaf(obj_template_t *parentobj, const xmlChar *leafname, const val_idref_t *leafval, status_t *res)

make an identityref val_value_t struct for a specified leaf or leaf-list

This is a main API for SIL and SIL-SA code to construct return data for GET2 callbacks.

See also

agt_make_idref_leaf2

Parameters
  • parentobj -- parent object to find child leaf object

  • leafname -- name of leaf to find (namespace hardwired)

  • leafval -- identityref value for leaf

  • res -- address of return status

Return values

*res -- return status

Returns

malloced value struct or NULL if some error

The following example shows how this API might be used to set the leaf 'idref1' to the identity 'val2':

#include "agt_util.h"
#include "status.h"
#include "val.h"
#include "xmlns.h"

val_idref_t idref = {0};
xmlChar buff[] = "val2";

idref.nsid = xmlns_find_ns_by_module((const xmlChar *)"foo");
idref.name = buff;

status_t res = NO_ERR;
val_value_t *newval =
    agt_make_idref_leaf(parentobj,
                        (const xmlChar *)"idref1",
                        &idref,
                        &res);
 if ((newval != NULL) && (res == NO_ERR)) {
     // valid leaf OK to use; must be freed with val_free_value
 } else {
     // error status and NULL return value expected
 }

Leaf-list Examples

The following examples show how to construct a simple leaf-list data node.

These nodes are constructed the same way as regular leaf nodes. The only difference is that the "val_child_add" APIs allow multiple instances to be created, instead of just one.

The following example code shows how to construct 3 leaf-list siblings using the same API functions as for leaf node:

/* construct 3 leaf-list entries */
status_t res = NO_ERR;
val_value_t *leaflist_value1 =
    val_make_simval_obj(leaflist_obj, (const xmlChar *)"53", &res);
if (!leaflist_value) {
    return res;
}

val_value_t *leaflist_value2 =
    val_make_simval_obj(leaflist_obj, (const xmlChar *)"30", &res);
if (!leaflist_value2) {
    return res;
}

val_value_t *leaflist_value3 =
    val_make_simval_obj(leaflist_obj, (const xmlChar *)"80", &res);
if (!leaflist_value3) {
    return res;
}

Alternatively, the following example can be used in order to construct multiple leaf-list entries of int32 type node and add them to the existent container parent:

status_t res = NO_ERR;
int32 value = 0;
for (value = 10; (value <= 15) && (res==NO_ERR); value++) {
    val_value_t *leaflist_value =
        agt_make_int_leaf(parentobj,
                          leaflistname,
                          value,
                          &res);
    if (!leaflist_value) {
        return res;
    }

    /* add a new leaf-list entry into target container */
    res = val_child_add(leaflist_value, container_value);
     if (res != NO_ERR) {
        val_free_value(leaflist_value);
    }
}

As a result, all the leaf-list entries will be added to the parent container.

Adding Child Leafy Nodes

YANG data trees are usually constructed top-down. The parent is created and then children are created and added to the new parent. This procedure can be done in a nested fashion, to create any data tree.

The following APIs should be used to add leaf or leaf-list nodes to a parent in one step. These simplified APIs replace the older 2 step APIs that first create a child node and then use val_child_add to add the child to its parent.

API Function

Description

agt_add_leafy

Add any data node using a string value

agt_add_uint_leafy

Add a numeric data node using a uint32 value

agt_add_int_leafy

Add a numeric data node using a int32 value

agt_add_uint64_leafy

Add a numeric data node using a uint64 value

agt_add_int64_leafy

Add a numeric data node using a int64 value

agt_add_boolean_leafy

Add a boolean data node using a boolean value

agt_add_idref_leafy

Add an identityref data node using a val_idref_t value

agt_add_bits_leafy

Add a bits data node using a ncx_list_t value

Example:

The previous leaf-list example can be simplified using the agt_add_int_leafy API.

status_t agt_add_int_leafy(val_value_t *parentval, const xmlChar *modname, const xmlChar *leafname, int32 leafval)

make a child node from a int32 and add to parent.

Add a simple child to a container or list

  • Combines agt_make_int_leaf2 and val_child_add

  • Can be used for leaf or leaf-list

Parameters
  • parentval -- parent value node to get new child

  • modname -- name of module defining leaf (may be NULL to pick parent)

  • leafname -- name of leaf to find (namespace hardwired)

  • leafval -- number value for leaf

Returns

status

status_t res = NO_ERR;
int32 value = 0;
for (value = 10; value <= 15 && res==NO_ERR; value++) {
    res = agt_add_bits_leafy(container_value,
                             NULL,    // modname
                             leaflistname,
                             value);
    if (res != NO_ERR) {
       // handle error, nothing to clean up here
    }
}

Container Examples

The following examples shows how to construct a container data node.

The container nodes can be constructed different ways depending whether it is a top level container or not. If the container is not a top level container, the following code can be used:

/* get the container obj template */
obj_template_t *cont_obj =
    obj_find_child(parentobj, modname, objname);
if (!cont_obj) {
    return ERR_NCX_DEF_NOT_FOUND;
}

/* make a container value */
val_value_t *cont_value = val_new_value();
if (!cont_value) {
    return ERR_INTERNAL_MEM;
}
val_init_from_template(cont_value, cont_obj);

The following example shows how multiple leaf-list entries can be added to the parent container:

status_t res = NO_ERR;
int32 value = 0;
for (value = 10; value <= 15 && res==NO_ERR; value++) {
    val_value_t *leaflist_value =
        agt_make_int_leaf(parentobj,
                          leaflistname,
                          value,
                          &res);
    if (!leaflist_value) {
        return res;
    }

    /* add a new leaf-list entry to parent container */
    res = val_child_add(leaflist_value, cont_value);
    if (res != NO_ERR) {
        val_free_value(leaflist_value);
         return res;
    }
}

List Example

The following example shows how to construct a list data node. Refer to the Child Data Nodes section for details on this procedure.

create_list_entry
   static val_value_t *
       create_list_entry (obj_template_t *parentobj,
                          int32 key,
                          status_t *res)
   {
       /* get the obj template for the list obj */
       obj_template_t *list_obj =
           obj_find_child(parentobj,
                          (const xmlChar *)"my-module",
                          (const xmlChar *)"my-list");
       if (!list_obj) {
           *res = ERR_NCX_DEF_NOT_FOUND;
           return NULL;
       }

       /* make the list node */
       val_value_t *list_value = val_new_value();
       if (!list_value) {
           *res = ERR_INTERNAL_MEM;
           return NULL;
       }
       val_init_from_template(list_value, list_obj);

       /* add key leaf entry */
       *res = agt_add_int_leafy(list_obj, NULL, keyname, key);
       if (*res != NO_ERR) {
           val_free_value(list_value);
           return NULL;
       }

       /* add an extra leaf entry */
       *res = agt_add_uint_leafy(list_obj,
                                 NULL,         // modname
                                 (const xmlChar *)"my-other-leaf",
                                 (uint32)32);
       if (*res != NO_ERR) {
           val_free_value(list_value);
           return NULL;
       }

       /* generate the internal index Q chain */
       *res = val_gen_index_chain(list_obj, list_value);
       if (*res != NO_ERR) {
           val_free_value(list_value);
           return NULL;
       }
       return list_value;

   }

In the next example, 5 list entries are created and added to the parent container contvalue.

/* malloc and construct list values and add to container parent */
status_t res = NO_ERR;
int32 key = 0;
for (key = 10; key <= 15; key++) {
    val_value_t *list_value =
        create_list_entry(container_obj, key, &res);
    if (!list_value) {
        return res;
    }

    /* add a new list entry into target container */
    res = val_child_add(list_value, contvalue);
    if (res != NO_ERR) {
        val_free_value(list_value);
        return res;
    }
}