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 */