Operational data is representing in YANG as a data node that has a "config" property of "false".
The netconfd-pro server has 3 ways of supporting operational data
| Name | Callback Type | Description |
| Static Node | None | Data node is a static value stored in the system. It can be used by SIL code only. |
| Virtual Node | GET1 | Data node is a placeholder stored in the system. There is a GET1 callback installed to retrieve the value as needed. There is one node for each instance of a list or leaf-list. It can be used by SIL code only. |
| Object Node | GET2 | There are no data nodes stored in the system. There is 1 GET2 callback for each complex object. The GET2 callback is called to retrieve one or more values as needed. It can be used by SIL or SIL-SA code |
This example uses code for the yuma-system YANG module.
Note: This module is being replaced by the ietf-system module from RFC 7317 in the near future.
Static Nodes vs. Virtual Nodes

1) Install the system container and leafs during the "init2" phase at boot-time.
/********************************************************************
* FUNCTION agt_sys_init2
*
* INIT 2:
* Initialize the monitoring data structures
* This must be done after the <running> config is loaded
*
* INPUTS:
* none
* RETURNS:
* status
*********************************************************************/
status_t
agt_sys_init2 (void)
{
if (!agt_sys_init_done) {
return SET_ERROR(ERR_INTERNAL_INIT_SEQ);
}
/* get the running config to add some static data into */
cfg_template_t *runningcfg = cfg_get_config_id(NCX_CFGID_RUNNING);
if (!runningcfg || !runningcfg->root) {
return SET_ERROR(ERR_INTERNAL_VAL);
}
/* add /system */
val_value_t *topval = val_new_value();
if (!topval) {
return ERR_INTERNAL_MEM;
}
val_init_from_template(topval, systemobj);
/* handing off the malloced memory here */
val_add_child_sorted(topval, runningcfg->root);
/* add /system/sysName */
const xmlChar *myhostname = (const xmlChar *)getenv("HOSTNAME");
if (!myhostname) {
myhostname = (const xmlChar *)"localhost";
}
status_t res = NO_ERR;
val_value_t *childval =
agt_make_leaf(systemobj, system_N_sysName, myhostname, &res);
if (childval) {
val_add_child(childval, topval);
} else {
return res;
}
/* add /system/sysCurrentDateTime */
childval = agt_make_virtual_leaf(systemobj,
system_N_sysCurrentDateTime,
get_currentDateTime, &res);
if (childval) {
val_add_child(childval, topval);
} else {
return res;
}
/* add /system/sysBootDateTime */
xmlChar tstampbuff[TSTAMP_MIN_SIZE];
tstamp_datetime(tstampbuff);
childval = agt_make_leaf(systemobj,
system_N_sysBootDateTime,
tstampbuff, &res);
if (childval) {
val_add_child(childval, topval);
} else {
return res;
}
2) Example GET1 Callback
/********************************************************************
* FUNCTION get_currentDateTime
*
* <get> operation handler for the sysCurrentDateTime leaf
*
* INPUTS:
* see ncx/getcb.h getcb_fn_t for details
*
* RETURNS:
* status
*********************************************************************/
static status_t
get_currentDateTime (ses_cb_t *scb,
getcb_mode_t cbmode,
const val_value_t *virval,
val_value_t *dstval)
{
(void)scb;
(void)virval;
if (cbmode == GETCB_GET_VALUE) {
xmlChar *buff = (xmlChar *)m__getMem(TSTAMP_MIN_SIZE);
if (!buff) {
return ERR_INTERNAL_MEM;
}
tstamp_datetime(buff);
VAL_STR(dstval) = buff;
return NO_ERR;
} else {
return ERR_NCX_OPERATION_NOT_SUPPORTED;
}
} /* get_currentDateTime */